Subversion Repositories Tewi

Rev

Rev 189 | Rev 213 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 189 Rev 212
Line 1... Line 1...
1
/* $Id: server.c 189 2024-09-29 00:37:00Z nishi $ */
1
/* $Id: server.c 212 2024-10-02 17:44:55Z nishi $ */
2
 
2
 
3
#define SOURCE
3
#define SOURCE
4
 
4
 
5
#include "../config.h"
5
#include "../config.h"
6
 
6
 
Line 13... Line 13...
13
#include "tw_config.h"
13
#include "tw_config.h"
14
#include "tw_http.h"
14
#include "tw_http.h"
15
#include "tw_module.h"
15
#include "tw_module.h"
16
#include "tw_version.h"
16
#include "tw_version.h"
17
 
17
 
-
 
18
#ifndef _MSC_VER
18
#include <unistd.h>
19
#include <unistd.h>
-
 
20
#endif
19
#include <string.h>
21
#include <string.h>
20
#include <stdbool.h>
22
#include <stdbool.h>
21
#include <stdarg.h>
23
#include <stdarg.h>
22
#include <stdio.h>
24
#include <stdio.h>
23
#include <stdlib.h>
25
#include <stdlib.h>
24
#include <errno.h>
26
#include <errno.h>
25
#include <sys/stat.h>
-
 
26
#include <sys/types.h>
27
#include <sys/types.h>
-
 
28
#include <sys/stat.h>
27
#include <time.h>
29
#include <time.h>
28
 
30
 
29
#include <cm_string.h>
31
#include <cm_string.h>
30
#include <cm_log.h>
32
#include <cm_log.h>
31
#include <cm_dir.h>
33
#include <cm_dir.h>
32
 
34
 
33
#ifdef __MINGW32__
35
#if defined(__MINGW32__) || defined(_MSC_VER)
34
#ifndef NO_GETADDRINFO
36
#ifndef NO_GETADDRINFO
35
#include <ws2tcpip.h>
37
#include <ws2tcpip.h>
36
#include <wspiapi.h>
38
#include <wspiapi.h>
37
#endif
39
#endif
38
#include <winsock2.h>
40
#include <winsock2.h>
Line 67... Line 69...
67
 
69
 
68
#ifdef __HAIKU__
70
#ifdef __HAIKU__
69
#include <OS.h>
71
#include <OS.h>
70
#endif
72
#endif
71
 
73
 
-
 
74
#ifndef S_ISDIR
-
 
75
#define S_ISDIR(x) ((x) & _S_IFDIR)
-
 
76
#endif
-
 
77
 
72
extern struct tw_config config;
78
extern struct tw_config config;
73
extern char tw_server[];
79
extern char tw_server[];
74
 
80
 
75
int sockcount = 0;
81
int sockcount = 0;
76
 
82
 
77
SOCKADDR addresses[MAX_PORTS];
83
SOCKADDR addresses[MAX_PORTS];
78
int sockets[MAX_PORTS];
84
int sockets[MAX_PORTS];
79
 
85
 
80
#ifdef __MINGW32__
86
#if defined(__MINGW32__) || defined(_MSC_VER)
81
const char* reserved_names[] = {"CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"};
87
const char* reserved_names[] = {"CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"};
82
#endif
88
#endif
83
 
89
 
84
/* https://qiita.com/gyu-don/items/5a640c6d2252a860c8cd */
90
/* https://qiita.com/gyu-don/items/5a640c6d2252a860c8cd */
85
int tw_wildcard_match(const char* wildcard, const char* target) {
91
int tw_wildcard_match(const char* wildcard, const char* target) {
Line 102... Line 108...
102
		}
108
		}
103
	}
109
	}
104
}
110
}
105
 
111
 
106
void close_socket(int sock) {
112
void close_socket(int sock) {
107
#if defined(__MINGW32__)
113
#if defined(__MINGW32__) || defined(_MSC_VER)
108
	closesocket(sock);
114
	closesocket(sock);
109
#else
115
#else
110
	close(sock);
116
	close(sock);
111
#endif
117
#endif
112
}
118
}
113
 
119
 
114
int tw_server_init(void) {
120
int tw_server_init(void) {
115
	int i;
121
	int i;
116
#ifdef __MINGW32__
122
#if defined(__MINGW32__) || defined(_MSC_VER)
117
	WSADATA wsa;
123
	WSADATA wsa;
118
	WSAStartup(MAKEWORD(2, 0), &wsa);
124
	WSAStartup(MAKEWORD(2, 0), &wsa);
119
#endif
125
#endif
120
	for(i = 0; config.ports[i] != -1; i++)
126
	for(i = 0; config.ports[i] != -1; i++)
121
		;
127
		;
122
	sockcount = i;
128
	sockcount = i;
123
	for(i = 0; config.ports[i] != -1; i++) {
129
	for(i = 0; config.ports[i] != -1; i++) {
-
 
130
		int yes = 1;
-
 
131
		int no = 0;
124
#ifdef NO_IPV6
132
#ifdef NO_IPV6
125
		int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
133
		int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
126
#else
134
#else
127
		int sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
135
		int sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
128
#endif
136
#endif
129
#ifdef __MINGW32__
137
#if defined(__MINGW32__) || defined(_MSC_VER)
130
		if(sock == INVALID_SOCKET)
138
		if(sock == INVALID_SOCKET)
131
#else
139
#else
132
		if(sock < 0)
140
		if(sock < 0)
133
#endif
141
#endif
134
		{
142
		{
135
			cm_log("Server", "Socket creation failure");
143
			cm_log("Server", "Socket creation failure");
136
			return 1;
144
			return 1;
137
		}
145
		}
138
		int yes = 1;
-
 
139
		if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(yes)) < 0) {
146
		if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(yes)) < 0) {
140
			close_socket(sock);
147
			close_socket(sock);
141
			cm_log("Server", "setsockopt failure (reuseaddr)");
148
			cm_log("Server", "setsockopt failure (reuseaddr)");
142
			return 1;
149
			return 1;
143
		}
150
		}
Line 147... Line 154...
147
			cm_log("Server", "setsockopt failure (nodelay)");
154
			cm_log("Server", "setsockopt failure (nodelay)");
148
			return 1;
155
			return 1;
149
		}
156
		}
150
#endif
157
#endif
151
#ifndef NO_IPV6
158
#ifndef NO_IPV6
152
		int no = 0;
-
 
153
		if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&no, sizeof(no)) < 0) {
159
		if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&no, sizeof(no)) < 0) {
154
			close_socket(sock);
160
			close_socket(sock);
155
			cm_log("Server", "setsockopt failure (IPv6)");
161
			cm_log("Server", "setsockopt failure (IPv6)");
156
			return 1;
162
			return 1;
157
		}
163
		}
Line 220... Line 226...
220
	    "	</body>\n" \
226
	    "	</body>\n" \
221
	    "</html>\n"
227
	    "</html>\n"
222
 
228
 
223
void _tw_process_page(SSL* ssl, int sock, const char* status, const char* type, FILE* f, const unsigned char* doc, size_t size, char** headers, time_t mtime, time_t cmtime) {
229
void _tw_process_page(SSL* ssl, int sock, const char* status, const char* type, FILE* f, const unsigned char* doc, size_t size, char** headers, time_t mtime, time_t cmtime) {
224
	char construct[512];
230
	char construct[512];
-
 
231
	size_t incr;
225
	if(mtime != 0 && cmtime != 0 && mtime <= cmtime) {
232
	if(mtime != 0 && cmtime != 0 && mtime <= cmtime) {
226
		status = "304 Not Modified";
233
		status = "304 Not Modified";
227
		type = NULL;
234
		type = NULL;
228
		size = 0;
235
		size = 0;
229
		headers = NULL;
236
		headers = NULL;
230
		f = NULL;
237
		f = NULL;
231
		doc = NULL;
238
		doc = NULL;
232
	}
239
	}
-
 
240
#ifdef _MSC_VER
-
 
241
	sprintf(construct, "%lu", (unsigned long)size);
-
 
242
#else
233
	sprintf(construct, "%llu", (unsigned long long)size);
243
	sprintf(construct, "%llu", (unsigned long long)size);
-
 
244
#endif
234
	tw_write(ssl, sock, "HTTP/1.1 ", 9);
245
	tw_write(ssl, sock, "HTTP/1.1 ", 9);
235
	tw_write(ssl, sock, (char*)status, strlen(status));
246
	tw_write(ssl, sock, (char*)status, strlen(status));
236
	tw_write(ssl, sock, "\r\n", 2);
247
	tw_write(ssl, sock, "\r\n", 2);
237
	if(type != NULL) {
248
	if(type != NULL) {
238
		tw_write(ssl, sock, "Content-Type: ", 7 + 5 + 2);
249
		tw_write(ssl, sock, "Content-Type: ", 7 + 5 + 2);
Line 253... Line 264...
253
			tw_write(ssl, sock, "Last-Modified: ", 5 + 8 + 2);
264
			tw_write(ssl, sock, "Last-Modified: ", 5 + 8 + 2);
254
			tw_write(ssl, sock, date, strlen(date));
265
			tw_write(ssl, sock, date, strlen(date));
255
			tw_write(ssl, sock, "\r\n", 2);
266
			tw_write(ssl, sock, "\r\n", 2);
256
		}
267
		}
257
	}
268
	}
258
	int i;
-
 
259
	if(headers != NULL) {
269
	if(headers != NULL) {
-
 
270
		int i;
260
		for(i = 0; headers[i] != NULL; i += 2) {
271
		for(i = 0; headers[i] != NULL; i += 2) {
261
			tw_write(ssl, sock, headers[i], strlen(headers[i]));
272
			tw_write(ssl, sock, headers[i], strlen(headers[i]));
262
			tw_write(ssl, sock, ": ", 2);
273
			tw_write(ssl, sock, ": ", 2);
263
			tw_write(ssl, sock, headers[i + 1], strlen(headers[i + 1]));
274
			tw_write(ssl, sock, headers[i + 1], strlen(headers[i + 1]));
264
			tw_write(ssl, sock, "\r\n", 2);
275
			tw_write(ssl, sock, "\r\n", 2);
265
		}
276
		}
266
	}
277
	}
267
	tw_write(ssl, sock, "\r\n", 2);
278
	tw_write(ssl, sock, "\r\n", 2);
268
	if(doc == NULL && f == NULL) return;
279
	if(doc == NULL && f == NULL) return;
269
	size_t incr = 0;
280
	incr = 0;
270
	while(1) {
281
	while(1) {
271
		if(f != NULL) {
282
		if(f != NULL) {
272
			char buffer[128];
283
			char buffer[128];
273
			fread(buffer, size < 128 ? size : 128, 1, f);
284
			fread(buffer, size < 128 ? size : 128, 1, f);
274
			tw_write(ssl, sock, buffer, size < 128 ? size : 128);
285
			tw_write(ssl, sock, buffer, size < 128 ? size : 128);
Line 305... Line 316...
305
	}
316
	}
306
}
317
}
307
 
318
 
308
char* tw_http_default_error(int code, char* name, int port, struct tw_config_entry* vhost) {
319
char* tw_http_default_error(int code, char* name, int port, struct tw_config_entry* vhost) {
309
	char address[1024];
320
	char address[1024];
-
 
321
	char* st;
-
 
322
	char* st2;
-
 
323
	char* buffer;
-
 
324
	char* str;
-
 
325
	int i;
310
 
326
 
311
	if((vhost->hideport == -1 ? config.root.hideport : vhost->hideport) == 1) {
327
	if((vhost->hideport == -1 ? config.root.hideport : vhost->hideport) == 1) {
312
		sprintf(address, "<address>%s Server at %s</address>", tw_server, name, port);
328
		sprintf(address, "<address>%s Server at %s</address>", tw_server, name, port);
313
	} else {
329
	} else {
314
		sprintf(address, "<address>%s Server at %s Port %d</address>", tw_server, name, port);
330
		sprintf(address, "<address>%s Server at %s Port %d</address>", tw_server, name, port);
315
	}
331
	}
316
 
332
 
317
	char* st = cm_strdup(tw_http_status(code));
333
	st = cm_strdup(tw_http_status(code));
318
	char* st2;
-
 
319
	int i;
-
 
320
	for(i = 0; st[i] != 0; i++) {
334
	for(i = 0; st[i] != 0; i++) {
321
		if(st[i] == ' ') {
335
		if(st[i] == ' ') {
322
			st2 = cm_strdup(st + i + 1);
336
			st2 = cm_strdup(st + i + 1);
323
			break;
337
			break;
324
		}
338
		}
325
	}
339
	}
326
	char* buffer = malloc(4096);
340
	buffer = malloc(4096);
327
	char* str = cm_strcat3(ERROR_HTML);
341
	str = cm_strcat3(ERROR_HTML);
328
	sprintf(buffer, str, st, st2);
342
	sprintf(buffer, str, st, st2);
329
	free(str);
343
	free(str);
330
	free(st);
344
	free(st);
331
	return buffer;
345
	return buffer;
332
}
346
}
Line 338... Line 352...
338
}
352
}
339
 
353
 
340
void addstring(char** str, const char* add, ...) {
354
void addstring(char** str, const char* add, ...) {
341
	int i;
355
	int i;
342
	char cbuf[2];
356
	char cbuf[2];
343
	cbuf[1] = 0;
-
 
344
	va_list va;
357
	va_list va;
-
 
358
	cbuf[1] = 0;
345
	va_start(va, add);
359
	va_start(va, add);
346
	for(i = 0; add[i] != 0; i++) {
360
	for(i = 0; add[i] != 0; i++) {
347
		cbuf[0] = add[i];
361
		cbuf[0] = add[i];
348
		if(add[i] == '%') {
362
		if(add[i] == '%') {
349
			i++;
363
			i++;
Line 364... Line 378...
364
				free(tmp);
378
				free(tmp);
365
				free(h);
379
				free(h);
366
			} else if(add[i] == 'd') {
380
			} else if(add[i] == 'd') {
367
				int n = va_arg(va, int);
381
				int n = va_arg(va, int);
368
				char* h = malloc(512);
382
				char* h = malloc(512);
369
				sprintf(h, "%d", n);
-
 
370
				char* tmp = *str;
383
				char* tmp = *str;
-
 
384
				sprintf(h, "%d", n);
371
				*str = cm_strcat(tmp, h);
385
				*str = cm_strcat(tmp, h);
372
				free(tmp);
386
				free(tmp);
373
				free(h);
387
				free(h);
374
			} else if(add[i] == '%') {
388
			} else if(add[i] == '%') {
375
				char* tmp = *str;
389
				char* tmp = *str;
Line 385... Line 399...
385
	va_end(va);
399
	va_end(va);
386
}
400
}
387
 
401
 
388
char* tw_get_mime(const char* ext, struct tw_config_entry* vhost_entry) {
402
char* tw_get_mime(const char* ext, struct tw_config_entry* vhost_entry) {
389
	char* mime = "application/octet-stream";
403
	char* mime = "application/octet-stream";
390
	if(ext == NULL) return mime;
-
 
391
	bool set = false;
404
	bool set = false;
392
	int i;
405
	int i;
-
 
406
	if(ext == NULL) return mime;
393
	for(i = 0; i < vhost_entry->mime_count; i++) {
407
	for(i = 0; i < vhost_entry->mime_count; i++) {
394
		if(strcmp(vhost_entry->mimes[i].ext, "all") == 0 || (ext != NULL && tw_wildcard_match(vhost_entry->mimes[i].ext, ext))) {
408
		if(strcmp(vhost_entry->mimes[i].ext, "all") == 0 || (ext != NULL && tw_wildcard_match(vhost_entry->mimes[i].ext, ext))) {
395
			mime = vhost_entry->mimes[i].mime;
409
			mime = vhost_entry->mimes[i].mime;
396
			set = true;
410
			set = true;
397
		}
411
		}
Line 406... Line 420...
406
	return mime;
420
	return mime;
407
}
421
}
408
 
422
 
409
char* tw_get_icon(const char* mime, struct tw_config_entry* vhost_entry) {
423
char* tw_get_icon(const char* mime, struct tw_config_entry* vhost_entry) {
410
	char* icon = "";
424
	char* icon = "";
411
	if(mime == NULL) return "";
-
 
412
	bool set = false;
425
	bool set = false;
413
	int i;
426
	int i;
-
 
427
	if(mime == NULL) return "";
414
	for(i = 0; i < vhost_entry->icon_count; i++) {
428
	for(i = 0; i < vhost_entry->icon_count; i++) {
415
		if(strcmp(vhost_entry->icons[i].mime, "all") == 0 || (mime != NULL && tw_wildcard_match(vhost_entry->icons[i].mime, mime))) {
429
		if(strcmp(vhost_entry->icons[i].mime, "all") == 0 || (mime != NULL && tw_wildcard_match(vhost_entry->icons[i].mime, mime))) {
416
			icon = vhost_entry->icons[i].icon;
430
			icon = vhost_entry->icons[i].icon;
417
			set = true;
431
			set = true;
418
		}
432
		}
Line 432... Line 446...
432
	int port;
446
	int port;
433
	bool ssl;
447
	bool ssl;
434
	SOCKADDR addr;
448
	SOCKADDR addr;
435
};
449
};
436
 
450
 
437
#ifdef __MINGW32__
451
#if defined(__MINGW32__) || defined(_MSC_VER)
438
unsigned int WINAPI tw_server_pass(void* ptr) {
452
unsigned int WINAPI tw_server_pass(void* ptr) {
439
#elif defined(__HAIKU__)
453
#elif defined(__HAIKU__)
440
int32_t tw_server_pass(void* ptr) {
454
int32_t tw_server_pass(void* ptr) {
441
#elif defined(_PSP) || defined(__PPU__)
455
#elif defined(_PSP) || defined(__PPU__)
442
int tw_server_pass(void* ptr) {
456
int tw_server_pass(void* ptr) {
443
#endif
457
#endif
444
#if defined(__HAIKU__) || defined(__MINGW32__) || defined(_PSP) || defined(__PPU__)
458
#if defined(__HAIKU__) || defined(__MINGW32__) || defined(_PSP) || defined(__PPU__) || defined(_MSC_VER)
-
 
459
#define FREE_PTR
445
	int sock = ((struct pass_entry*)ptr)->sock;
460
	int sock = ((struct pass_entry*)ptr)->sock;
446
	bool ssl = ((struct pass_entry*)ptr)->ssl;
461
	bool ssl = ((struct pass_entry*)ptr)->ssl;
447
	int port = ((struct pass_entry*)ptr)->port;
462
	int port = ((struct pass_entry*)ptr)->port;
448
	SOCKADDR addr = ((struct pass_entry*)ptr)->addr;
463
	SOCKADDR addr = ((struct pass_entry*)ptr)->addr;
449
	free(ptr);
-
 
450
#else
464
#else
451
	void tw_server_pass(int sock, bool ssl, int port, SOCKADDR addr) {
465
	void tw_server_pass(int sock, bool ssl, int port, SOCKADDR addr) {
452
#endif
466
#endif
453
	char* name = config.hostname;
467
	SSL* s = NULL;
454
 
-
 
455
#ifndef NO_SSL
468
#ifndef NO_SSL
456
	SSL_CTX* ctx = NULL;
469
	SSL_CTX* ctx = NULL;
457
	SSL* s = NULL;
-
 
458
	bool sslworks = false;
470
	bool sslworks = false;
459
	if(ssl) {
471
	if(ssl) {
460
		ctx = tw_create_ssl_ctx(port);
472
		ctx = tw_create_ssl_ctx(port);
461
		s = SSL_new(ctx);
473
		s = SSL_new(ctx);
462
		SSL_set_fd(s, sock);
474
		SSL_set_fd(s, sock);
463
		if(SSL_accept(s) <= 0) goto cleanup;
475
		if(SSL_accept(s) <= 0) goto cleanup;
464
		sslworks = true;
476
		sslworks = true;
465
	}
477
	}
466
#else
-
 
467
		void* s = NULL;
-
 
468
#endif
478
#endif
469
 
-
 
-
 
479
	char* name = config.hostname;
470
	char address[513];
480
	char address[513];
471
	address[0] = 0;
481
	int ret;
-
 
482
	struct tw_http_request req;
-
 
483
	struct tw_http_response res;
-
 
484
	struct tw_tool tools;
472
#ifndef NO_GETADDRINFO
485
#ifndef NO_GETADDRINFO
473
	struct sockaddr* sa = (struct sockaddr*)&addr;
486
	struct sockaddr* sa = (struct sockaddr*)&addr;
474
	getnameinfo(sa, sizeof(addr), address, 512, NULL, 0, NI_NUMERICHOST);
487
	getnameinfo(sa, sizeof(addr), address, 512, NULL, 0, NI_NUMERICHOST);
475
#endif
488
#endif
-
 
489
	address[0] = 0;
-
 
490
#ifdef FREE_PTR
-
 
491
	free(ptr);
-
 
492
#endif
476
 
493
 
477
	struct tw_http_request req;
-
 
478
	struct tw_http_response res;
-
 
479
	struct tw_tool tools;
-
 
480
	res._processed = false;
494
	res._processed = false;
481
	tw_init_tools(&tools);
495
	tw_init_tools(&tools);
482
	int ret = tw_http_parse(s, sock, &req);
496
	ret = tw_http_parse(s, sock, &req);
483
	if(ret == 0) {
497
	if(ret == 0) {
484
		char date[513];
498
		char date[513];
485
		time_t t = time(NULL);
499
		time_t t = time(NULL);
486
		struct tm* tm = localtime(&t);
500
		struct tm* tm = localtime(&t);
487
		strftime(date, 512, "%a, %d %b %Y %H:%M:%S %Z", tm);
-
 
488
 
-
 
489
		char* useragent = cm_strdup("");
501
		char* useragent = cm_strdup("");
490
 
-
 
491
		int i;
502
		int i;
-
 
503
		char* tmp;
-
 
504
		char* tmp2;
-
 
505
		char* tmp3;
-
 
506
		char* tmp4;
-
 
507
		char* tmp5;
-
 
508
		char* log;
-
 
509
		char* vhost;
-
 
510
		time_t cmtime;
-
 
511
		bool rej;
-
 
512
		char* host;
-
 
513
		int port;
-
 
514
		struct tw_config_entry* vhost_entry;
-
 
515
		strftime(date, 512, "%a, %d %b %Y %H:%M:%S %Z", tm);
-
 
516
 
492
		for(i = 0; req.headers[i] != NULL; i += 2) {
517
		for(i = 0; req.headers[i] != NULL; i += 2) {
493
			if(cm_strcaseequ(req.headers[i], "User-Agent")) {
518
			if(cm_strcaseequ(req.headers[i], "User-Agent")) {
494
				free(useragent);
519
				free(useragent);
495
				useragent = cm_strdup(req.headers[i + 1]);
520
				useragent = cm_strdup(req.headers[i + 1]);
496
			}
521
			}
497
		}
522
		}
498
 
523
 
499
		char* tmp = cm_strcat3(address, " - [", date);
524
		tmp = cm_strcat3(address, " - [", date);
500
		char* tmp2 = cm_strcat3(tmp, "] \"", req.method);
525
		tmp2 = cm_strcat3(tmp, "] \"", req.method);
501
		char* tmp3 = cm_strcat3(tmp2, " ", req.path);
526
		tmp3 = cm_strcat3(tmp2, " ", req.path);
502
		char* tmp4 = cm_strcat3(tmp3, " ", req.version);
527
		tmp4 = cm_strcat3(tmp3, " ", req.version);
503
		char* tmp5 = cm_strcat3(tmp4, "\" \"", useragent);
528
		tmp5 = cm_strcat3(tmp4, "\" \"", useragent);
504
		char* log = cm_strcat(tmp5, "\"");
529
		log = cm_strcat(tmp5, "\"");
505
		free(tmp);
530
		free(tmp);
506
		free(tmp2);
531
		free(tmp2);
507
		free(tmp3);
532
		free(tmp3);
508
		free(tmp4);
533
		free(tmp4);
509
		free(tmp5);
534
		free(tmp5);
510
		free(useragent);
535
		free(useragent);
511
		cm_force_log(log);
536
		cm_force_log(log);
512
		free(log);
537
		free(log);
513
 
538
 
514
		char* vhost = cm_strdup(config.hostname);
539
		vhost = cm_strdup(config.hostname);
515
		time_t cmtime = 0;
540
		cmtime = 0;
516
		if(req.headers != NULL) {
541
		if(req.headers != NULL) {
517
			for(i = 0; req.headers[i] != NULL; i += 2) {
542
			for(i = 0; req.headers[i] != NULL; i += 2) {
518
				if(cm_strcaseequ(req.headers[i], "Host")) {
543
				if(cm_strcaseequ(req.headers[i], "Host")) {
519
					free(vhost);
544
					free(vhost);
520
					vhost = cm_strdup(req.headers[i + 1]);
545
					vhost = cm_strdup(req.headers[i + 1]);
521
				} else if(cm_strcaseequ(req.headers[i], "If-Modified-Since")) {
546
				} else if(cm_strcaseequ(req.headers[i], "If-Modified-Since")) {
522
					struct tm tm;
547
					struct tm tm;
-
 
548
					time_t t;
-
 
549
					struct tm* btm;
523
					strptime(req.headers[i + 1], "%a, %d %b %Y %H:%M:%S GMT", &tm);
550
					strptime(req.headers[i + 1], "%a, %d %b %Y %H:%M:%S GMT", &tm);
524
#if defined(__MINGW32__) || defined(_PSP) || defined(__PPU__) || defined(__ps2sdk__)
551
#if defined(__MINGW32__) || defined(_PSP) || defined(__PPU__) || defined(__ps2sdk__) || defined(_MSC_VER)
525
					time_t t = 0;
552
					t = 0;
526
					struct tm* btm = localtime(&t);
553
					btm = localtime(&t);
527
					cmtime = mktime(&tm);
554
					cmtime = mktime(&tm);
528
					cmtime -= (btm->tm_hour * 60 + btm->tm_min) * 60;
555
					cmtime -= (btm->tm_hour * 60 + btm->tm_min) * 60;
529
#else
556
#else
530
						cmtime = timegm(&tm);
557
						cmtime = timegm(&tm);
531
#endif
558
#endif
532
				}
559
				}
533
			}
560
			}
534
		}
561
		}
535
		bool rej = false;
562
		rej = false;
536
		cm_log("Server", "Host is %s", vhost);
563
		cm_log("Server", "Host is %s", vhost);
537
		int port = s == NULL ? 80 : 443;
564
		port = s == NULL ? 80 : 443;
538
		char* host = cm_strdup(vhost);
565
		host = cm_strdup(vhost);
539
		for(i = 0; vhost[i] != 0; i++) {
566
		for(i = 0; vhost[i] != 0; i++) {
540
			if(vhost[i] == ':') {
567
			if(vhost[i] == ':') {
541
				host[i] = 0;
568
				host[i] = 0;
542
				port = atoi(host + i + 1);
569
				port = atoi(host + i + 1);
543
				break;
570
				break;
544
			}
571
			}
545
		}
572
		}
546
		name = host;
573
		name = host;
547
		cm_log("Server", "Hostname is `%s', port is `%d'", host, port);
574
		cm_log("Server", "Hostname is `%s', port is `%d'", host, port);
548
		struct tw_config_entry* vhost_entry = tw_vhost_match(host, port);
575
		vhost_entry = tw_vhost_match(host, port);
549
#ifdef HAS_CHROOT
576
#ifdef HAS_CHROOT
550
		char* chrootpath = vhost_entry->chroot_path != NULL ? vhost_entry->chroot_path : config.root.chroot_path;
577
		char* chrootpath = vhost_entry->chroot_path != NULL ? vhost_entry->chroot_path : config.root.chroot_path;
551
		if(chrootpath != NULL) {
578
		if(chrootpath != NULL) {
552
			if(chdir(chrootpath) == 0) {
579
			if(chdir(chrootpath) == 0) {
553
				if(chroot(".") == 0) {
580
				if(chroot(".") == 0) {
Line 579... Line 606...
579
					break;
606
					break;
580
				}
607
				}
581
			}
608
			}
582
		}
609
		}
583
		if(!res._processed) {
610
		if(!res._processed) {
-
 
611
			char* path;
-
 
612
			char* rpath;
-
 
613
			struct stat st;
584
			cm_log("Server", "Document root is %s", vhost_entry->root == NULL ? "not set" : vhost_entry->root);
614
			cm_log("Server", "Document root is %s", vhost_entry->root == NULL ? "not set" : vhost_entry->root);
585
			char* path = cm_strcat(vhost_entry->root == NULL ? "" : vhost_entry->root, req.path);
615
			path = cm_strcat(vhost_entry->root == NULL ? "" : vhost_entry->root, req.path);
586
			cm_log("Server", "Filesystem path is %s", path);
616
			cm_log("Server", "Filesystem path is %s", path);
587
#ifdef __MINGW32__
617
#if defined(__MINGW32__) || defined(_MSC_VER)
588
			char* rpath = cm_strdup(path);
618
			rpath = cm_strdup(path);
589
			for(i = strlen(rpath) - 1; i >= 0; i--) {
619
			for(i = strlen(rpath) - 1; i >= 0; i--) {
590
				if(rpath[i] == '/') {
620
				if(rpath[i] == '/') {
591
					int j;
621
					int j;
592
					for(j = i + 1; rpath[j] != 0; j++) {
622
					for(j = i + 1; rpath[j] != 0; j++) {
593
						if(rpath[j] == ':' || rpath[j] == '.') {
623
						if(rpath[j] == ':' || rpath[j] == '.') {
Line 609... Line 639...
609
				}
639
				}
610
				free(n);
640
				free(n);
611
			}
641
			}
612
			free(rpath);
642
			free(rpath);
613
#endif
643
#endif
614
			struct stat st;
-
 
615
			if(!rej && stat(path, &st) == 0) {
644
			if(!rej && stat(path, &st) == 0) {
616
				if(!tw_permission_allowed(path, addr, req, vhost_entry)) {
645
				if(!tw_permission_allowed(path, addr, req, vhost_entry)) {
617
					tw_http_error(s, sock, 403, name, port, vhost_entry);
646
					tw_http_error(s, sock, 403, name, port, vhost_entry);
618
				} else if(S_ISDIR(st.st_mode)) {
647
				} else if(S_ISDIR(st.st_mode)) {
619
					if(req.path[strlen(req.path) - 1] != '/') {
648
					if(req.path[strlen(req.path) - 1] != '/') {
620
						cm_log("Server", "Accessing directory without the slash at the end");
-
 
621
						char* headers[3] = {"Location", cm_strcat(req.path, "/"), NULL};
649
						char* headers[3] = {"Location", cm_strcat(req.path, "/"), NULL};
-
 
650
						cm_log("Server", "Accessing directory without the slash at the end");
622
						_tw_process_page(s, sock, tw_http_status(301), NULL, NULL, NULL, 0, headers, 0, 0);
651
						_tw_process_page(s, sock, tw_http_status(301), NULL, NULL, NULL, 0, headers, 0, 0);
623
						free(headers[1]);
652
						free(headers[1]);
624
					} else {
653
					} else {
625
						char** indexes = vhost_entry->index_count == 0 ? config.root.indexes : vhost_entry->indexes;
654
						char** indexes = vhost_entry->index_count == 0 ? config.root.indexes : vhost_entry->indexes;
626
						int index_count = vhost_entry->index_count == 0 ? config.root.index_count : vhost_entry->index_count;
655
						int index_count = vhost_entry->index_count == 0 ? config.root.index_count : vhost_entry->index_count;
Line 629... Line 658...
629
							char* p = cm_strcat3(path, "/", indexes[i]);
658
							char* p = cm_strcat3(path, "/", indexes[i]);
630
							FILE* f = fopen(p, "rb");
659
							FILE* f = fopen(p, "rb");
631
							if(f != NULL) {
660
							if(f != NULL) {
632
								char* ext = NULL;
661
								char* ext = NULL;
633
								int j;
662
								int j;
-
 
663
								struct stat st;
-
 
664
								char* mime;
634
								for(j = strlen(p) - 1; j >= 0; j--) {
665
								for(j = strlen(p) - 1; j >= 0; j--) {
635
									if(p[j] == '.') {
666
									if(p[j] == '.') {
636
										ext = cm_strdup(p + j);
667
										ext = cm_strdup(p + j);
637
										break;
668
										break;
638
									} else if(p[j] == '/') {
669
									} else if(p[j] == '/') {
639
										break;
670
										break;
640
									}
671
									}
641
								}
672
								}
642
								struct stat st;
-
 
643
								stat(p, &st);
673
								stat(p, &st);
644
								char* mime = tw_get_mime(ext, vhost_entry);
674
								mime = tw_get_mime(ext, vhost_entry);
645
								tw_process_page(s, sock, tw_http_status(200), mime, f, NULL, st.st_size, 0, 0);
675
								tw_process_page(s, sock, tw_http_status(200), mime, f, NULL, st.st_size, 0, 0);
646
								fclose(f);
676
								fclose(f);
647
								if(ext != NULL) free(ext);
677
								if(ext != NULL) free(ext);
648
								free(p);
678
								free(p);
649
								found = true;
679
								found = true;
Line 651... Line 681...
651
							}
681
							}
652
							free(p);
682
							free(p);
653
						}
683
						}
654
						if(!found) {
684
						if(!found) {
655
							char* str = malloc(1);
685
							char* str = malloc(1);
-
 
686
							char** items;
-
 
687
							int readme;
-
 
688
							char** readmes;
-
 
689
							int readme_count;
-
 
690
							int hp;
656
							str[0] = 0;
691
							str[0] = 0;
657
							char** items = cm_scandir(path);
692
							items = cm_scandir(path);
658
							addstring(&str, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n");
693
							addstring(&str, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n");
659
							addstring(&str, "<html>\n");
694
							addstring(&str, "<html>\n");
660
							addstring(&str, "	<head>\n");
695
							addstring(&str, "	<head>\n");
661
							addstring(&str, "		<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
696
							addstring(&str, "		<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
662
							addstring(&str, "		<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n");
697
							addstring(&str, "		<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n");
Line 670... Line 705...
670
							addstring(&str, "				<th></th>\n");
705
							addstring(&str, "				<th></th>\n");
671
							addstring(&str, "				<th>Filename</th>\n");
706
							addstring(&str, "				<th>Filename</th>\n");
672
							addstring(&str, "				<th>MIME</th>\n");
707
							addstring(&str, "				<th>MIME</th>\n");
673
							addstring(&str, "				<th>Size</th>\n");
708
							addstring(&str, "				<th>Size</th>\n");
674
							addstring(&str, "			</tr>\n");
709
							addstring(&str, "			</tr>\n");
675
							int readme = -1;
710
							readme = -1;
676
							char** readmes = vhost_entry->readme_count == 0 ? config.root.readmes : vhost_entry->readmes;
711
							readmes = vhost_entry->readme_count == 0 ? config.root.readmes : vhost_entry->readmes;
677
							int readme_count = vhost_entry->readme_count == 0 ? config.root.readme_count : vhost_entry->readme_count;
712
							readme_count = vhost_entry->readme_count == 0 ? config.root.readme_count : vhost_entry->readme_count;
678
							if(items != NULL) {
713
							if(items != NULL) {
679
								int phase = 0;
714
								int phase = 0;
680
							doit:
715
							doit:
681
								for(i = 0; items[i] != NULL; i++) {
716
								for(i = 0; items[i] != NULL; i++) {
682
									int j;
717
									int j;
-
 
718
									char* ext;
-
 
719
									char* itm;
-
 
720
									char* icon;
683
									char* fpth = cm_strcat3(path, "/", items[i]);
721
									char* fpth = cm_strcat3(path, "/", items[i]);
684
									struct stat s;
722
									struct stat s;
685
									char size[512];
723
									char size[512];
-
 
724
									char* showmime;
-
 
725
									char* mime;
686
									size[0] = 0;
726
									size[0] = 0;
687
									stat(fpth, &s);
727
									stat(fpth, &s);
688
									if(phase == 0 && !S_ISDIR(s.st_mode)) {
728
									if(phase == 0 && !S_ISDIR(s.st_mode)) {
689
										free(fpth);
729
										free(fpth);
690
										continue;
730
										continue;
Line 702... Line 742...
702
										if(readme != -1) {
742
										if(readme != -1) {
703
											free(fpth);
743
											free(fpth);
704
											continue;
744
											continue;
705
										}
745
										}
706
									}
746
									}
707
									if(s.st_size < 1024ULL) {
747
									if(s.st_size < NUM1024) {
708
										sprintf(size, "%d", (int)s.st_size);
748
										sprintf(size, "%d", (int)s.st_size);
709
									} else if(s.st_size < 1024ULL * 1024) {
749
									} else if(s.st_size < NUM1024 * 1024) {
710
										sprintf(size, "%.1fK", (double)s.st_size / 1024);
750
										sprintf(size, "%.1fK", (double)s.st_size / 1024);
711
									} else if(s.st_size < 1024ULL * 1024 * 1024) {
751
									} else if(s.st_size < NUM1024 * 1024 * 1024) {
712
										sprintf(size, "%.1fM", (double)s.st_size / 1024 / 1024);
752
										sprintf(size, "%.1fM", (double)s.st_size / 1024 / 1024);
713
									} else if(s.st_size < 1024ULL * 1024 * 1024 * 1024) {
753
									} else if(s.st_size < NUM1024 * 1024 * 1024 * 1024) {
714
										sprintf(size, "%.1fG", (double)s.st_size / 1024 / 1024 / 1024);
754
										sprintf(size, "%.1fG", (double)s.st_size / 1024 / 1024 / 1024);
715
									} else if(s.st_size < 1024ULL * 1024 * 1024 * 1024 * 1024) {
755
									} else if(s.st_size < NUM1024 * 1024 * 1024 * 1024 * 1024) {
716
										sprintf(size, "%.1fT", (double)s.st_size / 1024 / 1024 / 1024 / 1024);
756
										sprintf(size, "%.1fT", (double)s.st_size / 1024 / 1024 / 1024 / 1024);
717
									}
757
									}
718
 
758
 
719
									free(fpth);
759
									free(fpth);
720
 
760
 
721
									char* ext = NULL;
761
									ext = NULL;
722
									for(j = strlen(items[i]) - 1; j >= 0; j--) {
762
									for(j = strlen(items[i]) - 1; j >= 0; j--) {
723
										if(items[i][j] == '.') {
763
										if(items[i][j] == '.') {
724
											ext = cm_strdup(items[i] + j);
764
											ext = cm_strdup(items[i] + j);
725
											break;
765
											break;
726
										} else if(items[i][j] == '/') {
766
										} else if(items[i][j] == '/') {
727
											break;
767
											break;
728
										}
768
										}
729
									}
769
									}
730
									char* showmime = "";
770
									showmime = "";
731
									char* mime = tw_get_mime(ext, vhost_entry);
771
									mime = tw_get_mime(ext, vhost_entry);
732
									if(strcmp(items[i], "../") == 0) {
772
									if(strcmp(items[i], "../") == 0) {
733
										mime = "misc/parent";
773
										mime = "misc/parent";
734
										size[0] = 0;
774
										size[0] = 0;
735
									} else if(items[i][strlen(items[i]) - 1] == '/') {
775
									} else if(items[i][strlen(items[i]) - 1] == '/') {
736
										mime = "misc/dir";
776
										mime = "misc/dir";
737
										size[0] = 0;
777
										size[0] = 0;
738
									} else {
778
									} else {
739
										showmime = mime;
779
										showmime = mime;
740
									}
780
									}
741
									char* icon = tw_get_icon(mime, vhost_entry);
781
									icon = tw_get_icon(mime, vhost_entry);
742
									if(ext != NULL) free(ext);
782
									if(ext != NULL) free(ext);
743
									char* itm = cm_strdup(items[i]);
783
									itm = cm_strdup(items[i]);
744
									if(strlen(itm) >= 32) {
784
									if(strlen(itm) >= 32) {
745
										if(itm[strlen(itm) - 1] == '/') {
785
										if(itm[strlen(itm) - 1] == '/') {
746
											itm[31] = 0;
786
											itm[31] = 0;
747
											itm[30] = '/';
787
											itm[30] = '/';
748
											itm[29] = '.';
788
											itm[29] = '.';
Line 768... Line 808...
768
								for(i = 0; items[i] != NULL; i++) free(items[i]);
808
								for(i = 0; items[i] != NULL; i++) free(items[i]);
769
								free(items);
809
								free(items);
770
							}
810
							}
771
							addstring(&str, "		</table>\n");
811
							addstring(&str, "		</table>\n");
772
							if(readme != -1) {
812
							if(readme != -1) {
773
								addstring(&str, "<hr>\n");
-
 
774
								char* fpth = cm_strcat3(path, "/", readmes[readme]);
-
 
775
								struct stat s;
813
								struct stat s;
-
 
814
								FILE* fr;
-
 
815
								char* fpth;
-
 
816
								addstring(&str, "<hr>\n");
-
 
817
								fpth = cm_strcat3(path, "/", readmes[readme]);
776
								stat(fpth, &s);
818
								stat(fpth, &s);
777
								FILE* fr = fopen(fpth, "r");
819
								fr = fopen(fpth, "r");
778
								if(fr != NULL) {
820
								if(fr != NULL) {
779
									char* rmbuf = malloc(s.st_size + 1);
821
									char* rmbuf = malloc(s.st_size + 1);
780
									rmbuf[s.st_size] = 0;
822
									rmbuf[s.st_size] = 0;
781
									fread(rmbuf, s.st_size, 1, fr);
823
									fread(rmbuf, s.st_size, 1, fr);
782
									addstring(&str, "<pre><code>%h</code></pre>\n", rmbuf);
824
									addstring(&str, "<pre><code>%h</code></pre>\n", rmbuf);
Line 784... Line 826...
784
									free(rmbuf);
826
									free(rmbuf);
785
								}
827
								}
786
								free(fpth);
828
								free(fpth);
787
							}
829
							}
788
							addstring(&str, "		<hr>\n");
830
							addstring(&str, "		<hr>\n");
789
							int hp = vhost_entry->hideport == -1 ? config.root.hideport : vhost_entry->hideport;
831
							hp = vhost_entry->hideport == -1 ? config.root.hideport : vhost_entry->hideport;
790
							if(hp == 0) {
832
							if(hp == 0) {
791
								addstring(&str, "		<address>%s Server at %s Port %d</address>\n", tw_server, name, port);
833
								addstring(&str, "		<address>%s Server at %s Port %d</address>\n", tw_server, name, port);
792
							} else {
834
							} else {
793
								addstring(&str, "		<address>%s Server at %s</address>\n", tw_server, name, port);
835
								addstring(&str, "		<address>%s Server at %s</address>\n", tw_server, name, port);
794
							}
836
							}
Line 798... Line 840...
798
							free(str);
840
							free(str);
799
						}
841
						}
800
					}
842
					}
801
				} else {
843
				} else {
802
					char* ext = NULL;
844
					char* ext = NULL;
-
 
845
					char* mime;
-
 
846
					FILE* f;
803
					for(i = strlen(req.path) - 1; i >= 0; i--) {
847
					for(i = strlen(req.path) - 1; i >= 0; i--) {
804
						if(req.path[i] == '.') {
848
						if(req.path[i] == '.') {
805
							ext = cm_strdup(req.path + i);
849
							ext = cm_strdup(req.path + i);
806
							break;
850
							break;
807
						} else if(req.path[i] == '/') {
851
						} else if(req.path[i] == '/') {
808
							break;
852
							break;
809
						}
853
						}
810
					}
854
					}
811
					char* mime = tw_get_mime(ext, vhost_entry);
855
					mime = tw_get_mime(ext, vhost_entry);
812
					if(ext != NULL) free(ext);
856
					if(ext != NULL) free(ext);
813
					FILE* f = fopen(path, "rb");
857
					f = fopen(path, "rb");
814
					if(f == NULL) {
858
					if(f == NULL) {
815
						tw_http_error(s, sock, 403, name, port, vhost_entry);
859
						tw_http_error(s, sock, 403, name, port, vhost_entry);
816
					} else {
860
					} else {
817
						tw_process_page(s, sock, tw_http_status(200), mime, f, NULL, st.st_size, st.st_mtime, cmtime);
861
						tw_process_page(s, sock, tw_http_status(200), mime, f, NULL, st.st_size, st.st_mtime, cmtime);
818
						fclose(f);
862
						fclose(f);
Line 838... Line 882...
838
		SSL_shutdown(s);
882
		SSL_shutdown(s);
839
	}
883
	}
840
	SSL_free(s);
884
	SSL_free(s);
841
#endif
885
#endif
842
	close_socket(sock);
886
	close_socket(sock);
843
#ifdef __MINGW32__
887
#if defined(__MINGW32__) || defined(_MSC_VER)
844
	_endthreadex(0);
888
	_endthread(0);
845
#elif defined(__HAIKU__)
889
#elif defined(__HAIKU__)
846
		exit_thread(0);
890
		exit_thread(0);
847
#endif
891
#endif
848
	;
892
	;
849
}
893
}
Line 851... Line 895...
851
#ifdef SERVICE
895
#ifdef SERVICE
852
extern SERVICE_STATUS status;
896
extern SERVICE_STATUS status;
853
extern SERVICE_STATUS_HANDLE status_handle;
897
extern SERVICE_STATUS_HANDLE status_handle;
854
#endif
898
#endif
855
 
899
 
856
#if defined(__MINGW32__) || defined(__HAIKU__)
900
#if defined(__MINGW32__) || defined(__HAIKU__) || defined(_MSC_VER)
857
struct thread_entry {
901
struct thread_entry {
858
#ifdef __HAIKU__
902
#ifdef __HAIKU__
859
	thread_id thread;
903
	thread_id thread;
860
#else
904
#else
861
	HANDLE handle;
905
	HANDLE handle;
Line 866... Line 910...
866
 
910
 
867
extern int running;
911
extern int running;
868
 
912
 
869
void tw_server_loop(void) {
913
void tw_server_loop(void) {
870
	int i;
914
	int i;
-
 
915
#ifndef USE_POLL
-
 
916
		fd_set fdset;
-
 
917
		struct timeval tv;
-
 
918
#endif
871
#if defined(__MINGW32__) || defined(__HAIKU__)
919
#if defined(__MINGW32__) || defined(__HAIKU__) || defined(_MSC_VER)
872
	struct thread_entry threads[2048];
920
	struct thread_entry threads[2048];
873
	for(i = 0; i < sizeof(threads) / sizeof(threads[0]); i++) {
921
	for(i = 0; i < sizeof(threads) / sizeof(threads[0]); i++) {
874
		threads[i].used = false;
922
		threads[i].used = false;
875
	}
923
	}
876
#endif
924
#endif
Line 878... Line 926...
878
	struct pollfd pollfds[sockcount];
926
	struct pollfd pollfds[sockcount];
879
	for(i = 0; i < sockcount; i++) {
927
	for(i = 0; i < sockcount; i++) {
880
		pollfds[i].fd = sockets[i];
928
		pollfds[i].fd = sockets[i];
881
		pollfds[i].events = POLLIN | POLLPRI;
929
		pollfds[i].events = POLLIN | POLLPRI;
882
	}
930
	}
883
#else
-
 
884
		fd_set fdset;
-
 
885
		struct timeval tv;
-
 
886
#endif
931
#endif
887
	while(running) {
932
	while(running) {
-
 
933
		int ret;
888
#ifdef USE_POLL
934
#ifdef USE_POLL
889
		int ret = poll(pollfds, sockcount, 1000);
935
		ret = poll(pollfds, sockcount, 1000);
890
#else
936
#else
891
			FD_ZERO(&fdset);
937
			FD_ZERO(&fdset);
892
			for(i = 0; i < sockcount; i++) {
938
			for(i = 0; i < sockcount; i++) {
893
				FD_SET(sockets[i], &fdset);
939
				FD_SET(sockets[i], &fdset);
894
			}
940
			}
895
			tv.tv_sec = 1;
941
			tv.tv_sec = 1;
896
			tv.tv_usec = 0;
942
			tv.tv_usec = 0;
897
#ifdef __HAIKU__
943
#ifdef __HAIKU__
898
			int ret = select(32, &fdset, NULL, NULL, &tv);
944
			ret = select(32, &fdset, NULL, NULL, &tv);
899
#else
945
#else
900
			int ret = select(FD_SETSIZE, &fdset, NULL, NULL, &tv);
946
			ret = select(FD_SETSIZE, &fdset, NULL, NULL, &tv);
901
#endif
947
#endif
902
#endif
948
#endif
903
		if(ret == -1) {
949
		if(ret == -1) {
904
#ifndef __MINGW32__
950
#if !defined(__MINGW32__) && !defined(_MSC_VER)
905
			cm_log("Server", "Select failure: %s", strerror(errno));
951
			cm_log("Server", "Select failure: %s", strerror(errno));
906
#endif
952
#endif
907
			break;
953
			break;
908
		} else if(ret == 0) {
954
		} else if(ret == 0) {
909
#ifdef SERVICE
955
#ifdef SERVICE
Line 923... Line 969...
923
#endif
969
#endif
924
				if(cond) {
970
				if(cond) {
925
					SOCKADDR claddr;
971
					SOCKADDR claddr;
926
					socklen_t clen = sizeof(claddr);
972
					socklen_t clen = sizeof(claddr);
927
					int sock = accept(sockets[i], (struct sockaddr*)&claddr, &clen);
973
					int sock = accept(sockets[i], (struct sockaddr*)&claddr, &clen);
928
					cm_log("Server", "New connection accepted");
-
 
929
#if defined(__MINGW32__) || defined(__HAIKU__) || defined(_PSP) || defined(__PPU__)
974
#if defined(__MINGW32__) || defined(__HAIKU__) || defined(_PSP) || defined(__PPU__) || defined(_MSC_VER)
-
 
975
					int j;
930
					struct pass_entry* e = malloc(sizeof(*e));
976
					struct pass_entry* e = malloc(sizeof(*e));
-
 
977
					cm_log("Server", "New connection accepted");
931
					e->sock = sock;
978
					e->sock = sock;
-
 
979
#ifdef _MSC_VER
-
 
980
					e->ssl = config.ports[i] & (1UL << 31);
-
 
981
#else
932
					e->ssl = config.ports[i] & (1ULL << 32);
982
					e->ssl = config.ports[i] & (1ULL << 31);
-
 
983
#endif
933
					e->port = config.ports[i];
984
					e->port = config.ports[i];
934
					e->addr = claddr;
985
					e->addr = claddr;
935
#endif
986
#endif
936
#ifdef __MINGW32__
987
#if defined(__MINGW32__) || defined(_MSC_VER)
937
					int j;
-
 
938
					for(j = 0; j < sizeof(threads) / sizeof(threads[0]); j++) {
-
 
939
						if(threads[j].used) {
-
 
940
							DWORD ex;
-
 
941
							GetExitCodeThread(threads[j].handle, &ex);
988
					_beginthread(tw_server_pass, 0, e);
942
							if(ex != STILL_ACTIVE) {
-
 
943
								CloseHandle(threads[j].handle);
-
 
944
								threads[j].used = false;
-
 
945
							}
-
 
946
						}
-
 
947
					}
-
 
948
					for(j = 0; j < sizeof(threads) / sizeof(threads[0]); j++) {
-
 
949
						if(!threads[j].used) {
-
 
950
							threads[j].handle = (HANDLE)_beginthreadex(NULL, 0, tw_server_pass, e, 0, NULL);
-
 
951
							threads[j].used = true;
-
 
952
							break;
-
 
953
						}
-
 
954
					}
-
 
955
#elif defined(_PSP) || defined(__PPU__)
989
#elif defined(_PSP) || defined(__PPU__)
956
						tw_server_pass(e);
990
						tw_server_pass(e);
957
#elif defined(__HAIKU__)
991
#elif defined(__HAIKU__)
958
					int j;
-
 
959
					for(j = 0; j < sizeof(threads) / sizeof(threads[0]); j++) {
992
					for(j = 0; j < sizeof(threads) / sizeof(threads[0]); j++) {
960
						if(threads[j].used) {
993
						if(threads[j].used) {
961
							thread_info info;
994
							thread_info info;
962
							bool kill = false;
995
							bool kill = false;
963
							if(get_thread_info(threads[j].thread, &info) == B_OK) {
996
							if(get_thread_info(threads[j].thread, &info) == B_OK) {
Line 980... Line 1013...
980
#else
1013
#else
981
					pid_t pid = fork();
1014
					pid_t pid = fork();
982
					if(pid == 0) {
1015
					if(pid == 0) {
983
						int j;
1016
						int j;
984
						for(j = 0; j < sockcount; j++) close_socket(sockets[j]);
1017
						for(j = 0; j < sockcount; j++) close_socket(sockets[j]);
985
						tw_server_pass(sock, config.ports[i] & (1ULL << 32), config.ports[i], claddr);
1018
						tw_server_pass(sock, config.ports[i] & (1ULL << 31), config.ports[i], claddr);
986
						_exit(0);
1019
						_exit(0);
987
					} else {
1020
					} else {
988
						close_socket(sock);
1021
						close_socket(sock);
989
					}
1022
					}
990
#endif
1023
#endif