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