Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/azatoth/minidlna.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Maggard <jmaggard@users.sourceforce.net>2011-05-24 21:20:16 +0400
committerJustin Maggard <jmaggard@users.sourceforce.net>2011-05-24 21:20:16 +0400
commitccc7e35ee2b0047b7afb4f142387690f7b5f1b8f (patch)
treeab83b95459b5c171b390c78cd3ebbe3f4ac42231
parent2fb59c582306d3792779f3cef3c7f9416130f8e0 (diff)
* Add support for multiple network interfaces.
-rw-r--r--minidlna.c41
-rw-r--r--tivo_beacon.c31
-rw-r--r--upnphttp.c19
-rw-r--r--upnphttp.h3
-rw-r--r--upnpsoap.c65
-rw-r--r--upnpsoap.h1
6 files changed, 105 insertions, 55 deletions
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<argc; i++)
@@ -386,13 +386,25 @@ init(int argc, char * * argv)
switch(ary_options[i].id)
{
case UPNPIFNAME:
- if(getifaddr(ary_options[i].value, ext_ip_addr, sizeof(ext_ip_addr)) >= 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; j<n_lan_addr; j++)
{
struct lan_addr_s tmpaddr;
- parselanaddr(&tmpaddr, ext_ip_addr);
+ parselanaddr(&tmpaddr, ip_addr);
if(0 == strcmp(lan_addr[j].str, tmpaddr.str))
address_already_there = 1;
}
@@ -666,7 +679,7 @@ init(int argc, char * * argv)
break;
if(n_lan_addr < MAX_LAN_ADDR)
{
- if(parselanaddr(&lan_addr[n_lan_addr], ext_ip_addr) == 0)
+ if(parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0)
n_lan_addr++;
}
else
@@ -699,13 +712,13 @@ init(int argc, char * * argv)
/* If no IP was specified, try to detect one */
if( n_lan_addr < 1 )
{
- if( (getsysaddr(ext_ip_addr, sizeof(ext_ip_addr)) < 0) &&
- (getifaddr("eth0", ext_ip_addr, sizeof(ext_ip_addr)) < 0) &&
- (getifaddr("eth1", ext_ip_addr, sizeof(ext_ip_addr)) < 0) )
+ if( (getsysaddr(ip_addr, sizeof(ip_addr)) < 0) &&
+ (getifaddr("eth0", ip_addr, sizeof(ip_addr)) < 0) &&
+ (getifaddr("eth1", ip_addr, sizeof(ip_addr)) < 0) )
{
DPRINTF(E_OFF, L_GENERAL, "No IP address automatically detected!\n");
}
- if( *ext_ip_addr && parselanaddr(&lan_addr[n_lan_addr], ext_ip_addr) == 0 )
+ if( *ip_addr && parselanaddr(&lan_addr[n_lan_addr], ip_addr) == 0 )
{
n_lan_addr++;
}
diff --git a/tivo_beacon.c b/tivo_beacon.c
index 8de73af..5f11132 100644
--- a/tivo_beacon.c
+++ b/tivo_beacon.c
@@ -51,8 +51,6 @@
#include "upnpglobalvars.h"
#include "log.h"
-static struct aBeacon* topBeacon = NULL;
-
/* OpenAndConfHTTPSocket() :
* setup the socket used to handle incoming HTTP connections. */
int
@@ -187,8 +185,6 @@ rcvBeaconMessage(char * beacon)
char * cp;
char * scp;
char * tokptr;
- struct aBeacon * b;
- time_t current;
cp = strtok_r(beacon, "=\r\n", &tokptr);
while( cp != NULL )
@@ -217,6 +213,14 @@ rcvBeaconMessage(char * beacon)
if( strcmp(identity, uuidvalue) == 0)
return 0;
+#ifdef DEBUG
+ static struct aBeacon* topBeacon = NULL;
+ struct aBeacon * b;
+ time_t current;
+ int len;
+ char buf[32];
+ static time_t lastSummary = 0;
+
current = time(NULL);
for( b = topBeacon; b != NULL; b = b->next )
{
@@ -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; n<n_lan_addr; n++)
+ {
+ if( (sendername.sin_addr.s_addr & lan_addr[n].mask.s_addr)
+ == (lan_addr[n].addr.s_addr & lan_addr[n].mask.s_addr))
+ break;
+ }
+ if( n == n_lan_addr )
+ {
+ DPRINTF(E_DEBUG, L_TIVO, "Ignoring TiVo beacon on other interface [%s]\n",
+ inet_ntoa(sendername.sin_addr));
+ return;
+ }
+
for( cp = bufr; *cp; cp++ )
/* do nothing */;
if( cp[-1] == '\r' || cp[-1] == '\n' )
diff --git a/upnphttp.c b/upnphttp.c
index 96c2e81..5b9655f 100644
--- a/upnphttp.c
+++ b/upnphttp.c
@@ -263,7 +263,24 @@ intervening space) by either an integer or the keyword "infinite". */
}
else if(strncasecmp(line, "Host", 4)==0)
{
+ int i;
h->reqflags |= FLAG_HOST;
+ p = colon + 1;
+ while(isspace(*p))
+ p++;
+ for(n = 0; n<n_lan_addr; n++)
+ {
+ for(i=0; lan_addr[n].str[i]; i++)
+ {
+ if(lan_addr[n].str[i] != p[i])
+ break;
+ }
+ if(!lan_addr[n].str[i])
+ {
+ h->iface = 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, "&lt;res ");
- if( passed_args->filter & FILTER_RES_RESOLUTION )
+ strcatf(args->str, "&lt;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\"&gt;"
+ strcatf(args->str, "protocolInfo=\"http-get:*:image/jpeg:DLNA.ORG_PN=%s;DLNA.ORG_CI=1\"&gt;"
"http://%s:%d/Resized/%s.jpg?width=%d,height=%d"
"&lt;/res&gt;",
- 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, "&lt;res ");
- if( size && (passed_args->filter & FILTER_RES_SIZE) ) {
- strcatf(passed_args->str, "size=\"%s\" ", size);
+ strcatf(args->str, "&lt;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\"&gt;"
+ strcatf(args->str, "protocolInfo=\"http-get:*:%s:%s\"&gt;"
"http://%s:%d/MediaItems/%s.%s"
"&lt;/res&gt;",
- 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, "&lt;res protocolInfo=\"http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN\"&gt;"
"http://%s:%d/AlbumArt/%s-%s.jpg"
"&lt;/res&gt;",
- 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, "&lt;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, "&gt;http://%s:%d/AlbumArt/%s-%s.jpg&lt;/upnp:albumArtURI&gt;",
- 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, "&lt;upnp:albumArtURI&gt;"
"http://%s:%d/Thumbnails/%s.jpg"
"&lt;/upnp:albumArtURI&gt;",
- lan_addr[0].str, runtime_vars.port, detailID);
+ lan_addr[passed_args->iface].str, runtime_vars.port, detailID);
} else {
ret = strcatf(str, "&lt;upnp:albumArtURI&gt;"
"http://%s:%d/Resized/%s.jpg?width=160,height=160"
"&lt;/upnp:albumArtURI&gt;",
- 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, "&lt;res protocolInfo=\"http-get:*:%s:%s\"&gt;"
"http://%s:%d/Thumbnails/%s.jpg"
"&lt;/res&gt;",
- 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, "&lt;res protocolInfo=\"http-get:*:%s:%s\"&gt;"
"http://%s:%d/Thumbnails/%s.jpg"
"&lt;/res&gt;",
- 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, "&lt;res protocolInfo=\"http-get:*:text/srt:*\"&gt;"
"http://%s:%d/Captions/%s.srt"
"&lt;/res&gt;",
- 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, "&gt;http://%s:%d/AlbumArt/%s-%s.jpg&lt;/upnp:albumArtURI&gt;",
- 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, "&lt;/container&gt;");
}
@@ -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;