diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt
index 8319031..05c46ce 100644
--- a/miniupnpd/Changelog.txt
+++ b/miniupnpd/Changelog.txt
@@ -1,4 +1,7 @@
-$Id: Changelog.txt,v 1.255 2012/02/06 16:32:07 nanard Exp $
+$Id: Changelog.txt,v 1.256 2012/02/07 00:21:51 nanard Exp $
+
+2012/02/06:
+ Make HTTP (SOAP) sockets non blocking.
2012/02/05:
Compile ok with -ansi flag.
diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c
index 9ea1d84..1a7b4fb 100644
--- a/miniupnpd/miniupnpd.c
+++ b/miniupnpd/miniupnpd.c
@@ -1,4 +1,4 @@
-/* $Id: miniupnpd.c,v 1.142 2012/02/04 23:34:39 nanard Exp $ */
+/* $Id: miniupnpd.c,v 1.143 2012/02/07 00:21:52 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
@@ -1091,9 +1091,7 @@ main(int argc, char * * argv)
struct upnphttp * e = 0;
struct upnphttp * next;
fd_set readset; /* for select() */
-#ifdef ENABLE_EVENTS
fd_set writeset;
-#endif
struct timeval timeout, timeofday, lasttimeofday = {0, 0};
int max_fd = -1;
#ifdef USE_MINIUPNPDCTL
@@ -1359,6 +1357,7 @@ main(int argc, char * * argv)
/* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
FD_ZERO(&readset);
+ FD_ZERO(&writeset);
if (sudp >= 0)
{
@@ -1396,10 +1395,15 @@ main(int argc, char * * argv)
i = 0; /* active HTTP connections count */
for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
{
- if((e->socket >= 0) && (e->state <= 2))
+ if(e->socket >= 0)
{
- FD_SET(e->socket, &readset);
- max_fd = MAX( max_fd, e->socket);
+ if(e->state <= EWaitingForHttpContent)
+ FD_SET(e->socket, &readset);
+ else if(e->state == ESendingAndClosing)
+ FD_SET(e->socket, &writeset);
+ else
+ continue;
+ max_fd = MAX(max_fd, e->socket);
i++;
}
}
@@ -1434,15 +1438,10 @@ main(int argc, char * * argv)
#endif
#ifdef ENABLE_EVENTS
- FD_ZERO(&writeset);
upnpevents_selectfds(&readset, &writeset, &max_fd);
#endif
-#ifdef ENABLE_EVENTS
if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)
-#else
- if(select(max_fd+1, &readset, 0, 0, &timeout) < 0)
-#endif
{
if(quitting) goto shutdown;
if(errno == EINTR) continue; /* interrupted by a signal, start again */
@@ -1539,10 +1538,13 @@ main(int argc, char * * argv)
/* LIST_FOREACH macro is not available under linux */
for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
{
- if( (e->socket >= 0) && (e->state <= 2)
- &&(FD_ISSET(e->socket, &readset)) )
+ if(e->socket >= 0)
{
- Process_upnphttp(e);
+ if(FD_ISSET(e->socket, &readset) ||
+ FD_ISSET(e->socket, &writeset))
+ {
+ Process_upnphttp(e);
+ }
}
}
/* process incoming HTTP connections */
@@ -1623,7 +1625,7 @@ main(int argc, char * * argv)
for(e = upnphttphead.lh_first; e != NULL; )
{
next = e->entries.le_next;
- if(e->state >= 100)
+ if(e->state >= EToDelete)
{
LIST_REMOVE(e, entries);
Delete_upnphttp(e);
diff --git a/miniupnpd/upnpevents.c b/miniupnpd/upnpevents.c
index 28d090d..1ef545c 100644
--- a/miniupnpd/upnpevents.c
+++ b/miniupnpd/upnpevents.c
@@ -1,4 +1,4 @@
-/* $Id: upnpevents.c,v 1.19 2012/02/06 16:21:24 nanard Exp $ */
+/* $Id: upnpevents.c,v 1.20 2012/02/06 23:41:15 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2008-2012 Thomas Bernard
@@ -368,11 +368,16 @@ static void upnp_event_send(struct upnp_event_notify * obj)
"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;
diff --git a/miniupnpd/upnphttp.c b/miniupnpd/upnphttp.c
index 70e21fe..19f9b75 100644
--- a/miniupnpd/upnphttp.c
+++ b/miniupnpd/upnphttp.c
@@ -1,4 +1,4 @@
-/* $Id: upnphttp.c,v 1.66 2012/02/01 11:13:30 nanard Exp $ */
+/* $Id: upnphttp.c,v 1.67 2012/02/07 00:21:54 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
@@ -24,6 +24,7 @@
#include "miniupnpdpath.h"
#include "upnpsoap.h"
#include "upnpevents.h"
+#include "upnputils.h"
struct upnphttp *
New_upnphttp(int s)
@@ -36,6 +37,8 @@ New_upnphttp(int s)
return NULL;
memset(ret, 0, sizeof(struct upnphttp));
ret->socket = s;
+ if(!set_non_blocking(s))
+ syslog(LOG_WARNING, "New_upnphttp::set_non_blocking(): %m");
return ret;
}
@@ -47,7 +50,7 @@ CloseSocket_upnphttp(struct upnphttp * h)
syslog(LOG_ERR, "CloseSocket_upnphttp: close(%d): %m", h->socket);
}
h->socket = -1;
- h->state = 100;
+ h->state = EToDelete;
}
void
@@ -159,24 +162,11 @@ intervening space) by either an integer or the keyword "infinite". */
static void
Send404(struct upnphttp * h)
{
-/*
- static const char error404[] = "HTTP/1.1 404 Not found\r\n"
- "Connection: close\r\n"
- "Content-type: text/html\r\n"
- "\r\n"
- "
404 Not Found"
- "Not Found
The requested URL was not found"
- " on this server.\r\n";
- int n;
- n = send(h->socket, error404, sizeof(error404) - 1, 0);
- if(n < 0)
- {
- syslog(LOG_ERR, "Send404: send(http): %m");
- }*/
static const char body404[] =
"404 Not Found"
"Not Found
The requested URL was not found"
" on this server.\r\n";
+
h->respflags = FLAG_HTML;
BuildResp2_upnphttp(h, 404, "Not Found",
body404, sizeof(body404) - 1);
@@ -187,25 +177,11 @@ Send404(struct upnphttp * h)
static void
Send501(struct upnphttp * h)
{
-/*
- static const char error501[] = "HTTP/1.1 501 Not Implemented\r\n"
- "Connection: close\r\n"
- "Content-type: text/html\r\n"
- "\r\n"
- "501 Not Implemented"
- "Not Implemented
The HTTP Method "
- "is not implemented by this server.\r\n";
- int n;
- n = send(h->socket, error501, sizeof(error501) - 1, 0);
- if(n < 0)
- {
- syslog(LOG_ERR, "Send501: send(http): %m");
- }
-*/
static const char body501[] =
"501 Not Implemented"
"Not Implemented
The HTTP Method "
"is not implemented by this server.\r\n";
+
h->respflags = FLAG_HTML;
BuildResp2_upnphttp(h, 501, "Not Implemented",
body501, sizeof(body501) - 1);
@@ -296,7 +272,7 @@ ProcessHTTPPOST_upnphttp(struct upnphttp * h)
else
{
/* waiting for remaining data */
- h->state = 1;
+ h->state = EWaitingForHttpContent;
}
}
@@ -546,12 +522,13 @@ Process_upnphttp(struct upnphttp * h)
{
char buf[2048];
int n;
+
if(!h)
return;
switch(h->state)
{
- case 0:
- n = recv(h->socket, buf, 2048, 0);
+ case EWaitingForHttpRequest:
+ n = recv(h->socket, buf, sizeof(buf), 0);
if(n<0)
{
if(errno != EAGAIN &&
@@ -559,14 +536,14 @@ Process_upnphttp(struct upnphttp * h)
errno != EINTR)
{
syslog(LOG_ERR, "recv (state0): %m");
- h->state = 100;
+ h->state = EToDelete;
}
/* if errno is EAGAIN, EWOULDBLOCK or EINTR, try again later */
}
else if(n==0)
{
syslog(LOG_WARNING, "HTTP Connection closed unexpectedly");
- h->state = 100;
+ h->state = EToDelete;
}
else
{
@@ -586,8 +563,8 @@ Process_upnphttp(struct upnphttp * h)
}
}
break;
- case 1:
- n = recv(h->socket, buf, 2048, 0);
+ case EWaitingForHttpContent:
+ n = recv(h->socket, buf, sizeof(buf), 0);
if(n<0)
{
if(errno != EAGAIN &&
@@ -595,27 +572,38 @@ Process_upnphttp(struct upnphttp * h)
errno != EINTR)
{
syslog(LOG_ERR, "recv (state1): %m");
- h->state = 100;
+ h->state = EToDelete;
}
/* if errno is EAGAIN, EWOULDBLOCK or EINTR, try again later */
}
else if(n==0)
{
syslog(LOG_WARNING, "HTTP Connection closed inexpectedly");
- h->state = 100;
+ h->state = EToDelete;
}
else
{
- /*fwrite(buf, 1, n, stdout);*/ /* debug */
- h->req_buf = (char *)realloc(h->req_buf, n + h->req_buflen);
- memcpy(h->req_buf + h->req_buflen, buf, n);
- h->req_buflen += n;
- if((h->req_buflen - h->req_contentoff) >= h->req_contentlen)
+ void * tmp = realloc(h->req_buf, n + h->req_buflen);
+ if(!tmp)
{
- ProcessHTTPPOST_upnphttp(h);
+ syslog(LOG_ERR, "memory allocation error %m");
+ h->state = EToDelete;
+ }
+ else
+ {
+ h->req_buf = tmp;
+ memcpy(h->req_buf + h->req_buflen, buf, n);
+ h->req_buflen += n;
+ if((h->req_buflen - h->req_contentoff) >= h->req_contentlen)
+ {
+ ProcessHTTPPOST_upnphttp(h);
+ }
}
}
break;
+ case ESendingAndClosing:
+ SendRespAndClose_upnphttp(h);
+ break;
default:
syslog(LOG_WARNING, "Unexpected state: %d", h->state);
}
@@ -725,30 +713,34 @@ BuildResp_upnphttp(struct upnphttp * h,
void
SendRespAndClose_upnphttp(struct upnphttp * h)
{
- char * p;
ssize_t n;
- size_t len;
- p = h->res_buf;
- len = h->res_buflen;
- while (len > 0)
+
+ while (h->res_sent < h->res_buflen)
{
- n = send(h->socket, p, len, 0);
+ n = send(h->socket, h->res_buf + h->res_sent,
+ h->res_buflen - h->res_sent, 0);
if(n<0)
{
+ if(errno == EINTR)
+ continue; /* try again immediatly */
+ if(errno == EAGAIN || errno == EWOULDBLOCK)
+ {
+ /* try again later */
+ h->state = ESendingAndClosing;
+ return;
+ }
syslog(LOG_ERR, "send(res_buf): %m");
- if (errno != EINTR)
- break; /* avoid infinite loop */
+ break; /* avoid infinite loop */
}
else if(n == 0)
{
- syslog(LOG_ERR, "send(res_buf): %zd bytes sent (out of %zu)",
- n, len);
+ syslog(LOG_ERR, "send(res_buf): %d bytes sent (out of %d)",
+ h->res_sent, h->res_buflen);
break;
}
else
{
- p += n;
- len -= n;
+ h->res_sent += n;
}
}
CloseSocket_upnphttp(h);
diff --git a/miniupnpd/upnphttp.h b/miniupnpd/upnphttp.h
index c8462be..70278c3 100644
--- a/miniupnpd/upnphttp.h
+++ b/miniupnpd/upnphttp.h
@@ -1,4 +1,4 @@
-/* $Id: upnphttp.h,v 1.25 2011/11/18 11:21:18 nanard Exp $ */
+/* $Id: upnphttp.h,v 1.26 2012/02/07 00:21:54 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2011 Thomas Bernard
@@ -23,6 +23,13 @@
...
>= 100 - to be deleted
*/
+enum httpStates {
+ EWaitingForHttpRequest = 0,
+ EWaitingForHttpContent,
+ ESendingAndClosing,
+ EToDelete = 100
+};
+
enum httpCommands {
EUnknown = 0,
EGet,
@@ -38,7 +45,7 @@ struct upnphttp {
int ipv6;
struct in6_addr clientaddr_v6;
#endif
- int state;
+ enum httpStates state;
char HttpVer[16];
/* request */
char * req_buf;
@@ -59,9 +66,8 @@ struct upnphttp {
/* response */
char * res_buf;
int res_buflen;
+ int res_sent;
int res_buf_alloclen;
- /*int res_contentlen;*/
- /*int res_contentoff;*/ /* header length */
LIST_ENTRY(upnphttp) entries;
};