conf->error_handler = strdup(col1);
}
#ifdef HAVE_CGI
- else if( (line[0] == '.') && (strchr(line, ':') != NULL) )
+ else if( (line[0] == '*') && (strchr(line, ':') != NULL) )
{
- if( !(col1 = strchr(line, ':')) || (*col1++ = 0) ||
- !(eol = strchr(col1, '\n')) || (*eol++ = 0) )
+ if( !(col1 = strchr(line, '*')) || (*col1++ = 0) ||
+ !(col2 = strchr(col1, ':')) || (*col2++ = 0) ||
+ !(eol = strchr(col2, '\n')) || (*eol++ = 0) )
continue;
- if( !uh_interpreter_add(line, col1) )
+ if( !uh_interpreter_add(col1, col2) )
{
fprintf(stderr,
"Unable to add interpreter %s for extension %s: "
- "Out of memory\n", col1, line
+ "Out of memory\n", col2, col1
);
}
}
int status;
int bound = 0;
+ int tcp_ka_idl, tcp_ka_int, tcp_ka_cnt;
+
struct listener *l = NULL;
struct addrinfo *addrs = NULL, *p = NULL;
}
/* "address already in use" */
- if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1 )
+ if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) )
{
perror("setsockopt()");
goto error;
}
+ /* TCP keep-alive */
+ if( conf->tcp_keepalive > 0 )
+ {
+ tcp_ka_idl = 1;
+ tcp_ka_cnt = 3;
+ tcp_ka_int = conf->tcp_keepalive;
+
+ if( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) ||
+ setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &tcp_ka_idl, sizeof(tcp_ka_idl)) ||
+ setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &tcp_ka_int, sizeof(tcp_ka_int)) ||
+ setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &tcp_ka_cnt, sizeof(tcp_ka_cnt)) )
+ {
+ fprintf(stderr, "Notice: Unable to enable TCP keep-alive: %s\n",
+ strerror(errno));
+ }
+ }
+
/* required to get parallel v4 + v6 working */
if( p->ai_family == AF_INET6 )
{
hdrdata = &buffer[i+2];
}
- /* have no name and found [A-Z], start of name */
- else if( !hdrname && isalpha(buffer[i]) && isupper(buffer[i]) )
+ /* have no name and found [A-Za-z], start of name */
+ else if( !hdrname && isalpha(buffer[i]) )
{
hdrname = &buffer[i];
}
ssize_t blen = sizeof(buffer)-1;
ssize_t rlen = 0;
-
memset(buffer, 0, sizeof(buffer));
while( blen > 0 )
if( select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0 )
{
/* receive data */
- rlen = uh_tcp_peek(cl, bufptr, blen);
+ ensure_out(rlen = uh_tcp_peek(cl, bufptr, blen));
- if( rlen > 0 )
+ if( (idxptr = strfind(buffer, sizeof(buffer), "\r\n\r\n", 4)) )
{
- if( (idxptr = strfind(buffer, sizeof(buffer), "\r\n\r\n", 4)) )
- {
- blen -= uh_tcp_recv(cl, bufptr, (int)(idxptr - bufptr) + 4);
+ ensure_out(rlen = uh_tcp_recv(cl, bufptr,
+ (int)(idxptr - bufptr) + 4));
- /* header read complete ... */
- return uh_http_header_parse(cl, buffer, sizeof(buffer) - blen - 1);
- }
- else
- {
- rlen = uh_tcp_recv(cl, bufptr, rlen);
- blen -= rlen;
- bufptr += rlen;
- }
+ /* header read complete ... */
+ blen -= rlen;
+ return uh_http_header_parse(cl, buffer,
+ sizeof(buffer) - blen - 1);
}
else
{
- /* invalid request (unexpected eof/timeout) */
- uh_http_response(cl, 408, "Request Timeout");
- return NULL;
+ ensure_out(rlen = uh_tcp_recv(cl, bufptr, rlen));
+
+ /* unexpected eof - #7904 */
+ if( rlen == 0 )
+ return NULL;
+
+ blen -= rlen;
+ bufptr += rlen;
}
}
else
{
/* invalid request (unexpected eof/timeout) */
- uh_http_response(cl, 408, "Request Timeout");
return NULL;
}
}
/* request entity too large */
uh_http_response(cl, 413, "Request Entity Too Large");
+
+out:
return NULL;
}
if( (pin = uh_path_lookup(cl, req->url)) != NULL )
{
/* auth ok? */
- if( uh_auth_check(cl, req, pin) )
+ if( !pin->redirected && uh_auth_check(cl, req, pin) )
uh_dispatch_request(cl, req, pin);
}
int main (int argc, char **argv)
{
/* master file descriptor list */
- fd_set used_fds, serv_fds, read_fds;
+ fd_set serv_fds;
/* working structs */
struct addrinfo hints;
void *lib;
#endif
- /* clear the master and temp sets */
- FD_ZERO(&used_fds);
FD_ZERO(&serv_fds);
- FD_ZERO(&read_fds);
/* handle SIGPIPE, SIGINT, SIGTERM, SIGCHLD */
sa.sa_flags = 0;
#endif
while( (opt = getopt(argc, argv,
- "fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:i:t:T:")) > 0
+ "fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:i:t:T:A:")) > 0
) {
switch(opt)
{
conf.network_timeout = atoi(optarg);
break;
+ /* tcp keep-alive */
+ case 'A':
+ conf.tcp_keepalive = atoi(optarg);
+ break;
+
/* no fork */
case 'f':
nofork = 1;
return 0;
}
-