/*
 * 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);
}