version 1.1.1.2, 2012/05/29 12:55:57
|
version 1.1.1.3, 2013/07/22 00:32:35
|
Line 1
|
Line 1
|
/* $Id$ */ |
/* $Id$ */ |
/* MiniUPnP project |
/* MiniUPnP project |
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ |
* 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 |
* This software is subject to the conditions detailed |
* in the LICENCE file provided within the distribution */ |
* in the LICENCE file provided within the distribution */ |
|
|
Line 16
|
Line 16
|
#include <sys/socket.h> |
#include <sys/socket.h> |
#include <netinet/in.h> |
#include <netinet/in.h> |
#include <arpa/inet.h> |
#include <arpa/inet.h> |
#include <fcntl.h> |
|
#include <errno.h> |
#include <errno.h> |
#include "config.h" |
#include "config.h" |
#include "upnpevents.h" |
#include "upnpevents.h" |
#include "miniupnpdpath.h" |
#include "miniupnpdpath.h" |
#include "upnpglobalvars.h" |
#include "upnpglobalvars.h" |
#include "upnpdescgen.h" |
#include "upnpdescgen.h" |
|
#include "upnputils.h" |
|
|
#ifdef ENABLE_EVENTS |
#ifdef ENABLE_EVENTS |
/*enum subscriber_service_enum { |
/*enum subscriber_service_enum { |
Line 94 newSubscriber(const char * eventurl, const char * call
|
Line 94 newSubscriber(const char * eventurl, const char * call
|
else if(strcmp(eventurl, L3F_EVENTURL)==0) |
else if(strcmp(eventurl, L3F_EVENTURL)==0) |
tmp->service = EL3F; |
tmp->service = EL3F; |
#endif |
#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 { |
else { |
free(tmp); |
free(tmp); |
return NULL; |
return NULL; |
Line 140 renewSubscription(const char * sid, int sidlen, int ti
|
Line 148 renewSubscription(const char * sid, int sidlen, int ti
|
{ |
{ |
struct subscriber * sub; |
struct subscriber * sub; |
for(sub = subscriberlist.lh_first; sub != NULL; sub = sub->entries.le_next) { |
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); |
sub->timeout = (timeout ? time(NULL) + timeout : 0); |
return 0; |
return 0; |
} |
} |
Line 155 upnpevents_removeSubscriber(const char * sid, int sidl
|
Line 163 upnpevents_removeSubscriber(const char * sid, int sidl
|
if(!sid) |
if(!sid) |
return -1; |
return -1; |
for(sub = subscriberlist.lh_first; sub != NULL; sub = sub->entries.le_next) { |
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) { |
if(sub->notify) { |
sub->notify->sub = NULL; |
sub->notify->sub = NULL; |
} |
} |
Line 184 static void
|
Line 192 static void
|
upnp_event_create_notify(struct subscriber * sub) |
upnp_event_create_notify(struct subscriber * sub) |
{ |
{ |
struct upnp_event_notify * obj; |
struct upnp_event_notify * obj; |
int flags; | |
obj = calloc(1, sizeof(struct upnp_event_notify)); |
obj = calloc(1, sizeof(struct upnp_event_notify)); |
if(!obj) { |
if(!obj) { |
syslog(LOG_ERR, "%s: calloc(): %m", "upnp_event_create_notify"); |
syslog(LOG_ERR, "%s: calloc(): %m", "upnp_event_create_notify"); |
Line 202 upnp_event_create_notify(struct subscriber * sub)
|
Line 210 upnp_event_create_notify(struct subscriber * sub)
|
syslog(LOG_ERR, "%s: socket(): %m", "upnp_event_create_notify"); |
syslog(LOG_ERR, "%s: socket(): %m", "upnp_event_create_notify"); |
goto error; |
goto error; |
} |
} |
if((flags = fcntl(obj->s, F_GETFL, 0)) < 0) { | if(!set_non_blocking(obj->s)) { |
syslog(LOG_ERR, "%s: fcntl(..F_GETFL..): %m", | syslog(LOG_ERR, "%s: set_non_blocking(): %m", |
"upnp_event_create_notify"); |
"upnp_event_create_notify"); |
goto error; |
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) |
if(sub) |
sub->notify = obj; |
sub->notify = obj; |
LIST_INSERT_HEAD(¬ifylist, obj, entries); |
LIST_INSERT_HEAD(¬ifylist, obj, entries); |
Line 225 error:
|
Line 228 error:
|
static void |
static void |
upnp_event_notify_connect(struct upnp_event_notify * obj) |
upnp_event_notify_connect(struct upnp_event_notify * obj) |
{ |
{ |
int i; | unsigned int i; |
const char * p; |
const char * p; |
unsigned short port; |
unsigned short port; |
#ifdef ENABLE_IPV6 |
#ifdef ENABLE_IPV6 |
Line 304 upnp_event_notify_connect(struct upnp_event_notify * o
|
Line 307 upnp_event_notify_connect(struct upnp_event_notify * o
|
|
|
static void upnp_event_prepare(struct upnp_event_notify * obj) |
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" |
"NOTIFY %s HTTP/1.1\r\n" |
"Host: %s%s\r\n" |
"Host: %s%s\r\n" |
"Content-Type: text/xml\r\n" |
"Content-Type: text/xml\r\n" |
Line 351 static void upnp_event_prepare(struct upnp_event_notif
|
Line 354 static void upnp_event_prepare(struct upnp_event_notif
|
} |
} |
obj->buffersize = 1024; |
obj->buffersize = 1024; |
obj->buffer = malloc(obj->buffersize); |
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->tosend = snprintf(obj->buffer, obj->buffersize, notifymsg, |
obj->path, obj->addrstr, obj->portstr, l+2, |
obj->path, obj->addrstr, obj->portstr, l+2, |
obj->sub->uuid, obj->sub->seq, |
obj->sub->uuid, obj->sub->seq, |
Line 367 static void upnp_event_prepare(struct upnp_event_notif
|
Line 376 static void upnp_event_prepare(struct upnp_event_notif
|
static void upnp_event_send(struct upnp_event_notify * obj) |
static void upnp_event_send(struct upnp_event_notify * obj) |
{ |
{ |
int i; |
int i; |
|
|
syslog(LOG_DEBUG, "%s: sending event notify message to %s:%s", |
syslog(LOG_DEBUG, "%s: sending event notify message to %s:%s", |
"upnp_event_send", obj->addrstr, obj->portstr); |
"upnp_event_send", obj->addrstr, obj->portstr); |
syslog(LOG_DEBUG, "%s: msg: %s", |
syslog(LOG_DEBUG, "%s: msg: %s", |
"upnp_event_send", obj->buffer + obj->sent); |
"upnp_event_send", obj->buffer + obj->sent); |
i = send(obj->s, obj->buffer + obj->sent, obj->tosend - obj->sent, 0); |
i = send(obj->s, obj->buffer + obj->sent, obj->tosend - obj->sent, 0); |
if(i<0) { |
if(i<0) { |
syslog(LOG_NOTICE, "%s: send(): %m", "upnp_event_send"); | if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { |
obj->state = EError; | syslog(LOG_NOTICE, "%s: send(): %m", "upnp_event_send"); |
return; | 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", |
syslog(LOG_NOTICE, "%s: %d bytes send out of %d", |
"upnp_event_send", i, obj->tosend - obj->sent); |
"upnp_event_send", i, obj->tosend - obj->sent); |
obj->sent += i; |
obj->sent += i; |
Line 390 static void upnp_event_recv(struct upnp_event_notify *
|
Line 405 static void upnp_event_recv(struct upnp_event_notify *
|
int n; |
int n; |
n = recv(obj->s, obj->buffer, obj->buffersize, 0); |
n = recv(obj->s, obj->buffer, obj->buffersize, 0); |
if(n<0) { |
if(n<0) { |
syslog(LOG_ERR, "%s: recv(): %m", "upnp_event_recv"); | if(errno != EAGAIN && |
obj->state = EError; | errno != EWOULDBLOCK && |
| errno != EINTR) { |
| syslog(LOG_ERR, "%s: recv(): %m", "upnp_event_recv"); |
| obj->state = EError; |
| } |
return; |
return; |
} |
} |
syslog(LOG_DEBUG, "%s: (%dbytes) %.*s", "upnp_event_recv", |
syslog(LOG_DEBUG, "%s: (%dbytes) %.*s", "upnp_event_recv", |
n, n, obj->buffer); |
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; |
obj->state = EFinished; |
if(obj->sub) |
if(obj->sub) |
obj->sub->seq++; |
obj->sub->seq++; |
Line 404 static void upnp_event_recv(struct upnp_event_notify *
|
Line 426 static void upnp_event_recv(struct upnp_event_notify *
|
static void |
static void |
upnp_event_process_notify(struct upnp_event_notify * obj) |
upnp_event_process_notify(struct upnp_event_notify * obj) |
{ |
{ |
|
int err; |
|
socklen_t len; |
switch(obj->state) { |
switch(obj->state) { |
case EConnecting: |
case EConnecting: |
/* now connected or failed to connect */ |
/* 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_prepare(obj); |
upnp_event_send(obj); | if(obj->state == ESending) |
| upnp_event_send(obj); |
break; |
break; |
case ESending: |
case ESending: |
upnp_event_send(obj); |
upnp_event_send(obj); |
Line 421 upnp_event_process_notify(struct upnp_event_notify * o
|
Line 458 upnp_event_process_notify(struct upnp_event_notify * o
|
obj->s = -1; |
obj->s = -1; |
break; |
break; |
default: |
default: |
syslog(LOG_ERR, "upnp_event_process_notify: unknown state"); | syslog(LOG_ERR, "%s: unknown state", "upnp_event_process_notify"); |
} |
} |
} |
} |
|
|