diff --git a/reactos/apps/utils/net/tcpsvcs/chargen/chargen.c b/reactos/apps/utils/net/tcpsvcs/chargen/chargen.c new file mode 100644 index 00000000000..90b27a853df --- /dev/null +++ b/reactos/apps/utils/net/tcpsvcs/chargen/chargen.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include "chargen.h" +#include "../skelserver/skelserver.h" + +DWORD WINAPI ChargenHandler(VOID* Sock_) +{ + DWORD Retval = 0; + SOCKET Sock = (SOCKET)Sock_; + + if (!GenerateChars(Sock)) { + _tprintf(_T("Echo incoming packets failed\n")); + Retval = 3; + } + + _tprintf(_T("Shutting connection down...\n")); + if (ShutdownConnection(Sock)) { + _tprintf(_T("Connection is down.\n")); + } + else + { + _tprintf(_T("Connection shutdown failed\n")); + Retval = 3; + } + + return Retval; +} + + +BOOL GenerateChars(SOCKET Sock) +{ + int i, + charIndex, /* internal loop */ + loopIndex; /* line loop */ + char ring[END-START]; + char *endring; + + /* fill ring with printable characters */ + for (charIndex=0, i=START; i<=END; charIndex++, i++) + ring[charIndex] = i; + /* establish the end character in the ring */ + endring = &ring[charIndex]; + + /* where we will start output from */ + loopIndex = 0; + + while (1) + { + /* if the loop index is equal to number of chars previously + * printed, start the loop from the beginning */ + if (loopIndex == END-START) + loopIndex = 0; + + /* start printing from char controled by loopIndex */ + charIndex = loopIndex; + for (i=0; i 0) { + SentBytes += Temp; + } + else if (Temp == SOCKET_ERROR) { + return FALSE; + } + else + { + /* Client closed connection before we could reply to + all the data it sent, so quit early. */ + _tprintf(_T("Peer unexpectedly dropped connection!\n")); + return FALSE; + } + + _tprintf(("Connection closed by peer.\n")); + return TRUE; +} + + + + + diff --git a/reactos/apps/utils/net/tcpsvcs/chargen/chargen.h b/reactos/apps/utils/net/tcpsvcs/chargen/chargen.h new file mode 100644 index 00000000000..5155c552361 --- /dev/null +++ b/reactos/apps/utils/net/tcpsvcs/chargen/chargen.h @@ -0,0 +1,8 @@ +#define START 32 +#define END 126 +#define LINESIZ 72 +#define BUF 1024 + +DWORD WINAPI ChargenHandler(VOID* Sock_); +BOOL GenerateChars(SOCKET Sock); +BOOL SendChar(SOCKET Sock, CHAR c); diff --git a/reactos/apps/utils/net/tcpsvcs/chargen/chargen.xml b/reactos/apps/utils/net/tcpsvcs/chargen/chargen.xml new file mode 100644 index 00000000000..0adefdf7866 --- /dev/null +++ b/reactos/apps/utils/net/tcpsvcs/chargen/chargen.xml @@ -0,0 +1,9 @@ + + . + + kernel32 + iphlpapi + ws2_32 + chargen/chargen.c + + diff --git a/reactos/apps/utils/net/tcpsvcs/daytime/.gitignore b/reactos/apps/utils/net/tcpsvcs/daytime/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/reactos/apps/utils/net/tcpsvcs/discard/.gitignore b/reactos/apps/utils/net/tcpsvcs/discard/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/reactos/apps/utils/net/tcpsvcs/echo/echo.c b/reactos/apps/utils/net/tcpsvcs/echo/echo.c new file mode 100644 index 00000000000..ef8f5b432c2 --- /dev/null +++ b/reactos/apps/utils/net/tcpsvcs/echo/echo.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include "echo.h" +#include "../skelserver/skelserver.h" + +// Handles the incoming data by reflecting it back to the sender. +DWORD WINAPI EchoHandler(VOID* Sock_) +{ + DWORD Retval = 0; + SOCKET Sock = (SOCKET)Sock_; + + if (!EchoIncomingPackets(Sock)) { + _tprintf(_T("Echo incoming packets failed\n")); + Retval = 3; + } + + _tprintf(_T("Shutting connection down...\n")); + if (ShutdownConnection(Sock)) { + _tprintf(_T("Connection is down.\n")); + } + else + { + _tprintf(_T("Connection shutdown failed\n")); + Retval = 3; + } + + return Retval; +} + + + +BOOL EchoIncomingPackets(SOCKET Sock) +{ + TCHAR ReadBuffer[BUF]; + INT Temp; + INT ReadBytes; + INT SentBytes; + + do { + ReadBytes = recv(Sock, ReadBuffer, BUF, 0); + if (ReadBytes > 0) { + _tprintf(_T("Received %d bytes from client\n"), ReadBytes); + + SentBytes = 0; + while (SentBytes < ReadBytes) { + Temp = send(Sock, ReadBuffer + SentBytes, + ReadBytes - SentBytes, 0); + if (Temp > 0) { + _tprintf(_T("Sent %d bytes back to client\n"), Temp); + SentBytes += Temp; + } + else if (Temp == SOCKET_ERROR) { + return FALSE; + } + else { + /* Client closed connection before we could reply to + // all the data it sent, so quit early. */ + _tprintf(_T("Peer unexpectedly dropped connection!\n")); + return FALSE; + } + } + } + else if (ReadBytes == SOCKET_ERROR) { + return FALSE; + } + } while (ReadBytes != 0); + + _tprintf(("Connection closed by peer.\n")); + return TRUE; +} + diff --git a/reactos/apps/utils/net/tcpsvcs/echo/echo.h b/reactos/apps/utils/net/tcpsvcs/echo/echo.h new file mode 100644 index 00000000000..3f0d2a78271 --- /dev/null +++ b/reactos/apps/utils/net/tcpsvcs/echo/echo.h @@ -0,0 +1,4 @@ +#define BUF 1024 + +DWORD WINAPI EchoHandler(VOID* Sock_); +BOOL EchoIncomingPackets(SOCKET Sock); diff --git a/reactos/apps/utils/net/tcpsvcs/qotd/.gitignore b/reactos/apps/utils/net/tcpsvcs/qotd/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/reactos/apps/utils/net/tcpsvcs/skelserver/skelserver.c b/reactos/apps/utils/net/tcpsvcs/skelserver/skelserver.c new file mode 100644 index 00000000000..fa65f407da6 --- /dev/null +++ b/reactos/apps/utils/net/tcpsvcs/skelserver/skelserver.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include "../tcpsvcs.h" +#include "skelserver.h" + + +DWORD WINAPI StartServer(LPVOID lpParam) +{ + const TCHAR* HostIP = "127.0.0.1"; + DWORD RetVal; + WSADATA wsaData; + PMYDATA pData; + + pData = (PMYDATA)lpParam; + + if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) + { + _tprintf(_T("WSAStartup() failed : %lu\n"), RetVal); + return -1; + } + + SOCKET ListeningSocket = SetUpListener(HostIP, htons(pData->Port)); + if (ListeningSocket == INVALID_SOCKET) + { + _tprintf(_T("error setting up socket\n")); + return 3; + } + + printf("Waiting for connections...\n"); + while (1) + { + AcceptConnections(ListeningSocket, pData->Service); + printf("Acceptor restarting...\n"); + } + + WSACleanup(); + return 0; +} + + +SOCKET SetUpListener(const char* ServAddr, int Port) +{ + SOCKET Sock; + SOCKADDR_IN Server; + DWORD InterfaceAddr = inet_addr(ServAddr); + + if (InterfaceAddr != INADDR_NONE) + { + Sock = socket(AF_INET, SOCK_STREAM, 0); + if (Sock != INVALID_SOCKET) + { + Server.sin_family = AF_INET; + Server.sin_addr.s_addr = InterfaceAddr; + Server.sin_port = Port; + if (bind(Sock, (SOCKADDR*)&Server, sizeof(SOCKADDR_IN)) != SOCKET_ERROR) + { + listen(Sock, SOMAXCONN); + return Sock; + } + else + printf("bind() failed\n"); + + } + } + return INVALID_SOCKET; +} + + + + +VOID AcceptConnections(SOCKET ListeningSocket, LPTHREAD_START_ROUTINE Service) +{ + SOCKADDR_IN Client; + SOCKET Sock; + INT nAddrSize = sizeof(Client); + DWORD ThreadID; + + while (1) + { + Sock = accept(ListeningSocket, (SOCKADDR*)&Client, &nAddrSize); + if (Sock != INVALID_SOCKET) + { + _tprintf(_T("Accepted connection from %s:%d\n"), + inet_ntoa(Client.sin_addr), ntohs(Client.sin_port)); + + CreateThread(0, 0, Service, (void*)Sock, 0, &ThreadID); + } + else + { + _tprintf(_T("accept() failed\n")); + return; + } + } +} + +BOOL ShutdownConnection(SOCKET Sock) +{ + /* Disallow any further data sends. This will tell the other side + that we want to go away now. If we skip this step, we don't + shut the connection down nicely. */ + if (shutdown(Sock, SD_SEND) == SOCKET_ERROR) + return FALSE; + + /* Receive any extra data still sitting on the socket. After all + data is received, this call will block until the remote host + acknowledges the TCP control packet sent by the shutdown above. + Then we'll get a 0 back from recv, signalling that the remote + host has closed its side of the connection. */ + while (1) + { + char ReadBuffer[BUF]; + int NewBytes = recv(Sock, ReadBuffer, BUF, 0); + if (NewBytes == SOCKET_ERROR) + return FALSE; + else if (NewBytes != 0) + _tprintf(_T("FYI, received %d unexpected bytes during shutdown\n"), NewBytes); + else + break; + } + + /* Close the socket. */ + if (closesocket(Sock) == SOCKET_ERROR) + return FALSE; + + return TRUE; +} diff --git a/reactos/apps/utils/net/tcpsvcs/skelserver/skelserver.h b/reactos/apps/utils/net/tcpsvcs/skelserver/skelserver.h new file mode 100644 index 00000000000..21305dd520c --- /dev/null +++ b/reactos/apps/utils/net/tcpsvcs/skelserver/skelserver.h @@ -0,0 +1,7 @@ +#define BUF 1024 + +DWORD WINAPI StartServer(LPVOID lpParam); +SOCKET SetUpListener(const char* ServAddr, int Port); +VOID AcceptConnections(SOCKET ListeningSocket, LPTHREAD_START_ROUTINE Service); +BOOL EchoIncomingPackets(SOCKET sd); +BOOL ShutdownConnection(SOCKET Sock); diff --git a/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c b/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c new file mode 100644 index 00000000000..8628fb7268f --- /dev/null +++ b/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include "tcpsvcs.h" +#include "skelserver/skelserver.h" +#include "echo/echo.h" +#include "chargen/chargen.h" + +int main(int argc, char *argv[]) +{ + PMYDATA pData[MAX_THREADS]; + DWORD dwThreadId[MAX_THREADS]; + HANDLE hThread[MAX_THREADS]; + INT i; + + /* Create MAX_THREADS worker threads. */ + for( i=0; iPort = ECHO_PORT; + pData[0]->Service = EchoHandler; + pData[1]->Port = CHARGEN_PORT; + pData[1]->Service = ChargenHandler; + + hThread[i] = CreateThread( + NULL, // default security attributes + 0, // use default stack size + StartServer, // thread function + pData[i], // argument to thread function + 0, // use default creation flags + &dwThreadId[i]); // returns the thread identifier + + /* Check the return value for success. */ + if (hThread[i] == NULL) + { + ExitProcess(i); + } + } + + /* Wait until all threads have terminated. */ + WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE); + + /* Close all thread handles upon completion. */ + for(i=0; i + . + + kernel32 + iphlpapi + ws2_32 + shlwapi + tcpsvcs.c + skelserver/skelserver.c + echo/echo.c + chargen/chargen.c + +