Silence most of the msvc warnings
[reactos.git] / reactos / services / tcpsvcs / skelserver.c
1 /*
2 * ReactOS Services
3 * Copyright (C) 2005 ReactOS Team
4 *
5 * LICENCE: GPL - See COPYING in the top level directory
6 * PROJECT: ReactOS simple TCP/IP services
7 * FILE: apps/utils/net/tcpsvcs/skelserver.c
8 * PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
9 * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
10 * REVISIONS:
11 * GM 04/10/05 Created
12 *
13 */
14
15 #include "tcpsvcs.h"
16
17 extern BOOL bShutDown;
18 extern BOOL bPause;
19
20 DWORD WINAPI StartServer(LPVOID lpParam)
21 {
22 SOCKET ListeningSocket;
23 PSERVICES pServices;
24 TCHAR buf[256];
25
26 pServices = (PSERVICES)lpParam;
27
28 //DebugBreak();
29 ListeningSocket = SetUpListener(htons(pServices->Port));
30 if (ListeningSocket == INVALID_SOCKET)
31 {
32 LogEvent("Socket error when setting up listener\n", 0, TRUE);
33 return 3;
34 }
35
36 _stprintf(buf, _T("%s is waiting for connections on port %d...\n"),
37 pServices->Name, pServices->Port);
38 LogEvent(buf, 0, FALSE);
39
40 if (! bShutDown)
41 AcceptConnections(ListeningSocket, pServices->Service, pServices->Name);
42
43 ExitThread(0);
44 }
45
46
47 SOCKET SetUpListener(USHORT Port)
48 {
49 SOCKET Sock;
50 SOCKADDR_IN Server;
51
52 Sock = socket(AF_INET, SOCK_STREAM, 0);
53 if (Sock != INVALID_SOCKET)
54 {
55 Server.sin_family = AF_INET;
56 Server.sin_addr.s_addr = htonl(INADDR_ANY);
57 Server.sin_port = Port;
58 if (bind(Sock, (SOCKADDR*)&Server, sizeof(SOCKADDR_IN)) != SOCKET_ERROR)
59 {
60 listen(Sock, SOMAXCONN);
61 return Sock;
62 }
63 else
64 LogEvent(_T("bind() failed\n"), 0, TRUE);
65
66 }
67 return INVALID_SOCKET;
68 }
69
70 /* note: consider allowing a maximum number of connections
71 * A number of threads can be allocated and worker threads will
72 * only be spawned if a free space is available
73
74 typedef struct _WORKER_THREAD {
75 DWORD num;
76 BOOL available;
77 HANDLE hThread;
78 } WORKER_THREAD;
79
80 */
81
82 VOID AcceptConnections(SOCKET ListeningSocket,
83 LPTHREAD_START_ROUTINE Service, TCHAR *Name)
84 {
85 SOCKADDR_IN Client;
86 SOCKET Sock;
87 HANDLE hThread;
88 TIMEVAL TimeVal;
89 FD_SET ReadFDS;
90 INT nAddrSize = sizeof(Client);
91 DWORD ThreadID;
92 TCHAR buf[256];
93 INT TimeOut = 2000; // 2 seconds
94
95 //DebugBreak();
96
97 /* set timeout values */
98 TimeVal.tv_sec = TimeOut / 1000;
99 TimeVal.tv_usec = TimeOut % 1000;
100
101 while (! bShutDown) // (i<MAX_CLIENTS && !bShutDown)
102 {
103 INT SelRet = 0;
104
105 FD_ZERO(&ReadFDS);
106 FD_SET(ListeningSocket, &ReadFDS);
107
108 SelRet = select(0, &ReadFDS, NULL, NULL, &TimeVal);
109 if (SelRet == SOCKET_ERROR)
110 {
111 LogEvent(_T("select failed\n"), 0, TRUE);
112 return;
113 }
114 else if (SelRet > 0)
115 {
116 /* don't call FD_ISSET if bShutDown flag is set */
117 if ((! bShutDown) || (FD_ISSET(ListeningSocket, &ReadFDS)))
118 {
119 Sock = accept(ListeningSocket, (SOCKADDR*)&Client, &nAddrSize);
120 if (Sock != INVALID_SOCKET)
121 {
122 _stprintf(buf, _T("Accepted connection to %s server from %s:%d\n"),
123 Name, inet_ntoa(Client.sin_addr), ntohs(Client.sin_port));
124 LogEvent(buf, 0, FALSE);
125 _stprintf(buf, _T("Creating new thread for %s\n"), Name);
126 LogEvent(buf, 0, FALSE);
127
128 hThread = CreateThread(0, 0, Service, (void*)Sock, 0, &ThreadID);
129
130 /* Check the return value for success. */
131 if (hThread == NULL)
132 {
133 _stprintf(buf, _T("Failed to start worker thread for "
134 "the %s server....\n"), Name);
135 LogEvent(buf, 0, TRUE);
136 }
137
138 WaitForSingleObject(hThread, INFINITE);
139
140 CloseHandle(hThread);
141 }
142 else
143 {
144 LogEvent(_T("accept failed\n"), 0, TRUE);
145 return;
146 }
147 }
148 }
149 }
150 }
151
152 BOOL ShutdownConnection(SOCKET Sock, BOOL bRec)
153 {
154 TCHAR buf[256];
155
156 /* Disallow any further data sends. This will tell the other side
157 that we want to go away now. If we skip this step, we don't
158 shut the connection down nicely. */
159 if (shutdown(Sock, SD_SEND) == SOCKET_ERROR)
160 {
161 LogEvent(_T("Error in shutdown()\n"), 0, TRUE);
162 return FALSE;
163 }
164
165 /* Receive any extra data still sitting on the socket. After all
166 data is received, this call will block until the remote host
167 acknowledges the TCP control packet sent by the shutdown above.
168 Then we'll get a 0 back from recv, signalling that the remote
169 host has closed its side of the connection. */
170 if (bRec)
171 {
172 char ReadBuffer[BUF];
173 int NewBytes = recv(Sock, ReadBuffer, BUF, 0);
174 if (NewBytes == SOCKET_ERROR)
175 return FALSE;
176 else if (NewBytes != 0)
177 {
178 _stprintf(buf, _T("FYI, received %d unexpected bytes during shutdown\n"), NewBytes);
179 LogEvent(buf, 0, FALSE);
180 }
181 }
182
183 /* Close the socket. */
184 if (closesocket(Sock) == SOCKET_ERROR)
185 return FALSE;
186
187 return TRUE;
188 }