mirror of
https://github.com/emikulic/darkhttpd.git
synced 2023-08-10 21:13:08 +03:00
. Made all sockets non-blocking
. Used simpler way of ignoring SIGPIPE . Made sure closed sockets aren't written to
This commit is contained in:
@ -34,6 +34,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -71,6 +72,7 @@ struct connection
|
|||||||
char *request;
|
char *request;
|
||||||
unsigned int request_length;
|
unsigned int request_length;
|
||||||
|
|
||||||
|
/* request fields */
|
||||||
char *method, *uri, *referer, *user_agent;
|
char *method, *uri, *referer, *user_agent;
|
||||||
|
|
||||||
char *header;
|
char *header;
|
||||||
@ -211,6 +213,17 @@ static unsigned int xasprintf(char **ret, const char *format, ...)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------
|
||||||
|
* Make the specified socket non-blocking.
|
||||||
|
*/
|
||||||
|
static void nonblock_socket(const int sock)
|
||||||
|
{
|
||||||
|
if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
|
||||||
|
err(1, "fcntl() to set O_NONBLOCK");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------
|
||||||
* Split string out of src with range [left:right-1]
|
* Split string out of src with range [left:right-1]
|
||||||
*/
|
*/
|
||||||
@ -468,6 +481,8 @@ static void init_sockin(void)
|
|||||||
&sockopt, sizeof(sockopt)) == -1)
|
&sockopt, sizeof(sockopt)) == -1)
|
||||||
err(1, "setsockopt(SO_REUSEADDR)");
|
err(1, "setsockopt(SO_REUSEADDR)");
|
||||||
|
|
||||||
|
nonblock_socket(sockin);
|
||||||
|
|
||||||
/* bind socket */
|
/* bind socket */
|
||||||
addrin.sin_family = (u_char)PF_INET;
|
addrin.sin_family = (u_char)PF_INET;
|
||||||
addrin.sin_port = htons(bindport);
|
addrin.sin_port = htons(bindport);
|
||||||
@ -677,6 +692,8 @@ static void accept_connection(void)
|
|||||||
&sin_size);
|
&sin_size);
|
||||||
if (conn->socket == -1) err(1, "accept()");
|
if (conn->socket == -1) err(1, "accept()");
|
||||||
|
|
||||||
|
nonblock_socket(conn->socket);
|
||||||
|
|
||||||
conn->state = RECV_REQUEST;
|
conn->state = RECV_REQUEST;
|
||||||
conn->client = addrin.sin_addr.s_addr;
|
conn->client = addrin.sin_addr.s_addr;
|
||||||
LIST_INSERT_HEAD(&connlist, conn, entries);
|
LIST_INSERT_HEAD(&connlist, conn, entries);
|
||||||
@ -819,7 +836,7 @@ static void default_reply(struct connection *conn,
|
|||||||
"HTTP/1.1 %d %s\r\n"
|
"HTTP/1.1 %d %s\r\n"
|
||||||
"Date: %s\r\n"
|
"Date: %s\r\n"
|
||||||
"Server: %s\r\n"
|
"Server: %s\r\n"
|
||||||
"Connection: close\r\n"
|
"Connection: close\r\n" /* FIXME: remove for keepalive */
|
||||||
"Content-Length: %d\r\n"
|
"Content-Length: %d\r\n"
|
||||||
"Content-Type: text/html\r\n"
|
"Content-Type: text/html\r\n"
|
||||||
"\r\n",
|
"\r\n",
|
||||||
@ -851,7 +868,8 @@ static char *parse_field(const struct connection *conn, const char *field)
|
|||||||
/* find end */
|
/* find end */
|
||||||
for (bound2 = bound1;
|
for (bound2 = bound1;
|
||||||
conn->request[bound2] != '\r' &&
|
conn->request[bound2] != '\r' &&
|
||||||
bound2 < conn->request_length; bound2++);
|
bound2 < conn->request_length; bound2++)
|
||||||
|
;
|
||||||
|
|
||||||
/* copy to buffer */
|
/* copy to buffer */
|
||||||
return split_string(conn->request, bound1, bound2);
|
return split_string(conn->request, bound1, bound2);
|
||||||
@ -899,6 +917,9 @@ static void process_get(struct connection *conn)
|
|||||||
const char *mimetype = NULL;
|
const char *mimetype = NULL;
|
||||||
struct stat filestat;
|
struct stat filestat;
|
||||||
|
|
||||||
|
/* FIXME */
|
||||||
|
printf("-----\n%s-----\n\n", conn->request);
|
||||||
|
|
||||||
/* work out path of file being requested */
|
/* work out path of file being requested */
|
||||||
decoded_url = urldecode(conn->uri);
|
decoded_url = urldecode(conn->uri);
|
||||||
|
|
||||||
@ -957,7 +978,7 @@ static void process_get(struct connection *conn)
|
|||||||
conn->reply_length = filestat.st_size;
|
conn->reply_length = filestat.st_size;
|
||||||
conn->lastmod = xstrdup(rfc1123_date(filestat.st_mtime));
|
conn->lastmod = xstrdup(rfc1123_date(filestat.st_mtime));
|
||||||
|
|
||||||
/* the browser might already have it */
|
/* check for If-Modified-Since, may not have to send */
|
||||||
if_mod_since = parse_field(conn, "If-Modified-Since: ");
|
if_mod_since = parse_field(conn, "If-Modified-Since: ");
|
||||||
if (if_mod_since != NULL &&
|
if (if_mod_since != NULL &&
|
||||||
strcmp(if_mod_since, conn->lastmod) == 0)
|
strcmp(if_mod_since, conn->lastmod) == 0)
|
||||||
@ -972,7 +993,7 @@ static void process_get(struct connection *conn)
|
|||||||
"HTTP/1.1 200 OK\r\n"
|
"HTTP/1.1 200 OK\r\n"
|
||||||
"Date: %s\r\n"
|
"Date: %s\r\n"
|
||||||
"Server: %s\r\n"
|
"Server: %s\r\n"
|
||||||
"Connection: close\r\n"
|
"Connection: close\r\n" /* FIXME: remove this for keepalive */
|
||||||
"Content-Length: %d\r\n"
|
"Content-Length: %d\r\n"
|
||||||
"Content-Type: %s\r\n"
|
"Content-Type: %s\r\n"
|
||||||
"Last-Modified: %s\r\n"
|
"Last-Modified: %s\r\n"
|
||||||
@ -1084,9 +1105,11 @@ static void poll_send_header(struct connection *conn)
|
|||||||
conn->header_length - conn->header_sent, 0);
|
conn->header_length - conn->header_sent, 0);
|
||||||
conn->last_active = time(NULL);
|
conn->last_active = time(NULL);
|
||||||
debugf("poll_send_header(%d) sent %d bytes\n", conn->socket, sent);
|
debugf("poll_send_header(%d) sent %d bytes\n", conn->socket, sent);
|
||||||
if (sent == -1) err(1, "send()");
|
|
||||||
if (sent == 0)
|
/* handle any errors (-1) or closure (0) in send() */
|
||||||
|
if (sent < 1)
|
||||||
{
|
{
|
||||||
|
if (sent == -1) debugf("send() error: %s\n", strerror(errno));
|
||||||
conn->state = DONE;
|
conn->state = DONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1144,10 +1167,10 @@ static void poll_send_reply(struct connection *conn)
|
|||||||
debugf("poll_send_reply(%d) sent %d bytes [%d to %d]\n",
|
debugf("poll_send_reply(%d) sent %d bytes [%d to %d]\n",
|
||||||
conn->socket, sent, conn->reply_sent, conn->reply_sent+sent-1);
|
conn->socket, sent, conn->reply_sent, conn->reply_sent+sent-1);
|
||||||
|
|
||||||
/* handle any errors in send() */
|
/* handle any errors (-1) or closure (0) in send() */
|
||||||
if (sent == -1) err(1, "send()");
|
if (sent < 1)
|
||||||
if (sent == 0)
|
|
||||||
{
|
{
|
||||||
|
if (sent == -1) debugf("send() error: %s\n", strerror(errno));
|
||||||
conn->state = DONE;
|
conn->state = DONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1284,16 +1307,6 @@ static void httpd_poll(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------
|
|
||||||
* Ignore SIGPIPE
|
|
||||||
*/
|
|
||||||
static void ignore_signal(int signum)
|
|
||||||
{
|
|
||||||
if (signum == signum) { /* do nothing */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------
|
||||||
* Execution starts here.
|
* Execution starts here.
|
||||||
*/
|
*/
|
||||||
@ -1311,8 +1324,8 @@ int main(int argc, char *argv[])
|
|||||||
if (logfile == NULL) err(1, "fopen(\"%s\")", logfile_name);
|
if (logfile == NULL) err(1, "fopen(\"%s\")", logfile_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signal(SIGPIPE, ignore_signal) == SIG_ERR)
|
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
|
||||||
err(1, "signal(SIG_PIPE)");
|
err(1, "signal(ignore SIGPIPE)");
|
||||||
|
|
||||||
for (;;) httpd_poll();
|
for (;;) httpd_poll();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user