diff --git a/Makefile b/Makefile index cb62247..0dcb830 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ BASEOBJS = minidlna.o upnphttp.o upnpdescgen.o upnpsoap.o \ getifaddr.o daemonize.o upnpglobalvars.o \ options.o minissdp.o upnpevents.o \ sql.o utils.o metadata.o albumart.o scanner.o inotify.o \ + tivo_utils.o tivo_beacon.o tivo_commands.o \ log.o ALLOBJS = $(BASEOBJS) $(LNXOBJS) diff --git a/genconfig.sh b/genconfig.sh index c5e810e..607f5c8 100755 --- a/genconfig.sh +++ b/genconfig.sh @@ -140,10 +140,6 @@ echo "/*#define HAVE_INOTIFY_H*/" >> ${CONFIGFILE} fi echo "" >> ${CONFIGFILE} -echo "/* Experimental UPnP Events support. */" >> ${CONFIGFILE} -echo "#define ENABLE_EVENTS" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - echo "/* Enable NETGEAR ReadyNAS-specific tweaks. */" >> ${CONFIGFILE} echo "/*#define READYNAS*/" >> ${CONFIGFILE} echo "" >> ${CONFIGFILE} diff --git a/log.c b/log.c index 9baa85d..cca5320 100644 --- a/log.c +++ b/log.c @@ -35,6 +35,7 @@ char *facility_name[] = { "metadata", "http", "ssdp", + "tivo", 0 }; diff --git a/log.h b/log.h index 7b6fee3..5914a16 100644 --- a/log.h +++ b/log.h @@ -33,6 +33,7 @@ enum _log_facility L_METADATA, L_HTTP, L_SSDP, + L_TIVO, L_MAX }; diff --git a/minidlna.c b/minidlna.c index 6a755ea..bd96c9f 100644 --- a/minidlna.c +++ b/minidlna.c @@ -46,6 +46,9 @@ #include "inotify.h" #include "commonrdr.h" #include "log.h" +#ifdef ENABLE_TIVO +#include "tivo_beacon.h" +#endif /* MAX_LAN_ADDR : maximum number of interfaces * to listen to SSDP traffic */ @@ -509,7 +512,7 @@ init(int argc, char * * argv) if(debug_flag) { pid = getpid(); - log_init(NULL, "general,artwork,database,inotify,scanner,metadata,http,ssdp=debug"); + log_init(NULL, "general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=debug"); } else { @@ -579,10 +582,8 @@ main(int argc, char * * argv) struct upnphttp * e = 0; struct upnphttp * next; fd_set readset; /* for select() */ -#ifdef ENABLE_EVENTS fd_set writeset; -#endif - struct timeval timeout, timeofday, lasttimeofday = {0, 0}; + struct timeval timeout, timeofday, lasttimeofday = {0, 0}, lastupdatetime = {0, 0}; int max_fd = -1; int last_changecnt = 0; char * sql; @@ -658,6 +659,21 @@ main(int argc, char * * argv) "messages. EXITING\n"); } + #ifdef ENABLE_TIVO + /* open socket for sending Tivo notifications */ + unsigned short int loop_cnt = 0; + int sbeacon = OpenAndConfTivoBeaconSocket(); + struct sockaddr_in bcast; + if(sbeacon < 0) + { + DPRINTF(E_FATAL, L_GENERAL, "Failed to open sockets for sending Tivo beacon notify " + "messages. EXITING\n"); + } + bcast.sin_family = AF_INET; + bcast.sin_addr.s_addr = htonl(getBcastAddress()); + bcast.sin_port = htons( 2190 ); + #endif + SendSSDPGoodbye(snotify, n_lan_addr); /* main loop */ @@ -700,7 +716,7 @@ main(int argc, char * * argv) timeout.tv_usec = lasttimeofday.tv_usec - timeofday.tv_usec; } } - if(timeofday.tv_sec >= (lasttimeofday.tv_sec + 2)) + if(timeofday.tv_sec >= (lastupdatetime.tv_sec + 2)) { if( sqlite3_total_changes(db) != last_changecnt ) { @@ -708,6 +724,23 @@ main(int argc, char * * argv) last_changecnt = sqlite3_total_changes(db); upnp_event_var_change_notify(EContentDirectory); } + #ifdef ENABLE_TIVO + if( loop_cnt < 10 ) + { + sendBeaconMessage(sbeacon, &bcast, sizeof(struct sockaddr_in), 1); + loop_cnt++; + } + else + { + if( loop_cnt == 30 ) + { + sendBeaconMessage(sbeacon, &bcast, sizeof(struct sockaddr_in), 1); + loop_cnt = 10; + } + loop_cnt++; + } + #endif + memcpy(&lastupdatetime, &timeofday, sizeof(struct timeval)); } } @@ -744,24 +777,16 @@ main(int argc, char * * argv) } #endif -#ifdef ENABLE_EVENTS FD_ZERO(&writeset); upnpevents_selectfds(&readset, &writeset, &max_fd); -#endif -#ifdef ENABLE_EVENTS if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0) -#else - if(select(max_fd+1, &readset, 0, 0, &timeout) < 0) -#endif { if(quitting) goto shutdown; DPRINTF(E_ERROR, L_GENERAL, "select(all): %s\n", strerror(errno)); DPRINTF(E_FATAL, L_GENERAL, "Failed to select open sockets. EXITING\n"); } -#ifdef ENABLE_EVENTS upnpevents_processfds(&readset, &writeset); -#endif /* process SSDP packets */ if(sudp >= 0 && FD_ISSET(sudp, &readset)) { diff --git a/minidlna.conf b/minidlna.conf index c09c8ee..279933e 100644 --- a/minidlna.conf +++ b/minidlna.conf @@ -1,9 +1,6 @@ # port for HTTP (descriptions and SOAP) traffic port=5555 -# enable UPNP support (default is yes) -enable_upnp=yes - # set this to the directory you want scanned. # * if have multiple directories, you can have multiple media_dir= lines # * if you want to restrict a media_dir to a specific content type, you diff --git a/options.c b/options.c index c2e57d5..f9a7bdc 100644 --- a/options.c +++ b/options.c @@ -30,7 +30,6 @@ static const struct { { UPNPUUID, "uuid"}, { UPNPSERIAL, "serial"}, { UPNPMODEL_NUMBER, "model_number"}, - { UPNPENABLE, "enable_upnp"}, { UPNPFRIENDLYNAME, "friendly_name"}, { UPNPMEDIADIR, "media_dir"}, { UPNPALBUMART_NAMES, "album_art_names"}, diff --git a/options.h b/options.h index 090b019..8d4727e 100644 --- a/options.h +++ b/options.h @@ -26,8 +26,7 @@ enum upnpconfigoptions { UPNPFRIENDLYNAME, /* how the system should show up to DLNA clients */ UPNPMEDIADIR, /* directory to search for UPnP-A/V content */ UPNPALBUMART_NAMES, /* list of '/'-delimited file names to check for album art */ - UPNPINOTIFY, /* enable inotify on the media directories */ - UPNPENABLE /* enable_upnp */ + UPNPINOTIFY /* enable inotify on the media directories */ }; /* readoptionsfile() diff --git a/testupnpdescgen.c b/testupnpdescgen.c index 96a93d1..f366c5b 100644 --- a/testupnpdescgen.c +++ b/testupnpdescgen.c @@ -109,8 +109,6 @@ main(int argc, char * * argv) xml_pretty_print(s, l, stdout); free(s); printf("\n-------------\n"); -#ifdef ENABLE_EVENTS -#endif /* stupid_test(); */ diff --git a/tivo_beacon.c b/tivo_beacon.c new file mode 100644 index 0000000..3056025 --- /dev/null +++ b/tivo_beacon.c @@ -0,0 +1,293 @@ +/* + * Linux/C based server for TiVo Home Media Option protocol + * + * Based on version 1.5.1 of + * "TiVo Connect Automatic Machine; Discovery Protocol Specification" + * Based on version 1.1.0 of + * "TiVo Home Media Option; Music and Photos Server Protocol Specification" + * + * Dave Clemans, April 2003 + * + * Copyright (C) 2003 Dave Clemans + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * See the file "COPYING" for more details. + */ +#ifdef ENABLE_TIVO +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "tivo_beacon.h" +#include "upnpglobalvars.h" +#include "log.h" + +static struct aBeacon* topBeacon = NULL; + +/* OpenAndConfHTTPSocket() : + * setup the socket used to handle incoming HTTP connections. */ +int +OpenAndConfTivoBeaconSocket() +{ + int s; + int i = 1; + struct sockaddr_in beacon; + + if( (s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + { + DPRINTF(E_ERROR, L_TIVO, "socket(http): %s\n", strerror(errno)); + return -1; + } + + if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0) + { + DPRINTF(E_WARN, L_TIVO, "setsockopt(http, SO_REUSEADDR): %s\n", strerror(errno)); + } + + memset(&beacon, 0, sizeof(struct sockaddr_in)); + beacon.sin_family = AF_INET; + beacon.sin_port = htons(2190); + beacon.sin_addr.s_addr = htonl(INADDR_ANY); + + if(bind(s, (struct sockaddr *)&beacon, sizeof(struct sockaddr_in)) < 0) + { + DPRINTF(E_ERROR, L_TIVO, "bind(http): %s\n", strerror(errno)); + close(s); + return -1; + } + i = 1; + if(setsockopt(s, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i)) < 0 ) + { + DPRINTF(E_WARN, L_TIVO, "setsockopt(http, SO_BROADCAST): %s\n", strerror(errno)); + close(s); + return -1; + } + + return s; +} + +/* + * Returns the interface broadcast address to be used for beacons + */ +uint32_t getBcastAddress( void ) +{ + struct ifreq ifr; + struct sockaddr_in *sin; + int s, rval; + static int ifacePrinted = 0; + + s = socket( AF_INET, SOCK_DGRAM, 0 ); + if ( s < 0 ) + { + return INADDR_BROADCAST; + } + + strcpy( ifr.ifr_name, "eth0" ); + rval = ioctl( s, SIOCGIFBRDADDR, &ifr ); + if ( rval < 0 ) + { + close(s); + return INADDR_BROADCAST; + } + + sin = (struct sockaddr_in *)&ifr.ifr_broadaddr; + if( !ifacePrinted ) + { + printf( "Interface: %s broadcast addr %s \n", "eth0", inet_ntoa(sin->sin_addr) ); + ifacePrinted = 1; + } + + close(s); + + return ntohl((uint32_t)(sin->sin_addr.s_addr)); +} + +/* + * Send outgoing beacon to the specified address + * This will either be a specific or broadcast address + */ +void +sendBeaconMessage(int fd, struct sockaddr_in * client, int len, int broadcast) +{ + char * mesg; + int mesg_len; + time_t now = time(NULL); + + mesg_len = asprintf(&mesg, "TiVoConnect=1\n" + "swversion=%s\n" + "method=%s\n" + "identity=%s\n" + "machine=%s\n" + "platform=pc/minidlna\n" + "services=TiVoMediaServer:%d/http\n", + "1.0", + broadcast ? "broadcast" : "connected", + uuidvalue, friendly_name, runtime_vars.port); + printf("Sending beacon at %s%s", ctime(&now), mesg); + sendto(fd, mesg, mesg_len, 0, (struct sockaddr*)client, len); + free(mesg); +} + +/* + * Parse and save a received beacon packet from another server, or from + * a TiVo. + * + * Returns true if this was a broadcast beacon msg + */ +int +rcvBeaconMessage(char * beacon) +{ + char * tivoConnect = NULL; + char * swVersion = NULL; + char * method = NULL; + char * identity = NULL; + char * machine = NULL; + char * platform = NULL; + char * services = NULL; + char * cp; + char * scp; + char * tokptr; + struct aBeacon * b; + int len; + time_t current; + char buf[32]; + static time_t lastSummary = 0; + + cp = strtok_r( beacon, "=\r\n", &tokptr ); + while( cp != NULL ) + { + scp = cp; + cp = strtok_r( NULL, "=\r\n", &tokptr ); + if( strcasecmp( scp, "tivoconnect" ) == 0 ) + tivoConnect = cp; + else if( strcasecmp( scp, "swversion" ) == 0 ) + swVersion = cp; + else if( strcasecmp( scp, "method" ) == 0 ) + method = cp; + else if( strcasecmp( scp, "identity" ) == 0 ) + identity = cp; + else if( strcasecmp( scp, "machine" ) == 0 ) + machine = cp; + else if( strcasecmp( scp, "platform" ) == 0 ) + platform = cp; + else if( strcasecmp( scp, "services" ) == 0 ) + services = cp; + cp = strtok_r( NULL, "=\r\n", &tokptr ); + } + + if( tivoConnect == NULL ) + return 0; + + current = time( NULL ); + for( b = topBeacon; b != NULL; b = b->next ) + { + if( strcasecmp( machine, b->machine ) == 0 || + strcasecmp( identity, b->identity ) == 0 ) + { + break; + } + } + if( b == NULL ) + { + b = ( struct aBeacon* ) calloc( 1, sizeof( *b ) ); + b->next = NULL; + + if ( machine ) + { + b->machine = ( char* ) malloc( strlen( machine ) + 1 ); + strcpy( b->machine, machine ); + } + if ( identity ) + { + b->identity = ( char* ) malloc( strlen( identity ) + 1 ); + strcpy( b->identity, identity ); + } + if ( swVersion ) + { + b->swversion = ( char* ) malloc( strlen( swVersion ) + 1 ); + strcpy( b->swversion, swVersion ); + } + if ( method ) + { + b->method = ( char* ) malloc( strlen( method ) + 1 ); + strcpy( b->method, method ); + } + if ( platform ) + { + b->platform = ( char* ) malloc( strlen( platform ) + 1 ); + strcpy( b->platform, platform ); + } + if ( services ) + { + b->services = ( char* ) malloc( strlen( services ) + 1 ); + strcpy( b->services, services ); + } + + b->next = topBeacon; + topBeacon = b; + + printf( "Received new beacon: machine(%s) platform(%s) services(%s)\n", + b->machine ? b->machine : "-", + b->platform ? b->platform : "-", + b->services ? b->services : "-" ); + } + b->lastSeen = current; + + if( lastSummary == 0 ) + lastSummary = current; + if( lastSummary + 1800 < current ) + { /* Give a summary of received server beacons every half hour or so */ + len = 0; + for( b = topBeacon; b != NULL; b = b->next ) + { + len += strlen( b->machine ) + 32; + } + scp = ( char* ) malloc( len + 128 ); + strcpy( scp, "Known servers: " ); + for( b = topBeacon; b != NULL; b = b->next ) + { + strcat( scp, b->machine ); + sprintf( buf, "(%ld)", current - b->lastSeen ); + strcat( scp, buf ); + if( b->next != NULL ) + strcat( scp, "," ); + } + strcat(scp, "\n"); + printf("%s\n", scp); + free(scp); + lastSummary = current; + } + + if( strcasecmp( method, "broadcast" ) == 0 ) + return 1; + return 0; +} +#endif // ENABLE_TIVO diff --git a/tivo_beacon.h b/tivo_beacon.h new file mode 100644 index 0000000..2819891 --- /dev/null +++ b/tivo_beacon.h @@ -0,0 +1,25 @@ +#ifdef ENABLE_TIVO +/* + * * A saved copy of a beacon from another tivo or another server + * */ +struct aBeacon +{ + time_t lastSeen; + char* machine; + char* identity; + char* platform; + char* swversion; + char* method; + char* services; + struct aBeacon* next; +}; + + +uint32_t getBcastAddress( void ); + +int +OpenAndConfTivoBeaconSocket(); + +void +sendBeaconMessage(int fd, struct sockaddr_in * client, int len, int broadcast); +#endif diff --git a/tivo_commands.c b/tivo_commands.c new file mode 100644 index 0000000..37ebb7c --- /dev/null +++ b/tivo_commands.c @@ -0,0 +1,95 @@ +#ifdef ENABLE_TIVO +#include +#include + +#include "tivo_utils.h" +#include "upnpglobalvars.h" +#include "upnphttp.h" +#include "log.h" + +void +SendRootContainer(struct upnphttp * h) +{ + char * resp; + int len; + + len = asprintf(&resp, "\n" + "" + "
" + "x-container/tivo-server" + "x-container/folder" + "0" + "2" + "%s" + "
" + "0" + "2" + "" + "
" + "x-container/tivo-photos" + "x-container/folder" + "Pictures" + "
" + "" + "" + "/TiVoConnect?Command=QueryContainer&Container=3" + "" + "" + "
" + "" + "
" + "x-container/tivo-music" + "x-container/folder" + "Music" + "
" + "" + "" + "/TiVoConnect?Command=QueryContainer&Container=1" + "" + "" + "
" + "
", friendly_name); + BuildResp_upnphttp(h, resp, len); + SendResp_upnphttp(h); +} + +void +ProcessTiVoCommand(struct upnphttp * h, const char * orig_path) +{ + char *path; + char *key, *val; + char *saveptr, *item; + char *command = NULL, *container = NULL; + + path = decodeString(orig_path); + DPRINTF(E_DEBUG, L_GENERAL, "Processing TiVo command %s\n", path); + + item = strtok_r( path, "&", &saveptr ); + while( item != NULL ) + { + if( strlen( item ) == 0 ) + { + item = strtok_r( NULL, "&", &saveptr ); + continue; + } + val = item; + key = strsep(&val, "="); + DPRINTF(E_DEBUG, L_GENERAL, "%s: %s\n", key, val); + if( strcasecmp(key, "command") == 0 ) + { + command = val; + } + else if( strcasecmp(key, "container") == 0 ) + { + container = val; + } + item = strtok_r( NULL, "&", &saveptr ); + } + + if( !container || (strcmp(container, "/") == 0) ) + { + SendRootContainer(h); + } + CloseSocket_upnphttp(h); +} +#endif // ENABLE_TIVO diff --git a/tivo_commands.h b/tivo_commands.h new file mode 100644 index 0000000..67e4152 --- /dev/null +++ b/tivo_commands.h @@ -0,0 +1,4 @@ +#ifdef ENABLE_TIVO +void +ProcessTiVoCommand(struct upnphttp * h, const char * orig_path); +#endif diff --git a/tivo_utils.c b/tivo_utils.c new file mode 100644 index 0000000..8e0546a --- /dev/null +++ b/tivo_utils.c @@ -0,0 +1,47 @@ +#ifdef ENABLE_TIVO +#include +#include +#include + +/* This function stolen from byRequest */ +char * +decodeString(const char * string) +{ + if( !string ) + return NULL; + + int alloc = (int)strlen(string)+1; + char *ns = malloc(alloc); + unsigned char in; + int strindex=0; + long hex; + + if( !ns ) + return NULL; + + while(--alloc > 0) + { + in = *string; + if(('%' == in) && isxdigit(string[1]) && isxdigit(string[2])) + { + /* this is two hexadecimal digits following a '%' */ + char hexstr[3]; + char *ptr; + hexstr[0] = string[1]; + hexstr[1] = string[2]; + hexstr[2] = 0; + + hex = strtol(hexstr, &ptr, 16); + + in = (unsigned char)hex; /* this long is never bigger than 255 anyway */ + string+=2; + alloc-=2; + } + + ns[strindex++] = in; + string++; + } + ns[strindex]=0; /* terminate it */ + return ns; +} +#endif diff --git a/tivo_utils.h b/tivo_utils.h new file mode 100644 index 0000000..06f680b --- /dev/null +++ b/tivo_utils.h @@ -0,0 +1,4 @@ +#ifdef ENABLE_TIVO +char * +decodeString(const char * string); +#endif diff --git a/upnpdescgen.c b/upnpdescgen.c index 637d44d..6a08f26 100644 --- a/upnpdescgen.c +++ b/upnpdescgen.c @@ -691,13 +691,7 @@ genServiceDesc(int * len, const struct serviceDesc * s) { str = strcat_str(str, len, &tmplen, ""); str = strcat_str(str, len, &tmplen, vars[i].name); str = strcat_str(str, len, &tmplen, ""); @@ -755,7 +749,6 @@ genX_MS_MediaReceiverRegistrar(int * len) return genServiceDesc(len, &scpdX_MS_MediaReceiverRegistrar); } -#ifdef ENABLE_EVENTS static char * genEventVars(int * len, const struct serviceDesc * s, const char * servns) { @@ -825,4 +818,3 @@ getVarsX_MS_MediaReceiverRegistrar(int * l) "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1"); } -#endif diff --git a/upnpdescgen.h b/upnpdescgen.h index 054e069..ee3991b 100644 --- a/upnpdescgen.h +++ b/upnpdescgen.h @@ -68,7 +68,6 @@ genWANIPCn(int * len); char * genWANCfg(int * len); -#ifdef ENABLE_EVENTS char * getVarsContentDirectory(int * len); @@ -77,7 +76,6 @@ getVarsConnectionManager(int * len); char * getVarsX_MS_MediaReceiverRegistrar(int * len); -#endif #endif diff --git a/upnpevents.c b/upnpevents.c index 300ce7e..ad9d2ab 100644 --- a/upnpevents.c +++ b/upnpevents.c @@ -32,13 +32,6 @@ #include #endif -#ifdef ENABLE_EVENTS -/*enum subscriber_service_enum { - EWanCFG = 1, - EWanIPC, - EL3F -};*/ - /* stuctures definitions */ struct subscriber { LIST_ENTRY(subscriber) entries; @@ -483,6 +476,3 @@ void write_events_details(int s) { } } #endif - -#endif - diff --git a/upnpevents.h b/upnpevents.h index b685538..253e0c6 100644 --- a/upnpevents.h +++ b/upnpevents.h @@ -6,7 +6,6 @@ #ifndef __UPNPEVENTS_H__ #define __UPNPEVENTS_H__ -#ifdef ENABLE_EVENTS enum subscriber_service_enum { EContentDirectory = 1, EConnectionManager, @@ -35,4 +34,3 @@ void write_events_details(int s); #endif #endif -#endif diff --git a/upnpglobalvars.c b/upnpglobalvars.c index b21fadc..27e16ff 100644 --- a/upnpglobalvars.c +++ b/upnpglobalvars.c @@ -40,4 +40,4 @@ char friendly_name[FRIENDLYNAME_MAX_LEN]; struct media_dir_s * media_dirs = NULL; struct album_art_name_s * album_art_names = NULL; short int scanning = 0; -__u32 updateID = 0; +volatile __u32 updateID = 0; diff --git a/upnpglobalvars.h b/upnpglobalvars.h index c27ec10..681af97 100644 --- a/upnpglobalvars.h +++ b/upnpglobalvars.h @@ -86,6 +86,6 @@ extern char friendly_name[]; extern struct media_dir_s * media_dirs; extern struct album_art_name_s * album_art_names; extern short int scanning; -extern __u32 updateID; +extern volatile __u32 updateID; #endif diff --git a/upnphttp.c b/upnphttp.c index b99341f..8faf55b 100644 --- a/upnphttp.c +++ b/upnphttp.c @@ -39,6 +39,10 @@ #if 0 //JPEG_RESIZE #include #endif +#ifdef ENABLE_TIVO +#include "tivo_utils.h" +#include "tivo_commands.h" +#endif //#define MAX_BUFFER_SIZE 4194304 // 4MB -- Too much? #define MAX_BUFFER_SIZE 2147483647 // 2GB -- Too much? @@ -122,7 +126,6 @@ ParseHttpHeaders(struct upnphttp * h) h->req_soapAction = p; h->req_soapActionLen = n; } -#ifdef ENABLE_EVENTS else if(strncasecmp(line, "Callback", 8)==0) { p = colon; @@ -161,8 +164,6 @@ intervening space) by either an integer or the keyword "infinite". */ h->req_Timeout = atoi(p+7); } } -#endif -#if 1 // Range: bytes=xxx-yyy else if(strncasecmp(line, "Range", 5)==0) { @@ -235,7 +236,6 @@ intervening space) by either an integer or the keyword "infinite". */ h->reqflags |= FLAG_XFERBACKGROUND; } } -#endif } while(!(line[0] == '\r' && line[1] == '\n')) line++; @@ -406,7 +406,6 @@ ProcessHTTPPOST_upnphttp(struct upnphttp * h) } } -#ifdef ENABLE_EVENTS static void ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path) { @@ -472,7 +471,6 @@ ProcessHTTPUnSubscribe_upnphttp(struct upnphttp * h, const char * path) SendResp_upnphttp(h); CloseSocket_upnphttp(h); } -#endif /* Parse and process Http Query * called once all the HTTP headers have been received. */ @@ -589,6 +587,20 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h) SendResp_albumArt(h, HttpUrl+10); CloseSocket_upnphttp(h); } + #ifdef ENABLE_TIVO + else if(strncmp(HttpUrl, "/TiVoConnect", 12) == 0) + { + if( *(HttpUrl+12) == '?' ) + { + ProcessTiVoCommand(h, HttpUrl+13); + } + else if( *(HttpUrl+12) == '/' ) + { + printf("TiVo request: %c\n", *(HttpUrl+12)); + Send404(h); + } + } + #endif #if 0 //JPEG_RESIZE else if(strncmp(HttpUrl, "/Resized/", 7) == 0) { @@ -734,7 +746,6 @@ BuildHeader_upnphttp(struct upnphttp * h, int respcode, (h->respflags&FLAG_HTML)?"text/html":"text/xml; charset=\"utf-8\"", bodylen); /* Additional headers */ -#ifdef ENABLE_EVENTS if(h->respflags & FLAG_TIMEOUT) { h->res_buflen += snprintf(h->res_buf + h->res_buflen, h->res_buf_alloclen - h->res_buflen, @@ -755,7 +766,6 @@ BuildHeader_upnphttp(struct upnphttp * h, int respcode, h->res_buf_alloclen - h->res_buflen, "SID: %s\r\n", h->req_SID); } -#endif #if 0 // DLNA h->res_buflen += snprintf(h->res_buf + h->res_buflen, h->res_buf_alloclen - h->res_buflen, diff --git a/upnphttp.h b/upnphttp.h index 76b4144..89e4cc2 100644 --- a/upnphttp.h +++ b/upnphttp.h @@ -49,13 +49,11 @@ struct upnphttp { enum clientType req_client; const char * req_soapAction; int req_soapActionLen; -#ifdef ENABLE_EVENTS const char * req_Callback; /* For SUBSCRIBE */ int req_CallbackLen; int req_Timeout; const char * req_SID; /* For UNSUBSCRIBE */ int req_SIDLen; -#endif long long int req_RangeStart; long long int req_RangeEnd; long int req_chunklen;