summaryrefslogtreecommitdiff
path: root/uhttpd-utils.c
diff options
context:
space:
mode:
authorjow <jow@3c298f89-4303-0410-b956-a3cf2f4a3e73>2011-11-05 03:19:07 +0000
committerjow <jow@3c298f89-4303-0410-b956-a3cf2f4a3e73>2011-11-05 03:19:07 +0000
commitf82294618678cf43876d34cb3f092ca2600fcb18 (patch)
tree4d59d1502f1642223d3d840bef71a18fcb56795f /uhttpd-utils.c
parent659b5fdc5084938793985e407178d72b9dcc23c7 (diff)
downloaduhttpd-f82294618678cf43876d34cb3f092ca2600fcb18.tar.gz
[package] uhttpd: rework CyaSSL and OpenSSL integration; move protected recv() and send() operations below the ssl layer - fixes hangs when accessing via https
git-svn-id: svn://svn.openwrt.org/openwrt/trunk/package/uhttpd/src@28761 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'uhttpd-utils.c')
-rw-r--r--uhttpd-utils.c79
1 files changed, 44 insertions, 35 deletions
diff --git a/uhttpd-utils.c b/uhttpd-utils.c
index ac00af8..d48f6bc 100644
--- a/uhttpd-utils.c
+++ b/uhttpd-utils.c
@@ -124,7 +124,7 @@ int select_intr(int n, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
}
-int uh_tcp_send(struct client *cl, const char *buf, int len)
+int uh_tcp_send_lowlevel(struct client *cl, const char *buf, int len)
{
fd_set writer;
struct timeval timeout;
@@ -135,21 +135,28 @@ int uh_tcp_send(struct client *cl, const char *buf, int len)
timeout.tv_sec = cl->server->conf->network_timeout;
timeout.tv_usec = 0;
- if( select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 0 )
- {
-#ifdef HAVE_TLS
- if( cl->tls )
- return cl->server->conf->tls_send(cl, (void *)buf, len);
- else
-#endif
- return send(cl->socket, buf, len, 0);
- }
+ if (select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 0)
+ return send(cl->socket, buf, len, 0);
return -1;
}
+int uh_tcp_send(struct client *cl, const char *buf, int len)
+{
+#ifdef HAVE_TLS
+ if (cl->tls)
+ return cl->server->conf->tls_send(cl, (void *)buf, len);
+ else
+#endif
+ return uh_tcp_send_lowlevel(cl, buf, len);
+}
+
int uh_tcp_peek(struct client *cl, char *buf, int len)
{
+ /* sanity check, prevent overflowing peek buffer */
+ if (len > sizeof(cl->peekbuf))
+ return -1;
+
int sz = uh_tcp_recv(cl, buf, len);
/* store received data in peek buffer */
@@ -162,49 +169,51 @@ int uh_tcp_peek(struct client *cl, char *buf, int len)
return sz;
}
+int uh_tcp_recv_lowlevel(struct client *cl, char *buf, int len)
+{
+ fd_set reader;
+ struct timeval timeout;
+
+ FD_ZERO(&reader);
+ FD_SET(cl->socket, &reader);
+
+ timeout.tv_sec = cl->server->conf->network_timeout;
+ timeout.tv_usec = 0;
+
+ if (select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0)
+ return recv(cl->socket, buf, len, 0);
+
+ return -1;
+}
+
int uh_tcp_recv(struct client *cl, char *buf, int len)
{
int sz = 0;
int rsz = 0;
- fd_set reader;
- struct timeval timeout;
-
/* first serve data from peek buffer */
- if( cl->peeklen > 0 )
+ if (cl->peeklen > 0)
{
sz = min(cl->peeklen, len);
len -= sz; cl->peeklen -= sz;
-
memcpy(buf, cl->peekbuf, sz);
memmove(cl->peekbuf, &cl->peekbuf[sz], cl->peeklen);
}
/* caller wants more */
- if( len > 0 )
+ if (len > 0)
{
- FD_ZERO(&reader);
- FD_SET(cl->socket, &reader);
-
- timeout.tv_sec = cl->server->conf->network_timeout;
- timeout.tv_usec = 0;
-
- if( select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0 )
- {
#ifdef HAVE_TLS
- if( cl->tls )
- rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len);
- else
+ if (cl->tls)
+ rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len);
+ else
#endif
- rsz = recv(cl->socket, (void *)&buf[sz], len, 0);
+ rsz = uh_tcp_recv_lowlevel(cl, (void *)&buf[sz], len);
- if( (sz == 0) || (rsz > 0) )
- sz += rsz;
- }
- else if( sz == 0 )
- {
- sz = -1;
- }
+ if (rsz < 0)
+ return rsz;
+
+ sz += rsz;
}
return sz;