Make HTTP (SOAP) sockets non blocking
This commit is contained in:
parent
0d0a50a084
commit
af60fee984
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
"<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>"
|
||||
"<BODY><H1>Not Found</H1>The requested URL was not found"
|
||||
" on this server.</BODY></HTML>\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[] =
|
||||
"<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>"
|
||||
"<BODY><H1>Not Found</H1>The requested URL was not found"
|
||||
" on this server.</BODY></HTML>\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"
|
||||
"<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>"
|
||||
"<BODY><H1>Not Implemented</H1>The HTTP Method "
|
||||
"is not implemented by this server.</BODY></HTML>\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[] =
|
||||
"<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>"
|
||||
"<BODY><H1>Not Implemented</H1>The HTTP Method "
|
||||
"is not implemented by this server.</BODY></HTML>\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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue