/* darkstat 3
- * copyright (c) 2001-2011 Emil Mikulic.
+ * copyright (c) 2001-2012 Emil Mikulic.
*
* http.c: embedded webserver.
* This borrows a lot of code from darkhttpd.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
#include <zlib.h>
int socket;
struct sockaddr_storage client;
- time_t last_active;
+ long last_active_mono;
enum {
RECV_REQUEST, /* receiving request */
SEND_HEADER_AND_REPLY, /* try to send header+reply together */
conn->socket = -1;
memset(&conn->client, 0, sizeof(conn->client));
- conn->last_active = now;
+ conn->last_active_mono = now_mono();
conn->request = NULL;
conn->request_length = 0;
conn->accept_gzip = 0;
* buffer is returned for convenience.
*/
#define DATE_LEN 30 /* strlen("Fri, 28 Feb 2003 00:02:08 GMT")+1 */
-static char *rfc1123_date(char *dest, const time_t when)
-{
- time_t tmp = when;
+static char *rfc1123_date(char *dest, time_t when) {
if (strftime(dest, DATE_LEN,
- "%a, %d %b %Y %H:%M:%S %Z", gmtime(&tmp) ) == 0)
+ "%a, %d %b %Y %H:%M:%S %Z", gmtime(&when) ) == 0)
errx(1, "strftime() failed [%s]", dest);
- return (dest);
+ return dest;
}
static void generate_header(struct connection *conn,
if (conn->encoding == NULL)
conn->encoding = encoding_identity;
- verbosef("http: %d %s (%s: %d bytes)", code, text,
+ verbosef("http: %d %s (%s: %zu bytes)", code, text,
conn->encoding, conn->reply_length);
conn->header_length = xasprintf(&(conn->header),
"HTTP/1.1 %d %s\r\n"
"\r\n"
,
code, text,
- rfc1123_date(date, now), server,
+ rfc1123_date(date, now_real()), server,
conn->mime_type, conn->reply_length, conn->encoding,
conn->header_extra);
conn->http_code = code;
conn->state = DONE;
return;
}
- conn->last_active = now;
+ conn->last_active_mono = now_mono();
/* append to conn->request */
conn->request = xrealloc(conn->request, conn->request_length+recvd+1);
iov[1].iov_len = conn->reply_length;
sent = writev(conn->socket, iov, 2);
- conn->last_active = now;
+ conn->last_active_mono = now_mono();
/* handle any errors (-1) or closure (0) in send() */
if (sent < 1) {
sent = send(conn->socket, conn->header + conn->header_sent,
conn->header_length - conn->header_sent, 0);
- conn->last_active = now;
+ conn->last_active_mono = now_mono();
dverbosef("poll_send_header(%d) sent %d bytes", conn->socket, (int)sent);
/* handle any errors (-1) or closure (0) in send() */
sent = send(conn->socket,
conn->reply + conn->reply_sent,
conn->reply_length - conn->reply_sent, 0);
- conn->last_active = now;
+ conn->last_active_mono = now_mono();
dverbosef("poll_send_reply(%d) sent %d: [%d-%d] of %d",
conn->socket, (int)sent,
(int)conn->reply_sent,
/* create incoming socket */
if ((sockin = socket(ai->ai_family, ai->ai_socktype,
- ai->ai_protocol)) == -1)
- err(1, "http_listen_one(%s, %u): socket(%d (%s), %d, %d) failed",
+ ai->ai_protocol)) == -1) {
+ warn("http_listen_one(%s, %u): socket(%d (%s), %d, %d) failed",
ipaddr, (unsigned int)bindport,
ai->ai_family,
(ai->ai_family == AF_INET6) ? "AF_INET6" :
(ai->ai_family == AF_INET) ? "AF_INET" :
"?",
ai->ai_socktype, ai->ai_protocol);
+ return;
+ }
+
+ fd_set_nonblock(sockin);
/* reuse address */
sockopt = 1;
/* bind socket */
if (bind(sockin, ai->ai_addr, ai->ai_addrlen) == -1) {
warn("bind(\"%s\") failed", ipaddr);
+ close(sockin);
return;
}
/* listen on socket */
- if (listen(sockin, -1) == -1)
+ if (listen(sockin, 128) == -1)
err(1, "listen() failed");
verbosef("listening on http://%s%s%s:%u/",
free(bindaddr);
}
- if (insocks == 0)
+ if (insocks == NULL)
errx(1, "was not able to bind any ports for http interface");
/* ignore SIGPIPE */
LIST_FOREACH_SAFE(conn, &connlist, entries, next)
{
- int idlefor = now - conn->last_active;
+ int idlefor = now_mono() - conn->last_active_mono;
/* Time out dead connections. */
if (idlefor >= idletime) {