#define _GNU_SOURCE // sigaction #include #include #include #include #include #include #include #include #include #include #include #include "http.h" #include "memory.h" #include "plugin.h" #include "util.h" #define PORT 8080 int num_threads=0; static void signal_handler(int sig){ if(sig==SIGCHLD){ int saved_errno=errno; while(true){ int status; pid_t pid=waitpid(-1,&status,WNOHANG); if(pid<=0){ break; } if(WIFEXITED(status)){ num_threads--; } } errno=saved_errno; } } typedef struct Plugin{ char *name; Handler handler; struct Plugin *next; } Plugin; Plugin *pluginlist=NULL,*pluginlist_last=NULL; static void plugin_register_callback(const char *name,Handler handler){ if(pluginlist==NULL){ pluginlist=pluginlist_last=malloc(1,Plugin); pluginlist->name=copy_str(name); pluginlist->handler=handler; pluginlist->next=NULL; } else { Plugin *newplugin=malloc(1,Plugin); newplugin->name=copy_str(name); newplugin->handler=handler; newplugin->next=NULL; pluginlist_last->next=newplugin; pluginlist_last=newplugin; } printf("Registered plugin '%s' (handler %p)\n",name,handler); } typedef void (*register_function)(register_callback_t callback); static void load_plugin(const char *name){ void *lib=dlopen(name,RTLD_NOW|RTLD_LOCAL); if(lib==NULL){ fprintf(stderr,"dlopen(%s): %s\n",name,dlerror()); exit(1); } register_function regfunc=(register_function)dlsym(lib,"plugin_register_yourself"); if(regfunc==NULL){ fprintf(stderr,"Cannot find plugin_register_yourself symbol in library '%s'\n",name); exit(1); } regfunc(&plugin_register_callback); } static void connection_handler(int sock){ Headers *headers=http_get_headers(sock); if(headers==NULL){ return; } for(Plugin *pl=pluginlist;pl!=NULL;pl=pl->next){ switch(pl->handler(sock,headers)){ case HR_HANDLED: printf("Request handled by %s\n",pl->name); break; case HR_NEXT: continue; case HR_ERROR: printf("Request handler '%s' threw error\n",pl->name); break; } break; } } int main(int argc,char **argv){ if(argc==1){ printf("Loading no plugin files\n"); } else { for(int i=1;isin_addr, str,sizeof(str)); pid_t pid=fork(); if(pid==0){ close(sock); connection_handler(clientsock); close(clientsock); exit(0); } if(pid<0){ perror("fork"); return 1; } num_threads++; printf("Accept from %s; child pid %d, %d thread%s\n",str,pid,num_threads, num_threads==1?"":"s"); close(clientsock); } }