aboutsummaryrefslogtreecommitdiff
path: root/src/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.c')
-rw-r--r--src/server.c577
1 files changed, 204 insertions, 373 deletions
diff --git a/src/server.c b/src/server.c
index f21e9697..d028330b 100644
--- a/src/server.c
+++ b/src/server.c
@@ -12,437 +12,268 @@
12 * 12 *
13 */ 13 */
14 14
15#include "server.h" 15#include "webserver_gnunet.h"
16#include "logo.h" 16#include <stdio.h>
17#include <signal.h>
18#include <time.h>
17 19
18#ifdef WIN32 20#include "memory.h"
19 #define _SERVER_VERSION "libwebserver/0.5.3(win32)" // update allways when changing version (damn win) 21#include "client.h"
20#endif 22#include "socket.h"
21
22#ifndef _SERVER_VERSION
23 #define _SERVER_VERSION "libwebserver/(unknow)"
24#endif
25 23
26#ifdef DEBUG 24#ifdef WIN32
27 char *_libwebserver_version= _SERVER_VERSION "(debug)"; 25#define SHUT_RDWR SD_BOTH
28#else
29 char *_libwebserver_version= _SERVER_VERSION;
30#endif 26#endif
31 27
32struct web_server *current_web_server; 28struct web_server {
29 int socket;
30 unsigned int port;
31 struct gethandler * gethandler;
32 struct web_client *client;
33};
33 34
34 35
35/*********************************************************************************************************/
36/* 36/*
37 * Define certificate file (open_ssl) 37 * initializate (allocate) handler list
38 */ 38 */
39void web_server_useSSLcert(struct web_server *server,const char *file) { 39struct gethandler *__ILWS_init_handler_list() {
40#ifdef HAVE_OPENSSL 40 struct gethandler *ret;
41 if(!(server->cert_file=__ILWS_malloc(strlen(file)+1))) { 41
42 LWSERR(LE_MEMORY); 42 ret = __ILWS_malloc(sizeof(struct gethandler));
43 return; 43 if (ret==NULL)
44 }; 44 return NULL;
45 memcpy(server->cert_file,file,strlen(file)); 45 ret->next = NULL;
46 server->cert_file[strlen(file)]=0; 46 ret->func = NULL;
47#else 47 ret->ctx = NULL;
48 printf("OpenSSL not supported in this compilation\n"); 48 ret->str = NULL;
49#endif 49 return ret;
50} 50}
51 51
52void web_server_useMIMEfile(struct web_server *server,const char *file) { 52/*
53 if(!(server->mimefile=__ILWS_malloc(strlen(file)+1))) { 53 * add an handler to list
54 LWSERR(LE_MEMORY);
55 return;
56 };
57 memcpy(server->mimefile,file,strlen(file));
58 server->mimefile[strlen(file)]=0;
59};
60/*********************************************************************************************************/
61/*
62 * Handler for libwebserver logotipe
63 */ 54 */
64void _web_server_logo() { 55static int __ILWS_add_handler(struct gethandler * head,
65 printf("Content-type: image/gif\r\n\r\n"); 56 const char * mstr,
66 fwrite((char *)_logo,sizeof(_logo),1,stdout); 57 void (*func)(),
67} 58 void * ctx) {
68 59 struct gethandler * temp = head;
60 while (temp->next != NULL)
61 temp = temp->next;
62
63 temp->next = __ILWS_malloc(sizeof(struct gethandler));
64 if (temp->next==NULL)
65 return 0;
66 temp = temp->next;
67 temp->str=__ILWS_malloc(strlen(mstr)+1);
68 if (temp->str==NULL) {
69 __ILWS_free(temp);
70 return 0;
71 };
72 memcpy(temp->str,
73 mstr,
74 strlen(mstr) + 1);
75 temp->func = func;
76 temp->ctx = ctx;
77 temp->next = NULL;
78 return 1;
79}
69 80
70/*********************************************************************************************************/ 81/*
71/* 82 * Deletes the entire handler list including the head
72 * Add an handler to request data
73 */ 83 */
74int web_server_addhandler(struct web_server *server,const char *mstr,void (*func)(),int flag) { 84static void __ILWS_delete_handler_list(struct gethandler * handler) {
75 _logfile=server->weblog; 85 struct gethandler * next;
76 // xor? 86
77 flag ^= (server->flags & WS_LOCAL); // global flag to handler flag 87 while (handler) {
78 flag ^= (server->flags & WS_DYNVAR); // global flag to handler flag 88 next = handler->next;
79 flag ^= (server->flags & WS_USELEN); // global flag to handler flag 89 if (handler->str != NULL)
80 web_log("[%s] Adding handler %s <--%s%s%s\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),mstr, ((flag & WS_LOCAL) == WS_LOCAL && !((server->flags & WS_LOCAL) == WS_LOCAL))?"[LOCAL] ":"", ((flag & WS_DYNVAR) == WS_DYNVAR)?"[DYNVAR]":"", ((flag & WS_USELEN) == WS_USELEN)?"[USELEN]":""); 90 __ILWS_free(handler->str);
81 return __ILWS_add_handler((struct gethandler *)server->gethandler,mstr,func,NULL,flag,GH_FUNCTION); 91 __ILWS_free(handler);
92 handler = next;
93 }
82} 94}
83 95
84/*********************************************************************************************************/
85/* 96/*
86 * Add an alias dir (new on 0.5.2) 97 * to add a listen socket
87 */ 98 */
88int web_server_aliasdir(struct web_server *server, const char *str, char *path,int flag) { 99static int __ILWS_listensocket(short port,
89 char *mstr; 100 int saddr) {
90 int ret; 101 struct sockaddr_in sa;
91 mstr=__ILWS_malloc(strlen(str)+7); 102 int ret;
92 if(!strlen(str)) { 103 int sockopt=1;
93 snprintf(mstr,strlen(str)+7,"* /*");
94 } else {
95 snprintf(mstr,strlen(str)+7,"* /%s/*",str);
96 };
97 _logfile=server->weblog;
98 flag ^= (server->flags & WS_LOCAL); // global flag to handler flag
99 flag ^= (server->flags & WS_DYNVAR); // global flag to handler flag
100 flag ^= (server->flags & WS_USELEN); // global flag to handler flag
101 web_log("[%s] Adding directory %s <--%s%s%s\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),mstr, ((flag & WS_LOCAL) == WS_LOCAL && !((server->flags & WS_LOCAL) == WS_LOCAL))?"[LOCAL] ":"", ((flag & WS_DYNVAR) == WS_DYNVAR)?"[DYNVAR]":"", ((flag & WS_USELEN) == WS_USELEN)?"[USELEN]":"");
102 ret=__ILWS_add_handler((struct gethandler *)server->gethandler,mstr,NULL,path,flag,GH_DIRECTORY);
103 __ILWS_free(mstr);
104 return ret;
105};
106
107 104
108/*********************************************************************************************************/ 105 sa.sin_addr.s_addr=saddr;
109/* 106 sa.sin_port=htons((short)port);
110 * Personal config (new on 0.5.0) 107 sa.sin_family=AF_INET;
111 */ 108 ret=socket(AF_INET,SOCK_STREAM,6); // tcp
112char *web_server_getconf(struct web_server *server, const char *topic,const char *key) { 109 if(ret==-1)
113 char *dataconf; 110 return -1;
114 char *tmp1,*tmp2,*tmp3; 111
115 long tmpsize=0; 112 setsockopt(ret,
113 SOL_SOCKET,
114 SO_REUSEADDR,
115 (char *)&sockopt,
116 sizeof(sockopt));
117
118 if (bind(ret,
119 (struct sockaddr *)&sa,
120 sizeof(sa))==-1) {
121 close(ret);
122 return -1;
123 }
124
125 if (listen(ret,512)==-1) { // 512 backlog
126 close(ret);
127 return -1;
128 }
129 return ret;
130}
116 131
117 dataconf=__ILWS_stristr(server->dataconf,topic);
118 if(dataconf==NULL) {
119 return NULL;
120 };
121 dataconf+=strlen(topic);
122 tmp1=__ILWS_stristr(dataconf,key);
123 do {
124 tmp1=__ILWS_stristr(dataconf,key);
125 dataconf+=1;
126 if(dataconf[0]==0) {
127 return NULL;
128 };
129 if(dataconf[0]=='[' && dataconf[-1]=='\n') {
130 return NULL;
131 };
132 }while(!(tmp1!=NULL && tmp1[-1]=='\n' && tmp1[strlen(key)]=='='));
133
134 tmp1+=strlen(key)+1;
135 tmp2=__ILWS_stristr(tmp1,"\n");
136 if(tmp2==NULL) {
137 tmp2=tmp1+strlen(tmp1);
138 };
139 tmpsize=tmp2-tmp1;
140 if(!(tmp3=__ILWS_malloc(tmpsize+1))) {
141 LWSERR(LE_MEMORY);
142 return NULL;
143 };
144 memcpy(tmp3,tmp1,tmpsize);
145 tmp3[tmpsize]=0;
146 return tmp3;
147};
148 132
149/*********************************************************************************************************/
150/* 133/*
151 * Define config file to setup server (new on 0.5.0) 134 * Add an handler to request data
152 */ 135 */
153int web_server_setup(struct web_server *server,const char *conffile) { 136int web_server_addhandler(struct web_server *server,
154 FILE *tmpf; 137 const char *mstr,
155 char *tmp3; 138 void (*func)(),
156 //long tmpsize=0; 139 void * hctx) {
157 long sizec; 140 return __ILWS_add_handler(server->gethandler,
158 struct stat statf; // tested only on win 141 mstr,
159 142 func,
160 if(!(server->conffile=__ILWS_malloc(strlen(conffile)+1))) { 143 hctx);
161 LWSERR(LE_MEMORY); 144}
162 return 0;
163 };
164
165 memcpy(server->conffile,conffile,strlen(conffile));
166 server->conffile[strlen(conffile)]=0;
167
168 tmpf=fopen(server->conffile,"r");
169 if(tmpf==NULL) {
170 printf("no config file found\r\n");
171 server->dataconf="";
172 return(0);
173 };
174 fseek(tmpf,SEEK_SET,SEEK_END);
175 sizec=ftell(tmpf);
176 fseek(tmpf,0,SEEK_SET);
177 if(!(server->dataconf=__ILWS_malloc(sizec+1))) {
178 LWSERR(LE_MEMORY);
179 return 0;
180 };
181 fread(server->dataconf,sizec,1,tmpf);
182 server->dataconf[sizec]=0; // Hilobok Andrew (han@km.if.ua) said to remove the -9 :)
183 fclose(tmpf);
184
185 stat(server->conffile,&statf); // tested only on win
186 server->conffiletime=statf.st_mtime; // tested only on win
187
188 if((server->logfile=web_server_getconf(server,"LIBWEBSERVER","LOG"))) {
189 web_log("\nUsing logfile [%s]\n",server->logfile);
190 server->weblog=open_weblog(server->logfile);
191 } else {
192 web_log("\nLOG entry not found\r\n");
193 server->weblog=NULL;
194 };
195 if((tmp3=web_server_getconf(server,"LIBWEBSERVER","PORT"))) {
196 web_log("\nListen port [%s]\n",tmp3);
197 server->port=atoi(tmp3);
198 __ILWS_free(tmp3);
199 } else {
200 web_log("PORT entry not found\r\n");
201 server->port=0;
202 };
203#ifdef HAVE_OPENSSL
204 // Fetch SSL
205 if((tmp3=web_server_getconf(server,"LIBWEBSERVER","USESSL"))) {
206 if(tmp3[0]=='1') {
207 server->flags = server->flags | WS_USESSL;
208 }else if(tmp3[0]=='0') {
209 server->flags = server->flags & ~WS_USESSL;
210 } else {
211 fprintf(stderr,"[USESSL=] argument invalid\n");
212 };
213 __ILWS_free(tmp3);
214 }
215 // Fetch CERTFILE
216 server->cert_file=web_server_getconf(server,"LIBWEBSERVER","CERTFILE");
217 server->mimefile=web_server_getconf(server,"LIBWEBSERVER","MIMEFILE");
218#endif
219 // Fetch LOCAL
220 if((tmp3=web_server_getconf(server,"LIBWEBSERVER","LOCAL"))) {
221 if(tmp3[0]=='1') {
222 server->flags = server->flags | WS_LOCAL;
223 } else if(tmp3[0]=='0') {
224 server->flags=server->flags & ~WS_LOCAL;
225 }else {
226 fprintf(stderr,"[LOCAL=] argument invalid\n");
227 };
228 __ILWS_free(tmp3);
229 }
230
231 return 1;
232};
233 145
234/*********************************************************************************************************/
235/* 146/*
236 * This function initialize one web_server handler 147 * This function initialize one web_server handler
237 */ 148 */
238int web_server_init(struct web_server *server,int port,const char *logfile,int flags) { 149int web_server_init(struct web_server *server,
150 int port,
151 int flags) {
239#ifdef WIN32 152#ifdef WIN32
240 unsigned long t=IOC_INOUT; 153 unsigned long t=IOC_INOUT;
241 WSADATA WSAinfo; 154 WSADATA WSAinfo;
242 WSAStartup(2,&WSAinfo); // Damn w32 sockets 155 WSAStartup(2,&WSAinfo); // Damn w32 sockets
243#endif
244
245 current_web_server=server;
246 server->port=port;
247 server->conffile=NULL;
248 server->mimefile=NULL;
249 server->weblog=NULL;
250 server->usessl=0;
251 server->flags=flags;
252 server->dataconf="";
253 if((flags & WS_USEEXTCONF) == WS_USEEXTCONF) {
254 if(!(web_server_setup(server,logfile))) {
255#ifdef WIN32
256 WSACleanup();
257#endif 156#endif
258 return 0; 157 server->port=port;
259 }; 158 // Create a listen socket port 'port' and listen addr (0) (all interfaces)
260 _logfile=server->weblog; // Set current log stream 159 server->socket=__ILWS_listensocket((short)server->port,0);
261 web_log("%s using config file %s\n",_libwebserver_version,logfile); 160 if (server->socket==-1) {
262 };
263 // Create a listen socket port 'port' and listen addr (0) (all interfaces)
264 server->socket=__ILWS_listensocket((short)server->port,0);
265 if(server->socket==-1) {
266 LWSERR(LE_NET);
267#ifdef WIN32 161#ifdef WIN32
268 WSACleanup(); 162 WSACleanup();
269#endif 163#endif
270 return 0; 164 return 0;
271 }; 165 };
272#ifdef WIN32 166#ifdef WIN32
273 ioctlsocket(server->socket,FIONBIO,&t); //non blocking sockets for win32 167 ioctlsocket(server->socket,
168 FIONBIO,
169 &t); //non blocking sockets for win32
274#else 170#else
275 fcntl(server->socket,F_SETFL,O_NONBLOCK); 171 fcntl(server->socket,
172 F_SETFL,
173 O_NONBLOCK);
276#endif 174#endif
277 // Setup FILE structure of logfile 175
278 if(logfile!=NULL && !((flags & WS_USEEXTCONF) == WS_USEEXTCONF)) { 176 // Setup Flags
279 server->logfile=__ILWS_malloc(strlen(logfile)+1); 177 server->client = __ILWS_init_client_list();
280 memcpy(server->logfile,logfile,strlen(logfile)); 178 server->gethandler = __ILWS_init_handler_list();
281 server->logfile[strlen(logfile)]=0; 179
282 server->weblog=open_weblog(logfile); // Create File stream for log
283 };
284
285 web_log("\n[%s] Server started at port %d (%s)\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"),server->port,_libwebserver_version);
286
287 // Setup Flags
288
289 // openssl
290#ifdef HAVE_OPENSSL
291 if((server->flags & WS_USESSL) == WS_USESSL) {
292 web_log("[%s] (FLAG) Using SSL in connections\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"));
293 web_log(" +-- %s certificate file\n",server->cert_file);
294 SSL_load_error_strings();
295 SSLeay_add_ssl_algorithms();
296 server->ctx=SSL_CTX_new (SSLv23_server_method());
297 if (SSL_CTX_use_certificate_file(server->ctx, server->cert_file, SSL_FILETYPE_PEM) <= 0) {
298 ERR_print_errors_fp(stderr);
299 exit(3);
300 }
301 if (SSL_CTX_use_PrivateKey_file(server->ctx, server->cert_file, SSL_FILETYPE_PEM) <= 0) {
302 ERR_print_errors_fp(stderr);
303 exit(4);
304 }
305 if (SSL_CTX_check_private_key(server->ctx)<= 0) {
306 ERR_print_errors_fp(stderr);
307 exit(4);
308 };
309 server->usessl=1;
310 };
311#endif
312 if((server->flags & WS_LOCAL) == WS_LOCAL) {
313 web_log("[%s] (FLAG) Accepting only local connections\n",__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z"));
314 };
315 server->client=__ILWS_init_client_list(); // Initializate client list
316 server->gethandler=__ILWS_init_handler_list(); // Initializate handlers list
317 web_server_addhandler(server,"* /libwebserver.gif",_web_server_logo,0); // Add logo default handler
318
319#ifndef WIN32 180#ifndef WIN32
320 signal(SIGPIPE,SIG_IGN); 181 signal(SIGPIPE, SIG_IGN);
321#endif 182#endif
322 return 1; 183 return 1;
323} 184}
324 185
325
326/*********************************************************************************************************/
327/* 186/*
328 * This function shuts down a running web server, frees its allocated memory, 187 * This function shuts down a running web server, frees its allocated memory,
329 * and closes its socket. If called on a struct web_server that has already 188 * and closes its socket. If called on a struct web_server that has already
330 * been shut down, this is a noop. 189 * been shut down, this is a noop.
331 */ 190 */
332void web_server_shutdown(struct web_server *server) { 191void web_server_shutdown(struct web_server * server) {
333 // free and close things in opposite order of web_server_init 192 // free and close things in opposite order of web_server_init
334 193 __ILWS_delete_handler_list(server->gethandler);
335 __ILWS_delete_handler_list(server->gethandler); 194 server->gethandler = NULL;
336 server->gethandler = NULL; 195 __ILWS_delete_client_list(server->client);
337 __ILWS_delete_client_list(server->client); 196 server->client = NULL;
338 server->client = NULL; 197 if(server->socket > 0) {
339
340 if(server->socket > 0) {
341#ifdef WIN32 198#ifdef WIN32
342 closesocket(server->socket); 199 closesocket(server->socket);
343#else 200#else
344 close(server->socket); 201 close(server->socket);
345#endif 202#endif
346 server->socket = -1; 203 server->socket = -1;
347 } 204 }
348
349 if(server->weblog) {
350 fclose(server->weblog);
351 server->weblog = NULL;
352 __ILWS_free(server->logfile);
353 server->logfile = NULL;
354 }
355
356#ifdef WIN32 205#ifdef WIN32
357 WSACleanup(); 206 WSACleanup();
358#endif 207#endif
359} 208}
360 209
361/*********************************************************************************************************/
362/* 210/*
363 * Core function, return 2 if no client to process, 1 if some client processed, 0 if error 211 * Core function, return 2 if no client to process, 1 if some client processed, 0 if error
364 */ 212 */
365int web_server_run(struct web_server *server) { 213int web_server_run(struct web_server *server) {
366 struct web_client *client; 214 struct web_client * client;
367 int rt; 215 struct web_client * pos;
368 int tsalen=0; 216 int rt;
369 int tsocket=0; 217 size_t tsalen=0;
370 struct sockaddr_in tsa; 218 int tsocket=0;
371 _logfile=server->weblog; 219 int cond;
372 current_web_server=server; 220 struct sockaddr_in tsa;
373 if(server->client->next==NULL) { 221
374 //if(__ILWS_newdata(server->socket)); // does nothing but act like usleep 222 tsalen = sizeof(client->sa);
375 }; 223 tsocket = accept(server->socket,
376// search for client 224 (struct sockaddr *)&tsa,
377 tsalen=sizeof(client->sa); 225 &tsalen);
378 tsocket=accept(server->socket,(struct sockaddr *)&tsa,&tsalen); 226 if (tsocket == -1) {
379 if(tsocket==-1) {
380#ifdef WIN32 227#ifdef WIN32
381 if(WSAGetLastError()!=WSAEWOULDBLOCK) { 228 cond = WSAGetLastError() != WSAEWOULDBLOCK;
382#else 229#else
383 if(errno!=EAGAIN) { 230 cond = errno!=EAGAIN;
384#endif 231#endif
385 fprintf(stderr,"What kind of error is this?\n"); // REMOVE 232 if (cond) {
386 // client fucked up? warn somebody? (error or log or something?) 233 // client fucked up? warn somebody? (error or log or something?)
387 return 0; // don't process nothing 234 return 0;
388 }; 235 }
389 } else { 236 } else {
390 client=__ILWS_malloc(sizeof(struct web_client)); 237 client = __ILWS_malloc(sizeof(struct web_client));
391 if(client==NULL) { 238 if (client == NULL) {
392 rt=shutdown(tsocket,SHUT_RDWR); 239 rt = shutdown(tsocket,
240 SHUT_RDWR);
393#ifdef WIN32 241#ifdef WIN32
394 rt=closesocket(tsocket); 242 rt=closesocket(tsocket);
395#else 243#else
396 rt=close(tsocket); 244 rt=close(tsocket);
397#endif
398 LWSERR(LE_MEMORY);
399 return 0;
400 };
401 client->salen=tsalen;
402 client->socket=tsocket;
403 client->sa=tsa;
404#ifdef HAVE_OPENSSL
405 if((server->flags & WS_USESSL) == WS_USESSL) {
406 client->ssl = SSL_new(server->ctx);
407 SSL_set_fd(client->ssl,client->socket);
408 SSL_accept(client->ssl);
409 //client->cert = SSL_get_peer_certificate (client->ssl);
410 } else {
411 client->ssl=NULL;
412 };
413#endif 245#endif
414 if(!__ILWS_add_client(server->client,client)) { 246 return 0;
415 fprintf(stderr,"No client?\n"); // REMOVE 247 };
416 return 0; 248 client->salen=tsalen;
417 }else { 249 client->socket=tsocket;
418 web_log("%s - - [%s] Connected\n",inet_ntoa(client->sa.sin_addr),__ILWS_date(time(NULL),"%d/%b/%Y:%H:%M:%S %z")); //REMOBE 250 client->sa=tsa;
419 }; 251 if(!__ILWS_add_client(server->client,client))
420 }; 252 return 0;
421 // end search for client 253 };
422 client=server->client; // init list 254 // end search for client
423 if(!client->next) { // think of Rocco Carbone (rocco@tecsiel.it) 255 client = server->client; // init list
424 return 2; // i don't need to process the list (nothing next) returns 2 if there is no client to process 256 if(!client->next) { // think of Rocco Carbone (rocco@tecsiel.it)
425 }; 257 return 2; // i don't need to process the list (nothing next) returns 2 if there is no client to process
426 while(client->next!=NULL) { // Process the client and swap to next; 258 }
427 current_web_client=client->next; 259 while (client->next != NULL) { // Process the client and swap to next;
428 switch(client->next->stat) { 260 pos = client->next;
429 case 1: { 261 switch (pos->stat) {
430 __ILWS_read_client(current_web_client); 262 case 1:
431 };break; 263 __ILWS_read_client(pos);
432 case 2: { 264 break;
433 __ILWS_process_client(current_web_client,server->gethandler); 265 case 2:
434 };break; 266 __ILWS_process_client(pos, server->gethandler);
435 case 4: { 267 break;
436 __ILWS_output_client(current_web_client); 268 case 4:
437 };break; 269 __ILWS_output_client(pos);
438 case 5: { 270 break;
439 __ILWS_delete_next_client(client); 271 case 5:
440 continue; 272 __ILWS_delete_next_client(client);
441 };break; 273 continue;
442 }; 274 }
443 client=client->next; 275 client=client->next;
444 276 }
445 }; 277 return 1; // return 1 if something processed
446 return 1; // return 1 if something processed
447} 278}
448 279