Browse Source

Port web server code from mptsd

Georgi Chorbadzhiyski 7 years ago
parent
commit
217cae29b8
7 changed files with 377 additions and 89 deletions
  1. 1
    1
      Makefile
  2. 50
    0
      config.h
  3. 92
    88
      tomcast.c
  4. 45
    0
      web_pages.c
  5. 24
    0
      web_pages.h
  6. 139
    0
      web_server.c
  7. 26
    0
      web_server.h

+ 1
- 1
Makefile View File

9
 FUNCS_DIR = libfuncs
9
 FUNCS_DIR = libfuncs
10
 FUNCS_LIB = $(FUNCS_DIR)/libfuncs.a
10
 FUNCS_LIB = $(FUNCS_DIR)/libfuncs.a
11
 
11
 
12
-tomcast_OBJS =  tomcast.o $(FUNCS_LIB)
12
+tomcast_OBJS =  tomcast.o web_pages.o web_server.o $(FUNCS_LIB)
13
 
13
 
14
 all: tomcast
14
 all: tomcast
15
 
15
 

+ 50
- 0
config.h View File

1
+/*
2
+ * mptsd configuration header file
3
+ * Copyright (C) 2010-2011 Unix Solutions Ltd.
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2
7
+ * as published by the Free Software Foundation.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
17
+ */
18
+#ifndef CONFIG_H
19
+#define CONFIG_H
20
+
21
+#include <pthread.h>
22
+#include <arpa/inet.h>
23
+#include <netinet/in.h>
24
+
25
+#include "libfuncs/libfuncs.h"
26
+
27
+struct config {
28
+	char				*ident;
29
+	char				*pidfile;
30
+
31
+	int					syslog_active;
32
+	char				*logident;
33
+	char				*loghost;
34
+	int					logport;
35
+
36
+	struct sockaddr_in	server;
37
+	char				*server_addr;
38
+	int					server_port;
39
+	int					server_socket;
40
+	pthread_t			server_thread;
41
+
42
+	char				*channels_file;
43
+
44
+	LIST				*chanconf;
45
+	LIST				*restreamer;
46
+
47
+	pthread_mutex_t		channels_lock;
48
+};
49
+
50
+#endif

+ 92
- 88
tomcast.c View File

31
 #include <netdb.h> // for uint32_t
31
 #include <netdb.h> // for uint32_t
32
 
32
 
33
 #include "libfuncs/libfuncs.h"
33
 #include "libfuncs/libfuncs.h"
34
+#include "config.h"
35
+
36
+#include "web_server.h"
34
 
37
 
35
 #define DNS_RESOLVER_TIMEOUT 5000
38
 #define DNS_RESOLVER_TIMEOUT 5000
36
 
39
 
105
 	pthread_t thread;
108
 	pthread_t thread;
106
 } RESTREAMER;
109
 } RESTREAMER;
107
 
110
 
111
+static struct config config;
112
+
108
 channel_source get_sproto(char *url) {
113
 channel_source get_sproto(char *url) {
109
 	return strncmp(url, "http", 4)==0 ? tcp_sock : udp_sock;
114
 	return strncmp(url, "http", 4)==0 ? tcp_sock : udp_sock;
110
 }
115
 }
288
 	FREE(r);
293
 	FREE(r);
289
 }
294
 }
290
 
295
 
291
-
292
-
293
-
294
-char *pidfile = NULL;
295
-char *ident = NULL;
296
-char *logident = NULL;
297
-char *loghost = NULL;
298
-int logport = 514;
299
-
300
-char *channels_file = NULL;
301
-int syslog_active = 0;
302
-
303
 char TS_NULL_FRAME[FRAME_PACKET_SIZE];
296
 char TS_NULL_FRAME[FRAME_PACKET_SIZE];
304
 
297
 
305
 regex_t http_response;
298
 regex_t http_response;
306
 
299
 
307
-LIST *chanconf = NULL;
308
-LIST *restreamer = NULL;
309
-
310
-static pthread_mutex_t channels_lock = PTHREAD_MUTEX_INITIALIZER;
311
-
312
 void proxy_log(RESTREAMER *r, char *msg, char *info) {
300
 void proxy_log(RESTREAMER *r, char *msg, char *info) {
313
 	LOGf("%s: %sChan: %s Src: %s Dst: udp://%s:%d SrcIP: %s SrcFD: %i DstFD: %i\n",
301
 	LOGf("%s: %sChan: %s Src: %s Dst: udp://%s:%d SrcIP: %s SrcFD: %i DstFD: %i\n",
314
 		msg,
302
 		msg,
323
 	);
311
 	);
324
 }
312
 }
325
 
313
 
326
-int load_channels_config() {
314
+int load_channels_config(struct config *cfg) {
327
 	regex_t re;
315
 	regex_t re;
328
 	regmatch_t res[5];
316
 	regmatch_t res[5];
329
 	char line[1024];
317
 	char line[1024];
330
 	int fd;
318
 	int fd;
331
 	int num_channels = 0;
319
 	int num_channels = 0;
332
 
320
 
333
-	if (pthread_mutex_trylock(&channels_lock) != 0)
321
+	if (pthread_mutex_trylock(&cfg->channels_lock) != 0)
334
 		return -1;
322
 		return -1;
335
 
323
 
336
-	fd = open(channels_file, O_RDONLY);
324
+	fd = open(cfg->channels_file, O_RDONLY);
337
 
325
 
338
 	if (fd != -1) {
326
 	if (fd != -1) {
339
 		struct timeval tv;
327
 		struct timeval tv;
385
 		regfree(&re);
373
 		regfree(&re);
386
 		shutdown_fd(&fd);
374
 		shutdown_fd(&fd);
387
 		/* Save current chanconf */
375
 		/* Save current chanconf */
388
-		old_chanconf = chanconf;
376
+		old_chanconf = cfg->chanconf;
389
 		/* Switch chanconf */
377
 		/* Switch chanconf */
390
-		chanconf = new_chanconf;
378
+		cfg->chanconf = new_chanconf;
391
 		/* Rewrite restreamer channels */
379
 		/* Rewrite restreamer channels */
392
 		LNODE *lc, *lr, *lctmp, *lrtmp;
380
 		LNODE *lc, *lr, *lctmp, *lrtmp;
393
 		CHANNEL *chan;
381
 		CHANNEL *chan;
394
-		list_lock(restreamer);	// Unlocked after second list_for_each(restreamer)
382
+		list_lock(cfg->restreamer);	// Unlocked after second list_for_each(restreamer)
395
 
383
 
396
-		list_lock(chanconf);
397
-		list_for_each(chanconf, lc, lctmp) {
384
+		list_lock(cfg->chanconf);
385
+		list_for_each(cfg->chanconf, lc, lctmp) {
398
 			chan = lc->data;
386
 			chan = lc->data;
399
-			list_for_each(restreamer, lr, lrtmp) {
387
+			list_for_each(cfg->restreamer, lr, lrtmp) {
400
 				if (strcmp(chan->name, ((RESTREAMER *)lr->data)->name)==0) {
388
 				if (strcmp(chan->name, ((RESTREAMER *)lr->data)->name)==0) {
401
 					RESTREAMER *restr = lr->data;
389
 					RESTREAMER *restr = lr->data;
402
 					/* Mark the restreamer as valid */
390
 					/* Mark the restreamer as valid */
425
 				}
413
 				}
426
 			}
414
 			}
427
 		}
415
 		}
428
-		list_unlock(chanconf);
416
+		list_unlock(cfg->chanconf);
429
 
417
 
430
 		/* Kill restreamers that serve channels that no longer exist */
418
 		/* Kill restreamers that serve channels that no longer exist */
431
-		list_for_each(restreamer, lr, lrtmp) {
419
+		list_for_each(cfg->restreamer, lr, lrtmp) {
432
 			RESTREAMER *r = lr->data;
420
 			RESTREAMER *r = lr->data;
433
 			/* This restreamer should no longer serve clients */
421
 			/* This restreamer should no longer serve clients */
434
 			if (r->cookie != cookie) {
422
 			if (r->cookie != cookie) {
439
 				r->dienow = 1;
427
 				r->dienow = 1;
440
 			}
428
 			}
441
 		}
429
 		}
442
-		list_unlock(restreamer);
430
+		list_unlock(cfg->restreamer);
443
 
431
 
444
 		/* Free old_chanconf */
432
 		/* Free old_chanconf */
445
 		list_free(&old_chanconf, free_channel_p, NULL);
433
 		list_free(&old_chanconf, free_channel_p, NULL);
446
 	} else {
434
 	} else {
447
 		num_channels = -1;
435
 		num_channels = -1;
448
 	}
436
 	}
449
-	pthread_mutex_unlock(&channels_lock);
437
+	pthread_mutex_unlock(&cfg->channels_lock);
450
 	if (num_channels == -1)
438
 	if (num_channels == -1)
451
 		LOGf("CONF : Error loading channels!\n");
439
 		LOGf("CONF : Error loading channels!\n");
452
 	else
440
 	else
457
 void proxy_close(RESTREAMER *r) {
445
 void proxy_close(RESTREAMER *r) {
458
 	proxy_log(r, "STOP ","");
446
 	proxy_log(r, "STOP ","");
459
 	// If there are no clients left, no "Timeout" messages will be logged
447
 	// If there are no clients left, no "Timeout" messages will be logged
460
-	list_del_entry(restreamer, r);
448
+	list_del_entry(config.restreamer, r);
461
 	free_restreamer(r);
449
 	free_restreamer(r);
462
 }
450
 }
463
 
451
 
523
 		}
511
 		}
524
 
512
 
525
 		snprintf(buf,sizeof(buf)-1, "GET /%s HTTP/1.0\r\nHost: %s:%u\r\nX-Smart-Client: yes\r\nUser-Agent: %s %s (%s)\r\n\r\n",
513
 		snprintf(buf,sizeof(buf)-1, "GET /%s HTTP/1.0\r\nHost: %s:%u\r\nX-Smart-Client: yes\r\nUser-Agent: %s %s (%s)\r\n\r\n",
526
-		         src->path, src->host, src->port, server_sig, server_ver, ident);
514
+		         src->path, src->host, src->port, server_sig, server_ver, config.ident);
527
 		buf[sizeof(buf)-1] = 0;
515
 		buf[sizeof(buf)-1] = 0;
528
 		fdwrite(r->sock, buf, strlen(buf));
516
 		fdwrite(r->sock, buf, strlen(buf));
529
 
517
 
893
 	puts("\t-l host\t\tSyslog host (default: disabled)");
881
 	puts("\t-l host\t\tSyslog host (default: disabled)");
894
 	puts("\t-L port\t\tSyslog port (default: 514)");
882
 	puts("\t-L port\t\tSyslog port (default: 514)");
895
 	puts("\t-R\t\tSend reset packets when changing sources.");
883
 	puts("\t-R\t\tSend reset packets when changing sources.");
884
+	puts("Server settings:");
885
+	puts("\t-b addr\t\tLocal IP address to bind.   (default: 0.0.0.0)");
886
+	puts("\t-p port\t\tPort to listen.             (default: 0)");
896
 	puts("");
887
 	puts("");
897
 }
888
 }
898
 
889
 
899
-void set_ident(char *new_ident) {
900
-	ident = new_ident;
901
-	logident = strdup(ident);
902
-	char *c = logident;
890
+void set_ident(char *new_ident, struct config *cfg) {
891
+	cfg->ident = new_ident;
892
+	cfg->logident = strdup(new_ident);
893
+	char *c = cfg->logident;
903
 	while (*c) {
894
 	while (*c) {
904
 		if (*c=='/')
895
 		if (*c=='/')
905
 			*c='-';
896
 			*c='-';
907
 	}
898
 	}
908
 }
899
 }
909
 
900
 
910
-void parse_options(int argc, char **argv) {
901
+void parse_options(int argc, char **argv, struct config *cfg) {
911
 	int j, ttl;
902
 	int j, ttl;
912
 	while ((j = getopt(argc, argv, "i:c:d:t:o:l:L:RHh")) != -1) {
903
 	while ((j = getopt(argc, argv, "i:c:d:t:o:l:L:RHh")) != -1) {
913
 		switch (j) {
904
 		switch (j) {
905
+			case 'b':
906
+				cfg->server_addr = optarg;
907
+				break;
908
+			case 'p':
909
+				cfg->server_port = atoi(optarg);
910
+				break;
914
 			case 'i':
911
 			case 'i':
915
-				set_ident(optarg);
912
+				set_ident(optarg, cfg);
916
 				break;
913
 				break;
917
 			case 'c':
914
 			case 'c':
918
-				channels_file = optarg;
915
+				cfg->channels_file = optarg;
919
 				break;
916
 				break;
920
 			case 'd':
917
 			case 'd':
921
-				pidfile = optarg;
918
+				cfg->pidfile = optarg;
922
 				break;
919
 				break;
923
 			case 'o':
920
 			case 'o':
924
 				if (inet_aton(optarg, &output_intf) == 0) {
921
 				if (inet_aton(optarg, &output_intf) == 0) {
931
 				multicast_ttl = (ttl && ttl < 127) ? ttl : 1;
928
 				multicast_ttl = (ttl && ttl < 127) ? ttl : 1;
932
 				break;
929
 				break;
933
 			case 'l':
930
 			case 'l':
934
-				loghost = optarg;
935
-				syslog_active = 1;
931
+				cfg->loghost = optarg;
932
+				cfg->syslog_active = 1;
936
 				break;
933
 				break;
937
 			case 'L':
934
 			case 'L':
938
-				logport = atoi(optarg);
935
+				cfg->logport = atoi(optarg);
939
 				break;
936
 				break;
940
 			case 'R':
937
 			case 'R':
941
 				send_reset_opt = 1;
938
 				send_reset_opt = 1;
948
 		}
945
 		}
949
 	}
946
 	}
950
 
947
 
951
-	if (!channels_file) {
948
+	if (!cfg->channels_file) {
952
 		show_usage(0);
949
 		show_usage(0);
953
 		fprintf(stderr, "ERROR: No channels file is set (use -c option).\n");
950
 		fprintf(stderr, "ERROR: No channels file is set (use -c option).\n");
954
 		exit(1);
951
 		exit(1);
955
 	}
952
 	}
956
 
953
 
957
-	if (!ident) {
958
-		set_ident("unixsol/tomcast");
954
+	if (!cfg->ident) {
955
+		set_ident("unixsol/tomcast", cfg);
959
 	}
956
 	}
960
 
957
 
961
 	printf("Configuration:\n");
958
 	printf("Configuration:\n");
962
-	printf("\tServer ident      : %s\n", ident);
963
-	printf("\tChannels file     : %s\n", channels_file);
959
+	printf("\tServer ident      : %s\n", cfg->ident);
960
+	printf("\tChannels file     : %s\n", cfg->channels_file);
964
 	printf("\tOutput iface addr : %s\n", inet_ntoa(output_intf));
961
 	printf("\tOutput iface addr : %s\n", inet_ntoa(output_intf));
965
 	printf("\tMulticast ttl     : %d\n", multicast_ttl);
962
 	printf("\tMulticast ttl     : %d\n", multicast_ttl);
966
-	if (syslog_active) {
967
-		printf("\tSyslog host       : %s\n", loghost);
968
-		printf("\tSyslog port       : %d\n", logport);
963
+	if (cfg->syslog_active) {
964
+		printf("\tSyslog host       : %s\n", cfg->loghost);
965
+		printf("\tSyslog port       : %d\n", cfg->logport);
969
 	} else {
966
 	} else {
970
 		printf("\tSyslog disabled.\n");
967
 		printf("\tSyslog disabled.\n");
971
 	}
968
 	}
972
 	if (send_reset_opt)
969
 	if (send_reset_opt)
973
 		printf("\tSend reset packets.\n");
970
 		printf("\tSend reset packets.\n");
974
-	if (pidfile) {
975
-		printf("\tDaemonize         : %s\n", pidfile);
971
+	if (cfg->pidfile) {
972
+		printf("\tDaemonize         : %s\n", cfg->pidfile);
976
 	} else {
973
 	} else {
977
 		printf("\tDo not daemonize.\n");
974
 		printf("\tDo not daemonize.\n");
978
 	}
975
 	}
976
+
977
+	if (cfg->server_port)
978
+		init_server_socket(cfg->server_addr, cfg->server_port, &cfg->server, &cfg->server_socket);
979
 }
979
 }
980
 
980
 
981
-void init_vars() {
982
-	restreamer = list_new("restreamer");
981
+void init_vars(struct config *cfg) {
982
+	cfg->restreamer = list_new("restreamer");
983
 	regcomp(&http_response, "^HTTP/1.[0-1] (([0-9]{3}) .*)", REG_EXTENDED);
983
 	regcomp(&http_response, "^HTTP/1.[0-1] (([0-9]{3}) .*)", REG_EXTENDED);
984
 	memset(&TS_NULL_FRAME, 0xff, FRAME_PACKET_SIZE);
984
 	memset(&TS_NULL_FRAME, 0xff, FRAME_PACKET_SIZE);
985
 	int i;
985
 	int i;
991
 	}
991
 	}
992
 }
992
 }
993
 
993
 
994
-void spawn_proxy_threads() {
994
+void spawn_proxy_threads(struct config *cfg) {
995
 	LNODE *lc, *lctmp;
995
 	LNODE *lc, *lctmp;
996
 	LNODE *lr, *lrtmp;
996
 	LNODE *lr, *lrtmp;
997
 	int spawned = 0;
997
 	int spawned = 0;
998
-	list_for_each(chanconf, lc, lctmp) {
998
+	list_for_each(cfg->chanconf, lc, lctmp) {
999
 		CHANNEL *c = lc->data;
999
 		CHANNEL *c = lc->data;
1000
 		int restreamer_active = 0;
1000
 		int restreamer_active = 0;
1001
-		list_lock(restreamer);
1002
-		list_for_each(restreamer, lr, lrtmp) {
1001
+		list_lock(cfg->restreamer);
1002
+		list_for_each(cfg->restreamer, lr, lrtmp) {
1003
 			RESTREAMER *r = lr->data;
1003
 			RESTREAMER *r = lr->data;
1004
 			if (strcmp(r->name, c->name)==0) {
1004
 			if (strcmp(r->name, c->name)==0) {
1005
 				restreamer_active = 1;
1005
 				restreamer_active = 1;
1006
 				break;
1006
 				break;
1007
 			}
1007
 			}
1008
 		}
1008
 		}
1009
-		list_unlock(restreamer);
1009
+		list_unlock(cfg->restreamer);
1010
 		if (!restreamer_active) {
1010
 		if (!restreamer_active) {
1011
 			RESTREAMER *nr = new_restreamer(c->name, c);
1011
 			RESTREAMER *nr = new_restreamer(c->name, c);
1012
 			if (nr->clientsock < 0) {
1012
 			if (nr->clientsock < 0) {
1013
 				LOGf("Error creating proxy socket for %s\n", c->name);
1013
 				LOGf("Error creating proxy socket for %s\n", c->name);
1014
 				free_restreamer(nr);
1014
 				free_restreamer(nr);
1015
 			} else {
1015
 			} else {
1016
-				list_add(restreamer, nr);
1016
+				list_add(cfg->restreamer, nr);
1017
 				if (pthread_create(&nr->thread, NULL, &proxy_ts_stream, nr) == 0) {
1017
 				if (pthread_create(&nr->thread, NULL, &proxy_ts_stream, nr) == 0) {
1018
 					spawned++;
1018
 					spawned++;
1019
 					pthread_detach(nr->thread);
1019
 					pthread_detach(nr->thread);
1026
 	LOGf("INFO : %d proxy threads spawned\n", spawned);
1026
 	LOGf("INFO : %d proxy threads spawned\n", spawned);
1027
 }
1027
 }
1028
 
1028
 
1029
-void kill_proxy_threads() {
1029
+void kill_proxy_threads(struct config *cfg) {
1030
 	LNODE *l, *tmp;
1030
 	LNODE *l, *tmp;
1031
 	int killed = 0;
1031
 	int killed = 0;
1032
-	list_lock(restreamer);
1033
-	list_for_each(restreamer, l, tmp) {
1032
+	list_lock(cfg->restreamer);
1033
+	list_for_each(cfg->restreamer, l, tmp) {
1034
 		RESTREAMER *r = l->data;
1034
 		RESTREAMER *r = l->data;
1035
 		r->dienow = 1;
1035
 		r->dienow = 1;
1036
 		killed++;
1036
 		killed++;
1037
 	}
1037
 	}
1038
-	list_unlock(restreamer);
1038
+	list_unlock(cfg->restreamer);
1039
 	LOGf("INFO : %d proxy threads killed\n", killed);
1039
 	LOGf("INFO : %d proxy threads killed\n", killed);
1040
 }
1040
 }
1041
 
1041
 
1042
+int keep_going = 1;
1043
+
1042
 void signal_quit(int sig) {
1044
 void signal_quit(int sig) {
1043
-	kill_proxy_threads();
1045
+	keep_going = 0;
1046
+	kill_proxy_threads(&config);
1044
 	usleep(500000);
1047
 	usleep(500000);
1045
-	LOGf("KILL : Signal %i | %s %s (%s)\n", sig, server_sig, server_ver, ident);
1048
+	LOGf("KILL : Signal %i | %s %s (%s)\n", sig, server_sig, server_ver, config.ident);
1046
 	usleep(100000);
1049
 	usleep(100000);
1047
 	log_close();
1050
 	log_close();
1048
-	if (pidfile && strlen(pidfile))
1049
-		unlink(pidfile);
1051
+	if (config.pidfile && strlen(config.pidfile))
1052
+		unlink(config.pidfile);
1050
 	signal(sig, SIG_DFL);
1053
 	signal(sig, SIG_DFL);
1051
 	raise(sig);
1054
 	raise(sig);
1052
 }
1055
 }
1053
 
1056
 
1054
 void do_reconnect() {
1057
 void do_reconnect() {
1055
 	LNODE *l, *tmp;
1058
 	LNODE *l, *tmp;
1056
-	list_lock(restreamer);
1057
-	list_for_each(restreamer, l, tmp) {
1059
+	list_lock(config.restreamer);
1060
+	list_for_each(config.restreamer, l, tmp) {
1058
 		RESTREAMER *r = l->data;
1061
 		RESTREAMER *r = l->data;
1059
 		r->reconnect = 1;
1062
 		r->reconnect = 1;
1060
 	}
1063
 	}
1061
-	list_unlock(restreamer);
1064
+	list_unlock(config.restreamer);
1062
 }
1065
 }
1063
 
1066
 
1064
 void do_reconf() {
1067
 void do_reconf() {
1065
-	load_channels_config();
1066
-	spawn_proxy_threads();
1068
+	load_channels_config(&config);
1069
+	spawn_proxy_threads(&config);
1067
 }
1070
 }
1068
 
1071
 
1069
 void init_signals() {
1072
 void init_signals() {
1077
 	signal(SIGTERM, signal_quit);
1080
 	signal(SIGTERM, signal_quit);
1078
 }
1081
 }
1079
 
1082
 
1080
-void do_daemonize() {
1081
-	if (!pidfile)
1083
+void do_daemonize(struct config *cfg) {
1084
+	if (!cfg->pidfile)
1082
 		return;
1085
 		return;
1083
 	fprintf(stderr, "Daemonizing.\n");
1086
 	fprintf(stderr, "Daemonizing.\n");
1084
 	pid_t pid = fork();
1087
 	pid_t pid = fork();
1085
 	if (pid > 0) {
1088
 	if (pid > 0) {
1086
-		FILE *F = fopen(pidfile,"w");
1089
+		FILE *F = fopen(cfg->pidfile,"w");
1087
 		if (F) {
1090
 		if (F) {
1088
 			fprintf(F,"%i\n",pid);
1091
 			fprintf(F,"%i\n",pid);
1089
 			fclose(F);
1092
 			fclose(F);
1098
 }
1101
 }
1099
 
1102
 
1100
 /* Must be called after daemonize! */
1103
 /* Must be called after daemonize! */
1101
-void init_logger() {
1102
-	if (syslog_active)
1103
-		fprintf(stderr, "Logging to %s:%d\n", loghost, logport);
1104
-	log_init(logident, syslog_active, pidfile == NULL, loghost, logport);
1104
+void init_logger(struct config *cfg) {
1105
+	if (cfg->syslog_active)
1106
+		fprintf(stderr, "Logging to %s:%d\n", cfg->loghost, cfg->logport);
1107
+	log_init(cfg->logident, cfg->syslog_active, cfg->pidfile == NULL, cfg->loghost, cfg->logport);
1105
 }
1108
 }
1106
 
1109
 
1107
 int main(int argc, char **argv) {
1110
 int main(int argc, char **argv) {
1108
 	set_http_response_server_ident(server_sig, server_ver);
1111
 	set_http_response_server_ident(server_sig, server_ver);
1109
 	show_usage(1); // Show copyright and version
1112
 	show_usage(1); // Show copyright and version
1110
-	init_vars();
1111
-	parse_options(argc, argv);
1112
-	do_daemonize();
1113
-	init_logger();
1113
+	init_vars(&config);
1114
+	parse_options(argc, argv, &config);
1115
+	do_daemonize(&config);
1116
+	init_logger(&config);
1114
 	init_signals();
1117
 	init_signals();
1115
 
1118
 
1116
-	LOGf("INIT : %s %s (%s)\n" , server_sig, server_ver, ident);
1119
+	LOGf("INIT : %s %s (%s)\n" , server_sig, server_ver, config.ident);
1117
 
1120
 
1118
-	load_channels_config();
1119
-	spawn_proxy_threads();
1121
+	load_channels_config(&config);
1122
+	spawn_proxy_threads(&config);
1123
+	web_server_start(&config);
1120
 
1124
 
1121
 	do {
1125
 	do {
1122
 		sleep(60);
1126
 		sleep(60);

+ 45
- 0
web_pages.c View File

1
+/*
2
+ * mptsd internal web pages
3
+ * Copyright (C) 2010-2011 Unix Solutions Ltd.
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2
7
+ * as published by the Free Software Foundation.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
17
+ */
18
+#include <stdlib.h>
19
+#include <string.h>
20
+#include <sys/types.h>
21
+#include <sys/stat.h>
22
+#include <fcntl.h>
23
+#include <unistd.h>
24
+
25
+#include "libfuncs/io.h"
26
+#include "libfuncs/log.h"
27
+#include "libfuncs/list.h"
28
+#include "libfuncs/http_response.h"
29
+
30
+#include "config.h"
31
+
32
+extern struct config *config;
33
+
34
+void cmd_index(int clientsock) {
35
+	send_200_ok(clientsock);
36
+	send_header_textplain(clientsock);
37
+	fdputs(clientsock, "\nHi from tomcast.\n");
38
+}
39
+
40
+void cmd_reconnect(int clientsock) {
41
+	send_200_ok(clientsock);
42
+	send_header_textplain(clientsock);
43
+	fdputsf(clientsock, "\nReconnecting %d inputs.\n", 123);
44
+//	fdputsf(clientsock, "\nReconnecting %d inputs.\n", config->inputs->items);
45
+}

+ 24
- 0
web_pages.h View File

1
+/*
2
+ * mptsd internal web pages header file
3
+ * Copyright (C) 2010-2011 Unix Solutions Ltd.
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2
7
+ * as published by the Free Software Foundation.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
17
+ */
18
+#ifndef WEB_PAGES_H
19
+#define WEB_PAGES_H
20
+
21
+void cmd_index(int clientsock);
22
+void cmd_reconnect(int clientsock);
23
+
24
+#endif

+ 139
- 0
web_server.c View File

1
+/*
2
+ * mptsd internal web server
3
+ * Copyright (C) 2010-2011 Unix Solutions Ltd.
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2
7
+ * as published by the Free Software Foundation.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
17
+ */
18
+#include <stdlib.h>
19
+#include <regex.h>
20
+#include <errno.h>
21
+#include <string.h>
22
+#include <signal.h>
23
+#include <arpa/inet.h>
24
+#include <netinet/in.h>
25
+
26
+#include "libfuncs/libfuncs.h"
27
+
28
+#include "web_pages.h"
29
+#include "web_server.h"
30
+
31
+typedef struct req_info {
32
+	int clientsock;
33
+	struct sockaddr_in client;
34
+} request_info;
35
+
36
+extern int keep_going;
37
+
38
+#define NEXT_CLIENT { FREE(path); FREE(buf); pthread_exit(0); }
39
+#define SHUTDOWN_CLIENT { FREE(path); FREE(buf); shutdown_fd(&clientsock); pthread_exit(0); }
40
+#define BUF_SIZE 1024
41
+
42
+void *process_web_request(void *);
43
+
44
+void *web_server_thread(void *data) {
45
+	struct config *conf = data;
46
+	while (keep_going) {
47
+		struct sockaddr_in client;
48
+		unsigned int clientlen = sizeof(client);
49
+		int clientsock;
50
+		clientsock = accept(conf->server_socket, (struct sockaddr *) &client, &clientlen);
51
+		if (clientsock < 0) {
52
+			if (conf->server_socket > -1)	// The server_socket is closed on exit, so do not report errors
53
+				LOGf("ERROR : Failed to accept client fd: %i err: %s\n", clientsock, strerror(errno));
54
+			if (errno==EMFILE || errno==ENFILE) /* No more FDs */
55
+				break;
56
+		} else {
57
+			request_info *req;
58
+			pthread_t req_thread;
59
+			req = malloc(sizeof(request_info));
60
+			if (!req) {
61
+				log_perror("Can't allocate request_info", errno);
62
+				continue;
63
+			}
64
+			req->clientsock = clientsock;
65
+			req->client = client;
66
+			if (pthread_create(&req_thread, NULL, (void *)&process_web_request, (void *)req)) {
67
+				log_perror("Error creating request processing thread.", errno);
68
+				exit(1);
69
+			}
70
+			pthread_detach(req_thread);
71
+		}
72
+	}
73
+
74
+	pthread_exit(0);
75
+}
76
+
77
+void web_server_start(struct config *conf) {
78
+	if (conf->server_socket > -1)
79
+		pthread_create(&conf->server_thread, NULL, &web_server_thread, conf);
80
+}
81
+
82
+void web_server_stop(struct config *conf) {
83
+	if (conf->server_socket > -1) {
84
+		shutdown_fd(&conf->server_socket);
85
+		pthread_join(conf->server_thread, NULL);
86
+	}
87
+}
88
+
89
+void *process_web_request(void *in_req) {
90
+	request_info *req = (request_info *)in_req;
91
+	int clientsock = req->clientsock;
92
+	regmatch_t res[3];
93
+	char *path=NULL, *buf=NULL;
94
+	FREE(req);
95
+
96
+	signal(SIGPIPE, SIG_IGN);
97
+
98
+	if (!keep_going)
99
+		pthread_exit(0);
100
+
101
+	buf = malloc(BUF_SIZE);
102
+	if (!buf) {
103
+		log_perror("Can't allocate buffer", errno);
104
+		SHUTDOWN_CLIENT;
105
+	}
106
+
107
+	if (fdgetline(clientsock,buf,BUF_SIZE)<=0) {
108
+		SHUTDOWN_CLIENT;
109
+	}
110
+
111
+	regex_t request_get;
112
+	regcomp(&request_get, "^GET /([^ ]*) HTTP/1.*$", REG_EXTENDED);
113
+	if (regexec(&request_get,buf,2,res,0)==REG_NOMATCH) {
114
+		send_501_not_implemented(clientsock);
115
+		SHUTDOWN_CLIENT;
116
+	}
117
+
118
+	buf[res[1].rm_eo]=0;
119
+	chomp(buf+res[1].rm_so);
120
+	if (buf[res[1].rm_eo-1]=='/') buf[res[1].rm_eo-1]=0;
121
+	path = strdup(buf+res[1].rm_so);
122
+	regfree(&request_get);
123
+
124
+	while (fdgetline(clientsock,buf,BUF_SIZE) > 0) {
125
+		if (buf[0] == '\n' || buf[0] == '\r') // End of headers
126
+			break;
127
+	}
128
+
129
+	if (strlen(path) == 0) {
130
+		cmd_index(clientsock);
131
+	} else if (strstr(path,"reconnect")==path) {
132
+		cmd_reconnect(clientsock);
133
+	} else {
134
+		send_404_not_found(clientsock);
135
+	}
136
+
137
+	SHUTDOWN_CLIENT;
138
+}
139
+

+ 26
- 0
web_server.h View File

1
+/*
2
+ * mptsd internal web server header file
3
+ * Copyright (C) 2010-2011 Unix Solutions Ltd.
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License version 2
7
+ * as published by the Free Software Foundation.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ * GNU General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
17
+ */
18
+#ifndef WEB_SERVER_H
19
+# define WEB_SERVER_H
20
+
21
+#include "config.h"
22
+
23
+void web_server_start(struct config *conf);
24
+void web_server_stop(struct config *conf);
25
+
26
+#endif

Loading…
Cancel
Save