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>
15 SetUpListener(USHORT Port
)
21 sock
= socket(AF_INET
, SOCK_STREAM
, 0);
22 if (sock
!= INVALID_SOCKET
)
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
;
29 if (bind(sock
, (SOCKADDR
*)&server
, sizeof(SOCKADDR_IN
)) != SOCKET_ERROR
)
31 if (listen(sock
, SOMAXCONN
) != SOCKET_ERROR
)
37 LogEvent(L
"listen() failed", WSAGetLastError(), 0, LOG_ERROR
);
42 LogEvent(L
"bind() failed", WSAGetLastError(), 0, LOG_ERROR
);
47 LogEvent(L
"socket() failed", WSAGetLastError(), 0, LOG_ERROR
);
50 return bSetup
? sock
: INVALID_SOCKET
;
55 AcceptConnections(SOCKET listeningSocket
,
56 LPTHREAD_START_ROUTINE lpService
,
67 timeVal
.tv_sec
= timeOut
/ 1000;
68 timeVal
.tv_usec
= timeOut
% 1000;
75 FD_SET(listeningSocket
, &readFD
);
77 selRet
= select(0, &readFD
, NULL
, NULL
, &timeVal
);
80 if (!bShutdown
|| FD_ISSET(listeningSocket
, &readFD
))
82 INT addrSize
= sizeof(SOCKADDR_IN
);
84 sock
= accept(listeningSocket
, (SOCKADDR
*)&client
, &addrSize
);
85 if (sock
!= INVALID_SOCKET
)
88 L
"Accepted connection to %s server from %S:%d",
90 inet_ntoa(client
.sin_addr
),
91 ntohs(client
.sin_port
));
92 LogEvent(logBuf
, 0, 0, LOG_FILE
);
94 swprintf(logBuf
, L
"Creating worker thread for %s", lpName
);
95 LogEvent(logBuf
, 0, 0, LOG_FILE
);
99 hThread
= CreateThread(0, 0, lpService
, (void*)sock
, 0, NULL
);
102 CloseHandle(hThread
);
106 swprintf(logBuf
, L
"Failed to start worker thread for the %s server",
108 LogEvent(logBuf
, 0, 0, LOG_FILE
);
114 LogEvent(L
"accept failed", WSAGetLastError(), 0, LOG_ERROR
);
118 else if (selRet
== SOCKET_ERROR
)
120 LogEvent(L
"select failed", WSAGetLastError(), 0, LOG_ERROR
);
126 ShutdownConnection(SOCKET sock
,
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
)
136 LogEvent(L
"Error in shutdown()", WSAGetLastError(), 0, LOG_ERROR
);
140 /* Receive any extra data still sitting on the socket
141 before we close it */
144 CHAR readBuffer
[BUF
];
149 ret
= recv(sock
, readBuffer
, BUF
, 0);
152 swprintf(logBuf
, L
"FYI, received %d unexpected bytes during shutdown", ret
);
153 LogEvent(logBuf
, 0, 0, LOG_FILE
);
165 StartServer(LPVOID lpParam
)
167 SOCKET listeningSocket
;
171 pServices
= (PSERVICES
)lpParam
;
173 swprintf(logBuf
, L
"Starting %s server", pServices
->lpName
);
174 LogEvent(logBuf
, 0, 0, LOG_FILE
);
178 listeningSocket
= SetUpListener(htons(pServices
->Port
));
179 if (!bShutdown
&& listeningSocket
!= INVALID_SOCKET
)
182 L
"%s is waiting for connections on port %d",
185 LogEvent(logBuf
, 0, 0, LOG_FILE
);
187 AcceptConnections(listeningSocket
, pServices
->lpService
, pServices
->lpName
);
191 LogEvent(L
"Socket error when setting up listener", 0, 0, LOG_FILE
);
195 swprintf(logBuf
, L
"Exiting %s thread", pServices
->lpName
);
196 LogEvent(logBuf
, 0, 0, LOG_FILE
);