diff --git a/minidlna.c b/minidlna.c index 4f37349..1e2301a 100644 --- a/minidlna.c +++ b/minidlna.c @@ -344,7 +344,7 @@ init(int argc, char * * argv) enum media_types type; char * path; char real_path[PATH_MAX]; - char ext_ip_addr[INET_ADDRSTRLEN + 3] = {'\0'}; + char ip_addr[INET_ADDRSTRLEN + 3] = {'\0'}; /* first check if "-f" option is used */ for(i=2; i= 0) + for( string = ary_options[i].value; (word = strtok(string, ",")); string = NULL ) { - if( *ext_ip_addr && parselanaddr(&lan_addr[n_lan_addr], ext_ip_addr) == 0 ) - n_lan_addr++; + if(n_lan_addr < MAX_LAN_ADDR) + { + if(getifaddr(word, ip_addr, sizeof(ip_addr)) >= 0) + { + if( *ip_addr && parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0 ) + if(n_lan_addr < MAX_LAN_ADDR) + n_lan_addr++; + } + else + fprintf(stderr, "Interface %s not found, ignoring.\n", word); + } + else + { + fprintf(stderr, "Too many listening ips (max: %d), ignoring %s\n", + MAX_LAN_ADDR, word); + } } - else - fprintf(stderr, "Interface %s not found, ignoring.\n", ary_options[i].value); break; case UPNPLISTENING_IP: if(n_lan_addr < MAX_LAN_ADDR) @@ -482,7 +494,8 @@ init(int argc, char * * argv) } break; case UPNPALBUMART_NAMES: - for( string = ary_options[i].value; (word = strtok(string, "/")); string = NULL ) { + for( string = ary_options[i].value; (word = strtok(string, "/")); string = NULL ) + { struct album_art_name_s * this_name = calloc(1, sizeof(struct album_art_name_s)); int len = strlen(word); if( word[len-1] == '*' ) @@ -649,7 +662,7 @@ init(int argc, char * * argv) int address_already_there = 0; int j; i++; - if( getifaddr(argv[i], ext_ip_addr, sizeof(ext_ip_addr)) < 0 ) + if( getifaddr(argv[i], ip_addr, sizeof(ip_addr)) < 0 ) { fprintf(stderr, "Network interface '%s' not found.\n", argv[i]); @@ -658,7 +671,7 @@ init(int argc, char * * argv) for(j=0; jnext ) { @@ -241,10 +245,6 @@ rcvBeaconMessage(char * beacon) platform ? platform : "-", services ? services : "-" ); } -#ifdef DEBUG - int len; - char buf[32]; - static time_t lastSummary = 0; b->lastSeen = current; if( !lastSummary ) @@ -292,6 +292,21 @@ void ProcessTiVoBeacon(int s) (struct sockaddr *)&sendername, &len_r); if( n > 0 ) bufr[n] = '\0'; + + /* find which subnet the client is in */ + for(n = 0; nreqflags |= FLAG_HOST; + p = colon + 1; + while(isspace(*p)) + p++; + for(n = 0; niface = n; + break; + } + } } else if(strncasecmp(line, "User-Agent", 10)==0) { @@ -1847,7 +1864,7 @@ SendResp_dlnafile(struct upnphttp * h, char * object) if( sql_get_int_field(db, "SELECT ID from CAPTIONS where ID = '%lld'", id) > 0 ) { strcatf(&str, "CaptionInfo.sec: http://%s:%d/Captions/%lld.srt\r\n", - lan_addr[0].str, runtime_vars.port, id); + lan_addr[h->iface].str, runtime_vars.port, id); } } diff --git a/upnphttp.h b/upnphttp.h index 74134f7..339e28d 100644 --- a/upnphttp.h +++ b/upnphttp.h @@ -57,6 +57,7 @@ enum httpCommands { struct upnphttp { int socket; struct in_addr clientaddr; /* client address */ + int iface; int state; char HttpVer[16]; /* request */ @@ -77,11 +78,11 @@ struct upnphttp { off_t req_RangeEnd; long int req_chunklen; uint32_t reqflags; - uint32_t respflags; /* response */ char * res_buf; int res_buflen; int res_buf_alloclen; + uint32_t respflags; /*int res_contentlen;*/ /*int res_contentoff;*/ /* header length */ LIST_ENTRY(upnphttp) entries; diff --git a/upnpsoap.c b/upnpsoap.c index 90c907c..5af8746 100644 --- a/upnpsoap.c +++ b/upnpsoap.c @@ -552,16 +552,16 @@ parse_sort_criteria(char * sortCriteria, int * error) inline static void add_resized_res(int srcw, int srch, int reqw, int reqh, char *dlna_pn, - char *detailID, struct Response *passed_args) + char *detailID, struct Response *args) { int dstw = reqw; int dsth = reqh; - if( passed_args->flags & FLAG_NO_RESIZE ) + if( args->flags & FLAG_NO_RESIZE ) return; - strcatf(passed_args->str, "<res "); - if( passed_args->filter & FILTER_RES_RESOLUTION ) + strcatf(args->str, "<res "); + if( args->filter & FILTER_RES_RESOLUTION ) { dstw = reqw; dsth = ((((reqw<<10)/srcw)*srch)>>10); @@ -569,42 +569,43 @@ add_resized_res(int srcw, int srch, int reqw, int reqh, char *dlna_pn, dsth = reqh; dstw = (((reqh<<10)/srch) * srcw>>10); } - strcatf(passed_args->str, "resolution=\"%dx%d\" ", dstw, dsth); + strcatf(args->str, "resolution=\"%dx%d\" ", dstw, dsth); } - strcatf(passed_args->str, "protocolInfo=\"http-get:*:image/jpeg:DLNA.ORG_PN=%s;DLNA.ORG_CI=1\">" + strcatf(args->str, "protocolInfo=\"http-get:*:image/jpeg:DLNA.ORG_PN=%s;DLNA.ORG_CI=1\">" "http://%s:%d/Resized/%s.jpg?width=%d,height=%d" "</res>", - dlna_pn, lan_addr[0].str, runtime_vars.port, detailID, dstw, dsth); + dlna_pn, lan_addr[args->iface].str, runtime_vars.port, + detailID, dstw, dsth); } inline static void add_res(char *size, char *duration, char *bitrate, char *sampleFrequency, char *nrAudioChannels, char *resolution, char *dlna_pn, char *mime, - char *detailID, char *ext, struct Response *passed_args) + char *detailID, char *ext, struct Response *args) { - strcatf(passed_args->str, "<res "); - if( size && (passed_args->filter & FILTER_RES_SIZE) ) { - strcatf(passed_args->str, "size=\"%s\" ", size); + strcatf(args->str, "<res "); + if( size && (args->filter & FILTER_RES_SIZE) ) { + strcatf(args->str, "size=\"%s\" ", size); } - if( duration && (passed_args->filter & FILTER_RES_DURATION) ) { - strcatf(passed_args->str, "duration=\"%s\" ", duration); + if( duration && (args->filter & FILTER_RES_DURATION) ) { + strcatf(args->str, "duration=\"%s\" ", duration); } - if( bitrate && (passed_args->filter & FILTER_RES_BITRATE) ) { - strcatf(passed_args->str, "bitrate=\"%s\" ", bitrate); + if( bitrate && (args->filter & FILTER_RES_BITRATE) ) { + strcatf(args->str, "bitrate=\"%s\" ", bitrate); } - if( sampleFrequency && (passed_args->filter & FILTER_RES_SAMPLEFREQUENCY) ) { - strcatf(passed_args->str, "sampleFrequency=\"%s\" ", sampleFrequency); + if( sampleFrequency && (args->filter & FILTER_RES_SAMPLEFREQUENCY) ) { + strcatf(args->str, "sampleFrequency=\"%s\" ", sampleFrequency); } - if( nrAudioChannels && (passed_args->filter & FILTER_RES_NRAUDIOCHANNELS) ) { - strcatf(passed_args->str, "nrAudioChannels=\"%s\" ", nrAudioChannels); + if( nrAudioChannels && (args->filter & FILTER_RES_NRAUDIOCHANNELS) ) { + strcatf(args->str, "nrAudioChannels=\"%s\" ", nrAudioChannels); } - if( resolution && (passed_args->filter & FILTER_RES_RESOLUTION) ) { - strcatf(passed_args->str, "resolution=\"%s\" ", resolution); + if( resolution && (args->filter & FILTER_RES_RESOLUTION) ) { + strcatf(args->str, "resolution=\"%s\" ", resolution); } - strcatf(passed_args->str, "protocolInfo=\"http-get:*:%s:%s\">" + strcatf(args->str, "protocolInfo=\"http-get:*:%s:%s\">" "http://%s:%d/MediaItems/%s.%s" "</res>", - mime, dlna_pn, lan_addr[0].str, + mime, dlna_pn, lan_addr[args->iface].str, runtime_vars.port, detailID, ext); } @@ -756,14 +757,14 @@ callback(void *args, int argc, char **argv, char **azColName) ret = strcatf(str, "<res protocolInfo=\"http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN\">" "http://%s:%d/AlbumArt/%s-%s.jpg" "</res>", - lan_addr[0].str, runtime_vars.port, album_art, detailID); + lan_addr[passed_args->iface].str, runtime_vars.port, album_art, detailID); } else if( passed_args->filter & FILTER_UPNP_ALBUMARTURI ) { ret = strcatf(str, "<upnp:albumArtURI"); if( passed_args->filter & FILTER_UPNP_ALBUMARTURI_DLNA_PROFILEID ) { ret = strcatf(str, " dlna:profileID=\"JPEG_TN\" xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\""); } ret = strcatf(str, ">http://%s:%d/AlbumArt/%s-%s.jpg</upnp:albumArtURI>", - lan_addr[0].str, runtime_vars.port, album_art, detailID); + lan_addr[passed_args->iface].str, runtime_vars.port, album_art, detailID); } } #ifdef PFS_HACK @@ -774,12 +775,12 @@ callback(void *args, int argc, char **argv, char **azColName) ret = strcatf(str, "<upnp:albumArtURI>" "http://%s:%d/Thumbnails/%s.jpg" "</upnp:albumArtURI>", - lan_addr[0].str, runtime_vars.port, detailID); + lan_addr[passed_args->iface].str, runtime_vars.port, detailID); } else { ret = strcatf(str, "<upnp:albumArtURI>" "http://%s:%d/Resized/%s.jpg?width=160,height=160" "</upnp:albumArtURI>", - lan_addr[0].str, runtime_vars.port, detailID); + lan_addr[passed_args->iface].str, runtime_vars.port, detailID); } } #endif @@ -789,7 +790,7 @@ callback(void *args, int argc, char **argv, char **azColName) ret = strcatf(str, "<res protocolInfo=\"http-get:*:%s:%s\">" "http://%s:%d/Thumbnails/%s.jpg" "</res>", - mime, "DLNA.ORG_PN=JPEG_TN", lan_addr[0].str, + mime, "DLNA.ORG_PN=JPEG_TN", lan_addr[passed_args->iface].str, runtime_vars.port, detailID); } add_res(size, duration, bitrate, sampleFrequency, nrAudioChannels, @@ -809,7 +810,7 @@ callback(void *args, int argc, char **argv, char **azColName) ret = strcatf(str, "<res protocolInfo=\"http-get:*:%s:%s\">" "http://%s:%d/Thumbnails/%s.jpg" "</res>", - mime, "DLNA.ORG_PN=JPEG_TN", lan_addr[0].str, + mime, "DLNA.ORG_PN=JPEG_TN", lan_addr[passed_args->iface].str, runtime_vars.port, detailID); } } @@ -886,7 +887,7 @@ callback(void *args, int argc, char **argv, char **azColName) ret = strcatf(str, "<res protocolInfo=\"http-get:*:text/srt:*\">" "http://%s:%d/Captions/%s.srt" "</res>", - lan_addr[0].str, runtime_vars.port, detailID); + lan_addr[passed_args->iface].str, runtime_vars.port, detailID); } break; default: @@ -936,7 +937,7 @@ callback(void *args, int argc, char **argv, char **azColName) ret = strcatf(str, "dlna:profileID=\"JPEG_TN\" xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\""); } ret = strcatf(str, ">http://%s:%d/AlbumArt/%s-%s.jpg</upnp:albumArtURI>", - lan_addr[0].str, runtime_vars.port, album_art, detailID); + lan_addr[passed_args->iface].str, runtime_vars.port, album_art, detailID); } ret = strcatf(str, "</container>"); } @@ -997,6 +998,7 @@ BrowseContentDirectory(struct upnphttp * h, const char * action) str.off = sprintf(str.data, "%s", resp0); args.str = &str; /* See if we need to include DLNA namespace reference */ + args.iface = h->iface; args.filter = set_filter_flags(Filter, h->req_client); if( args.filter & FILTER_DLNA_NAMESPACE ) { @@ -1174,6 +1176,7 @@ SearchContentDirectory(struct upnphttp * h, const char * action) str.size = DEFAULT_RESP_SIZE; str.off = sprintf(str.data, "%s", resp0); /* See if we need to include DLNA namespace reference */ + args.iface = h->iface; args.filter = set_filter_flags(Filter, h->req_client); if( args.filter & FILTER_DLNA_NAMESPACE ) { diff --git a/upnpsoap.h b/upnpsoap.h index 9f75c03..d235466 100644 --- a/upnpsoap.h +++ b/upnpsoap.h @@ -37,6 +37,7 @@ struct Response int start; int returned; int requested; + int iface; uint32_t filter; uint32_t flags; enum client_types client;