/* * recremote.c * * Web frontend to control recording with ALSA * * Author: Dario Rodriguez dario@softhome.net * This program is licensed under the terms of the Affero GPL v1+ */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include "gen_res.h" #include "socklib.h" #include "loglib.h" #include "webkernel.h" #include "recremote.h" #include "rec_config.h" #define CONFIGFILE "recremote.cfg" #define CFLOGFILE "recremote.log" static int signal_init(int signum, void (*fn)(int)); static void sigint(int signum); volatile int sigint_flag=0; wk_action callback_http(wk *web, int connid, wk_uri *uri, void *userptr); int main(int argc, char *argv[]) { int timeout=500; int serverfd; recremote *rec,recstore; char *hostnameport; char hostname[128]; char *host; long hostsize; char *ptr,*sep; memset(&recstore,0,sizeof(recstore)); rec=&recstore; if(argc!=2) { printf("Syntax: %s [ip:]port\n",argv[0]); return(1); } hostnameport=argv[1]; if(recconfig_exists(CONFIGFILE)!=0) { log_setlogfile(CFLOGFILE); log_write("INIT","Config file not found, writing default file %s",CONFIGFILE); recconfig_write(CONFIGFILE,CFLOGFILE); } if((rec->config=recconfig_init(CONFIGFILE))==NULL) { log_setlogfile(CFLOGFILE); log_write("INIT","ERROR: insufficient memory or config file error"); return(1); } log_setlogfile((rec->config->logfile!=NULL)?rec->config->logfile:CFLOGFILE); if((rec->ssel=sselect_init())==NULL) { log_write("INIT","ERROR: insufficient memory"); return(1); } if((sep=strchr(hostnameport,':'))!=NULL) { serverfd=-1; strncpy(hostname,hostnameport,sizeof(hostname)); hostname[sizeof(hostname)-1]='\0'; if((ptr=strchr(hostname,':'))!=NULL) *ptr='\0'; if((host=ipv4_genip(hostname,&hostsize))!=NULL) { serverfd=ipv4_serverbinded(host,hostsize,atoi(sep+1)); free(host),host=NULL; } } else { serverfd=ipv4_server(atoi(hostnameport)); } if(serverfd==-1) { sselect_free(rec->ssel),rec->ssel=NULL; log_write("INIT","ERROR: couldn't listen on port"); return(2); } sock_setunsafe(serverfd); if((rec->web=wk_init(serverfd,rec->ssel,NULL,callback_http,NULL,NULL,rec))==NULL) { sselect_free(rec->ssel),rec->ssel=NULL; log_write("INIT","ERROR: couldn't init web server"); return(2); } sigint_flag=0; signal_init(SIGINT,sigint); log_write("INIT","Server initialized, waiting connections..."); while(!sigint_flag) { sselect_wait(rec->ssel,timeout); if(sigint_flag) break; wk_service(rec->web); } wk_free(rec->web),rec->web=NULL; close(serverfd),serverfd=-1; sselect_free(rec->ssel),rec->ssel=NULL; recconfig_free(rec->config),rec->config=NULL; log_write("FINI","SIGINT detected, exiting..."); return(0); } static int signal_init(int signum, void (*fn)(int)) { struct sigaction sa; sa.sa_handler=fn; sigemptyset(&sa.sa_mask); sa.sa_flags=0; return(sigaction(signum,&sa,0)); } static void sigint(int signum) { sigint_flag=1; } wk_action callback_http(wk *web, int connid, wk_uri *uri, void *userptr) { recremote *rec=(recremote *)userptr; resindex *res; char partialpath[1024]; if(rec==NULL) return(wkact_finished); strncpy(partialpath,uri->path,sizeof(partialpath)-1); partialpath[sizeof(partialpath)-1]='\0'; if(strcmp(uri->path,"/")==0) strcpy(partialpath,"/index.html"); if(partialpath[0]=='/' && (res=res_find(resindexdata,partialpath+1))!=NULL) { log_write("HTTP","Serving in-memory file %s",partialpath+1); wk_serve_etagset(web,connid,res->etag); wk_serve_buffer_as_file(web,connid,res->data,res->len,mime_getdefault(res->name,"application/octet-stream")); return(wkact_finished); } wk_serve_error(web,connid,wkerr_notfound); return(wkact_finished); }