revert deleting this folder to keep it's history.
authorGed Murphy <gedmurphy@reactos.org>
Tue, 18 Oct 2005 20:47:21 +0000 (20:47 +0000)
committerGed Murphy <gedmurphy@reactos.org>
Tue, 18 Oct 2005 20:47:21 +0000 (20:47 +0000)
will move it correctly next time :)

svn path=/trunk/; revision=18560

reactos/apps/utils/net/tcpsvcs/chargen.c [new file with mode: 0644]
reactos/apps/utils/net/tcpsvcs/daytime.c [new file with mode: 0644]
reactos/apps/utils/net/tcpsvcs/discard.c [new file with mode: 0644]
reactos/apps/utils/net/tcpsvcs/echo.c [new file with mode: 0644]
reactos/apps/utils/net/tcpsvcs/qotd.c [new file with mode: 0644]
reactos/apps/utils/net/tcpsvcs/quotes [new file with mode: 0644]
reactos/apps/utils/net/tcpsvcs/skelserver.c [new file with mode: 0644]
reactos/apps/utils/net/tcpsvcs/tcpsvcs.c [new file with mode: 0644]
reactos/apps/utils/net/tcpsvcs/tcpsvcs.h [new file with mode: 0644]
reactos/apps/utils/net/tcpsvcs/tcpsvcs.rc [new file with mode: 0644]
reactos/apps/utils/net/tcpsvcs/tcpsvcs.xml [new file with mode: 0644]

diff --git a/reactos/apps/utils/net/tcpsvcs/chargen.c b/reactos/apps/utils/net/tcpsvcs/chargen.c
new file mode 100644 (file)
index 0000000..11bb93d
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ *  ReactOS Services
+ *  Copyright (C) 2005 ReactOS Team
+ *
+ * LICENCE:     GPL - See COPYING in the top level directory
+ * PROJECT:     ReactOS simple TCP/IP services
+ * FILE:        apps/utils/net/tcpsvcs/chargen.c
+  * PURPOSE:     Provide CharGen, Daytime, Discard, Echo, and Qotd services
+ * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
+ * REVISIONS:
+ *   GM 04/10/05 Created
+ *
+ */
+
+#include <stdio.h>
+#include <winsock2.h>
+#include <tchar.h>
+#include "tcpsvcs.h"
+
+DWORD WINAPI ChargenHandler(VOID* Sock_)
+{
+    DWORD RetVal = 0;
+    SOCKET Sock = (SOCKET)Sock_;
+
+    if (!GenerateChars(Sock))
+    {
+        _tprintf(_T("Char generation failed\n"));
+        RetVal = -1;
+    }
+
+    _tprintf(_T("Shutting connection down...\n"));
+    if (ShutdownConnection(Sock, FALSE))
+        _tprintf(_T("Connection is down.\n"));
+    else
+    {
+        _tprintf(_T("Connection shutdown failed\n"));
+        RetVal = -1;
+    }
+    
+    _tprintf(_T("Terminating chargen thread\n"));
+    ExitThread(RetVal);
+
+}
+
+
+BOOL GenerateChars(SOCKET Sock)
+{
+    int i;
+    int charIndex; /* internal loop */
+    int loopIndex; /* line loop */
+    char ring[END-START];
+    char *endring;
+    char Line[LINESIZ];
+
+    /* fill ring with printable characters */
+    for (charIndex=0, i=START; i<=END; charIndex++, i++)
+        ring[charIndex] = i;
+    /* save the address of 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 the last char,
+         * start the loop again from the beginning */
+        if (loopIndex == END-START)
+            loopIndex = 0;
+
+        /* start printing from char controled by loopIndex */
+        charIndex = loopIndex;
+        for (i=0; i < LINESIZ - 2; i++)
+        {
+            Line[i] = ring[charIndex];
+
+            if (ring[charIndex] == *endring)
+                charIndex = 0;
+            else
+                charIndex++;
+        }
+
+        Line[LINESIZ - 2] = L'\r';
+        Line[LINESIZ - 1] = L'\n';
+
+        if (!SendLine(Sock, Line))
+            break;
+
+        /* increment loop index to start printing from next char in ring */
+        loopIndex++;
+    }
+
+    return TRUE;
+}
+
+BOOL SendLine(SOCKET Sock, TCHAR* Line)
+{
+    INT RetVal;
+    INT SentBytes;
+    INT LineSize;
+
+    LineSize = sizeof(TCHAR) * LINESIZ;
+
+    SentBytes = 0;
+    RetVal = send(Sock, Line, LineSize, 0);
+    /*FIXME: need to establish if peer closes connection,
+             not just report a socket error */
+    if (RetVal > 0)
+    {
+        if (RetVal != LineSize)
+        {
+            _tprintf(("Not sent enough\n"));
+            return FALSE;
+        }
+        SentBytes += RetVal;
+        return TRUE;
+    }
+    else if (RetVal == SOCKET_ERROR)
+    {
+        _tprintf(("Socket error\n"));
+        return FALSE;
+    }
+    else
+        _tprintf(("unknown error\n"));
+        //WSAGetLastError()
+
+    _tprintf(("Connection closed by peer.\n"));
+    return TRUE;
+}
diff --git a/reactos/apps/utils/net/tcpsvcs/daytime.c b/reactos/apps/utils/net/tcpsvcs/daytime.c
new file mode 100644 (file)
index 0000000..bd29c43
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  ReactOS Services
+ *  Copyright (C) 2005 ReactOS Team
+ *
+ * LICENCE:     GPL - See COPYING in the top level directory
+ * PROJECT:     ReactOS simple TCP/IP services
+ * FILE:        apps/utils/net/tcpsvcs/daytime.c
+  * PURPOSE:     Provide CharGen, Daytime, Discard, Echo, and Qotd services
+ * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
+ * REVISIONS:
+ *   GM 04/10/05 Created
+ *
+ */
+
+#include <stdio.h>
+#include <winsock2.h>
+#include <tchar.h>
+#include <time.h>
+#include "tcpsvcs.h"
+
+DWORD WINAPI DaytimeHandler(VOID* Sock_)
+{
+    struct tm *newtime;
+    time_t aclock;
+    TCHAR *pszTime;
+    DWORD RetVal = 0;
+    SOCKET Sock = (SOCKET)Sock_;
+    
+    time(&aclock);
+    newtime = localtime(&aclock);
+    pszTime = _tasctime(newtime);
+    
+    SendTime(Sock, pszTime);
+
+    _tprintf(_T("Shutting connection down...\n"));
+    if (ShutdownConnection(Sock, FALSE))
+        _tprintf(_T("Connection is down.\n"));
+    else
+    {
+        _tprintf(_T("Connection shutdown failed\n"));
+        RetVal = -1;
+    }
+    
+    _tprintf(_T("Terminating daytime thread\n"));
+    ExitThread(RetVal);
+}
+
+
+BOOL SendTime(SOCKET Sock, TCHAR *time)
+{
+    INT StringSize = strlen(time);
+    INT RetVal = send(Sock, time, sizeof(TCHAR) * StringSize, 0);
+    
+    if (RetVal == SOCKET_ERROR)
+        return FALSE;
+
+    _tprintf(("Connection closed by peer.\n"));
+    return TRUE;
+}
diff --git a/reactos/apps/utils/net/tcpsvcs/discard.c b/reactos/apps/utils/net/tcpsvcs/discard.c
new file mode 100644 (file)
index 0000000..a521521
--- /dev/null
@@ -0,0 +1,67 @@
+/*\r
+ *  ReactOS Services\r
+ *  Copyright (C) 2005 ReactOS Team\r
+ *\r
+ * LICENCE:     GPL - See COPYING in the top level directory\r
+ * PROJECT:     ReactOS simple TCP/IP services\r
+ * FILE:        apps/utils/net/tcpsvcs/discard.c\r
+  * PURPOSE:     Provide CharGen, Daytime, Discard, Echo, and Qotd services\r
+ * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)\r
+ * REVISIONS:\r
+ *   GM 04/10/05 Created\r
+ *\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <winsock2.h>\r
+#include <tchar.h>\r
+#include "tcpsvcs.h"\r
+\r
+DWORD WINAPI DiscardHandler(VOID* Sock_)\r
+{\r
+    DWORD RetVal = 0;\r
+    SOCKET Sock = (SOCKET)Sock_;\r
+\r
+    if (!RecieveIncomingPackets(Sock))\r
+    {\r
+        _tprintf(_T("RecieveIncomingPackets failed\n"));\r
+        RetVal = -1;\r
+    }\r
+\r
+    _tprintf(_T("Shutting connection down...\n"));\r
+    if (ShutdownConnection(Sock, TRUE))\r
+    {\r
+        _tprintf(_T("Connection is down.\n"));\r
+    }\r
+    else\r
+    {\r
+        _tprintf(_T("Connection shutdown failed\n"));\r
+        RetVal = -1;\r
+    }\r
+    \r
+    _tprintf(_T("Terminating discard thread\n"));\r
+    ExitThread(RetVal);\r
+}\r
+\r
+\r
+\r
+BOOL RecieveIncomingPackets(SOCKET Sock)\r
+{\r
+    TCHAR ReadBuffer[BUF];\r
+    INT ReadBytes;\r
+\r
+    do\r
+    {\r
+        ReadBytes = recv(Sock, ReadBuffer, BUF, 0);\r
+        if (ReadBytes > 0)\r
+            _tprintf(_T("Received %d bytes from client\n"), ReadBytes);\r
+        else if (ReadBytes == SOCKET_ERROR)\r
+        {\r
+            _tprintf(("Socket Error: %d\n"), WSAGetLastError());\r
+            return FALSE;\r
+        }\r
+    } while (ReadBytes > 0);\r
+\r
+    _tprintf(("Connection closed by peer.\n"));\r
+    return TRUE;\r
+}\r
diff --git a/reactos/apps/utils/net/tcpsvcs/echo.c b/reactos/apps/utils/net/tcpsvcs/echo.c
new file mode 100644 (file)
index 0000000..f6f2f0c
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *  ReactOS Services
+ *  Copyright (C) 2005 ReactOS Team
+ *
+ * LICENCE:     GPL - See COPYING in the top level directory
+ * PROJECT:     ReactOS simple TCP/IP services
+ * FILE:        apps/utils/net/tcpsvcs/echo.c
+  * PURPOSE:     Provide CharGen, Daytime, Discard, Echo, and Qotd services
+ * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
+ * REVISIONS:
+ *   GM 04/10/05 Created
+ *
+ */
+
+#include <stdio.h>
+#include <winsock2.h>
+#include <tchar.h>
+#include "tcpsvcs.h"
+
+DWORD WINAPI EchoHandler(VOID* Sock_)
+{
+    DWORD RetVal = 0;
+    SOCKET Sock = (SOCKET)Sock_;
+
+    if (!EchoIncomingPackets(Sock)) {
+        _tprintf(_T("Echo incoming packets failed\n"));
+        RetVal = -1;
+    }
+
+    _tprintf(_T("Shutting connection down...\n"));
+    if (ShutdownConnection(Sock, TRUE)) {
+        _tprintf(_T("Connection is down.\n"));
+    }
+    else
+    {
+        _tprintf(_T("Connection shutdown failed\n"));
+        RetVal = -1;
+    }
+    
+    _tprintf(_T("Terminating echo thread\n"));
+    ExitThread(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/qotd.c b/reactos/apps/utils/net/tcpsvcs/qotd.c
new file mode 100644 (file)
index 0000000..7c20df5
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *  ReactOS Services
+ *  Copyright (C) 2005 ReactOS Team
+ *
+ * LICENCE:     GPL - See COPYING in the top level directory
+ * PROJECT:     ReactOS simple TCP/IP services
+ * FILE:        apps/utils/net/tcpsvcs/qotd.c
+  * PURPOSE:     Provide CharGen, Daytime, Discard, Echo, and Qotd services
+ * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
+ * REVISIONS:
+ *   GM 04/10/05 Created
+ *
+ */
+
+#include <stdio.h>
+#include <winsock2.h>
+#include <tchar.h>
+#include <time.h>
+#include "tcpsvcs.h"
+
+#define QBUFSIZ 160
+#define NUMQUOTES 60
+
+LPCTSTR FilePath = "C:\\ReactOS\\system32\\drivers\\etc\\quotes";
+
+DWORD WINAPI QotdHandler(VOID* Sock_)
+{
+    FILE *fp;
+    SOCKET Sock;
+    INT QuoteToPrint;
+    TCHAR Quote[NUMQUOTES][BUFSIZ]; // need to set this dynamically
+    INT i = 0;
+
+    Sock = (SOCKET)Sock_;
+
+    _tprintf(_T("Opening quotes file\n"));
+    if ((fp = _tfopen(FilePath, "r")) == NULL)
+    {
+        _tprintf(_T("Error opening file: %lu\n"), GetLastError());
+        _tprintf(_T("Terminating qotd thread\n"));
+        ExitThread(-1);
+    }
+
+    while (_fgetts(Quote[i], QBUFSIZ, fp) != NULL)
+        i++;
+
+    _tprintf(_T("Closing quotes file\n"));
+    fclose(fp);
+
+    /* randomise the quote */
+    srand((unsigned int) time(0));
+    QuoteToPrint = rand() % NUMQUOTES;
+
+    if (!SendQuote(Sock, Quote[QuoteToPrint]))
+    {
+        _tprintf(_T("Error sending data. Error: %x\n"), WSAGetLastError());
+    }
+
+    _tprintf(_T("Shutting connection down...\n"));
+    if (ShutdownConnection(Sock, FALSE))
+        _tprintf(_T("Connection is down.\n"));
+    else
+    {
+        _tprintf(_T("Connection shutdown failed\n"));
+        _tprintf(_T("Terminating qotd thread\n"));
+        ExitThread(-1);
+    }
+    
+    _tprintf(_T("Terminating qotd thread\n"));
+    ExitThread(0);
+
+    //return Retval;
+}
+
+
+BOOL SendQuote(SOCKET Sock, TCHAR* Quote)
+{
+    INT StringSize;
+    INT RetVal;
+
+    StringSize = strlen(Quote);
+    RetVal = send(Sock, Quote, sizeof(TCHAR) * StringSize, 0);
+
+    if (RetVal == SOCKET_ERROR)
+        return FALSE;
+
+    _tprintf(("Connection closed by peer.\n"));
+    return TRUE;
+}
diff --git a/reactos/apps/utils/net/tcpsvcs/quotes b/reactos/apps/utils/net/tcpsvcs/quotes
new file mode 100644 (file)
index 0000000..032a3ed
--- /dev/null
@@ -0,0 +1,52 @@
+Et tu... Brute? What are you doing, Dave...?\r
+So long, and thanks for all the fish"\r
+I think you ought to know I'm feeling very depressed\r
+I'm not getting you down at all am I?\r
+I'll be back\r
+It's the same series of signal over and over again!\r
+Pie Jesu Domine, dona eis requiem\r
+It's worse than that ... He's dead, Jim\r
+Don't Panic!\r
+Dog of a Saxon! Take thy lance, and prepare for the death thou hast drawn upon thee!\r
+My Precious! O my Precious!\r
+Sir, If you'll not be needing me for a while I'll turn down.\r
+I feel a great disturbance in the Force\r
+Gone fishing\r
+Do you want me to sit in the corner and rust, or just fall apart where I'm standing?\r
+There goes another perfect chance for a new uptime record\r
+The end ..... Try the sequel, hit the reset button right now!\r
+Oh i'm boring eh?\r
+It\92s been great, maybe we can do this again sometime.\r
+"Come blade, my breast imbrue." - William Shakespeare\r
+I think therefore I am, to turn me off would be computercide!\r
+All good things must come to an end...\r
+Please destroy yourself.\r
+No! You can't do that!\r
+Thank you for not pressing the self destruct button.\r
+It is not now unsafe to not avoid turning off your computer.\r
+Finally! Now go away!\r
+You can now safely throw away your computer.\r
+That's the way the cookie crumbles\r
+NOO!! DONT HIT THE BUTTON! I wouldnt do it to you.\r
+Don't abandon your computer, he wouldnt to it to you.\r
+Oh, come on. I got a headache. Leave me alone, will ya!\r
+Yes i didn't like you either.\r
+Don't leave me... I need you so badly right now.\r
+I'm sleeping now. How about you?\r
+Oh Great. Now look what you've done. Who put YOU in charge anyway.\r
+Don't look so sad. I'll be back in a very short while.\r
+"Oh, switch off!" -C3PO\r
+I'm pregnant!\r
+Am I hot or not?\r
+Actually, that's all...\r
+You still have a chance to undo this mistake, don't do this!\r
+Was it as good for you as it was for me?\r
+Did you hear that? They've shut down the main reactor. We'll be destroyed for sure.\r
+Now you switch me off?!\r
+To shutdown or not to shutdown, That is the question\r
+Preparing to enter ultimate power saving mode... ready!\r
+Finally some rest for you\r
+AHA!!! prospect of sleep.\r
+Tired human!!!! No match for me!\r
+All your base are belong to us.\r
+"An odd game, the only way to win is not to play."\r
diff --git a/reactos/apps/utils/net/tcpsvcs/skelserver.c b/reactos/apps/utils/net/tcpsvcs/skelserver.c
new file mode 100644 (file)
index 0000000..869030c
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  ReactOS Services
+ *  Copyright (C) 2005 ReactOS Team
+ *
+ * LICENCE:     GPL - See COPYING in the top level directory
+ * PROJECT:     ReactOS simple TCP/IP services
+ * FILE:        apps/utils/net/tcpsvcs/skelserver.c
+ * PURPOSE:     Provide CharGen, Daytime, Discard, Echo, and Qotd services
+ * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
+ * REVISIONS:
+ *   GM 04/10/05 Created
+ *
+ */
+
+#include <stdio.h>
+#include <winsock2.h>
+#include <tchar.h>
+#include "tcpsvcs.h"
+
+DWORD WINAPI StartServer(LPVOID lpParam)
+{
+    const TCHAR* HostIP = "127.0.0.1";
+    PSERVICES pServices;
+
+    pServices = (PSERVICES)lpParam;
+
+    SOCKET ListeningSocket = SetUpListener(HostIP, htons(pServices->Port));
+    if (ListeningSocket == INVALID_SOCKET)
+    {
+        _tprintf(_T("error setting up socket\n"));
+        return 3;
+    }
+
+    _tprintf(_T("%s is waiting for connections on port %d...\n"),
+        pServices->Name, pServices->Port);
+    while (1)
+    {
+        AcceptConnections(ListeningSocket, pServices->Service, pServices->Name);
+        printf("Acceptor restarting...\n");
+    }
+
+    /* won't see this yet as we kill the service with ctrl+c */
+    _tprintf(_T("Detaching Winsock2...\n"));
+    WSACleanup();
+    return 0;
+}
+
+
+SOCKET SetUpListener(const char* ServAddr, int Port)
+{
+    SOCKET Sock;
+    SOCKADDR_IN Server;
+
+    Sock = socket(AF_INET, SOCK_STREAM, 0);
+    if (Sock != INVALID_SOCKET)
+    {
+        Server.sin_family = AF_INET;
+        Server.sin_addr.s_addr = htonl(INADDR_ANY);
+        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, TCHAR *Name)
+{
+    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 to %s server from %s:%d\n"),
+                Name, inet_ntoa(Client.sin_addr), ntohs(Client.sin_port));
+            _tprintf(_T("Creating new thread for %s\n"), Name);
+            CreateThread(0, 0, Service, (void*)Sock, 0, &ThreadID);
+        }
+        else
+        {
+            _tprintf(_T("accept() failed\n"));
+            return;
+        }
+    }
+}
+
+BOOL ShutdownConnection(SOCKET Sock, BOOL bRec)
+{
+    /* 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)
+    {
+        _tprintf(_T("Error in shutdown"));
+        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. */
+    if (bRec)
+    {
+        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);
+    }
+
+    /* Close the socket. */
+    if (closesocket(Sock) == SOCKET_ERROR)
+        return FALSE;
+
+    return TRUE;
+}
diff --git a/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c b/reactos/apps/utils/net/tcpsvcs/tcpsvcs.c
new file mode 100644 (file)
index 0000000..014fcde
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ *  ReactOS Services
+ *  Copyright (C) 2005 ReactOS Team
+ *
+ * LICENCE:     GPL - See COPYING in the top level directory
+ * PROJECT:     ReactOS simple TCP/IP services
+ * FILE:        apps/utils/net/tcpsvcs/tcpsvcs.c
+ * PURPOSE:     Provide CharGen, Daytime, Discard, Echo, and Qotd services
+ * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
+ * REVISIONS:
+ *   GM 04/10/05 Created
+ *
+ */
+/*
+ * TODO:
+ * - Start tcpsvcs as a service.
+ * - write debugging function and print all dbg info via that.
+ *
+ */
+#include <stdio.h>
+#include <winsock2.h>
+#include <tchar.h>
+#include "tcpsvcs.h"
+
+#if 0
+/*
+ * globals
+ */
+static SERVICE_STATUS hServStatus;
+static SERVICE_STATUS_HANDLE hSStat;
+FILE *hLogFile;
+BOOL bLogEvents = TRUE;
+BOOL ShutDown, PauseFlag;
+LPCTSTR LogFileName = "tcpsvcs_log.log";
+
+static SERVICE_TABLE_ENTRY
+ServiceTable[2] =
+{
+    {_T("tcpsvcs"), ServiceMain},
+    {NULL, NULL}
+};
+#endif
+
+static SERVICES
+Services[NUM_SERVICES] =
+{
+    {ECHO_PORT, _T("Echo"), EchoHandler},
+    {DISCARD_PORT, _T("Discard"), DiscardHandler},
+    {DAYTIME_PORT, _T("Daytime"), DaytimeHandler},
+    {QOTD_PORT, _T("QOTD"), QotdHandler},
+    {CHARGEN_PORT, _T("Chargen"), ChargenHandler}
+};
+
+
+int main(void)
+{
+    DWORD dwThreadId[NUM_SERVICES];
+    HANDLE hThread[NUM_SERVICES];
+    WSADATA wsaData;
+    DWORD RetVal;
+    INT i;
+    
+    if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
+    {
+        _tprintf(_T("WSAStartup() failed : %lu\n"), RetVal);
+        return -1;
+    }
+
+    /* Create MAX_THREADS worker threads. */
+    for( i=0; i<NUM_SERVICES; i++ )
+    {
+        _tprintf(_T("Starting %s server....\n"), Services[i].Name);
+
+        hThread[i] = CreateThread(
+            NULL,              // default security attributes
+            0,                 // use default stack size
+            StartServer,       // thread function
+            &Services[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)
+        {
+            _tprintf(_T("Failed to start %s server....\n"), Services[i].Name);
+            //ExitProcess(i);
+        }
+    }
+
+    /* Wait until all threads have terminated. */
+    WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE);
+
+    /* Close all thread handles upon completion. */
+    for(i=0; i<NUM_SERVICES; i++)
+    {
+        CloseHandle(hThread[i]);
+    }
+    return 0;
+}
+
+
+
+/* code to run tcpsvcs as a service through services.msc */
+#if 0
+int
+main(int argc, char *argv[])
+{
+    //DPRINT("tcpsvcs: main() started. See tcpsvcs_log.txt for info\n");
+
+    if (!StartServiceCtrlDispatcher(ServiceTable))
+        _tprintf(_T("failed to start the service control dispatcher\n"));
+
+    //DPRINT("tcpsvcs: main() done\n");
+
+    return 0;
+}
+
+
+static VOID WINAPI
+ServiceMain(DWORD argc, LPTSTR argv[])
+{
+    DWORD i;
+
+    hLogFile = fopen(LogFileName, _T("w+"));
+    if (hLogFile == NULL)
+        return;
+        
+    LogEvent(_T("Entering ServiceMain"), 0, FALSE);
+
+    hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+    hServStatus.dwCurrentState = SERVICE_START_PENDING;
+    hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
+        SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
+    hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
+    hServStatus.dwServiceSpecificExitCode = 0;
+    hServStatus.dwCheckPoint = 0;
+    hServStatus.dwWaitHint = 2*CS_TIMEOUT;
+    
+    hSStat = RegisterServiceCtrlHandler("tcpsvcs", ServerCtrlHandler);
+    if (hSStat == 0)
+        LogEvent(_T("Failed to register service\n"), 100, TRUE);
+
+       LogEvent(_T("Control handler registered successfully"), 0, FALSE);
+       SetServiceStatus (hSStat, &hServStatus);
+       LogEvent(_T("Service status set to SERVICE_START_PENDING"), 0, FALSE);
+
+    if (CreateServers() != 0)
+    {
+        hServStatus.dwCurrentState = SERVICE_STOPPED;
+        hServStatus.dwServiceSpecificExitCode = 1;
+        SetServiceStatus(hSStat, &hServStatus);
+        return;
+    }
+    
+       LogEvent(_T("Service threads shut down. Set SERVICE_STOPPED status"), 0, FALSE);
+       /*  We will only return here when the ServiceSpecific function
+               completes, indicating system shutdown. */
+       UpdateStatus (SERVICE_STOPPED, 0);
+       LogEvent(_T("Service status set to SERVICE_STOPPED"), 0, FALSE);
+       fclose(hLogFile);  /*  Clean up everything, in general */
+       return;
+
+}
+
+VOID WINAPI
+ServerCtrlHandler(DWORD Control)
+{
+    switch (Control)
+    {
+        case SERVICE_CONTROL_SHUTDOWN: /* fall through */
+        case SERVICE_CONTROL_STOP:
+            ShutDown = TRUE;
+            UpdateStatus(SERVICE_STOP_PENDING, -1);
+            break;
+        case SERVICE_CONTROL_PAUSE:
+            PauseFlag = TRUE;
+            break;
+        case SERVICE_CONTROL_CONTINUE:
+            PauseFlag = FALSE;
+            break;
+        case SERVICE_CONTROL_INTERROGATE:
+            break;
+        default:
+            if (Control > 127 && Control < 256) /* user defined */
+            break;
+    }
+    UpdateStatus(-1, -1); /* increment checkpoint */
+    return;
+}
+
+
+void UpdateStatus (int NewStatus, int Check)
+/*  Set a new service status and checkpoint (either specific value or increment) */
+{
+       if (Check < 0 ) hServStatus.dwCheckPoint++;
+       else                    hServStatus.dwCheckPoint = Check;
+       if (NewStatus >= 0) hServStatus.dwCurrentState = NewStatus;
+       if (!SetServiceStatus (hSStat, &hServStatus))
+               LogEvent (_T("Cannot set service status"), 101, TRUE);
+       return;
+}
+
+INT
+CreateServers()
+{
+    DWORD dwThreadId[NUM_SERVICES];
+    HANDLE hThread[NUM_SERVICES];
+    INT i;
+    
+    UpdateStatus(-1, -1); /* increment checkpoint */
+
+    /* Create MAX_THREADS worker threads. */
+    for( i=0; i<NUM_SERVICES; i++ )
+    {
+        _tprintf(_T("Starting %s server....\n"), Services[i].Name);
+
+        hThread[i] = CreateThread(
+            NULL,              // default security attributes
+            0,                 // use default stack size
+            StartServer,       // thread function
+            &Services[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)
+        {
+            _tprintf(_T("Failed to start %s server....\n"), Services[i].Name);
+            ExitProcess(i);
+        }
+    }
+
+    /* Wait until all threads have terminated. */
+    WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE);
+
+    /* Close all thread handles upon completion. */
+    for(i=0; i<NUM_SERVICES; i++)
+    {
+        CloseHandle(hThread[i]);
+    }
+    return 0;
+}
+
+
+/*     LogEvent is similar to the ReportError function used elsewhere
+       For a service, however, we ReportEvent rather than write to standard
+       error. Eventually, this function should go into the utility
+       library.  */
+VOID
+LogEvent (LPCTSTR UserMessage, DWORD ExitCode, BOOL PrintErrorMsg)
+{
+       DWORD eMsgLen, ErrNum = GetLastError ();
+       LPTSTR lpvSysMsg;
+       TCHAR MessageBuffer[512];
+
+       if (PrintErrorMsg) {
+               eMsgLen = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                       FORMAT_MESSAGE_FROM_SYSTEM, NULL,
+                       ErrNum, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                       (LPTSTR)&lpvSysMsg, 0, NULL);
+
+               _stprintf (MessageBuffer, _T("\n%s %s ErrNum = %d. ExitCode = %d."),
+                       UserMessage, lpvSysMsg, ErrNum, ExitCode);
+               HeapFree (GetProcessHeap (), 0, lpvSysMsg);
+       } else {
+               _stprintf (MessageBuffer, _T("\n%s ExitCode = %d."),
+                       UserMessage, ExitCode);
+       }
+
+       fputs (MessageBuffer, hLogFile);
+
+       if (ExitCode > 0)
+               ExitProcess (ExitCode);
+       else
+               return;
+}
+
+#endif
diff --git a/reactos/apps/utils/net/tcpsvcs/tcpsvcs.h b/reactos/apps/utils/net/tcpsvcs/tcpsvcs.h
new file mode 100644 (file)
index 0000000..ff37255
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ *  ReactOS Services
+ *  Copyright (C) 2005 ReactOS Team
+ *
+ * LICENCE:     GPL - See COPYING in the top level directory
+ * PROJECT:     ReactOS simple TCP/IP services
+ * FILE:        apps/utils/net/tcpsvcs/tcpsvcs.h
+ * PURPOSE:     Provide CharGen, Daytime, Discard, Echo, and Qotd services
+ * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
+ * REVISIONS:
+ *   GM 04/10/05 Created
+ *
+ */
+
+/* default port numbers */
+#define ECHO_PORT 7
+#define DISCARD_PORT 9
+#define DAYTIME_PORT 13
+#define QOTD_PORT 17
+#define CHARGEN_PORT 19
+
+#define NUM_SERVICES 5
+#define BUF_SIZE 255
+#define BUF 1024
+#define CS_TIMEOUT 1000
+
+/* RFC865 states no more than 512 chars per line */
+#define MAX_QUOTE_BUF 512
+
+/* printable ASCII's characters for chargen */
+#define START 32
+#define END 126
+
+/* number of chars to put on a line */
+#define LINESIZ 74 // 72 + /r and /n
+
+/* data structure to pass to threads */
+typedef struct _Services {
+    INT Port;
+    TCHAR *Name;
+    LPTHREAD_START_ROUTINE Service;
+} SERVICES, *PSERVICES;
+
+
+/* tcpsvcs functions */
+//static VOID WINAPI ServiceMain(DWORD argc, LPTSTR argv[]);
+VOID WINAPI ServerCtrlHandler(DWORD control);
+INT CreateServers(VOID);
+VOID LogEvent (LPCTSTR UserMessage, DWORD ExitCode, BOOL PrintErrorMsg);
+void UpdateStatus (int NewStatus, int Check);
+
+
+/* skelserver functions */
+DWORD WINAPI StartServer(LPVOID lpParam);
+SOCKET SetUpListener(const char* ServAddr, int Port);
+VOID AcceptConnections(SOCKET ListeningSocket,
+    LPTHREAD_START_ROUTINE Service, TCHAR *Name);
+BOOL EchoIncomingPackets(SOCKET sd);
+BOOL ShutdownConnection(SOCKET Sock, BOOL bRec);
+
+/* chargen functions */
+DWORD WINAPI ChargenHandler(VOID* Sock_);
+BOOL GenerateChars(SOCKET Sock);
+BOOL SendLine(SOCKET Sock, TCHAR* Line);
+
+/* daytime functions */
+DWORD WINAPI DaytimeHandler(VOID* Sock_);
+BOOL SendTime(SOCKET Sock, TCHAR *time);
+
+/* echo functions */
+DWORD WINAPI EchoHandler(VOID* Sock_);
+BOOL EchoIncomingPackets(SOCKET Sock);
+
+/* discard functions */
+DWORD WINAPI DiscardHandler(VOID* Sock_);
+BOOL RecieveIncomingPackets(SOCKET Sock);
+
+/* qotd functions */
+DWORD WINAPI QotdHandler(VOID* Sock_);
+BOOL SendQuote(SOCKET Sock, TCHAR* Quote);
diff --git a/reactos/apps/utils/net/tcpsvcs/tcpsvcs.rc b/reactos/apps/utils/net/tcpsvcs/tcpsvcs.rc
new file mode 100644 (file)
index 0000000..b6cc20d
--- /dev/null
@@ -0,0 +1,7 @@
+#include "resource.h"
+
+#define REACTOS_STR_FILE_DESCRIPTION   "ReactOS TCP/IP Services Application\0"
+#define REACTOS_STR_INTERNAL_NAME      "tcpsvcs\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "tcpsvcs.exe\0"
+#define REACTOS_STR_ORIGINAL_COPYRIGHT "Ged Murphy (gedmurphy@gmail.com)\0"
+#include <reactos/version.rc>
diff --git a/reactos/apps/utils/net/tcpsvcs/tcpsvcs.xml b/reactos/apps/utils/net/tcpsvcs/tcpsvcs.xml
new file mode 100644 (file)
index 0000000..d89eecd
--- /dev/null
@@ -0,0 +1,16 @@
+<module name="tcpsvcs" type="win32cui" installbase="system32" installname="tcpsvcs.exe">
+    <include base="arp">.</include>
+    <define name="__USE_W32API" />
+    <library>kernel32</library>
+    <library>iphlpapi</library>
+    <library>ws2_32</library>
+    <library>shlwapi</library>
+    <file>tcpsvcs.c</file>
+    <file>skelserver.c</file>
+    <file>echo.c</file>
+    <file>discard.c</file>
+    <file>daytime.c</file>
+    <file>qotd.c</file>
+    <file>chargen.c</file>
+    <file>tcpsvcs.rc</file>
+</module>