* Code reformatting.
This commit is contained in:
parent
77c30bdfba
commit
11998204e2
321
minissdp.c
321
minissdp.c
@ -83,16 +83,15 @@ OpenAndConfSSDPReceiveSocket(void)
|
||||
int i = 1;
|
||||
struct sockaddr_in sockname;
|
||||
|
||||
if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_SSDP, "socket(udp): %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
|
||||
{
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
|
||||
DPRINTF(E_WARN, L_SSDP, "setsockopt(udp, SO_REUSEADDR): %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
memset(&sockname, 0, sizeof(struct sockaddr_in));
|
||||
sockname.sin_family = AF_INET;
|
||||
@ -100,7 +99,7 @@ OpenAndConfSSDPReceiveSocket(void)
|
||||
/* NOTE : it seems it doesnt work when binding on the specific address */
|
||||
sockname.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
if(bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0)
|
||||
if (bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_SSDP, "bind(udp): %s\n", strerror(errno));
|
||||
close(s);
|
||||
@ -108,10 +107,10 @@ OpenAndConfSSDPReceiveSocket(void)
|
||||
}
|
||||
|
||||
i = n_lan_addr;
|
||||
while(i>0)
|
||||
while (i > 0)
|
||||
{
|
||||
i--;
|
||||
if(AddMulticastMembership(s, lan_addr[i].addr.s_addr) < 0)
|
||||
if (AddMulticastMembership(s, lan_addr[i].addr.s_addr) < 0)
|
||||
{
|
||||
DPRINTF(E_WARN, L_SSDP,
|
||||
"Failed to add multicast membership for address %s\n",
|
||||
@ -134,7 +133,8 @@ OpenAndConfSSDPNotifySocket(in_addr_t addr)
|
||||
struct in_addr mc_if;
|
||||
struct sockaddr_in sockname;
|
||||
|
||||
if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_SSDP, "socket(udp_notify): %s\n", strerror(errno));
|
||||
return -1;
|
||||
@ -142,14 +142,14 @@ OpenAndConfSSDPNotifySocket(in_addr_t addr)
|
||||
|
||||
mc_if.s_addr = addr; /*inet_addr(addr);*/
|
||||
|
||||
if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopchar, sizeof(loopchar)) < 0)
|
||||
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopchar, sizeof(loopchar)) < 0)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_SSDP, "setsockopt(udp_notify, IP_MULTICAST_LOOP): %s\n", strerror(errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char *)&mc_if, sizeof(mc_if)) < 0)
|
||||
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char *)&mc_if, sizeof(mc_if)) < 0)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_SSDP, "setsockopt(udp_notify, IP_MULTICAST_IF): %s\n", strerror(errno));
|
||||
close(s);
|
||||
@ -158,7 +158,7 @@ OpenAndConfSSDPNotifySocket(in_addr_t addr)
|
||||
|
||||
setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
|
||||
|
||||
if(setsockopt(s, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast)) < 0)
|
||||
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast)) < 0)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_SSDP, "setsockopt(udp_notify, SO_BROADCAST): %s\n", strerror(errno));
|
||||
close(s);
|
||||
@ -180,15 +180,15 @@ OpenAndConfSSDPNotifySocket(in_addr_t addr)
|
||||
}
|
||||
|
||||
int
|
||||
OpenAndConfSSDPNotifySockets(int * sockets)
|
||||
OpenAndConfSSDPNotifySockets(int *sockets)
|
||||
{
|
||||
int i, j;
|
||||
for(i=0; i<n_lan_addr; i++)
|
||||
for (i = 0; i < n_lan_addr; i++)
|
||||
{
|
||||
sockets[i] = OpenAndConfSSDPNotifySocket(lan_addr[i].addr.s_addr);
|
||||
if(sockets[i] < 0)
|
||||
if (sockets[i] < 0)
|
||||
{
|
||||
for(j=0; j<i; j++)
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
close(sockets[j]);
|
||||
sockets[j] = -1;
|
||||
@ -199,27 +199,6 @@ OpenAndConfSSDPNotifySockets(int * sockets)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* response from a LiveBox (Wanadoo)
|
||||
HTTP/1.1 200 OK
|
||||
CACHE-CONTROL: max-age=1800
|
||||
DATE: Thu, 01 Jan 1970 04:03:23 GMT
|
||||
EXT:
|
||||
LOCATION: http://192.168.0.1:49152/gatedesc.xml
|
||||
SERVER: Linux/2.4.17, UPnP/1.0, Intel SDK for UPnP devices /1.2
|
||||
ST: upnp:rootdevice
|
||||
USN: uuid:75802409-bccb-40e7-8e6c-fa095ecce13e::upnp:rootdevice
|
||||
|
||||
* response from a Linksys 802.11b :
|
||||
HTTP/1.1 200 OK
|
||||
Cache-Control:max-age=120
|
||||
Location:http://192.168.5.1:5678/rootDesc.xml
|
||||
Server:NT/5.0 UPnP/1.0
|
||||
ST:upnp:rootdevice
|
||||
USN:uuid:upnp-InternetGatewayDevice-1_0-0090a2777777::upnp:rootdevice
|
||||
EXT:
|
||||
*/
|
||||
|
||||
static const char * const known_service_types[] =
|
||||
{
|
||||
uuidvalue,
|
||||
@ -245,10 +224,13 @@ _usleep(long usecs)
|
||||
* to a SSDP "M-SEARCH" */
|
||||
static void
|
||||
SendSSDPAnnounce2(int s, struct sockaddr_in sockname, int st_no,
|
||||
const char * host, unsigned short port)
|
||||
const char *host, unsigned short port)
|
||||
{
|
||||
int l, n;
|
||||
char buf[512];
|
||||
char tmstr[30];
|
||||
time_t tm = time(NULL);
|
||||
|
||||
/*
|
||||
* follow guideline from document "UPnP Device Architecture 1.0"
|
||||
* uppercase is recommended.
|
||||
@ -256,10 +238,7 @@ SendSSDPAnnounce2(int s, struct sockaddr_in sockname, int st_no,
|
||||
* SERVER: OS/ver UPnP/1.0 minidlna/1.0
|
||||
* - check what to put in the 'Cache-Control' header
|
||||
* */
|
||||
char szTime[30];
|
||||
time_t tTime = time(NULL);
|
||||
strftime(szTime, 30,"%a, %d %b %Y %H:%M:%S GMT" , gmtime(&tTime));
|
||||
|
||||
strftime(tmstr, sizeof(tmstr), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&tm));
|
||||
l = snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\r\n"
|
||||
"CACHE-CONTROL: max-age=%u\r\n"
|
||||
"DATE: %s\r\n"
|
||||
@ -271,21 +250,23 @@ SendSSDPAnnounce2(int s, struct sockaddr_in sockname, int st_no,
|
||||
"Content-Length: 0\r\n"
|
||||
"\r\n",
|
||||
(runtime_vars.notify_interval<<1)+10,
|
||||
szTime,
|
||||
known_service_types[st_no], (st_no>1?"1":""),
|
||||
uuidvalue, (st_no>0?"::":""), (st_no>0?known_service_types[st_no]:""), (st_no>1?"1":""),
|
||||
tmstr,
|
||||
known_service_types[st_no],
|
||||
(st_no>1?"1":""),
|
||||
uuidvalue,
|
||||
(st_no > 0 ? "::" : ""),
|
||||
(st_no > 0 ? known_service_types[st_no] : ""),
|
||||
(st_no > 1 ? "1" : ""),
|
||||
host, (unsigned int)port);
|
||||
//DEBUG DPRINTF(E_DEBUG, L_SSDP, "Sending M-SEARCH response:\n%s", buf);
|
||||
n = sendto(s, buf, l, 0,
|
||||
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
||||
if(n < 0)
|
||||
{
|
||||
if (n < 0)
|
||||
DPRINTF(E_ERROR, L_SSDP, "sendto(udp): %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
SendSSDPNotifies(int s, const char * host, unsigned short port,
|
||||
SendSSDPNotifies(int s, const char *host, unsigned short port,
|
||||
unsigned int lifetime)
|
||||
{
|
||||
struct sockaddr_in sockname;
|
||||
@ -297,12 +278,12 @@ SendSSDPNotifies(int s, const char * host, unsigned short port,
|
||||
sockname.sin_port = htons(SSDP_PORT);
|
||||
sockname.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR);
|
||||
|
||||
for( dup=0; dup<2; dup++ )
|
||||
for (dup = 0; dup < 2; dup++)
|
||||
{
|
||||
if( dup )
|
||||
if (dup)
|
||||
_usleep(200000);
|
||||
i=0;
|
||||
while(known_service_types[i])
|
||||
i = 0;
|
||||
while (known_service_types[i])
|
||||
{
|
||||
l = snprintf(bufr, sizeof(bufr),
|
||||
"NOTIFY * HTTP/1.1\r\n"
|
||||
@ -317,36 +298,36 @@ SendSSDPNotifies(int s, const char * host, unsigned short port,
|
||||
SSDP_MCAST_ADDR, SSDP_PORT,
|
||||
lifetime,
|
||||
host, port,
|
||||
known_service_types[i], (i>1?"1":""),
|
||||
uuidvalue, (i>0?"::":""), (i>0?known_service_types[i]:""), (i>1?"1":"") );
|
||||
if(l>=sizeof(bufr))
|
||||
known_service_types[i],
|
||||
(i > 1 ? "1" : ""),
|
||||
uuidvalue,
|
||||
(i > 0 ? "::" : ""),
|
||||
(i > 0 ? known_service_types[i] : ""),
|
||||
(i > 1 ? "1" : ""));
|
||||
if (l >= sizeof(bufr))
|
||||
{
|
||||
DPRINTF(E_WARN, L_SSDP, "SendSSDPNotifies(): truncated output\n");
|
||||
l = sizeof(bufr);
|
||||
}
|
||||
//DEBUG DPRINTF(E_DEBUG, L_SSDP, "Sending NOTIFY:\n%s", bufr);
|
||||
n = sendto(s, bufr, l, 0,
|
||||
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
||||
if(n < 0)
|
||||
{
|
||||
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in));
|
||||
if (n < 0)
|
||||
DPRINTF(E_ERROR, L_SSDP, "sendto(udp_notify=%d, %s): %s\n", s, host, strerror(errno));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SendSSDPNotifies2(int * sockets,
|
||||
SendSSDPNotifies2(int *sockets,
|
||||
unsigned short port,
|
||||
unsigned int lifetime)
|
||||
/*SendSSDPNotifies2(int * sockets, struct lan_addr_s * lan_addr, int n_lan_addr,
|
||||
unsigned short port,
|
||||
unsigned int lifetime)*/
|
||||
{
|
||||
int i;
|
||||
|
||||
DPRINTF(E_DEBUG, L_SSDP, "Sending SSDP notifies\n");
|
||||
for(i=0; i<n_lan_addr; i++)
|
||||
for (i = 0; i < n_lan_addr; i++)
|
||||
{
|
||||
SendSSDPNotifies(sockets[i], lan_addr[i].str, port, lifetime);
|
||||
}
|
||||
@ -391,7 +372,7 @@ ParseUPnPClient(char *location)
|
||||
dest.sin_port = htons(port);
|
||||
|
||||
s = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if( s < 0 )
|
||||
if (s < 0)
|
||||
return;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
@ -399,74 +380,76 @@ ParseUPnPClient(char *location)
|
||||
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
||||
setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
|
||||
|
||||
if( connect(s, (struct sockaddr*)&dest, sizeof(struct sockaddr_in)) < 0 )
|
||||
if (connect(s, (struct sockaddr*)&dest, sizeof(struct sockaddr_in)) < 0)
|
||||
goto close;
|
||||
|
||||
n = snprintf(buf, sizeof(buf), "GET /%s HTTP/1.0\r\n"
|
||||
"HOST: %s:%ld\r\n\r\n",
|
||||
path, addr, port);
|
||||
if( write(s, buf, n) < 1 )
|
||||
if (write(s, buf, n) < 1)
|
||||
goto close;
|
||||
|
||||
while( (n = read(s, buf+nread, sizeof(buf)-nread-1)) > 0 )
|
||||
while ((n = read(s, buf+nread, sizeof(buf)-nread-1)) > 0)
|
||||
{
|
||||
nread += n;
|
||||
buf[nread] = '\0';
|
||||
n = nread;
|
||||
p = buf;
|
||||
|
||||
while( !off && n-- > 0 )
|
||||
while (!off && (n-- > 0))
|
||||
{
|
||||
if(p[0]=='\r' && p[1]=='\n' && p[2]=='\r' && p[3]=='\n')
|
||||
if (p[0] == '\r' && p[1] == '\n' && p[2] == '\r' && p[3] == '\n')
|
||||
{
|
||||
off = p + 4;
|
||||
do_headers = 1;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if( !off )
|
||||
if (!off)
|
||||
continue;
|
||||
|
||||
if( do_headers )
|
||||
if (do_headers)
|
||||
{
|
||||
p = buf;
|
||||
if( strncmp(p, "HTTP/", 5) != 0 )
|
||||
if (strncmp(p, "HTTP/", 5) != 0)
|
||||
goto close;
|
||||
while(*p != ' ' && *p != '\t') p++;
|
||||
while (*p != ' ' && *p != '\t')
|
||||
p++;
|
||||
/* If we don't get a 200 status, ignore it */
|
||||
if( strtol(p, NULL, 10) != 200 )
|
||||
if (strtol(p, NULL, 10) != 200)
|
||||
goto close;
|
||||
if( (p = strcasestr(p, "Content-Length:")) )
|
||||
p = strcasestr(p, "Content-Length:");
|
||||
if (p)
|
||||
content_len = strtol(p+15, NULL, 10);
|
||||
do_headers = 0;
|
||||
}
|
||||
if( buf + nread - off >= content_len )
|
||||
if ((buf + nread - off) >= content_len)
|
||||
break;
|
||||
}
|
||||
close:
|
||||
close(s);
|
||||
if( !off )
|
||||
if (!off)
|
||||
return;
|
||||
nread -= off - buf;
|
||||
ParseNameValue(off, nread, &xml, 0);
|
||||
model = GetValueFromNameValueList(&xml, "modelName");
|
||||
serial = GetValueFromNameValueList(&xml, "serialNumber");
|
||||
name = GetValueFromNameValueList(&xml, "friendlyName");
|
||||
if( model )
|
||||
if (model)
|
||||
{
|
||||
DPRINTF(E_DEBUG, L_SSDP, "Model: %s\n", model);
|
||||
if( strstr(model, "Roku SoundBridge") )
|
||||
if (strstr(model, "Roku SoundBridge") != NULL)
|
||||
{
|
||||
type = ERokuSoundBridge;
|
||||
flags |= FLAG_MS_PFS;
|
||||
flags |= FLAG_AUDIO_ONLY;
|
||||
flags |= FLAG_MIME_WAV_WAV;
|
||||
}
|
||||
else if( strcmp(model, "Samsung DTV DMR") == 0 && serial )
|
||||
else if ((strcmp(model, "Samsung DTV DMR") == 0) && serial )
|
||||
{
|
||||
DPRINTF(E_DEBUG, L_SSDP, "Serial: %s\n", serial);
|
||||
/* The Series B I saw was 20081224DMR. Series A should be older than that. */
|
||||
if( atoi(serial) > 20081200 )
|
||||
if (atoi(serial) > 20081200)
|
||||
{
|
||||
type = ESamsungSeriesB;
|
||||
flags |= FLAG_SAMSUNG;
|
||||
@ -476,7 +459,7 @@ close:
|
||||
}
|
||||
else
|
||||
{
|
||||
if( name && (strcmp(name, "marantz DMP") == 0) )
|
||||
if (name && (strcmp(name, "marantz DMP") == 0))
|
||||
{
|
||||
type = EMarantzDMP;
|
||||
flags |= FLAG_DLNA;
|
||||
@ -485,15 +468,15 @@ close:
|
||||
}
|
||||
}
|
||||
ClearNameValueList(&xml);
|
||||
if( !type )
|
||||
if (!type)
|
||||
return;
|
||||
/* Add this client to the cache if it's not there already. */
|
||||
client = SearchClientCache(dest.sin_addr, 1);
|
||||
if( client < 0 )
|
||||
if (client < 0)
|
||||
{
|
||||
for( client=0; client<CLIENT_CACHE_SLOTS; client++ )
|
||||
for (client=0; client<CLIENT_CACHE_SLOTS; client++)
|
||||
{
|
||||
if( clients[client].addr.s_addr )
|
||||
if (clients[client].addr.s_addr)
|
||||
continue;
|
||||
get_remote_mac(dest.sin_addr, clients[client].mac);
|
||||
clients[client].addr = dest.sin_addr;
|
||||
@ -525,68 +508,72 @@ ProcessSSDPRequest(int s, unsigned short port)
|
||||
|
||||
n = recvfrom(s, bufr, sizeof(bufr)-1, 0,
|
||||
(struct sockaddr *)&sendername, &len_r);
|
||||
if(n < 0)
|
||||
if (n < 0)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_SSDP, "recvfrom(udp): %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
bufr[n] = '\0';
|
||||
n -= 2;
|
||||
|
||||
if(memcmp(bufr, "NOTIFY", 6) == 0)
|
||||
if (memcmp(bufr, "NOTIFY", 6) == 0)
|
||||
{
|
||||
char *loc = NULL, *srv = NULL, *nts = NULL, *nt = NULL;
|
||||
int loc_len = 0;
|
||||
//DEBUG DPRINTF(E_DEBUG, L_SSDP, "Received SSDP notify:\n%.*s", n, bufr);
|
||||
for(i=0; i < n; i++)
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if( bufr[i] == '*' )
|
||||
break;
|
||||
}
|
||||
if( !strcasestrc(bufr+i, "HTTP/1.1", '\r') )
|
||||
if (strcasestrc(bufr+i, "HTTP/1.1", '\r') == NULL)
|
||||
return;
|
||||
while(i < n)
|
||||
while (i < n)
|
||||
{
|
||||
while((i < n - 2) && (bufr[i] != '\r' || bufr[i+1] != '\n'))
|
||||
while ((i < n) && (bufr[i] != '\r' || bufr[i+1] != '\n'))
|
||||
i++;
|
||||
i += 2;
|
||||
if(strncasecmp(bufr+i, "SERVER:", 7) == 0)
|
||||
if (strncasecmp(bufr+i, "SERVER:", 7) == 0)
|
||||
{
|
||||
srv = bufr+i+7;
|
||||
while(*srv == ' ' || *srv == '\t') srv++;
|
||||
while (*srv == ' ' || *srv == '\t')
|
||||
srv++;
|
||||
}
|
||||
else if(strncasecmp(bufr+i, "LOCATION:", 9) == 0)
|
||||
else if (strncasecmp(bufr+i, "LOCATION:", 9) == 0)
|
||||
{
|
||||
loc = bufr+i+9;
|
||||
while(*loc == ' ' || *loc == '\t') loc++;
|
||||
while(loc[loc_len]!='\r' && loc[loc_len]!='\n') loc_len++;
|
||||
while (*loc == ' ' || *loc == '\t')
|
||||
loc++;
|
||||
while (loc[loc_len]!='\r' && loc[loc_len]!='\n')
|
||||
loc_len++;
|
||||
}
|
||||
else if(strncasecmp(bufr+i, "NTS:", 4) == 0)
|
||||
else if (strncasecmp(bufr+i, "NTS:", 4) == 0)
|
||||
{
|
||||
nts = bufr+i+4;
|
||||
while(*nts == ' ' || *nts == '\t') nts++;
|
||||
while (*nts == ' ' || *nts == '\t')
|
||||
nts++;
|
||||
}
|
||||
else if(strncasecmp(bufr+i, "NT:", 3) == 0)
|
||||
else if (strncasecmp(bufr+i, "NT:", 3) == 0)
|
||||
{
|
||||
nt = bufr+i+3;
|
||||
while(*nt == ' ' || *nt == '\t') nt++;
|
||||
while(*nt == ' ' || *nt == '\t')
|
||||
nt++;
|
||||
}
|
||||
}
|
||||
if( !loc || !srv || !nt || !nts || (strncmp(nts, "ssdp:alive", 10) != 0) ||
|
||||
(strncmp(nt, "urn:schemas-upnp-org:device:MediaRenderer", 41) != 0) )
|
||||
{
|
||||
if (!loc || !srv || !nt || !nts || (strncmp(nts, "ssdp:alive", 10) != 0) ||
|
||||
(strncmp(nt, "urn:schemas-upnp-org:device:MediaRenderer", 41) != 0))
|
||||
return;
|
||||
}
|
||||
loc[loc_len] = '\0';
|
||||
if( (strncmp(srv, "Allegro-Software-RomPlug", 24) == 0) || /* Roku */
|
||||
if ((strncmp(srv, "Allegro-Software-RomPlug", 24) == 0) || /* Roku */
|
||||
(strstr(loc, "SamsungMRDesc.xml") != NULL) || /* Samsung TV */
|
||||
(strstrc(srv, "DigiOn DiXiM", '\r') != NULL) ) /* Marantz Receiver */
|
||||
(strstrc(srv, "DigiOn DiXiM", '\r') != NULL)) /* Marantz Receiver */
|
||||
{
|
||||
/* Check if the client is already in cache */
|
||||
i = SearchClientCache(sendername.sin_addr, 1);
|
||||
if( i >= 0 )
|
||||
if (i >= 0)
|
||||
{
|
||||
if( clients[i].type < EStandardDLNA150 &&
|
||||
clients[i].type != ESamsungSeriesA )
|
||||
if (clients[i].type < EStandardDLNA150 &&
|
||||
clients[i].type != ESamsungSeriesA)
|
||||
{
|
||||
clients[i].age = time(NULL);
|
||||
return;
|
||||
@ -595,77 +582,84 @@ ProcessSSDPRequest(int s, unsigned short port)
|
||||
ParseUPnPClient(loc);
|
||||
}
|
||||
}
|
||||
else if(memcmp(bufr, "M-SEARCH", 8) == 0)
|
||||
else if (memcmp(bufr, "M-SEARCH", 8) == 0)
|
||||
{
|
||||
int st_len = 0, mx_len = 0, mx_val = 0;
|
||||
//DPRINTF(E_DEBUG, L_SSDP, "Received SSDP request:\n%.*s\n", n, bufr);
|
||||
for(i=0; i < n; i++)
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if( bufr[i] == '*' )
|
||||
if (bufr[i] == '*')
|
||||
break;
|
||||
}
|
||||
if( !strcasestrc(bufr+i, "HTTP/1.1", '\r') )
|
||||
if (strcasestrc(bufr+i, "HTTP/1.1", '\r') == NULL)
|
||||
return;
|
||||
while(i < n)
|
||||
while (i < n)
|
||||
{
|
||||
while((i < n - 2) && (bufr[i] != '\r' || bufr[i+1] != '\n'))
|
||||
while ((i < n) && (bufr[i] != '\r' || bufr[i+1] != '\n'))
|
||||
i++;
|
||||
i += 2;
|
||||
if(strncasecmp(bufr+i, "ST:", 3) == 0)
|
||||
if (strncasecmp(bufr+i, "ST:", 3) == 0)
|
||||
{
|
||||
st = bufr+i+3;
|
||||
st_len = 0;
|
||||
while(*st == ' ' || *st == '\t') st++;
|
||||
while(st[st_len]!='\r' && st[st_len]!='\n') st_len++;
|
||||
while (*st == ' ' || *st == '\t')
|
||||
st++;
|
||||
while (st[st_len]!='\r' && st[st_len]!='\n')
|
||||
st_len++;
|
||||
}
|
||||
else if(strncasecmp(bufr+i, "MX:", 3) == 0)
|
||||
else if (strncasecmp(bufr+i, "MX:", 3) == 0)
|
||||
{
|
||||
mx = bufr+i+3;
|
||||
mx_len = 0;
|
||||
while(*mx == ' ' || *mx == '\t') mx++;
|
||||
while(mx[mx_len]!='\r' && mx[mx_len]!='\n') mx_len++;
|
||||
while (*mx == ' ' || *mx == '\t')
|
||||
mx++;
|
||||
while (mx[mx_len]!='\r' && mx[mx_len]!='\n')
|
||||
mx_len++;
|
||||
mx_val = strtol(mx, &mx_end, 10);
|
||||
}
|
||||
else if(strncasecmp(bufr+i, "MAN:", 4) == 0)
|
||||
else if (strncasecmp(bufr+i, "MAN:", 4) == 0)
|
||||
{
|
||||
man = bufr+i+4;
|
||||
man_len = 0;
|
||||
while(*man == ' ' || *man == '\t') man++;
|
||||
while(man[man_len]!='\r' && man[man_len]!='\n') man_len++;
|
||||
while (*man == ' ' || *man == '\t')
|
||||
man++;
|
||||
while (man[man_len]!='\r' && man[man_len]!='\n')
|
||||
man_len++;
|
||||
}
|
||||
}
|
||||
/*DPRINTF(E_INFO, L_SSDP, "SSDP M-SEARCH packet received from %s:%d\n",
|
||||
inet_ntoa(sendername.sin_addr),
|
||||
ntohs(sendername.sin_port) );*/
|
||||
if( GETFLAG(DLNA_STRICT_MASK) && (ntohs(sendername.sin_port) <= 1024 || ntohs(sendername.sin_port) == 1900) )
|
||||
if (GETFLAG(DLNA_STRICT_MASK) && (ntohs(sendername.sin_port) <= 1024 || ntohs(sendername.sin_port) == 1900))
|
||||
{
|
||||
DPRINTF(E_INFO, L_SSDP, "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad source port %d]\n",
|
||||
inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port));
|
||||
}
|
||||
else if( !man || (strncmp(man, "\"ssdp:discover\"", 15) != 0) )
|
||||
else if (!man || (strncmp(man, "\"ssdp:discover\"", 15) != 0))
|
||||
{
|
||||
DPRINTF(E_INFO, L_SSDP, "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad %s header '%.*s']\n",
|
||||
inet_ntoa(sendername.sin_addr), "MAN", man_len, man);
|
||||
}
|
||||
else if( !mx || mx == mx_end || mx_val < 0 ) {
|
||||
else if (!mx || mx == mx_end || mx_val < 0)
|
||||
{
|
||||
DPRINTF(E_INFO, L_SSDP, "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad %s header '%.*s']\n",
|
||||
inet_ntoa(sendername.sin_addr), "MX", mx_len, mx);
|
||||
}
|
||||
else if( st && (st_len > 0) )
|
||||
else if (st && (st_len > 0))
|
||||
{
|
||||
int l;
|
||||
int lan_addr_index = 0;
|
||||
/* find in which sub network the client is */
|
||||
for(i = 0; i<n_lan_addr; i++)
|
||||
for (i = 0; i < n_lan_addr; i++)
|
||||
{
|
||||
if( (sendername.sin_addr.s_addr & lan_addr[i].mask.s_addr)
|
||||
== (lan_addr[i].addr.s_addr & lan_addr[i].mask.s_addr))
|
||||
if((sendername.sin_addr.s_addr & lan_addr[i].mask.s_addr) ==
|
||||
(lan_addr[i].addr.s_addr & lan_addr[i].mask.s_addr))
|
||||
{
|
||||
lan_addr_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( i == n_lan_addr )
|
||||
if (n_lan_addr == i)
|
||||
{
|
||||
DPRINTF(E_DEBUG, L_SSDP, "Ignoring SSDP M-SEARCH on other interface [%s]\n",
|
||||
inet_ntoa(sendername.sin_addr));
|
||||
@ -676,19 +670,19 @@ ProcessSSDPRequest(int s, unsigned short port)
|
||||
ntohs(sendername.sin_port),
|
||||
st_len, st, mx_len, mx, man_len, man);
|
||||
/* Responds to request with a device as ST header */
|
||||
for(i = 0; known_service_types[i]; i++)
|
||||
for (i = 0; known_service_types[i]; i++)
|
||||
{
|
||||
l = strlen(known_service_types[i]);
|
||||
if( l <= st_len && (memcmp(st, known_service_types[i], l) == 0))
|
||||
if ((l <= st_len) && (memcmp(st, known_service_types[i], l) == 0))
|
||||
{
|
||||
if( st_len != l )
|
||||
if (st_len != l)
|
||||
{
|
||||
/* Check version number - must always be 1 currently. */
|
||||
if( (st[l-1] == ':') && (st[l] == '1') )
|
||||
if ((st[l-1] == ':') && (st[l] == '1'))
|
||||
l++;
|
||||
while( l < st_len )
|
||||
while (l < st_len)
|
||||
{
|
||||
if( !isspace(st[l]) )
|
||||
if (!isspace(st[l]))
|
||||
{
|
||||
DPRINTF(E_DEBUG, L_SSDP, "Ignoring SSDP M-SEARCH with bad extra data [%s]\n",
|
||||
inet_ntoa(sendername.sin_addr));
|
||||
@ -696,25 +690,23 @@ ProcessSSDPRequest(int s, unsigned short port)
|
||||
}
|
||||
l++;
|
||||
}
|
||||
if( l != st_len )
|
||||
if (l != st_len)
|
||||
break;
|
||||
}
|
||||
_usleep(random()>>20);
|
||||
SendSSDPAnnounce2(s, sendername,
|
||||
i,
|
||||
SendSSDPAnnounce2(s, sendername, i,
|
||||
lan_addr[lan_addr_index].str, port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Responds to request with ST: ssdp:all */
|
||||
/* strlen("ssdp:all") == 8 */
|
||||
if(st_len==8 && (0 == memcmp(st, "ssdp:all", 8)))
|
||||
if ((st_len == 8) && (memcmp(st, "ssdp:all", 8) == 0))
|
||||
{
|
||||
for(i=0; known_service_types[i]; i++)
|
||||
for (i=0; known_service_types[i]; i++)
|
||||
{
|
||||
l = (int)strlen(known_service_types[i]);
|
||||
SendSSDPAnnounce2(s, sendername,
|
||||
i,
|
||||
l = strlen(known_service_types[i]);
|
||||
SendSSDPAnnounce2(s, sendername, i,
|
||||
lan_addr[lan_addr_index].str, port);
|
||||
}
|
||||
}
|
||||
@ -735,7 +727,7 @@ ProcessSSDPRequest(int s, unsigned short port)
|
||||
/* This will broadcast ssdp:byebye notifications to inform
|
||||
* the network that UPnP is going down. */
|
||||
int
|
||||
SendSSDPGoodbye(int * sockets, int n_sockets)
|
||||
SendSSDPGoodbye(int *sockets, int n_sockets)
|
||||
{
|
||||
struct sockaddr_in sockname;
|
||||
int n, l;
|
||||
@ -750,9 +742,9 @@ SendSSDPGoodbye(int * sockets, int n_sockets)
|
||||
|
||||
for (dup = 0; dup < 2; dup++)
|
||||
{
|
||||
for(j=0; j<n_sockets; j++)
|
||||
for (j = 0; j < n_sockets; j++)
|
||||
{
|
||||
for(i=0; known_service_types[i]; i++)
|
||||
for (i = 0; known_service_types[i]; i++)
|
||||
{
|
||||
l = snprintf(bufr, sizeof(bufr),
|
||||
"NOTIFY * HTTP/1.1\r\n"
|
||||
@ -767,7 +759,7 @@ SendSSDPGoodbye(int * sockets, int n_sockets)
|
||||
//DEBUG DPRINTF(E_DEBUG, L_SSDP, "Sending NOTIFY:\n%s", bufr);
|
||||
n = sendto(sockets[j], bufr, l, 0,
|
||||
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
||||
if(n < 0)
|
||||
if (n < 0)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_SSDP, "sendto(udp_shutdown=%d): %s\n", sockets[j], strerror(errno));
|
||||
ret = -1;
|
||||
@ -783,35 +775,39 @@ SendSSDPGoodbye(int * sockets, int n_sockets)
|
||||
* register services offered by MiniUPnPd to a running instance of
|
||||
* MiniSSDPd */
|
||||
int
|
||||
SubmitServicesToMiniSSDPD(const char * host, unsigned short port) {
|
||||
SubmitServicesToMiniSSDPD(const char *host, unsigned short port)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int s;
|
||||
unsigned char buffer[2048];
|
||||
char strbuf[256];
|
||||
unsigned char * p;
|
||||
unsigned char *p;
|
||||
int i, l;
|
||||
|
||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if(s < 0) {
|
||||
if (s < 0)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_SSDP, "socket(unix): %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, minissdpdsocketpath, sizeof(addr.sun_path));
|
||||
if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
|
||||
if (connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_SSDP, "connect(\"%s\"): %s",
|
||||
minissdpdsocketpath, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
for(i = 0; known_service_types[i]; i++) {
|
||||
for (i = 0; known_service_types[i]; i++)
|
||||
{
|
||||
buffer[0] = 4;
|
||||
p = buffer + 1;
|
||||
l = (int)strlen(known_service_types[i]);
|
||||
if(i > 0)
|
||||
l = strlen(known_service_types[i]);
|
||||
if (i > 0)
|
||||
l++;
|
||||
CODELENGTH(l, p);
|
||||
memcpy(p, known_service_types[i], l);
|
||||
if(i > 0)
|
||||
if (i > 0)
|
||||
p[l-1] = '1';
|
||||
p += l;
|
||||
l = snprintf(strbuf, sizeof(strbuf), "%s::%s%s",
|
||||
@ -819,7 +815,7 @@ SubmitServicesToMiniSSDPD(const char * host, unsigned short port) {
|
||||
CODELENGTH(l, p);
|
||||
memcpy(p, strbuf, l);
|
||||
p += l;
|
||||
l = (int)strlen(MINIDLNA_SERVER_STRING);
|
||||
l = strlen(MINIDLNA_SERVER_STRING);
|
||||
CODELENGTH(l, p);
|
||||
memcpy(p, MINIDLNA_SERVER_STRING, l);
|
||||
p += l;
|
||||
@ -828,7 +824,8 @@ SubmitServicesToMiniSSDPD(const char * host, unsigned short port) {
|
||||
CODELENGTH(l, p);
|
||||
memcpy(p, strbuf, l);
|
||||
p += l;
|
||||
if(write(s, buffer, p - buffer) < 0) {
|
||||
if(write(s, buffer, p - buffer) < 0)
|
||||
{
|
||||
DPRINTF(E_ERROR, L_SSDP, "write(): %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user