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