* Add support for multiple network interfaces.
This commit is contained in:
parent
ffd5df4a58
commit
9806103335
37
minidlna.c
37
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 )
|
||||
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", ary_options[i].value);
|
||||
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);
|
||||
}
|
||||
}
|
||||
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++;
|
||||
}
|
||||
|
@ -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' )
|
||||
|
19
upnphttp.c
19
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
65
upnpsoap.c
65
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 )
|
||||
{
|
||||
|
@ -37,6 +37,7 @@ struct Response
|
||||
int start;
|
||||
int returned;
|
||||
int requested;
|
||||
int iface;
|
||||
uint32_t filter;
|
||||
uint32_t flags;
|
||||
enum client_types client;
|
||||
|
Loading…
x
Reference in New Issue
Block a user