Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions include/httpcgi.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,9 @@ struct httpc {
UCHAR ssilevel; /* 51 SSI processing level */
#define SSI_LEVEL_MAX 10 /* ... max SSI processing level */
UCHAR content_length_set; /* 52 Content-Length was sent */
UCHAR unused2; /* 53 available */
unsigned unused3; /* 54 available */
UCHAR keepalive; /* 53 keep-alive active */
unsigned short request_count; /* 54 requests on this connection */
unsigned short unused3; /* 56 available */

#define CBUFSIZE (0x1000-0x0058) /* ... 4096-88 = 4008 */
UCHAR buf[CBUFSIZE]; /* 58 data buffer */
Expand Down
10 changes: 7 additions & 3 deletions include/httpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,10 @@ struct httpd {
UCHAR listen_queue; /* 120 listen backlog */
UCHAR unused_121[3]; /* 121 alignment padding */
char codepage[16]; /* 124 codepage name */
}; /* 134 */
UCHAR cfg_keepalive_timeout; /* 134 keepalive idle secs */
UCHAR cfg_keepalive_max; /* 135 max reqs per connection */
UCHAR unused_136[2]; /* 136 alignment padding */
}; /* 138 */

/* HTTP variables */
struct httpv {
Expand Down Expand Up @@ -210,8 +213,9 @@ struct httpc {
UCHAR ssilevel; /* 51 SSI processing level */
#define SSI_LEVEL_MAX 10 /* ... max SSI processing levele*/
UCHAR content_length_set; /* 52 Content-Length was sent */
UCHAR unused2; /* 53 available */
unsigned unused3; /* 54 available */
UCHAR keepalive; /* 53 keep-alive active */
unsigned short request_count; /* 54 requests on this conn */
unsigned short unused3; /* 56 available */

#define CBUFSIZE (0x1000-0x0058) /* ... 4096-88 = 4008 */
UCHAR buf[CBUFSIZE]; /* 50 data buffer */
Expand Down
4 changes: 4 additions & 0 deletions samplib/httpprm0
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
# MAXTASK=9
# CLIENT_TIMEOUT=10
#
# --- Keep-Alive ---
# KEEPALIVE_TIMEOUT=5
# KEEPALIVE_MAX=100
#
# --- Security ---
# LOGIN=NONE
#
Expand Down
8 changes: 6 additions & 2 deletions src/httpgets.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ int http_gets(HTTPC *httpc, UCHAR *buf, unsigned max)
unsigned seconds;
unsigned ecb;

seconds = httpd->cfg_client_timeout;
if (seconds == 0) seconds = 10;
if (httpc->request_count > 0 && httpd->cfg_keepalive_timeout) {
seconds = httpd->cfg_keepalive_timeout;
} else {
seconds = httpd->cfg_client_timeout;
if (seconds == 0) seconds = 10;
}
time64(&now);
__64_add_u32(&now, seconds, &timeout);

Expand Down
26 changes: 22 additions & 4 deletions src/httpin.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ int http_in(HTTPC *httpc)
/* HTTP/1.1 requires a Host header */
{
UCHAR *ver = http_get_env(httpc, "REQUEST_VERSION");
UCHAR *conn = http_get_env(httpc, "HTTP_CONNECTION");

if (ver && http_cmp(ver, "HTTP/1.1") == 0) {
UCHAR *host = http_get_env(httpc, "HTTP_HOST");
if (!host || !host[0]) {
Expand All @@ -83,7 +85,20 @@ int http_in(HTTPC *httpc)
httpc->state = CSTATE_DONE;
goto quit;
}
/* HTTP/1.1: default keep-alive */
httpc->keepalive = 1;
if (conn && http_cmp(conn, "close") == 0)
httpc->keepalive = 0;
} else {
/* HTTP/1.0: default close */
httpc->keepalive = 0;
if (conn && http_cmp(conn, "keep-alive") == 0)
httpc->keepalive = 1;
}

/* enforce max requests per connection */
if (httpc->request_count >= httpc->httpd->cfg_keepalive_max)
httpc->keepalive = 0;
}

/* next step will parse and do any additional processing */
Expand All @@ -92,10 +107,13 @@ int http_in(HTTPC *httpc)
goto quit;

failed:
// wtof("%s: failed", __func__);

/* most likely a bad request, reset the connection */
httpc->state = CSTATE_RESET;
if (httpc->request_count > 0) {
/* keep-alive: idle timeout or client disconnect — just close */
httpc->state = CSTATE_CLOSE;
} else {
/* first request: bad request, reset the connection */
httpc->state = CSTATE_RESET;
}

quit:
// wtof("%s: exit rc=%d", __func__, rc);
Expand Down
16 changes: 16 additions & 0 deletions src/httpprm.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ http_config(HTTPD *httpd, const char *member)
wtof("HTTPD033I MINTASK=%d MAXTASK=%d CLIENT_TIMEOUT=%d",
httpd->cfg_mintask, httpd->cfg_maxtask,
httpd->cfg_client_timeout);
wtof("HTTPD034I KEEPALIVE_TIMEOUT=%d KEEPALIVE_MAX=%d",
httpd->cfg_keepalive_timeout, httpd->cfg_keepalive_max);

return 0;
}
Expand Down Expand Up @@ -120,6 +122,8 @@ set_defaults(HTTPD *httpd)
httpd->docroot[0] = '\0';
httpd->codepage[0] = '\0';
httpd->dbg_enabled = 0;
httpd->cfg_keepalive_timeout = 5;
httpd->cfg_keepalive_max = 100;
}

/* ====================================================================
Expand Down Expand Up @@ -357,6 +361,18 @@ parse_keyvalue(HTTPD *httpd, const char *key, const char *value)
else if (strcmp(key, "CLIENT_STATS_DATASET") == 0) {
if (*value) httpd->st_dataset = strdup(value);
}
else if (strcmp(key, "KEEPALIVE_TIMEOUT") == 0) {
i = atoi(value);
if (i < 1) i = 1;
if (i > 255) i = 255;
httpd->cfg_keepalive_timeout = (UCHAR)i;
}
else if (strcmp(key, "KEEPALIVE_MAX") == 0) {
i = atoi(value);
if (i < 1) i = 1;
if (i > 255) i = 255;
httpd->cfg_keepalive_max = (UCHAR)i;
}
else if (strcmp(key, "CGI_CONTEXT_POINTERS") == 0) {
i = atoi(value);
if (i >= HTTPD_CGICTX_MIN) {
Expand Down
20 changes: 13 additions & 7 deletions src/httprese.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,26 @@ httprese(HTTPC *httpc)
httpc->substate = 0;
httpc->chunked = 0;
httpc->content_length_set = 0;
httpc->start = 0.0;
httpc->end = 0.0;
memset(httpc->buf, 0, CBUFSIZE);

/* clear ACEE on UFS session between requests */
if (httpc->ufs) {
ufs_set_acee(httpc->ufs, NULL);
}

/* if this is was HTTP1.1 or higher client then we
** *could* transition to CSTATE_IN. We'll leave that
** for another time.
*/
httpc->state = CSTATE_CLOSE;
if (httpc->keepalive) {
/* keep connection open for next request */
httpc->request_count++;
httpc->keepalive = 0;
httpc->start = 0.0;
httpc->end = 0.0;
httpsecs(&httpc->start);
httpc->state = CSTATE_IN;
} else {
httpc->start = 0.0;
httpc->end = 0.0;
httpc->state = CSTATE_CLOSE;
}

http_exit("httprese(), rc=%d\n", rc);
return rc;
Expand Down
7 changes: 5 additions & 2 deletions src/httpresp.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,11 @@ httpresp(HTTPC *httpc, int resp)
if (rc) goto quit;
}

/* HTTP/1.1: always close for now (keep-alive planned) */
rc = http_printf(httpc, "Connection: close\r\n");
if (httpc->keepalive) {
rc = http_printf(httpc, "Connection: keep-alive\r\n");
} else {
rc = http_printf(httpc, "Connection: close\r\n");
}
if (rc) goto quit;

quit:
Expand Down
Loading