Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / base / services / tcpsvcs / chargen.c
diff --git a/base/services/tcpsvcs/chargen.c b/base/services/tcpsvcs/chargen.c
new file mode 100644 (file)
index 0000000..2b5ab22
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * PROJECT:     ReactOS simple TCP/IP services
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        base/services/tcpsvcs/chargen.c
+ * PURPOSE:     Sends continuous lines of chars to the client
+ * COPYRIGHT:   Copyright 2005 - 2008 Ged Murphy <gedmurphy@reactos.org>
+ *
+ */
+
+#include "tcpsvcs.h"
+
+/* printable ASCII's characters for chargen */
+#define ASCII_START 32
+#define ASCII_END 126
+#define NUM_CHARS ASCII_END - ASCII_START + 1
+
+/* number of chars to put on a line */
+#define LINESIZE 74 // 72 + CR + NL
+
+static BOOL
+SendLine(SOCKET sock, LPSTR lpLine)
+{
+    BOOL bRet = FALSE;
+
+    /*FIXME: need to establish if peer closes connection, not just report a socket error */
+    INT retVal = send(sock, lpLine, LINESIZE, 0);
+    if (retVal > 0)
+    {
+        if (retVal == LINESIZE)
+        {
+            bRet = TRUE;
+        }
+        else
+        {
+            LogEvent(L"Chargen: Not sent enough bytes", 0, 0, LOG_FILE);
+        }
+    }
+    else if (retVal == SOCKET_ERROR)
+    {
+        LogEvent(L"Chargen: Socket error\n", WSAGetLastError(), 0, LOG_ERROR);
+    }
+    else
+    {
+        LogEvent(L"Chargen: unknown error\n", WSAGetLastError(), 0, LOG_ERROR);
+    }
+
+    return bRet;
+}
+
+static BOOL
+GenerateChars(SOCKET sock)
+{
+    CHAR chars[NUM_CHARS];
+    CHAR line[LINESIZE];
+    INT charIndex;
+    INT loopIndex;
+    INT i;
+
+    /* fill the array with printable characters */
+    for (charIndex = 0, i = ASCII_START; i <= ASCII_END; charIndex++, i++)
+        chars[charIndex] = (CHAR)i;
+
+    loopIndex = 0;
+    while (!bShutdown)
+    {
+        /* reset the loop when we hit the last char */
+        if (loopIndex == NUM_CHARS)
+            loopIndex = 0;
+
+        /* fill a line array to send */
+        charIndex = loopIndex;
+        for (i=0; i < LINESIZE - 2; i++)
+        {
+            line[i] = chars[charIndex];
+
+            /* if we hit the end char, reset it */
+            if (chars[charIndex] == chars[NUM_CHARS - 1])
+                charIndex = 0;
+            else
+                charIndex++;
+        }
+        line[LINESIZE - 2] = '\r';
+        line[LINESIZE - 1] = '\n';
+
+        if (!SendLine(sock, line))
+            break;
+
+        /* start printing from next char in the array */
+        loopIndex++;
+    }
+
+    return TRUE;
+}
+
+DWORD WINAPI
+ChargenHandler(VOID* sock_)
+{
+    INT retVal = 0;
+    SOCKET sock = (SOCKET)sock_;
+
+    if (!GenerateChars(sock))
+    {
+        LogEvent(L"Chargen: Char generation failed", 0, 0, LOG_FILE);
+        retVal = 1;
+    }
+
+    LogEvent(L"Chargen: Shutting connection down...", 0, 0, LOG_FILE);
+    if (ShutdownConnection(sock, FALSE))
+    {
+        LogEvent(L"Chargen: Connection is down", 0, 0, LOG_FILE);
+    }
+    else
+    {
+        LogEvent(L"Chargen: Connection shutdown failed", 0, 0, LOG_FILE);
+        retVal = 1;
+    }
+
+    LogEvent(L"Chargen: Terminating thread", 0, 0, LOG_FILE);
+    ExitThread(retVal);
+}