1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3*c2c66affSColin Finck * PROJECT: ReactOS HTTP Daemon
4*c2c66affSColin Finck * FILE: socket.cpp
5*c2c66affSColin Finck * PURPOSE: Socket classes
6*c2c66affSColin Finck * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7*c2c66affSColin Finck * REVISIONS:
8*c2c66affSColin Finck * CSH 01/09/2000 Created
9*c2c66affSColin Finck */
10*c2c66affSColin Finck #include <socket.h>
11*c2c66affSColin Finck #include <string.h>
12*c2c66affSColin Finck #include <error.h>
13*c2c66affSColin Finck #include <iterator.h>
14*c2c66affSColin Finck
15*c2c66affSColin Finck // ***************************** CSocket *****************************
16*c2c66affSColin Finck
17*c2c66affSColin Finck // Default constructor
CSocket()18*c2c66affSColin Finck CSocket::CSocket()
19*c2c66affSColin Finck {
20*c2c66affSColin Finck Active = FALSE;
21*c2c66affSColin Finck Event = WSA_INVALID_EVENT;
22*c2c66affSColin Finck Events = 0;
23*c2c66affSColin Finck Socket = INVALID_SOCKET;
24*c2c66affSColin Finck
25*c2c66affSColin Finck // INET address family
26*c2c66affSColin Finck SockAddrIn.sin_family = AF_INET;
27*c2c66affSColin Finck
28*c2c66affSColin Finck // Any address will do
29*c2c66affSColin Finck SockAddrIn.sin_addr.s_addr = INADDR_ANY;
30*c2c66affSColin Finck
31*c2c66affSColin Finck // Convert to network ordering
32*c2c66affSColin Finck SockAddrIn.sin_port = htons(0);
33*c2c66affSColin Finck }
34*c2c66affSColin Finck
35*c2c66affSColin Finck // Default destructor
~CSocket()36*c2c66affSColin Finck CSocket::~CSocket()
37*c2c66affSColin Finck {
38*c2c66affSColin Finck }
39*c2c66affSColin Finck
40*c2c66affSColin Finck // Return winsock socket handle
GetSocket()41*c2c66affSColin Finck SOCKET CSocket::GetSocket()
42*c2c66affSColin Finck {
43*c2c66affSColin Finck return Socket;
44*c2c66affSColin Finck }
45*c2c66affSColin Finck
46*c2c66affSColin Finck // Set winsock socket handle
SetSocket(SOCKET socket)47*c2c66affSColin Finck VOID CSocket::SetSocket(SOCKET socket)
48*c2c66affSColin Finck {
49*c2c66affSColin Finck Socket = socket;
50*c2c66affSColin Finck }
51*c2c66affSColin Finck
52*c2c66affSColin Finck
53*c2c66affSColin Finck // Return socket address
GetSockAddrIn()54*c2c66affSColin Finck SOCKADDR_IN CSocket::GetSockAddrIn()
55*c2c66affSColin Finck {
56*c2c66affSColin Finck return SockAddrIn;
57*c2c66affSColin Finck }
58*c2c66affSColin Finck
59*c2c66affSColin Finck // Set socket address
SetSockAddrIn(SOCKADDR_IN sockaddrin)60*c2c66affSColin Finck VOID CSocket::SetSockAddrIn(SOCKADDR_IN sockaddrin)
61*c2c66affSColin Finck {
62*c2c66affSColin Finck SockAddrIn = sockaddrin;
63*c2c66affSColin Finck }
64*c2c66affSColin Finck
65*c2c66affSColin Finck // Associate winsock events with socket
SetEvents(LONG lEvents)66*c2c66affSColin Finck VOID CSocket::SetEvents(LONG lEvents)
67*c2c66affSColin Finck {
68*c2c66affSColin Finck if (Event == WSA_INVALID_EVENT) {
69*c2c66affSColin Finck // Create socket event
70*c2c66affSColin Finck Event = WSACreateEvent();
71*c2c66affSColin Finck if (Event == WSA_INVALID_EVENT)
72*c2c66affSColin Finck throw ESocketOpen(TS("Unable to create event."));
73*c2c66affSColin Finck }
74*c2c66affSColin Finck
75*c2c66affSColin Finck if (lEvents != Events) {
76*c2c66affSColin Finck // Associate network events with socket
77*c2c66affSColin Finck if (WSAEventSelect(Socket, Event, lEvents) == SOCKET_ERROR)
78*c2c66affSColin Finck throw ESocketOpen(TS("Unable to select socket events."));
79*c2c66affSColin Finck Events = lEvents;
80*c2c66affSColin Finck }
81*c2c66affSColin Finck }
82*c2c66affSColin Finck
83*c2c66affSColin Finck // Return associated winsock events
GetEvents()84*c2c66affSColin Finck LONG CSocket::GetEvents()
85*c2c66affSColin Finck {
86*c2c66affSColin Finck return Events;
87*c2c66affSColin Finck }
88*c2c66affSColin Finck
89*c2c66affSColin Finck // Open socket
Open()90*c2c66affSColin Finck VOID CSocket::Open()
91*c2c66affSColin Finck {
92*c2c66affSColin Finck }
93*c2c66affSColin Finck
94*c2c66affSColin Finck // Close socket
Close()95*c2c66affSColin Finck VOID CSocket::Close()
96*c2c66affSColin Finck {
97*c2c66affSColin Finck }
98*c2c66affSColin Finck
99*c2c66affSColin Finck
100*c2c66affSColin Finck // *********************** CServerClientSocket ***********************
101*c2c66affSColin Finck
102*c2c66affSColin Finck // Constructor with serversocket as parameter
CServerClientSocket(LPCServerSocket lpServerSocket)103*c2c66affSColin Finck CServerClientSocket::CServerClientSocket(LPCServerSocket lpServerSocket)
104*c2c66affSColin Finck {
105*c2c66affSColin Finck ServerSocket = lpServerSocket;
106*c2c66affSColin Finck }
107*c2c66affSColin Finck
108*c2c66affSColin Finck // Transmit data to socket
Transmit(LPCSTR lpsBuffer,UINT nLength)109*c2c66affSColin Finck INT CServerClientSocket::Transmit( LPCSTR lpsBuffer, UINT nLength)
110*c2c66affSColin Finck {
111*c2c66affSColin Finck return send(Socket, lpsBuffer, nLength, 0);
112*c2c66affSColin Finck }
113*c2c66affSColin Finck
114*c2c66affSColin Finck // Send a string to socket
SendText(LPCSTR lpsText)115*c2c66affSColin Finck INT CServerClientSocket::SendText( LPCSTR lpsText)
116*c2c66affSColin Finck {
117*c2c66affSColin Finck static CHAR crlf[3] = {0x0D, 0x0A, 0x00};
118*c2c66affSColin Finck INT nCount;
119*c2c66affSColin Finck
120*c2c66affSColin Finck nCount = Transmit(lpsText, strlen(lpsText));
121*c2c66affSColin Finck nCount += Transmit(crlf, strlen(crlf));
122*c2c66affSColin Finck return nCount;
123*c2c66affSColin Finck }
124*c2c66affSColin Finck
125*c2c66affSColin Finck // Receive data from socket
Receive(LPSTR lpsBuffer,UINT nLength)126*c2c66affSColin Finck INT CServerClientSocket::Receive(LPSTR lpsBuffer, UINT nLength)
127*c2c66affSColin Finck {
128*c2c66affSColin Finck return recv(Socket, lpsBuffer, nLength, 0);
129*c2c66affSColin Finck }
130*c2c66affSColin Finck
131*c2c66affSColin Finck // Process winsock messages if any
MessageLoop()132*c2c66affSColin Finck VOID CServerClientSocket::MessageLoop()
133*c2c66affSColin Finck {
134*c2c66affSColin Finck UINT nStatus;
135*c2c66affSColin Finck WSANETWORKEVENTS NetworkEvents;
136*c2c66affSColin Finck
137*c2c66affSColin Finck nStatus = WSAWaitForMultipleEvents(1, &Event, FALSE, 0, FALSE);
138*c2c66affSColin Finck if ((nStatus == 0) && (WSAEnumNetworkEvents(Socket, Event, &NetworkEvents) != SOCKET_ERROR)) {
139*c2c66affSColin Finck if ((NetworkEvents.lNetworkEvents & FD_READ) != 0) {
140*c2c66affSColin Finck OnRead();
141*c2c66affSColin Finck }
142*c2c66affSColin Finck if ((NetworkEvents.lNetworkEvents & FD_CLOSE) != 0) {
143*c2c66affSColin Finck OnClose();
144*c2c66affSColin Finck }
145*c2c66affSColin Finck }
146*c2c66affSColin Finck }
147*c2c66affSColin Finck
148*c2c66affSColin Finck // Return server socket that own this socket
GetServerSocket()149*c2c66affSColin Finck LPCServerSocket CServerClientSocket::GetServerSocket()
150*c2c66affSColin Finck {
151*c2c66affSColin Finck return ServerSocket;
152*c2c66affSColin Finck }
153*c2c66affSColin Finck
154*c2c66affSColin Finck
155*c2c66affSColin Finck // *********************** CServerClientThread ***********************
156*c2c66affSColin Finck
CServerClientThread(LPCServerClientSocket lpSocket)157*c2c66affSColin Finck CServerClientThread::CServerClientThread(LPCServerClientSocket lpSocket)
158*c2c66affSColin Finck {
159*c2c66affSColin Finck ClientSocket = lpSocket;
160*c2c66affSColin Finck }
161*c2c66affSColin Finck
~CServerClientThread()162*c2c66affSColin Finck CServerClientThread::~CServerClientThread()
163*c2c66affSColin Finck {
164*c2c66affSColin Finck ClientSocket->GetServerSocket()->RemoveClient((LPCServerClientThread) this);
165*c2c66affSColin Finck }
166*c2c66affSColin Finck
167*c2c66affSColin Finck
168*c2c66affSColin Finck // ************************** CServerSocket **************************
169*c2c66affSColin Finck
170*c2c66affSColin Finck // Default constructor
CServerSocket()171*c2c66affSColin Finck CServerSocket::CServerSocket()
172*c2c66affSColin Finck {
173*c2c66affSColin Finck }
174*c2c66affSColin Finck
175*c2c66affSColin Finck // Default destructor
~CServerSocket()176*c2c66affSColin Finck CServerSocket::~CServerSocket()
177*c2c66affSColin Finck {
178*c2c66affSColin Finck if (Active)
179*c2c66affSColin Finck Close();
180*c2c66affSColin Finck }
181*c2c66affSColin Finck
182*c2c66affSColin Finck // Open server socket so clients can connect
Open()183*c2c66affSColin Finck VOID CServerSocket::Open()
184*c2c66affSColin Finck {
185*c2c66affSColin Finck assert(!Active);
186*c2c66affSColin Finck
187*c2c66affSColin Finck // Convert to network ordering
188*c2c66affSColin Finck SockAddrIn.sin_port = htons(Port);
189*c2c66affSColin Finck
190*c2c66affSColin Finck if (Socket == INVALID_SOCKET) {
191*c2c66affSColin Finck // Create socket
192*c2c66affSColin Finck Socket = socket(AF_INET, SOCK_STREAM, 0);
193*c2c66affSColin Finck if (Socket == INVALID_SOCKET)
194*c2c66affSColin Finck throw ESocketOpen(TS("Unable to allocate a socket."));
195*c2c66affSColin Finck }
196*c2c66affSColin Finck
197*c2c66affSColin Finck // Associate an address with server socket
198*c2c66affSColin Finck if (bind(Socket, (struct sockaddr FAR *) &SockAddrIn, sizeof(SockAddrIn)) == SOCKET_ERROR)
199*c2c66affSColin Finck throw ESocketOpen(TS("Unable to associate address with socket."));
200*c2c66affSColin Finck
201*c2c66affSColin Finck // Listen for incoming connections
202*c2c66affSColin Finck if (listen(Socket, MAX_PENDING_CONNECTS) != 0)
203*c2c66affSColin Finck throw ESocketOpen(TS("Unable to listen on socket."));
204*c2c66affSColin Finck
205*c2c66affSColin Finck // Associate network events with socket
206*c2c66affSColin Finck SetEvents(FD_ACCEPT | FD_CONNECT | FD_CLOSE);
207*c2c66affSColin Finck
208*c2c66affSColin Finck Active = TRUE;
209*c2c66affSColin Finck }
210*c2c66affSColin Finck
211*c2c66affSColin Finck // Close server socket and all current connections
Close()212*c2c66affSColin Finck VOID CServerSocket::Close()
213*c2c66affSColin Finck {
214*c2c66affSColin Finck assert(Active);
215*c2c66affSColin Finck
216*c2c66affSColin Finck if (Event != WSA_INVALID_EVENT) {
217*c2c66affSColin Finck // Tell winsock not to notify us about any events
218*c2c66affSColin Finck if (WSAEventSelect(Socket, Event, 0) == SOCKET_ERROR)
219*c2c66affSColin Finck throw ESocketClose(TS("Unable to select socket events."));
220*c2c66affSColin Finck
221*c2c66affSColin Finck if (!WSACloseEvent(Event))
222*c2c66affSColin Finck throw ESocketClose(TS("Unable to close socket event."));
223*c2c66affSColin Finck Event = WSA_INVALID_EVENT;
224*c2c66affSColin Finck }
225*c2c66affSColin Finck
226*c2c66affSColin Finck CIterator<LPCServerClientThread> *i = Connections.CreateIterator();
227*c2c66affSColin Finck
228*c2c66affSColin Finck // Terminate and free all client threads
229*c2c66affSColin Finck for (i->First(); !i->IsDone(); i->Next()) {
230*c2c66affSColin Finck //i->CurrentItem()->Terminate();
231*c2c66affSColin Finck delete i->CurrentItem();
232*c2c66affSColin Finck }
233*c2c66affSColin Finck delete i;
234*c2c66affSColin Finck Connections.RemoveAll();
235*c2c66affSColin Finck
236*c2c66affSColin Finck closesocket(Socket);
237*c2c66affSColin Finck Socket = INVALID_SOCKET;
238*c2c66affSColin Finck
239*c2c66affSColin Finck Active = FALSE;
240*c2c66affSColin Finck }
241*c2c66affSColin Finck
242*c2c66affSColin Finck // Set port number to listen on
SetPort(UINT nPort)243*c2c66affSColin Finck VOID CServerSocket::SetPort(UINT nPort)
244*c2c66affSColin Finck {
245*c2c66affSColin Finck assert(!Active);
246*c2c66affSColin Finck
247*c2c66affSColin Finck Port = nPort;
248*c2c66affSColin Finck }
249*c2c66affSColin Finck
250*c2c66affSColin Finck // Process messages from winsock if any
MessageLoop()251*c2c66affSColin Finck VOID CServerSocket::MessageLoop()
252*c2c66affSColin Finck {
253*c2c66affSColin Finck UINT nStatus;
254*c2c66affSColin Finck INT nAddrLen;
255*c2c66affSColin Finck SOCKET ClientSocket;
256*c2c66affSColin Finck SOCKADDR_IN SockAddrIn;
257*c2c66affSColin Finck WSANETWORKEVENTS NetworkEvents;
258*c2c66affSColin Finck LPCServerClientSocket lpClient;
259*c2c66affSColin Finck LPCServerClientThread lpThread;
260*c2c66affSColin Finck
261*c2c66affSColin Finck nStatus = WSAWaitForMultipleEvents(1, &Event, FALSE, 0, FALSE);
262*c2c66affSColin Finck if ((nStatus == 0) && (WSAEnumNetworkEvents(Socket, Event, &NetworkEvents) != SOCKET_ERROR)) {
263*c2c66affSColin Finck if ((NetworkEvents.lNetworkEvents & FD_ACCEPT) != 0) {
264*c2c66affSColin Finck lpClient = OnGetSocket(this);
265*c2c66affSColin Finck nAddrLen = sizeof(SockAddrIn);
266*c2c66affSColin Finck ClientSocket = accept(Socket, (SOCKADDR *) &SockAddrIn, &nAddrLen);
267*c2c66affSColin Finck if (ClientSocket != INVALID_SOCKET) {
268*c2c66affSColin Finck // Set socket handle
269*c2c66affSColin Finck lpClient->SetSocket(ClientSocket);
270*c2c66affSColin Finck // Set socket address
271*c2c66affSColin Finck lpClient->SetSockAddrIn(SockAddrIn);
272*c2c66affSColin Finck // Set winsock events
273*c2c66affSColin Finck lpClient->SetEvents(FD_READ | FD_CLOSE);
274*c2c66affSColin Finck // Create client connection thread
275*c2c66affSColin Finck lpThread = OnGetThread(lpClient);
276*c2c66affSColin Finck // Add client thread to connection list
277*c2c66affSColin Finck InsertClient(lpThread);
278*c2c66affSColin Finck // Call OnAccept event handler
279*c2c66affSColin Finck OnAccept(lpThread);
280*c2c66affSColin Finck } else {
281*c2c66affSColin Finck delete lpClient;
282*c2c66affSColin Finck lpClient = NULL;
283*c2c66affSColin Finck throw ESocketOpen(TS("No more sockets available."));
284*c2c66affSColin Finck }
285*c2c66affSColin Finck }
286*c2c66affSColin Finck /*if ((NetworkEvents.lNetworkEvents & FD_CONNECT) != 0) {
287*c2c66affSColin Finck }
288*c2c66affSColin Finck if ((NetworkEvents.lNetworkEvents & FD_CLOSE) != 0) {
289*c2c66affSColin Finck }*/
290*c2c66affSColin Finck }
291*c2c66affSColin Finck }
292*c2c66affSColin Finck
293*c2c66affSColin Finck // Insert client into connection list
InsertClient(LPCServerClientThread lpClient)294*c2c66affSColin Finck VOID CServerSocket::InsertClient(LPCServerClientThread lpClient)
295*c2c66affSColin Finck {
296*c2c66affSColin Finck Connections.Insert(lpClient);
297*c2c66affSColin Finck }
298*c2c66affSColin Finck
299*c2c66affSColin Finck // Remove client from connection list
RemoveClient(LPCServerClientThread lpClient)300*c2c66affSColin Finck VOID CServerSocket::RemoveClient(LPCServerClientThread lpClient)
301*c2c66affSColin Finck {
302*c2c66affSColin Finck Connections.Remove(lpClient);
303*c2c66affSColin Finck }
304*c2c66affSColin Finck
305*c2c66affSColin Finck // OnGetSocket event handler
OnGetSocket(LPCServerSocket lpServerSocket)306*c2c66affSColin Finck LPCServerClientSocket CServerSocket::OnGetSocket(LPCServerSocket lpServerSocket)
307*c2c66affSColin Finck {
308*c2c66affSColin Finck return NULL;
309*c2c66affSColin Finck }
310*c2c66affSColin Finck
311*c2c66affSColin Finck // OnGetThread event handler
OnGetThread(LPCServerClientSocket lpSocket)312*c2c66affSColin Finck LPCServerClientThread CServerSocket::OnGetThread(LPCServerClientSocket lpSocket)
313*c2c66affSColin Finck {
314*c2c66affSColin Finck return NULL;
315*c2c66affSColin Finck }
316*c2c66affSColin Finck
317*c2c66affSColin Finck
318*c2c66affSColin Finck // Initialize WinSock DLL
InitWinsock()319*c2c66affSColin Finck VOID InitWinsock()
320*c2c66affSColin Finck {
321*c2c66affSColin Finck WORD wVersionRequested;
322*c2c66affSColin Finck WSADATA wsaData;
323*c2c66affSColin Finck
324*c2c66affSColin Finck wVersionRequested = MAKEWORD(2, 0);
325*c2c66affSColin Finck
326*c2c66affSColin Finck if (WSAStartup(wVersionRequested, &wsaData) != 0)
327*c2c66affSColin Finck // Return FALSE as we couldn't find a usable WinSock DLL
328*c2c66affSColin Finck throw ESocketWinsock(TS("Unable to initialize winsock dll."));
329*c2c66affSColin Finck
330*c2c66affSColin Finck /* Confirm that the WinSock DLL supports 2.0 */
331*c2c66affSColin Finck
332*c2c66affSColin Finck if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) {
333*c2c66affSColin Finck // We couldn't find a usable winsock dll
334*c2c66affSColin Finck WSACleanup();
335*c2c66affSColin Finck throw ESocketDll(TS("Winsock dll version is not 2.0 or higher."));
336*c2c66affSColin Finck }
337*c2c66affSColin Finck }
338*c2c66affSColin Finck
339*c2c66affSColin Finck // Deinitialize WinSock DLL
DeinitWinsock()340*c2c66affSColin Finck VOID DeinitWinsock()
341*c2c66affSColin Finck {
342*c2c66affSColin Finck if (WSACleanup() != 0)
343*c2c66affSColin Finck throw ESocketWinsock(TS("Unable to deinitialize winsock dll."));
344*c2c66affSColin Finck }
345