xref: /reactos/base/services/tcpsvcs/chargen.c (revision 40462c92)
1 /*
2  * PROJECT:     ReactOS simple TCP/IP services
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        base/services/tcpsvcs/chargen.c
5  * PURPOSE:     Sends continuous lines of chars to the client
6  * COPYRIGHT:   Copyright 2005 - 2008 Ged Murphy <gedmurphy@reactos.org>
7  *
8  */
9 
10 #include "tcpsvcs.h"
11 
12 /* printable ASCII's characters for chargen */
13 #define ASCII_START 32
14 #define ASCII_END 126
15 #define NUM_CHARS ASCII_END - ASCII_START + 1
16 
17 /* number of chars to put on a line */
18 #define LINESIZE 74 // 72 + CR + NL
19 
20 static BOOL
21 SendLine(SOCKET sock, LPSTR lpLine)
22 {
23     BOOL bRet = FALSE;
24 
25     /*FIXME: need to establish if peer closes connection, not just report a socket error */
26     INT retVal = send(sock, lpLine, LINESIZE, 0);
27     if (retVal > 0)
28     {
29         if (retVal == LINESIZE)
30         {
31             bRet = TRUE;
32         }
33         else
34         {
35             LogEvent(L"Chargen: Not sent enough bytes", 0, 0, LOG_FILE);
36         }
37     }
38     else if (retVal == SOCKET_ERROR)
39     {
40         LogEvent(L"Chargen: Socket error\n", WSAGetLastError(), 0, LOG_ERROR);
41     }
42     else
43     {
44         LogEvent(L"Chargen: unknown error\n", WSAGetLastError(), 0, LOG_ERROR);
45     }
46 
47     return bRet;
48 }
49 
50 static BOOL
51 GenerateChars(SOCKET sock)
52 {
53     CHAR chars[NUM_CHARS];
54     CHAR line[LINESIZE];
55     INT charIndex;
56     INT loopIndex;
57     INT i;
58 
59     /* fill the array with printable characters */
60     for (charIndex = 0, i = ASCII_START; i <= ASCII_END; charIndex++, i++)
61         chars[charIndex] = (CHAR)i;
62 
63     loopIndex = 0;
64     while (!bShutdown)
65     {
66         /* reset the loop when we hit the last char */
67         if (loopIndex == NUM_CHARS)
68             loopIndex = 0;
69 
70         /* fill a line array to send */
71         charIndex = loopIndex;
72         for (i=0; i < LINESIZE - 2; i++)
73         {
74             line[i] = chars[charIndex];
75 
76             /* if we hit the end char, reset it */
77             if (chars[charIndex] == chars[NUM_CHARS - 1])
78                 charIndex = 0;
79             else
80                 charIndex++;
81         }
82         line[LINESIZE - 2] = '\r';
83         line[LINESIZE - 1] = '\n';
84 
85         if (!SendLine(sock, line))
86             break;
87 
88         /* start printing from next char in the array */
89         loopIndex++;
90     }
91 
92     return TRUE;
93 }
94 
95 DWORD WINAPI
96 ChargenHandler(VOID* sock_)
97 {
98     INT retVal = 0;
99     SOCKET sock = (SOCKET)sock_;
100 
101     if (!GenerateChars(sock))
102     {
103         LogEvent(L"Chargen: Char generation failed", 0, 0, LOG_FILE);
104         retVal = 1;
105     }
106 
107     LogEvent(L"Chargen: Shutting connection down...", 0, 0, LOG_FILE);
108     if (ShutdownConnection(sock, FALSE))
109     {
110         LogEvent(L"Chargen: Connection is down", 0, 0, LOG_FILE);
111     }
112     else
113     {
114         LogEvent(L"Chargen: Connection shutdown failed", 0, 0, LOG_FILE);
115         retVal = 1;
116     }
117 
118     LogEvent(L"Chargen: Terminating thread", 0, 0, LOG_FILE);
119     ExitThread(retVal);
120 }
121