* Add support for multiple network interfaces.

This commit is contained in:
Justin Maggard 2011-05-24 17:20:16 +00:00
parent ffd5df4a58
commit 9806103335
6 changed files with 105 additions and 55 deletions

View File

@ -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++;
}

View File

@ -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' )

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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 )
{

View File

@ -37,6 +37,7 @@ struct Response
int start;
int returned;
int requested;
int iface;
uint32_t filter;
uint32_t flags;
enum client_types client;