ReactOS  0.4.12-dev-51-ge94618b
skelserver.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS simple TCP/IP services
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: base/services/tcpsvcs/skelserver.c
5  * PURPOSE: Sets up a server and listens for connections
6  * COPYRIGHT: Copyright 2005 - 2008 Ged Murphy <gedmurphy@gmail.com>
7  *
8  */
9 
10 #include "tcpsvcs.h"
11 
12 #define BUF 1024
13 
14 static SOCKET
16 {
17  SOCKET sock;
19  BOOL bSetup = FALSE;
20 
21  sock = socket(AF_INET, SOCK_STREAM, 0);
22  if (sock != INVALID_SOCKET)
23  {
24  ZeroMemory(&server, sizeof(SOCKADDR_IN));
25  server.sin_family = AF_INET;
26  server.sin_addr.s_addr = htonl(INADDR_ANY);
27  server.sin_port = Port;
28 
29  if (bind(sock, (SOCKADDR*)&server, sizeof(SOCKADDR_IN)) != SOCKET_ERROR)
30  {
31  if (listen(sock, SOMAXCONN) != SOCKET_ERROR)
32  {
33  bSetup = TRUE;
34  }
35  else
36  {
37  LogEvent(L"listen() failed", WSAGetLastError(), 0, LOG_ERROR);
38  }
39  }
40  else
41  {
42  LogEvent(L"bind() failed", WSAGetLastError(), 0, LOG_ERROR);
43  }
44  }
45  else
46  {
47  LogEvent(L"socket() failed", WSAGetLastError(), 0, LOG_ERROR);
48  }
49 
50  return bSetup ? sock : INVALID_SOCKET;
51 }
52 
53 
54 static VOID
55 AcceptConnections(SOCKET listeningSocket,
56  LPTHREAD_START_ROUTINE lpService,
57  LPWSTR lpName)
58 {
60  SOCKET sock;
62  TIMEVAL timeVal;
63  FD_SET readFD;
64  WCHAR logBuf[256];
65  INT timeOut = 2000;
66 
67  timeVal.tv_sec = timeOut / 1000;
68  timeVal.tv_usec = timeOut % 1000;
69 
70  while (!bShutdown)
71  {
72  INT selRet = 0;
73 
74  FD_ZERO(&readFD);
75  FD_SET(listeningSocket, &readFD);
76 
77  selRet = select(0, &readFD, NULL, NULL, &timeVal);
78  if (selRet > 0)
79  {
80  if (!bShutdown || FD_ISSET(listeningSocket, &readFD))
81  {
82  INT addrSize = sizeof(SOCKADDR_IN);
83 
84  sock = accept(listeningSocket, (SOCKADDR*)&client, &addrSize);
85  if (sock != INVALID_SOCKET)
86  {
87  swprintf(logBuf,
88  L"Accepted connection to %s server from %S:%d",
89  lpName,
90  inet_ntoa(client.sin_addr),
91  ntohs(client.sin_port));
92  LogEvent(logBuf, 0, 0, LOG_FILE);
93 
94  swprintf(logBuf, L"Creating worker thread for %s", lpName);
95  LogEvent(logBuf, 0, 0, LOG_FILE);
96 
97  if (!bShutdown)
98  {
99  hThread = CreateThread(0, 0, lpService, (void*)sock, 0, NULL);
100  if (hThread != NULL)
101  {
102  CloseHandle(hThread);
103  }
104  else
105  {
106  swprintf(logBuf, L"Failed to start worker thread for the %s server",
107  lpName);
108  LogEvent(logBuf, 0, 0, LOG_FILE);
109  }
110  }
111  }
112  else
113  {
114  LogEvent(L"accept failed", WSAGetLastError(), 0, LOG_ERROR);
115  }
116  }
117  }
118  else if (selRet == SOCKET_ERROR)
119  {
120  LogEvent(L"select failed", WSAGetLastError(), 0, LOG_ERROR);
121  }
122  }
123 }
124 
125 BOOL
127  BOOL bRec)
128 {
129  WCHAR logBuf[256];
130 
131  /* Disallow any further data sends. This will tell the other side
132  that we want to go away now. If we skip this step, we don't
133  shut the connection down nicely. */
134  if (shutdown(sock, SD_SEND) == SOCKET_ERROR)
135  {
136  LogEvent(L"Error in shutdown()", WSAGetLastError(), 0, LOG_ERROR);
137  return FALSE;
138  }
139 
140  /* Receive any extra data still sitting on the socket
141  before we close it */
142  if (bRec)
143  {
144  CHAR readBuffer[BUF];
145  INT ret;
146 
147  do
148  {
149  ret = recv(sock, readBuffer, BUF, 0);
150  if (ret >= 0)
151  {
152  swprintf(logBuf, L"FYI, received %d unexpected bytes during shutdown", ret);
153  LogEvent(logBuf, 0, 0, LOG_FILE);
154  }
155  } while (ret > 0);
156  }
157 
158  closesocket(sock);
159 
160  return TRUE;
161 }
162 
163 
166 {
167  SOCKET listeningSocket;
168  PSERVICES pServices;
169  TCHAR logBuf[256];
170 
171  pServices = (PSERVICES)lpParam;
172 
173  swprintf(logBuf, L"Starting %s server", pServices->lpName);
174  LogEvent(logBuf, 0, 0, LOG_FILE);
175 
176  if (!bShutdown)
177  {
178  listeningSocket = SetUpListener(htons(pServices->Port));
179  if (!bShutdown && listeningSocket != INVALID_SOCKET)
180  {
181  swprintf(logBuf,
182  L"%s is waiting for connections on port %d",
183  pServices->lpName,
184  pServices->Port);
185  LogEvent(logBuf, 0, 0, LOG_FILE);
186 
187  AcceptConnections(listeningSocket, pServices->lpService, pServices->lpName);
188  }
189  else
190  {
191  LogEvent(L"Socket error when setting up listener", 0, 0, LOG_FILE);
192  }
193  }
194 
195  swprintf(logBuf, L"Exiting %s thread", pServices->lpName);
196  LogEvent(logBuf, 0, 0, LOG_FILE);
197  ExitThread(0);
198 }
Definition: winsock.h:66
volatile BOOL bShutdown
Definition: tcpsvcs.c:16
#define SOCKET_ERROR
Definition: winsock.h:333
CPPORT Port[4]
Definition: headless.c:34
DWORD(WINAPI * LPTHREAD_START_ROUTINE)(LPVOID)
Definition: winbase.h:707
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
static rfbScreenInfoPtr server
Definition: vnc.c:74
static SOCKET sock
Definition: syslog.c:45
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
u_short sin_port
Definition: winsock.h:511
#define htonl(x)
Definition: module.h:212
struct _Services * PSERVICES
__wchar_t WCHAR
Definition: xmlstorage.h:180
INT WSAAPI bind(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: socklife.c:36
char CHAR
Definition: xmlstorage.h:175
unsigned long tv_sec
Definition: linux.h:1738
_In_ LPCSTR lpName
Definition: winbase.h:2729
#define INADDR_ANY
Definition: StrAddr.c:4
#define ZeroMemory
Definition: winbase.h:1635
#define FD_ZERO(set)
Definition: winsock.h:96
#define BUF
Definition: skelserver.c:12
#define FD_SET(fd, set)
Definition: winsock.h:89
int32_t INT
Definition: typedefs.h:56
#define ntohs(x)
Definition: module.h:208
#define SOMAXCONN
Definition: winsock.h:399
#define closesocket
Definition: main.c:39
#define FD_ISSET(fd, set)
Definition: winsock.h:100
Definition: jssnprintf.c:29
INT WSAAPI select(IN INT s, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout)
Definition: select.c:41
static VOID AcceptConnections(SOCKET listeningSocket, LPTHREAD_START_ROUTINE lpService, LPWSTR lpName)
Definition: skelserver.c:55
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:112
smooth NULL
Definition: ftsmooth.c:416
unsigned long tv_usec
Definition: linux.h:1739
#define LOG_ERROR
Definition: tcpsvcs.h:16
VOID WINAPI ExitThread(IN DWORD uExitCode)
Definition: thread.c:327
#define inet_ntoa(addr)
Definition: inet.h:100
USHORT Port
Definition: tcpsvcs.h:33
LPWSTR lpName
Definition: tcpsvcs.h:34
char TCHAR
Definition: xmlstorage.h:189
INT WSAAPI WSAGetLastError(VOID)
Definition: dllmain.c:112
unsigned int BOOL
Definition: ntddk_ex.h:94
#define INVALID_SOCKET
Definition: winsock.h:332
INT WSAAPI shutdown(IN SOCKET s, IN INT how)
Definition: sockctrl.c:506
#define swprintf(buf, format,...)
Definition: sprintf.c:56
static FILE * client
Definition: client.c:41
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL ShutdownConnection(SOCKET sock, BOOL bRec)
Definition: skelserver.c:126
int ret
static const WCHAR L[]
Definition: oid.c:1087
LPTHREAD_START_ROUTINE lpService
Definition: tcpsvcs.h:35
SOCKET WSAAPI accept(IN SOCKET s, OUT LPSOCKADDR addr, OUT INT FAR *addrlen)
Definition: socklife.c:23
#define WINAPI
Definition: msvc.h:20
struct in_addr sin_addr
Definition: winsock.h:512
VOID LogEvent(LPCWSTR lpMsg, DWORD errNum, DWORD exitCode, UINT flags)
Definition: log.c:196
#define SD_SEND
Definition: winsock.h:55
unsigned short USHORT
Definition: pedump.c:61
struct sockaddr_in SOCKADDR_IN
Definition: winsock.h:487
HANDLE hThread
Definition: wizard.c:27
INT WSAAPI listen(IN SOCKET s, IN INT backlog)
Definition: sockctrl.c:123
Definition: tcpcore.h:1455
#define AF_INET
Definition: tcpip.h:117
UINT_PTR SOCKET
Definition: winsock.h:47
#define SOCK_STREAM
Definition: tcpip.h:118
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define htons(x)
Definition: module.h:213
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
short sin_family
Definition: winsock.h:510
DWORD WINAPI StartServer(LPVOID lpParam)
Definition: skelserver.c:165
static SOCKET SetUpListener(USHORT Port)
Definition: skelserver.c:15