Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
NetServer.cpp
Go to the documentation of this file.
1 /* Project nGenEx
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: NetEx.lib
6  FILE: NetServer.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Network Server Pump for HTTP Server
13 */
14 
15 
16 #include "MemDebug.h"
17 #include "NetServer.h"
18 #include "NetHost.h"
19 #include "NetLayer.h"
20 
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <mmsystem.h>
24 
25 // +-------------------------------------------------------------------+
26 
27 DWORD WINAPI NetServerListenerProc(LPVOID link);
28 DWORD WINAPI NetServerReaderProc(LPVOID link);
29 
31 
32 // +-------------------------------------------------------------------+
33 
34 NetServer::NetServer(WORD port, int nthreads)
35  : sock(true), pool(0), conn(0), poolsize(nthreads), err(0),
36  server_shutdown(false), hreader(0)
37 {
38  NetHost host;
39  addr = NetAddr(host.Address().IPAddr(), port);
40 
41  sock.bind(addr);
42  sock.listen(3);
43 
44  if (poolsize < 1) poolsize = 1;
45 
46  pool = new(__FILE__,__LINE__) HANDLE[poolsize];
47  conn = new(__FILE__,__LINE__) NetSock*[poolsize];
48  clients = new(__FILE__,__LINE__) NetAddr[poolsize];
49 
50  if (pool && conn && clients) {
51  ZeroMemory(pool, poolsize * sizeof(HANDLE));
52  ZeroMemory(conn, poolsize * sizeof(NetSock*));
53 
54  DWORD thread_id = 0;
55 
56  for (int i = 0; i < poolsize; i++) {
57  thread_id = 0;
58  PoolItem* item = new PoolItem;
59  item->server = this;
60  item->thread_index = i;
61 
62  pool[i] = CreateThread(0, 4096, NetServerReaderProc, (LPVOID) item, 0, &thread_id);
63  }
64 
65  thread_id = 0;
66  hreader = CreateThread(0, 4096, NetServerListenerProc, (LPVOID) this, 0, &thread_id);
67  }
68 }
69 
71 {
72  if (!server_shutdown) {
73  server_shutdown = true;
74  sock.close();
75  }
76 
77  if (hreader) {
78  WaitForSingleObject(hreader, 1000);
79  CloseHandle(hreader);
80  }
81 
82  if (pool && poolsize) {
83  for (int i = 0; i < poolsize; i++) {
84  WaitForSingleObject(pool[i], 1000);
85  CloseHandle(pool[i]);
86  delete conn[i];
87  conn[i] = 0;
88  }
89 
90  delete [] pool;
91  delete [] conn;
92  delete [] clients;
93  }
94 }
95 
96 // +--------------------------------------------------------------------+
97 
98 void
100 {
101  server_shutdown = true;
102 }
103 
104 // +--------------------------------------------------------------------+
105 
106 DWORD WINAPI NetServerListenerProc(LPVOID link)
107 {
108  NetServer* net_server = (NetServer*) link;
109 
110  if (net_server)
111  return net_server->Listener();
112 
113  return (DWORD) E_POINTER;
114 }
115 
116 DWORD
118 {
119  while (!server_shutdown) {
121 
122  while (s) {
123  sync.acquire();
124 
125  for (int i = 0; i < poolsize; i++) {
126  if (conn[i] == 0) {
127  conn[i] = s;
128  clients[i] = client_addr;
129  s = 0;
130  break;
131  }
132  }
133 
134  sync.release();
135 
136  // wait for a thread to become not busy
137  if (s)
138  Sleep(10);
139  }
140  }
141 
142  return 0;
143 }
144 
145 // +--------------------------------------------------------------------+
146 
147 DWORD WINAPI NetServerReaderProc(LPVOID link)
148 {
149  if (!link) return (DWORD) E_POINTER;
150 
151  PoolItem* item = (PoolItem*) link;
152  NetServer* net_server = item->server;
153  int index = item->thread_index;
154 
155  delete item;
156 
157  if (net_server)
158  return net_server->Reader(index);
159 
160  return (DWORD) E_POINTER;
161 }
162 
163 DWORD
165 {
166  // init random seed for this thread:
167  srand(timeGetTime());
168 
169  while (!server_shutdown) {
170  sync.acquire();
171  NetSock* s = conn[index];
172  sync.release();
173 
174  if (s) {
175  const int MAX_REQUEST = 4096;
176  Text request;
177 
178  /***
179  *** NOT SURE WHY, BUT THIS DOESN'T WORK FOR SHIT
180  ***
181  *** Setting the socket timeout to 2 seconds caused it
182  *** to wait for two seconds, read nothing, and give up
183  *** with a WSAETIMEDOUT error. Meanwhile, the client
184  *** immediately registered a failure (during the 2 sec
185  *** delay) and aborted the request.
186  ***
187 
188  s->set_timeout(2000);
189  Text msg = s->recv();
190 
191  while (msg.length() > 0 && request.length() < MAX_REQUEST) {
192  request += msg;
193  msg = s->recv();
194  }
195 
196  ***/
197 
198  request = s->recv();
199 
200  if (request.length() > 0 && !s->is_closed()) {
201  Text response = ProcessRequest(request, clients[index]);
202  err = s->send(response);
203  if (err < 0) {
205  }
206  }
207 
208  sync.acquire();
209  delete conn[index];
210  conn[index] = 0;
211  sync.release();
212  }
213  else {
214  Sleep(5);
215  }
216  }
217 
218  return 0;
219 }
220 
221 // +--------------------------------------------------------------------+
222 
223 Text
225 {
226  if (msg.indexOf("GET ") == 0)
227  return DefaultResponse();
228 
229  return ErrorResponse();
230 }
231 
232 Text
234 {
235  Text response =
236  "HTTP/1.0 200 OK\nServer: Generic NetServer 1.0\nMIME-Version: 1.0\nContent-type: text/html\n\n";
237 
238  response += "<html><head><title>Generic NetServer 1.0</title></head>\n\n";
239  response += "<body bgcolor=\"black\" text=\"white\">\n";
240  response += "<h1>Generic NetServer 1.0</h1>\n";
241  response += "<p>Didn't think I could do it, did ya?\n";
242  response += "</body></html>\n\n";
243 
244  return response;
245 }
246 
247 Text
249 {
250  Text response =
251  "HTTP/1.0 501 Not Implemented\nServer: Generic NetServer 1.0\nMIME-Version: 1.0\nContent-type: text/html\n\n";
252 
253  response += "<html><head><title>Generic NetServer 1.0</title></head>\n\n";
254  response += "<body bgcolor=\"black\" text=\"white\">\n";
255  response += "<h1>Generic NetServer 1.0</h1>\n";
256  response += "<p>Sorry charlie... I'm not a magician.\n";
257  response += "</body></html>\n\n";
258 
259  return response;
260 }