1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,144 @@ |
1 |
+/* |
|
2 |
+ * recremote.c |
|
3 |
+ * |
|
4 |
+ * Web frontend to control recording with ALSA |
|
5 |
+ * |
|
6 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
7 |
+ * This program is licensed under the terms of the Affero GPL v1+ |
|
8 |
+ */ |
|
9 |
+ |
|
10 |
+#include <stdio.h> |
|
11 |
+#include <stdlib.h> |
|
12 |
+#include <unistd.h> |
|
13 |
+#include <string.h> |
|
14 |
+#include <signal.h> |
|
15 |
+#include <sys/types.h> |
|
16 |
+#include <sys/stat.h> |
|
17 |
+#include "gen_res.h" |
|
18 |
+#include "socklib.h" |
|
19 |
+#include "loglib.h" |
|
20 |
+#include "webkernel.h" |
|
21 |
+#include "recremote.h" |
|
22 |
+#include "rec_config.h" |
|
23 |
+ |
|
24 |
+#define CONFIGFILE "recremote.cfg" |
|
25 |
+#define CFLOGFILE "recremote.log" |
|
26 |
+ |
|
27 |
+static int signal_init(int signum, void (*fn)(int)); |
|
28 |
+static void sigint(int signum); |
|
29 |
+volatile int sigint_flag=0; |
|
30 |
+ |
|
31 |
+wk_action callback_http(wk *web, int connid, wk_uri *uri, void *userptr); |
|
32 |
+ |
|
33 |
+int |
|
34 |
+main(int argc, char *argv[]) |
|
35 |
+{ |
|
36 |
+ int timeout=500; |
|
37 |
+ int serverfd; |
|
38 |
+ recremote *rec,recstore; |
|
39 |
+ char *hostnameport; |
|
40 |
+ char hostname[128]; |
|
41 |
+ char *host; |
|
42 |
+ long hostsize; |
|
43 |
+ char *ptr,*sep; |
|
44 |
+ memset(&recstore,0,sizeof(recstore)); |
|
45 |
+ rec=&recstore; |
|
46 |
+ if(argc!=2) { |
|
47 |
+ printf("Syntax: %s [ip:]port\n",argv[0]); |
|
48 |
+ return(1); |
|
49 |
+ } |
|
50 |
+ hostnameport=argv[1]; |
|
51 |
+ if(recconfig_exists(CONFIGFILE)!=0) { |
|
52 |
+ log_setlogfile(CFLOGFILE); |
|
53 |
+ log_write("INIT","Config file not found, writing default file %s",CONFIGFILE); |
|
54 |
+ recconfig_write(CONFIGFILE,CFLOGFILE); |
|
55 |
+ } |
|
56 |
+ if((rec->config=recconfig_init(CONFIGFILE))==NULL) { |
|
57 |
+ log_setlogfile(CFLOGFILE); |
|
58 |
+ log_write("INIT","ERROR: insufficient memory or config file error"); |
|
59 |
+ return(1); |
|
60 |
+ } |
|
61 |
+ log_setlogfile((rec->config->logfile!=NULL)?rec->config->logfile:CFLOGFILE); |
|
62 |
+ if((rec->ssel=sselect_init())==NULL) { |
|
63 |
+ log_write("INIT","ERROR: insufficient memory"); |
|
64 |
+ return(1); |
|
65 |
+ } |
|
66 |
+ if((sep=strchr(hostnameport,':'))!=NULL) { |
|
67 |
+ serverfd=-1; |
|
68 |
+ strncpy(hostname,hostnameport,sizeof(hostname)); |
|
69 |
+ hostname[sizeof(hostname)-1]='\0'; |
|
70 |
+ if((ptr=strchr(hostname,':'))!=NULL) |
|
71 |
+ *ptr='\0'; |
|
72 |
+ if((host=ipv4_genip(hostname,&hostsize))!=NULL) { |
|
73 |
+ serverfd=ipv4_serverbinded(host,hostsize,atoi(sep+1)); |
|
74 |
+ free(host),host=NULL; |
|
75 |
+ } |
|
76 |
+ } else { |
|
77 |
+ serverfd=ipv4_server(atoi(hostnameport)); |
|
78 |
+ } |
|
79 |
+ if(serverfd==-1) { |
|
80 |
+ sselect_free(rec->ssel),rec->ssel=NULL; |
|
81 |
+ log_write("INIT","ERROR: couldn't listen on port"); |
|
82 |
+ return(2); |
|
83 |
+ } |
|
84 |
+ sock_setunsafe(serverfd); |
|
85 |
+ if((rec->web=wk_init(serverfd,rec->ssel,NULL,callback_http,NULL,NULL,rec))==NULL) { |
|
86 |
+ sselect_free(rec->ssel),rec->ssel=NULL; |
|
87 |
+ log_write("INIT","ERROR: couldn't init web server"); |
|
88 |
+ return(2); |
|
89 |
+ } |
|
90 |
+ sigint_flag=0; |
|
91 |
+ signal_init(SIGINT,sigint); |
|
92 |
+ log_write("INIT","Server initialized, waiting connections..."); |
|
93 |
+ while(!sigint_flag) { |
|
94 |
+ sselect_wait(rec->ssel,timeout); |
|
95 |
+ if(sigint_flag) |
|
96 |
+ break; |
|
97 |
+ wk_service(rec->web); |
|
98 |
+ } |
|
99 |
+ wk_free(rec->web),rec->web=NULL; |
|
100 |
+ close(serverfd),serverfd=-1; |
|
101 |
+ sselect_free(rec->ssel),rec->ssel=NULL; |
|
102 |
+ recconfig_free(rec->config),rec->config=NULL; |
|
103 |
+ log_write("FINI","SIGINT detected, exiting..."); |
|
104 |
+ return(0); |
|
105 |
+} |
|
106 |
+ |
|
107 |
+static int |
|
108 |
+signal_init(int signum, void (*fn)(int)) |
|
109 |
+{ |
|
110 |
+ struct sigaction sa; |
|
111 |
+ sa.sa_handler=fn; |
|
112 |
+ sigemptyset(&sa.sa_mask); |
|
113 |
+ sa.sa_flags=0; |
|
114 |
+ return(sigaction(signum,&sa,0)); |
|
115 |
+} |
|
116 |
+ |
|
117 |
+static void |
|
118 |
+sigint(int signum) |
|
119 |
+{ |
|
120 |
+ sigint_flag=1; |
|
121 |
+} |
|
122 |
+ |
|
123 |
+wk_action |
|
124 |
+callback_http(wk *web, int connid, wk_uri *uri, void *userptr) |
|
125 |
+{ |
|
126 |
+ recremote *rec=(recremote *)userptr; |
|
127 |
+ resindex *res; |
|
128 |
+ char partialpath[1024]; |
|
129 |
+ if(rec==NULL) |
|
130 |
+ return(wkact_finished); |
|
131 |
+ strncpy(partialpath,uri->path,sizeof(partialpath)-1); |
|
132 |
+ partialpath[sizeof(partialpath)-1]='\0'; |
|
133 |
+ if(strcmp(uri->path,"/")==0) |
|
134 |
+ strcpy(partialpath,"/index.html"); |
|
135 |
+ if(partialpath[0]=='/' && (res=res_find(resindexdata,partialpath+1))!=NULL) { |
|
136 |
+ log_write("HTTP","Serving in-memory file %s",partialpath+1); |
|
137 |
+ wk_serve_etagset(web,connid,res->etag); |
|
138 |
+ wk_serve_buffer_as_file(web,connid,res->data,res->len,mime_getdefault(res->name,"application/octet-stream")); |
|
139 |
+ return(wkact_finished); |
|
140 |
+ } |
|
141 |
+ wk_serve_error(web,connid,wkerr_notfound); |
|
142 |
+ return(wkact_finished); |
|
143 |
+} |
|
144 |
+ |