- Merge from trunk up to r45543
[reactos.git] / base / services / tcpsvcs / chargen.c
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 continous 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
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 }