--- embedaddon/miniupnpd/upnpevents.c 2012/05/29 12:55:57 1.1.1.2 +++ embedaddon/miniupnpd/upnpevents.c 2013/07/22 00:32:35 1.1.1.3 @@ -1,7 +1,7 @@ -/* $Id: upnpevents.c,v 1.1.1.2 2012/05/29 12:55:57 misho Exp $ */ +/* $Id: upnpevents.c,v 1.1.1.3 2013/07/22 00:32:35 misho Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2008-2011 Thomas Bernard + * (c) 2008-2012 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -16,13 +16,13 @@ #include #include #include -#include #include #include "config.h" #include "upnpevents.h" #include "miniupnpdpath.h" #include "upnpglobalvars.h" #include "upnpdescgen.h" +#include "upnputils.h" #ifdef ENABLE_EVENTS /*enum subscriber_service_enum { @@ -94,6 +94,14 @@ newSubscriber(const char * eventurl, const char * call else if(strcmp(eventurl, L3F_EVENTURL)==0) tmp->service = EL3F; #endif +#ifdef ENABLE_6FC_SERVICE + else if(strcmp(eventurl, WANIP6FC_EVENTURL)==0) + tmp->service = E6FC; +#endif +#ifdef ENABLE_DP_SERVICE + else if(strcmp(eventurl, DP_EVENTURL)==0) + tmp->service = EDP; +#endif else { free(tmp); return NULL; @@ -140,7 +148,7 @@ renewSubscription(const char * sid, int sidlen, int ti { struct subscriber * sub; for(sub = subscriberlist.lh_first; sub != NULL; sub = sub->entries.le_next) { - if(memcmp(sid, sub->uuid, 41) == 0) { + if((sidlen == 41) && (memcmp(sid, sub->uuid, 41) == 0)) { sub->timeout = (timeout ? time(NULL) + timeout : 0); return 0; } @@ -155,7 +163,7 @@ upnpevents_removeSubscriber(const char * sid, int sidl if(!sid) return -1; for(sub = subscriberlist.lh_first; sub != NULL; sub = sub->entries.le_next) { - if(memcmp(sid, sub->uuid, 41) == 0) { + if((sidlen == 41) && (memcmp(sid, sub->uuid, 41) == 0)) { if(sub->notify) { sub->notify->sub = NULL; } @@ -184,7 +192,7 @@ static void upnp_event_create_notify(struct subscriber * sub) { struct upnp_event_notify * obj; - int flags; + obj = calloc(1, sizeof(struct upnp_event_notify)); if(!obj) { syslog(LOG_ERR, "%s: calloc(): %m", "upnp_event_create_notify"); @@ -202,16 +210,11 @@ upnp_event_create_notify(struct subscriber * sub) syslog(LOG_ERR, "%s: socket(): %m", "upnp_event_create_notify"); goto error; } - if((flags = fcntl(obj->s, F_GETFL, 0)) < 0) { - syslog(LOG_ERR, "%s: fcntl(..F_GETFL..): %m", + if(!set_non_blocking(obj->s)) { + syslog(LOG_ERR, "%s: set_non_blocking(): %m", "upnp_event_create_notify"); goto error; } - if(fcntl(obj->s, F_SETFL, flags | O_NONBLOCK) < 0) { - syslog(LOG_ERR, "%s: fcntl(..F_SETFL..): %m", - "upnp_event_create_notify"); - goto error; - } if(sub) sub->notify = obj; LIST_INSERT_HEAD(¬ifylist, obj, entries); @@ -225,7 +228,7 @@ error: static void upnp_event_notify_connect(struct upnp_event_notify * obj) { - int i; + unsigned int i; const char * p; unsigned short port; #ifdef ENABLE_IPV6 @@ -304,7 +307,7 @@ upnp_event_notify_connect(struct upnp_event_notify * o static void upnp_event_prepare(struct upnp_event_notify * obj) { - static const char notifymsg[] = + static const char notifymsg[] = "NOTIFY %s HTTP/1.1\r\n" "Host: %s%s\r\n" "Content-Type: text/xml\r\n" @@ -351,8 +354,14 @@ static void upnp_event_prepare(struct upnp_event_notif } obj->buffersize = 1024; obj->buffer = malloc(obj->buffersize); - /*if(!obj->buffer) { - }*/ + if(!obj->buffer) { + syslog(LOG_ERR, "%s: malloc returned NULL", "upnp_event_prepare"); + if(xml) { + free(xml); + } + obj->state = EError; + return; + } obj->tosend = snprintf(obj->buffer, obj->buffersize, notifymsg, obj->path, obj->addrstr, obj->portstr, l+2, obj->sub->uuid, obj->sub->seq, @@ -367,17 +376,23 @@ static void upnp_event_prepare(struct upnp_event_notif static void upnp_event_send(struct upnp_event_notify * obj) { int i; + syslog(LOG_DEBUG, "%s: sending event notify message to %s:%s", "upnp_event_send", obj->addrstr, obj->portstr); syslog(LOG_DEBUG, "%s: msg: %s", "upnp_event_send", obj->buffer + obj->sent); i = send(obj->s, obj->buffer + obj->sent, obj->tosend - obj->sent, 0); if(i<0) { - syslog(LOG_NOTICE, "%s: send(): %m", "upnp_event_send"); - obj->state = EError; - return; + if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { + syslog(LOG_NOTICE, "%s: send(): %m", "upnp_event_send"); + obj->state = EError; + return; + } else { + /* EAGAIN or EWOULDBLOCK or EINTR : no data sent */ + i = 0; + } } - else if(i != (obj->tosend - obj->sent)) + if(i != (obj->tosend - obj->sent)) syslog(LOG_NOTICE, "%s: %d bytes send out of %d", "upnp_event_send", i, obj->tosend - obj->sent); obj->sent += i; @@ -390,12 +405,19 @@ static void upnp_event_recv(struct upnp_event_notify * int n; n = recv(obj->s, obj->buffer, obj->buffersize, 0); if(n<0) { - syslog(LOG_ERR, "%s: recv(): %m", "upnp_event_recv"); - obj->state = EError; + if(errno != EAGAIN && + errno != EWOULDBLOCK && + errno != EINTR) { + syslog(LOG_ERR, "%s: recv(): %m", "upnp_event_recv"); + obj->state = EError; + } return; } syslog(LOG_DEBUG, "%s: (%dbytes) %.*s", "upnp_event_recv", n, n, obj->buffer); + /* TODO : do something with the data recevied ? + * right now, n (number of bytes received) is ignored + * We may need to recv() more bytes. */ obj->state = EFinished; if(obj->sub) obj->sub->seq++; @@ -404,11 +426,26 @@ static void upnp_event_recv(struct upnp_event_notify * static void upnp_event_process_notify(struct upnp_event_notify * obj) { + int err; + socklen_t len; switch(obj->state) { case EConnecting: /* now connected or failed to connect */ + len = sizeof(err); + if(getsockopt(obj->s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { + syslog(LOG_ERR, "%s: getsockopt: %m", "upnp_event_process_notify"); + obj->state = EError; + break; + } + if(err != 0) { + errno = err; + syslog(LOG_WARNING, "%s: connect failed: %m", "upnp_event_process_notify"); + obj->state = EError; + break; + } upnp_event_prepare(obj); - upnp_event_send(obj); + if(obj->state == ESending) + upnp_event_send(obj); break; case ESending: upnp_event_send(obj); @@ -421,7 +458,7 @@ upnp_event_process_notify(struct upnp_event_notify * o obj->s = -1; break; default: - syslog(LOG_ERR, "upnp_event_process_notify: unknown state"); + syslog(LOG_ERR, "%s: unknown state", "upnp_event_process_notify"); } }