miniupnpd: use asyncsendto

This commit is contained in:
Thomas Bernard 2014-02-25 11:15:30 +01:00
parent cbc1a3c96a
commit c1e624ecd4
3 changed files with 38 additions and 20 deletions

View File

@ -24,6 +24,7 @@
#include "minissdp.h" #include "minissdp.h"
#include "upnputils.h" #include "upnputils.h"
#include "getroute.h" #include "getroute.h"
#include "asyncsendto.h"
#include "codelength.h" #include "codelength.h"
/* SSDP ip/port */ /* SSDP ip/port */
@ -330,11 +331,13 @@ EXT:
* st, st_len : ST: header * st, st_len : ST: header
* suffix : suffix for USN: header * suffix : suffix for USN: header
* host, port : our HTTP host, port * host, port : our HTTP host, port
* delay : in milli-seconds
*/ */
static void static void
SendSSDPResponse(int s, const struct sockaddr * addr, SendSSDPResponse(int s, const struct sockaddr * addr,
const char * st, int st_len, const char * suffix, const char * st, int st_len, const char * suffix,
const char * host, unsigned short port, const char * uuidvalue) const char * host, unsigned short port, const char * uuidvalue,
unsigned int delay)
{ {
int l, n; int l, n;
char buf[512]; char buf[512];
@ -399,15 +402,14 @@ SendSSDPResponse(int s, const struct sockaddr * addr,
} }
addrlen = (addr->sa_family == AF_INET6) addrlen = (addr->sa_family == AF_INET6)
? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
n = sendto(s, buf, l, 0, n = sendto_schedule(s, buf, l, 0,
addr, addrlen); addr, addrlen, delay);
sockaddr_to_string(addr, addr_str, sizeof(addr_str)); sockaddr_to_string(addr, addr_str, sizeof(addr_str));
syslog(LOG_INFO, "SSDP Announce %d bytes to %s ST: %.*s",n, syslog(LOG_INFO, "SSDP Announce %d bytes to %s ST: %.*s",n,
addr_str, addr_str,
l, buf); l, buf);
if(n < 0) if(n < 0)
{ {
/* XXX handle EINTR, EAGAIN, EWOULDBLOCK */
syslog(LOG_ERR, "sendto(udp): %m"); syslog(LOG_ERR, "sendto(udp): %m");
} }
} }
@ -488,7 +490,7 @@ SendSSDPNotify(int s, const struct sockaddr * dest,
syslog(LOG_WARNING, "SendSSDPNotify(): truncated output"); syslog(LOG_WARNING, "SendSSDPNotify(): truncated output");
l = sizeof(bufr) - 1; l = sizeof(bufr) - 1;
} }
n = sendto(s, bufr, l, 0, dest, n = sendto_or_schedule(s, bufr, l, 0, dest,
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in) ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)
#else #else
@ -497,7 +499,6 @@ SendSSDPNotify(int s, const struct sockaddr * dest,
); );
if(n < 0) if(n < 0)
{ {
/* XXX handle EINTR, EAGAIN, EWOULDBLOCK */
syslog(LOG_ERR, "sendto(udp_notify=%d, %s): %m", s, syslog(LOG_ERR, "sendto(udp_notify=%d, %s): %m", s,
host ? host : "NULL"); host ? host : "NULL");
} }
@ -636,6 +637,16 @@ ProcessSSDPData(int s, const char *bufr, int n,
#endif #endif
int mx_value = -1; int mx_value = -1;
#endif #endif
unsigned int delay = 0;
/* UPnP Device Architecture v1.1. 1.3.3 Search response :
* Devices responding to a multicast M-SEARCH SHOULD wait a random period
* of time between 0 seconds and the number of seconds specified in the
* MX field value of the search request before responding, in order to
* avoid flooding the requesting control point with search responses
* from multiple devices. If the search request results in the need for
* a multiple part response from the device, those multiple part
* responses SHOULD be spread at random intervals through the time period
* from 0 to the number of seconds specified in the MX header field. */
/* get the string representation of the sender address */ /* get the string representation of the sender address */
sockaddr_to_string(sender, sender_str, sizeof(sender_str)); sockaddr_to_string(sender, sender_str, sizeof(sender_str));
@ -771,7 +782,8 @@ ProcessSSDPData(int s, const char *bufr, int n,
SendSSDPResponse(s, sender, SendSSDPResponse(s, sender,
st, st_len, "", st, st_len, "",
announced_host, port, announced_host, port,
known_service_types[i].uuid); known_service_types[i].uuid,
delay);
break; break;
} }
} }
@ -790,15 +802,16 @@ ProcessSSDPData(int s, const char *bufr, int n,
SendSSDPResponse(s, sender, SendSSDPResponse(s, sender,
known_service_types[i].s, l, ver_str, known_service_types[i].s, l, ver_str,
announced_host, port, announced_host, port,
known_service_types[i].uuid); known_service_types[i].uuid,
delay);
} }
/* also answer for uuid */ /* also answer for uuid */
SendSSDPResponse(s, sender, uuidvalue_igd, strlen(uuidvalue_igd), "", SendSSDPResponse(s, sender, uuidvalue_igd, strlen(uuidvalue_igd), "",
announced_host, port, uuidvalue_igd); announced_host, port, uuidvalue_igd, delay);
SendSSDPResponse(s, sender, uuidvalue_wan, strlen(uuidvalue_wan), "", SendSSDPResponse(s, sender, uuidvalue_wan, strlen(uuidvalue_wan), "",
announced_host, port, uuidvalue_wan); announced_host, port, uuidvalue_wan, delay);
SendSSDPResponse(s, sender, uuidvalue_wcd, strlen(uuidvalue_wcd), "", SendSSDPResponse(s, sender, uuidvalue_wcd, strlen(uuidvalue_wcd), "",
announced_host, port, uuidvalue_wcd); announced_host, port, uuidvalue_wcd, delay);
} }
/* responds to request by UUID value */ /* responds to request by UUID value */
l = (int)strlen(uuidvalue_igd); l = (int)strlen(uuidvalue_igd);
@ -808,19 +821,22 @@ ProcessSSDPData(int s, const char *bufr, int n,
{ {
syslog(LOG_INFO, "ssdp:uuid (IGD) found"); syslog(LOG_INFO, "ssdp:uuid (IGD) found");
SendSSDPResponse(s, sender, st, st_len, "", SendSSDPResponse(s, sender, st, st_len, "",
announced_host, port, uuidvalue_igd); announced_host, port, uuidvalue_igd,
delay);
} }
else if(0 == memcmp(st, uuidvalue_wan, l)) else if(0 == memcmp(st, uuidvalue_wan, l))
{ {
syslog(LOG_INFO, "ssdp:uuid (WAN) found"); syslog(LOG_INFO, "ssdp:uuid (WAN) found");
SendSSDPResponse(s, sender, st, st_len, "", SendSSDPResponse(s, sender, st, st_len, "",
announced_host, port, uuidvalue_wan); announced_host, port, uuidvalue_wan,
delay);
} }
else if(0 == memcmp(st, uuidvalue_wcd, l)) else if(0 == memcmp(st, uuidvalue_wcd, l))
{ {
syslog(LOG_INFO, "ssdp:uuid (WCD) found"); syslog(LOG_INFO, "ssdp:uuid (WCD) found");
SendSSDPResponse(s, sender, st, st_len, "", SendSSDPResponse(s, sender, st, st_len, "",
announced_host, port, uuidvalue_wcd); announced_host, port, uuidvalue_wcd,
delay);
} }
} }
} }
@ -870,7 +886,7 @@ SendSSDPbyebye(int s, const struct sockaddr * dest,
syslog(LOG_WARNING, "SendSSDPbyebye(): truncated output"); syslog(LOG_WARNING, "SendSSDPbyebye(): truncated output");
l = sizeof(bufr) - 1; l = sizeof(bufr) - 1;
} }
n = sendto(s, bufr, l, 0, dest, n = sendto_or_schedule(s, bufr, l, 0, dest,
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in) ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)
#else #else

View File

@ -1,6 +1,6 @@
/* $Id: natpmp.c,v 1.36 2014/02/01 17:17:35 nanard Exp $ */ /* $Id: natpmp.c,v 1.36 2014/02/01 17:17:35 nanard Exp $ */
/* MiniUPnP project /* MiniUPnP project
* (c) 2007-2013 Thomas Bernard * (c) 2007-2014 Thomas Bernard
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* This software is subject to the conditions detailed * This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */ * in the LICENCE file provided within the distribution */
@ -23,6 +23,7 @@
#include "upnpredirect.h" #include "upnpredirect.h"
#include "commonrdr.h" #include "commonrdr.h"
#include "upnputils.h" #include "upnputils.h"
#include "asyncsendto.h"
#ifdef ENABLE_NATPMP #ifdef ENABLE_NATPMP
@ -324,7 +325,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
default: default:
resp[3] = 5; /* Unsupported OPCODE */ resp[3] = 5; /* Unsupported OPCODE */
} }
n = sendto(s, resp, resplen, 0, n = sendto_or_schedule(s, resp, resplen, 0,
(struct sockaddr *)senderaddr, sizeof(*senderaddr)); (struct sockaddr *)senderaddr, sizeof(*senderaddr));
if(n<0) { if(n<0) {
syslog(LOG_ERR, "sendto(natpmp): %m"); syslog(LOG_ERR, "sendto(natpmp): %m");
@ -378,7 +379,7 @@ void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets)
#endif #endif
/* Port to use in 2006 version of the NAT-PMP specification */ /* Port to use in 2006 version of the NAT-PMP specification */
sockname.sin_port = htons(NATPMP_PORT); sockname.sin_port = htons(NATPMP_PORT);
n = sendto(sockets[j], notif, 12, 0, n = sendto_or_schedule(sockets[j], notif, 12, 0,
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in)); (struct sockaddr *)&sockname, sizeof(struct sockaddr_in));
if(n < 0) if(n < 0)
{ {
@ -388,7 +389,7 @@ void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets)
} }
/* Port to use in 2008 version of the NAT-PMP specification */ /* Port to use in 2008 version of the NAT-PMP specification */
sockname.sin_port = htons(NATPMP_NOTIF_PORT); sockname.sin_port = htons(NATPMP_NOTIF_PORT);
n = sendto(sockets[j], notif, 12, 0, n = sendto_or_schedule(sockets[j], notif, 12, 0,
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in)); (struct sockaddr *)&sockname, sizeof(struct sockaddr_in));
if(n < 0) if(n < 0)
{ {

View File

@ -58,6 +58,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "upnpredirect.h" #include "upnpredirect.h"
#include "commonrdr.h" #include "commonrdr.h"
#include "getifaddr.h" #include "getifaddr.h"
#include "asyncsendto.h"
#include "pcp_msg_struct.h" #include "pcp_msg_struct.h"
#ifdef PCP_PEER #ifdef PCP_PEER
@ -1325,7 +1326,7 @@ int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len,
len = PCP_MIN_LEN; len = PCP_MIN_LEN;
else else
len = (len + 3) & ~3; /* round up resp. length to multiple of 4 */ len = (len + 3) & ~3; /* round up resp. length to multiple of 4 */
len = sendto(s, buff, len, 0, len = sendto_or_schedule(s, buff, len, 0,
(struct sockaddr *)senderaddr, sizeof(struct sockaddr_in)); (struct sockaddr *)senderaddr, sizeof(struct sockaddr_in));
if( len < 0 ) { if( len < 0 ) {
syslog(LOG_ERR, "sendto(pcpserver): %m"); syslog(LOG_ERR, "sendto(pcpserver): %m");