From 506cbcfb03756e61f488cc7e0b997e71dbf8c08b Mon Sep 17 00:00:00 2001 From: Ron Pedde Date: Thu, 30 Oct 2003 22:42:11 +0000 Subject: [PATCH] Up to enumerating the database --- src/Makefile | 27 ++++++++---- src/main.c | 85 +++++++++++++++++++++++++++++++++++-- src/webserver.c | 110 ++++++++++++++++++++++++++++++++++++------------ src/webserver.h | 6 ++- 4 files changed, 186 insertions(+), 42 deletions(-) diff --git a/src/Makefile b/src/Makefile index e642eb5b..14e83318 100644 --- a/src/Makefile +++ b/src/Makefile @@ -82,7 +82,12 @@ install_sh = /Users/ron/Documents/School/cs4953 - Concurrency/mt-daapd/install-s # sbin_PROGRAMS = mt-daapd -mt_daapd_SOURCES = main.c rend.c uici.c webserver.c configfile.c err.c restart.c mdns/mDNS.c mdns/mDNSClientAPI.h mdns/mDNSDebug.h mdns/mDNSPosix.c mdns/mDNSUNP.c +mt_daapd_SOURCES = main.c daapd.h rend.c rend.h uici.c uici.h webserver.c \ + webserver.h configfile.c configfile.h err.c err.h restart.c restart.h \ + daap-proto.c daap-proto.h daap.c daap.h \ + mdns/mDNS.c mdns/mDNSClientAPI.h mdns/mDNSDebug.h mdns/mDNSPosix.c \ + mdns/mDNSUNP.c + subdir = src mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h @@ -92,8 +97,8 @@ PROGRAMS = $(sbin_PROGRAMS) am_mt_daapd_OBJECTS = main.$(OBJEXT) rend.$(OBJEXT) uici.$(OBJEXT) \ webserver.$(OBJEXT) configfile.$(OBJEXT) err.$(OBJEXT) \ - restart.$(OBJEXT) mDNS.$(OBJEXT) mDNSPosix.$(OBJEXT) \ - mDNSUNP.$(OBJEXT) + restart.$(OBJEXT) daap-proto.$(OBJEXT) daap.$(OBJEXT) \ + mDNS.$(OBJEXT) mDNSPosix.$(OBJEXT) mDNSUNP.$(OBJEXT) mt_daapd_OBJECTS = $(am_mt_daapd_OBJECTS) mt_daapd_LDADD = $(LDADD) mt_daapd_DEPENDENCIES = @@ -102,15 +107,17 @@ mt_daapd_LDFLAGS = DEFS = -DHAVE_CONFIG_H DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) CPPFLAGS = -DDEBUG -g -no-cpp-precomp -DHAVE_SOCKADDR_SA_LEN -DHAVE_SOCKLEN_T -LDFLAGS = -lpthread +LDFLAGS = -lpthread -lz LIBS = depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles -DEP_FILES = ./$(DEPDIR)/configfile.Po ./$(DEPDIR)/err.Po \ - ./$(DEPDIR)/mDNS.Po ./$(DEPDIR)/mDNSPosix.Po \ - ./$(DEPDIR)/mDNSUNP.Po ./$(DEPDIR)/main.Po \ - ./$(DEPDIR)/rend.Po ./$(DEPDIR)/restart.Po \ - ./$(DEPDIR)/uici.Po ./$(DEPDIR)/webserver.Po +DEP_FILES = ./$(DEPDIR)/configfile.Po \ + ./$(DEPDIR)/daap-proto.Po ./$(DEPDIR)/daap.Po \ + ./$(DEPDIR)/err.Po ./$(DEPDIR)/mDNS.Po \ + ./$(DEPDIR)/mDNSPosix.Po ./$(DEPDIR)/mDNSUNP.Po \ + ./$(DEPDIR)/main.Po ./$(DEPDIR)/rend.Po \ + ./$(DEPDIR)/restart.Po ./$(DEPDIR)/uici.Po \ + ./$(DEPDIR)/webserver.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) @@ -167,6 +174,8 @@ distclean-compile: -rm -f *.tab.c include ./$(DEPDIR)/configfile.Po +include ./$(DEPDIR)/daap-proto.Po +include ./$(DEPDIR)/daap.Po include ./$(DEPDIR)/err.Po include ./$(DEPDIR)/mDNS.Po include ./$(DEPDIR)/mDNSPosix.Po diff --git a/src/main.c b/src/main.c index 0152fdd5..2981ff67 100644 --- a/src/main.c +++ b/src/main.c @@ -33,6 +33,8 @@ #include #include "configfile.h" +#include "daap.h" +#include "daap-proto.h" #include "err.h" #include "rend.h" #include "webserver.h" @@ -46,6 +48,67 @@ CONFIG config; +/* + * daap_handler + * + * Handle daap-related web pages + */ +void daap_handler(WS_CONNINFO *pwsc) { + int len; + int close; + DAAP_BLOCK *root,*error; + int compress=0; + + close=pwsc->close; + pwsc->close=1; + + ws_addresponseheader(pwsc,"Accept-Ranges","bytes"); + ws_addresponseheader(pwsc,"DAAP-Server","iTunes/4.1 (Mac OS X)"); + ws_addresponseheader(pwsc,"Content-Type","application/x-dmap-tagged"); + + + if(!strcasecmp(pwsc->uri,"/server-info")) { + root=daap_response_server_info(); + } else if (!strcasecmp(pwsc->uri,"/content-codes")) { + root=daap_response_content_codes(); + } else if (!strcasecmp(pwsc->uri,"/login")) { + root=daap_response_login(); + } else if (!strcasecmp(pwsc->uri,"/update")) { + root=daap_response_update(); + } else if (!strcasecmp(pwsc->uri,"/databases")) { + root=daap_response_databases(); + } else if (!strcasecmp(pwsc->uri,"/logout")) { + ws_returnerror(pwsc,204,"Logout Successful"); + return; + } else { + DPRINTF(ERR_WARN,"Bad handler! Can't find uri handler for %s\n", + pwsc->uri); + return; + } + + if(!root) + return; + + pwsc->close=close; + + ws_addresponseheader(pwsc,"Content-Length","%d",root->reported_size + 8); + + ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n"); + ws_emitheaders(pwsc); + + /* + if(ws_testrequestheader(pwsc,"Accept-Encoding","gzip")) { + ws_addresponseheader(pwsc,"Content-Encoding","gzip"); + compress=1; + } + */ + + daap_serialize(root,pwsc->fd,0); + daap_free(root); + + return; +} + /* * config_handler * @@ -164,6 +227,7 @@ void usage(char *program) { #ifdef DEBUG printf(" -d Debuglevel (0-9)\n"); #endif + printf(" -m Use mDNS\n"); printf(" -c Use configfile specified"); printf("\n\n"); } @@ -174,11 +238,12 @@ int main(int argc, char *argv[]) { WSCONFIG ws_config; WSHANDLE server; pid_t rendezvous_pid; + int use_mdns=0; #ifdef DEBUG - char *optval="d:c:"; + char *optval="d:c:m"; #else - char *optval="c:"; + char *optval="c:m"; #endif /* DEBUG */ printf("mt-daapd: version $Revision$\n"); @@ -195,6 +260,11 @@ int main(int argc, char *argv[]) { case 'c': configfile=optarg; break; + + case 'm': + use_mdns=1; + break; + default: usage(argv[0]); exit(EXIT_FAILURE); @@ -231,9 +301,16 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } - ws_registerhandler(server, "^.*$",config_handler,config_auth); + ws_registerhandler(server, "^.*$",config_handler,config_auth,1); + ws_registerhandler(server, "^/server-info$",daap_handler,NULL,0); + ws_registerhandler(server, "^/content-codes$",daap_handler,NULL,0); + ws_registerhandler(server,"^/login$",daap_handler,NULL,0); + ws_registerhandler(server,"^/update$",daap_handler,NULL,0); + ws_registerhandler(server,"^/databases$",daap_handler,NULL,0); + ws_registerhandler(server,"^/logout$",daap_handler,NULL,0); - rend_init(&rendezvous_pid); + if(use_mdns) + rend_init(&rendezvous_pid); while(1) { sleep(20); diff --git a/src/webserver.c b/src/webserver.c index a4e0f02c..fa479c9e 100644 --- a/src/webserver.c +++ b/src/webserver.c @@ -25,12 +25,13 @@ #include #include +#include #include #include #include #include #include -#include +#include #include #include @@ -43,7 +44,7 @@ */ #define MAX_HOSTNAME 256 -#define MAX_LINEBUFFER 256 +#define MAX_LINEBUFFER 1024 /* * Local (private) typedefs @@ -53,6 +54,7 @@ typedef struct tag_ws_handler { regex_t regex; void (*req_handler)(WS_CONNINFO*); int(*auth_handler)(char *, char *); + int addheaders; struct tag_ws_handler *next; } WS_HANDLER; @@ -91,16 +93,22 @@ int ws_testarg(ARGLIST *root, char *key, char *value); void ws_emitheaders(WS_CONNINFO *pwsc); int ws_findhandler(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc, void(**preq)(WS_CONNINFO*), - int(**pauth)(char *, char *)); + int(**pauth)(char *, char *), + int *addheaders); int ws_registerhandler(WSHANDLE ws, char *regex, void(*handler)(WS_CONNINFO*), - int(*auth)(char *, char *)); + int(*auth)(char *, char *), + int addheaders); int ws_decodepassword(char *header, char **username, char **password); +int ws_testrequestheader(WS_CONNINFO *pwsc, char *header, char *value); /* * Globals */ pthread_mutex_t munsafe=PTHREAD_MUTEX_INITIALIZER; +char *ws_dow[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; +char *ws_moy[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", + "Aug", "Sep", "Oct", "Nov", "Dec" }; /* * ws_lock_unsafe @@ -517,6 +525,9 @@ void *ws_dispatcher(void *arg) { int connection_done=0; int can_dispatch; char *auth, *username, *password; + int hdrs,handler; + time_t now; + struct tm now_tm; void (*req_handler)(WS_CONNINFO*); int(*auth_handler)(char *, char *); @@ -546,6 +557,7 @@ void *ws_dispatcher(void *arg) { pwsc->error=EINVAL; free(argvp[0]); ws_returnerror(pwsc,400,"Bad request"); + ws_close(pwsc); return NULL; } @@ -558,6 +570,7 @@ void *ws_dispatcher(void *arg) { pwsc->error=EINVAL; free(argvp[0]); ws_returnerror(pwsc,501,"Not implemented"); + ws_close(pwsc); return NULL; } @@ -575,18 +588,6 @@ void *ws_dispatcher(void *arg) { * decide whether or not this is a persistant * connection */ - pwsc->close=!ws_testarg(&pwsc->request_headers,"connection", - "keep-alive"); - - ws_addarg(&pwsc->response_headers,"Connection", - pwsc->close ? "close" : "keep-alive"); - - ws_addarg(&pwsc->response_headers,"Server", - "mt-daapd/%s",VERSION); - - ws_addarg(&pwsc->response_headers,"Content-Type","text/html"); - ws_addarg(&pwsc->response_headers,"Content-Language","en_us"); - pwsc->uri=strdup(argvp[1]); free(argvp[0]); @@ -597,6 +598,7 @@ void *ws_dispatcher(void *arg) { DPRINTF(ERR_FATAL,"Thread %d: Error allocation URI\n", pwsc->threadno); ws_returnerror(pwsc,500,"Internal server error"); + ws_close(pwsc); return NULL; } @@ -625,8 +627,37 @@ void *ws_dispatcher(void *arg) { if(pwsc->request_type == RT_POST) ws_getpostvars(pwsc); + hdrs=1; + + handler=ws_findhandler(pwsp,pwsc,&req_handler,&auth_handler,&hdrs); + + time(&now); + DPRINTF(ERR_DEBUG,"Thread %d: Time is %d seconds after epoch\n", + pwsc->threadno,now); + gmtime_r(&now,&now_tm); + DPRINTF(ERR_DEBUG,"Thread %d: Setting time header\n",pwsc->threadno); + ws_addarg(&pwsc->response_headers,"Date", + "%s, %d %s %d %02d:%02d:%02d GMT", + ws_dow[now_tm.tm_wday],now_tm.tm_mday, + ws_moy[now_tm.tm_mon],now_tm.tm_year + 1900, + now_tm.tm_hour,now_tm.tm_min,now_tm.tm_sec); + + pwsc->close=ws_testarg(&pwsc->request_headers,"connection", + "close"); + + if(hdrs) { + ws_addarg(&pwsc->response_headers,"Connection", + pwsc->close ? "close" : "keep-alive"); + + ws_addarg(&pwsc->response_headers,"Server", + "mt-daapd/%s",VERSION); + + ws_addarg(&pwsc->response_headers,"Content-Type","text/html"); + ws_addarg(&pwsc->response_headers,"Content-Language","en_us"); + } + /* Find the appropriate handler and dispatch it */ - if(ws_findhandler(pwsp,pwsc,&req_handler,&auth_handler) == -1) { + if(handler == -1) { DPRINTF(ERR_DEBUG,"Thread %d: Using default handler.\n", pwsc->threadno); ws_defaulthandler(pwsp,pwsc); @@ -651,14 +682,14 @@ void *ws_dispatcher(void *arg) { "Basic realm=\"webserver\""); pwsc->close=1; ws_returnerror(pwsc,401,"Unauthorized"); + ws_close(pwsc); return NULL; } - - if(req_handler) - req_handler(pwsc); - else - ws_defaulthandler(pwsp,pwsc); } + if(req_handler) + req_handler(pwsc); + else + ws_defaulthandler(pwsp,pwsc); } if((pwsc->close)||(pwsc->error)) @@ -713,7 +744,6 @@ int ws_returnerror(WS_CONNINFO *pwsc,int error, char *description) { ws_writefd(pwsc,"\r\n\r\n"); - ws_close(pwsc); return 0; } @@ -797,6 +827,7 @@ void ws_defaulthandler(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc) { pwsc->error=errno; DPRINTF(ERR_WARN,"Cannot resolve %s\n",path); ws_returnerror(pwsc,404,"Not found"); + ws_close(pwsc); return; } @@ -809,6 +840,7 @@ void ws_defaulthandler(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc) { DPRINTF(ERR_WARN,"Thread %d: Requested file %s out of root\n", pwsc->threadno,resolved_path); ws_returnerror(pwsc,403,"Forbidden"); + ws_close(pwsc); return; } @@ -818,6 +850,7 @@ void ws_defaulthandler(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc) { DPRINTF(ERR_WARN,"Thread %d: Error opening %s: %s\n", pwsc->threadno,resolved_path,strerror(errno)); ws_returnerror(pwsc,404,"Not found"); + ws_close(pwsc); return; } @@ -845,6 +878,18 @@ void ws_defaulthandler(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc) { } +/* + * ws_testrequestheader + * + * Check to see if a request header is a particular value + * + * Example: + * + */ +int ws_testrequestheader(WS_CONNINFO *pwsc, char *header, char *value) { + return ws_testarg(&pwsc->request_headers,header,value); +} + /* * ws_testarg * @@ -1025,7 +1070,8 @@ char *ws_urldecode(char *string) { */ int ws_registerhandler(WSHANDLE ws, char *regex, void(*handler)(WS_CONNINFO*), - int(*auth)(char *, char *)) { + int(*auth)(char *, char *), + int addheaders) { WS_HANDLER *phandler; WS_PRIVATE *pwsp = (WS_PRIVATE *)ws; @@ -1041,6 +1087,7 @@ int ws_registerhandler(WSHANDLE ws, char *regex, phandler->req_handler=handler; phandler->auth_handler=auth; + phandler->addheaders=addheaders; ws_lock_unsafe(); phandler->next=pwsp->handlers.next; @@ -1060,7 +1107,8 @@ int ws_registerhandler(WSHANDLE ws, char *regex, */ int ws_findhandler(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc, void(**preq)(WS_CONNINFO*), - int(**pauth)(char *, char *)) { + int(**pauth)(char *, char *), + int *addheaders) { WS_HANDLER *phandler=pwsp->handlers.next; ws_lock_unsafe(); @@ -1074,6 +1122,7 @@ int ws_findhandler(WS_PRIVATE *pwsp, WS_CONNINFO *pwsc, DPRINTF(ERR_DEBUG,"Thread %d: URI Match!\n",pwsc->threadno); *preq=phandler->req_handler; *pauth=phandler->auth_handler; + *addheaders=phandler->addheaders; ws_unlock_unsafe(); return 0; } @@ -1202,8 +1251,15 @@ int ws_decodepassword(char *header, char **username, char **password) { * * Simple wrapper around the CONNINFO response headers */ -int ws_addresponseheader(WS_CONNINFO *pwsc, char *header, char *val) { - return ws_addarg(&pwsc->response_headers,header,val); +int ws_addresponseheader(WS_CONNINFO *pwsc, char *header, char *fmt, ...) { + va_list ap; + char value[MAX_LINEBUFFER]; + + va_start(ap,fmt); + vsnprintf(value,sizeof(value),fmt,ap); + va_end(ap); + + return ws_addarg(&pwsc->response_headers,header,value); } /* diff --git a/src/webserver.h b/src/webserver.h index 747f47fb..9bbe8687 100644 --- a/src/webserver.h +++ b/src/webserver.h @@ -71,12 +71,14 @@ extern WSHANDLE ws_start(WSCONFIG *config); extern int ws_stop(WSHANDLE ws); extern int ws_registerhandler(WSHANDLE ws, char *regex, void(*handler)(WS_CONNINFO*), - int(*auth)(char *, char *)); + int(*auth)(char *, char *), + int addheaders); /* for handlers */ extern void ws_close(WS_CONNINFO *pwsc); extern int ws_returnerror(WS_CONNINFO *pwsc, int error, char *description); -extern int ws_addresponseheader(WS_CONNINFO *pwsc, char *header, char *val); +extern int ws_addresponseheader(WS_CONNINFO *pwsc, char *header, char *fmt, ...); extern int ws_writefd(WS_CONNINFO *pwsc, char *fmt, ...); extern char *ws_getvar(WS_CONNINFO *pwsc, char *var); +extern int ws_testrequestheader(WS_CONNINFO *pwsc, char *header, char *value); #endif /* _WEBSERVER_H_ */