Browse code

Skeleton server (shamelessly ripped from newslettersan)

Dario Rodriguez authored on 25/04/2015 09:55:24
Showing 1 changed files
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
+