small update to python binding
[ebb.git] / src / ebb.c
blobbb2a53cbf9aaae80afdf3a5299dc91c39a52883d
1 /* The Ebb Web Server
2 * Copyright (c) 2008 Ry Dahl. This software is released under the MIT
3 * License. See README file for details.
4 */
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/types.h>
8 #include <arpa/inet.h>
9 #include <netinet/tcp.h>
10 #include <sys/un.h>
11 #include <netdb.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <errno.h>
17 #include <signal.h>
18 #include <assert.h>
20 #include <pthread.h>
21 #include <glib.h>
23 #define EV_STANDALONE 1
24 #include <ev.c>
26 #include "parser.h"
27 #include "ebb.h"
29 #define min(a,b) (a < b ? a : b)
30 #define ramp(a) (a > 0 ? a : 0)
32 static int server_socket_unix(const char *path, int access_mask);
34 void env_add(ebb_client *client, const char *field, int flen, const char *value, int vlen)
36 if(client->env_size >= EBB_MAX_ENV) {
37 client->parser.overflow_error = TRUE;
38 return;
40 client->env[client->env_size].type = EBB_FIELD_VALUE_PAIR;
41 client->env[client->env_size].field = field;
42 client->env[client->env_size].field_length = flen;
43 client->env[client->env_size].value = value;
44 client->env[client->env_size].value_length = vlen;
45 client->env_size += 1;
49 void env_add_const(ebb_client *client, int type, const char *value, int vlen)
51 if(client->env_size >= EBB_MAX_ENV) {
52 client->parser.overflow_error = TRUE;
53 return;
55 client->env[client->env_size].type = type;
56 client->env[client->env_size].field = NULL;
57 client->env[client->env_size].field_length = -1;
58 client->env[client->env_size].value = value;
59 client->env[client->env_size].value_length = vlen;
60 client->env_size += 1;
64 void http_field_cb(void *data, const char *field, size_t flen, const char *value, size_t vlen)
66 ebb_client *client = (ebb_client*)(data);
67 assert(field != NULL);
68 assert(value != NULL);
69 env_add(client, field, flen, value, vlen);
73 void request_method_cb(void *data, const char *at, size_t length)
75 ebb_client *client = (ebb_client*)(data);
76 env_add_const(client, EBB_REQUEST_METHOD, at, length);
80 void request_uri_cb(void *data, const char *at, size_t length)
82 ebb_client *client = (ebb_client*)(data);
83 env_add_const(client, EBB_REQUEST_URI, at, length);
87 void fragment_cb(void *data, const char *at, size_t length)
89 ebb_client *client = (ebb_client*)(data);
90 env_add_const(client, EBB_FRAGMENT, at, length);
94 void request_path_cb(void *data, const char *at, size_t length)
96 ebb_client *client = (ebb_client*)(data);
97 env_add_const(client, EBB_REQUEST_PATH, at, length);
101 void query_string_cb(void *data, const char *at, size_t length)
103 ebb_client *client = (ebb_client*)(data);
104 env_add_const(client, EBB_QUERY_STRING, at, length);
108 void http_version_cb(void *data, const char *at, size_t length)
110 ebb_client *client = (ebb_client*)(data);
111 env_add_const(client, EBB_HTTP_VERSION, at, length);
115 void content_length_cb(void *data, const char *at, size_t length)
117 ebb_client *client = (ebb_client*)(data);
118 env_add_const(client, EBB_CONTENT_LENGTH, at, length);
119 /* atoi_length - why isn't this in the statndard library? i hate c */
120 assert(client->content_length == 0);
121 int i, mult;
122 for(mult=1, i=length-1; i>=0; i--, mult*=10)
123 client->content_length += (at[i] - '0') * mult;
127 static void dispatch(ebb_client *client)
129 ebb_server *server = client->server;
131 if(client->open == FALSE)
132 return;
134 /* Set the env variables */
135 if(server->port) {
136 env_add_const(client, EBB_SERVER_PORT
137 , server->port
138 , strlen(server->port)
141 client->in_use = TRUE;
142 server->request_cb(client, server->request_cb_data);
146 static void on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
148 ebb_client *client = (ebb_client*)(watcher->data);
150 assert(client->server->loop == loop);
151 assert(&(client->timeout_watcher) == watcher);
153 ebb_client_close(client);
154 #ifdef DEBUG
155 g_message("peer timed out");
156 #endif
159 #define client_finished_parsing http_parser_is_finished(&client->parser)
160 #define total_request_size (client->content_length + client->parser.nread)
162 static void* read_body_into_file(void *_client)
164 ebb_client *client = (ebb_client*)_client;
165 static unsigned int id;
166 FILE *tmpfile;
168 assert(client->open);
169 assert(client->server->open);
170 assert(client->content_length > 0);
171 assert(client_finished_parsing);
173 /* set blocking socket */
174 int flags = fcntl(client->fd, F_GETFL, 0);
175 assert(0 <= fcntl(client->fd, F_SETFL, flags & ~O_NONBLOCK));
177 sprintf(client->upload_file_filename, "/tmp/ebb_upload_%010d", id++);
178 tmpfile = fopen(client->upload_file_filename, "w+");
179 if(tmpfile == NULL) g_message("Cannot open tmpfile %s", client->upload_file_filename);
180 client->upload_file = tmpfile;
182 size_t body_head_length = client->read - client->parser.nread;
183 size_t written = 0, r;
184 while(written < body_head_length) {
185 r = fwrite( client->request_buffer + sizeof(char)*(client->parser.nread + written)
186 , sizeof(char)
187 , body_head_length - written
188 , tmpfile
190 if(r <= 0) {
191 ebb_client_close(client);
192 return NULL;
194 written += r;
197 int bufsize = 5*1024;
198 char buffer[bufsize];
199 size_t received;
200 while(written < client->content_length) {
201 received = recv(client->fd
202 , buffer
203 , min(client->content_length - written, bufsize)
206 if(received < 0) goto error;
207 client->read += received;
209 ssize_t w = 0;
210 int rv;
211 while(w < received) {
212 rv = fwrite( buffer + w*sizeof(char)
213 , sizeof(char)
214 , received - w
215 , tmpfile
217 if(rv <= 0) goto error;
218 w += rv;
220 written += received;
222 rewind(tmpfile);
223 // g_debug("%d bytes written to file %s", written, client->upload_file_filename);
224 dispatch(client);
225 return NULL;
226 error:
227 ebb_client_close(client);
228 return NULL;
232 static void on_client_readable(struct ev_loop *loop, ev_io *watcher, int revents)
234 ebb_client *client = (ebb_client*)(watcher->data);
236 assert(client->in_use == FALSE);
237 assert(client->open);
238 assert(client->server->open);
239 assert(client->server->loop == loop);
240 assert(&client->read_watcher == watcher);
242 ssize_t read = recv( client->fd
243 , client->request_buffer + client->read
244 , EBB_BUFFERSIZE - client->read
247 if(read < 0) goto error;
248 if(read == 0) goto error; /* XXX is this the right action to take for read==0 ? */
249 client->read += read;
250 ev_timer_again(loop, &client->timeout_watcher);
252 if(client->read == EBB_BUFFERSIZE) goto error;
254 if(FALSE == client_finished_parsing) {
255 http_parser_execute( &client->parser
256 , client->request_buffer
257 , client->read
258 , client->parser.nread
260 if(http_parser_has_error(&client->parser)) goto error;
263 if(client_finished_parsing) {
264 if(total_request_size == client->read) {
265 ev_io_stop(loop, watcher);
266 client->nread_from_body = 0;
267 dispatch(client);
268 return;
270 if(total_request_size > EBB_BUFFERSIZE ) {
271 /* read body into file - in a thread */
272 ev_io_stop(loop, watcher);
273 pthread_t thread;
274 assert(0 <= pthread_create(&thread, NULL, read_body_into_file, client));
275 pthread_detach(thread);
276 return;
279 return;
280 error:
281 if(read < 0) g_message("Error recving data: %s", strerror(errno));
282 ebb_client_close(client);
285 static client_init(ebb_server *server, ebb_client *client)
287 assert(client->in_use == FALSE);
288 #ifdef DEBUG
289 /* does ragel fuck up if request buffer isn't null? */
290 for(i=0; i< EBB_BUFFERSIZE; i++)
291 client->request_buffer[i] = 'A';
292 #endif
294 client->open = TRUE;
295 client->server = server;
297 /* DO SOCKET STUFF */
298 socklen_t len;
299 client->fd = accept(server->fd, (struct sockaddr*)&(server->sockaddr), &len);
300 assert(client->fd >= 0);
301 int flags = fcntl(client->fd, F_GETFL, 0);
302 assert(0 <= fcntl(client->fd, F_SETFL, flags | O_NONBLOCK));
304 /* INITIALIZE http_parser */
305 http_parser_init(&(client->parser));
306 client->parser.data = client;
307 client->parser.http_field = http_field_cb;
308 client->parser.request_method = request_method_cb;
309 client->parser.request_uri = request_uri_cb;
310 client->parser.fragment = fragment_cb;
311 client->parser.request_path = request_path_cb;
312 client->parser.query_string = query_string_cb;
313 client->parser.http_version = http_version_cb;
314 client->parser.content_length = content_length_cb;
316 /* OTHER */
317 client->env_size = 0;
318 client->read = client->nread_from_body = 0;
319 client->response_buffer->len = 0; /* see note in ebb_client_close */
320 client->content_length = 0;
322 client->status_written = FALSE;
323 client->headers_written = FALSE;
324 client->body_written = FALSE;
325 client->began_transmission = FALSE;
327 /* SETUP READ AND TIMEOUT WATCHERS */
328 client->read_watcher.data = client;
329 ev_init(&client->read_watcher, on_client_readable);
330 ev_io_set(&client->read_watcher, client->fd, EV_READ | EV_ERROR);
331 ev_io_start(server->loop, &client->read_watcher);
333 client->timeout_watcher.data = client;
334 ev_timer_init(&client->timeout_watcher, on_timeout, EBB_TIMEOUT, EBB_TIMEOUT);
335 ev_timer_start(server->loop, &client->timeout_watcher);
338 static void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
340 ebb_server *server = (ebb_server*)(watcher->data);
341 assert(server->open);
342 assert(server->loop == loop);
343 assert(&server->request_watcher == watcher);
345 if(EV_ERROR & revents) {
346 g_message("on_request() got error event, closing server.");
347 ebb_server_unlisten(server);
348 return;
350 /* Now we're going to initialize the client
351 * and set up her callbacks for read and write
352 * the client won't get passed back to the user, however,
353 * until the request is complete and parsed.
355 int i;
356 ebb_client *client;
357 /* Get next availible peer */
358 for(i=0; i < EBB_MAX_CLIENTS; i++)
359 if(!server->clients[i].in_use && !server->clients[i].open) {
360 client = &(server->clients[i]);
361 break;
363 if(client == NULL) {
364 g_message("Too many peers. Refusing connections.");
365 return;
368 #ifdef DEBUG
369 int count = 0;
370 for(i = 0; i < EBB_MAX_CLIENTS; i++)
371 if(server->clients[i].open) count += 1;
372 g_debug("%d open connections", count);
373 #endif
375 client_init(server, client);
379 ebb_server* ebb_server_alloc()
381 ebb_server *server = g_new0(ebb_server, 1);
382 return server;
386 void ebb_server_init( ebb_server *server
387 , struct ev_loop *loop
388 , ebb_request_cb request_cb
389 , void *request_cb_data
392 int i;
393 for(i=0; i < EBB_MAX_CLIENTS; i++) {
394 server->clients[i].response_buffer = g_string_new("");
395 server->clients[i].open = FALSE;
396 server->clients[i].in_use = FALSE;
399 server->request_cb = request_cb;
400 server->request_cb_data = request_cb_data;
401 server->loop = loop;
402 server->open = FALSE;
403 server->fd = -1;
404 return;
405 error:
406 ebb_server_free(server);
407 return;
411 void ebb_server_free(ebb_server *server)
413 ebb_server_unlisten(server);
415 int i;
416 for(i=0; i < EBB_MAX_CLIENTS; i++)
417 g_string_free(server->clients[i].response_buffer, TRUE);
418 if(server->port)
419 free(server->port);
420 if(server->socketpath)
421 free(server->socketpath);
422 free(server);
426 void ebb_server_unlisten(ebb_server *server)
428 if(server->open) {
429 int i;
430 ebb_client *client;
431 ev_io_stop(server->loop, &server->request_watcher);
432 close(server->fd);
433 if(server->socketpath)
434 unlink(server->socketpath);
435 server->open = FALSE;
439 int ebb_server_listen_on_port(ebb_server *server, const int port)
441 int sfd = -1;
442 struct linger ling = {0, 0};
443 struct sockaddr_in addr;
444 int flags = 1;
446 if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
447 perror("socket()");
448 goto error;
451 flags = fcntl(sfd, F_GETFL, 0);
452 if(fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
453 perror("setting O_NONBLOCK");
454 goto error;
457 flags = 1;
458 setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
459 setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
460 setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
461 setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
464 * the memset call clears nonstandard fields in some impementations
465 * that otherwise mess things up.
467 memset(&addr, 0, sizeof(addr));
469 addr.sin_family = AF_INET;
470 addr.sin_port = htons(port);
471 addr.sin_addr.s_addr = htonl(INADDR_ANY);
473 if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
474 perror("bind()");
475 goto error;
477 if (listen(sfd, EBB_MAX_CLIENTS) < 0) {
478 perror("listen()");
479 goto error;
481 server->fd = sfd;
482 server->port = malloc(sizeof(char)*8); /* for easy access to the port */
483 sprintf(server->port, "%d", port);
484 assert(server->open == FALSE);
485 server->open = TRUE;
487 server->request_watcher.data = server;
488 ev_init (&server->request_watcher, on_request);
489 ev_io_set (&server->request_watcher, server->fd, EV_READ | EV_ERROR);
490 ev_io_start (server->loop, &server->request_watcher);
492 return server->fd;
493 error:
494 if(sfd > 0) close(sfd);
495 return -1;
499 int ebb_server_listen_on_socket(ebb_server *server, const char *socketpath)
501 // int fd = server_socket_unix(socketpath, 0755);
502 // if(fd < 0) return 0;
503 // server->socketpath = strdup(socketpath);
504 // server->fd = fd;
505 // server_listen(server);
506 // return fd;
510 void ebb_client_release(ebb_client *client)
512 assert(client->in_use);
513 client->in_use = FALSE;
514 if(client->written == client->response_buffer->len)
515 ebb_client_close(client);
519 void ebb_client_close(ebb_client *client)
521 if(client->open) {
522 ev_io_stop(client->server->loop, &client->read_watcher);
523 ev_io_stop(client->server->loop, &client->write_watcher);
524 ev_timer_stop(client->server->loop, &client->timeout_watcher);
526 if(client->upload_file) {
527 fclose(client->upload_file);
528 unlink(client->upload_file_filename);
531 /* here we do not free the already allocated GString client->response_buffer
532 * that we're holding the response in. we reuse it again -
533 * presumably because the backend is going to keep sending such long
534 * requests.
536 client->response_buffer->len = 0;
538 close(client->fd);
539 client->open = FALSE;
544 static void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
546 ebb_client *client = (ebb_client*)(watcher->data);
547 ssize_t sent;
549 assert(client->status_written);
550 assert(client->headers_written);
551 assert(client->began_transmission);
553 if(EV_ERROR & revents) {
554 g_message("on_client_writable() got error event, closing peer");
555 ebb_client_close(client);
556 return;
559 //if(client->written != 0)
560 // g_debug("total written: %d", (int)(client->written));
562 sent = send( client->fd
563 , client->response_buffer->str + sizeof(gchar)*(client->written)
564 , client->response_buffer->len - client->written
567 if(sent < 0) {
568 #ifdef DEBUG
569 g_message("Error writing: %s", strerror(errno));
570 #endif
571 ebb_client_close(client);
572 return;
573 } else if(sent == 0) {
574 g_message("Sent zero bytes? Closing connection");
575 ebb_client_close(client);
577 client->written += sent;
579 assert(client->written <= client->response_buffer->len);
580 //g_message("wrote %d bytes. total: %d", (int)sent, (int)(client->written));
582 ev_timer_again(loop, &(client->timeout_watcher));
584 if(client->written == client->response_buffer->len) {
585 ev_io_stop(loop, watcher);
586 if(client->body_written)
587 ebb_client_close(client);
591 void ebb_client_write_status(ebb_client *client, int status, const char *human_status)
593 assert(client->in_use);
594 if(!client->open) return;
595 assert(client->status_written == FALSE);
596 g_string_append_printf( client->response_buffer
597 , "HTTP/1.1 %d %s\r\n"
598 , status
599 , human_status
601 client->status_written = TRUE;
604 void ebb_client_write_header(ebb_client *client, const char *field, const char *value)
606 assert(client->in_use);
607 if(!client->open) return;
608 assert(client->status_written == TRUE);
609 assert(client->headers_written == FALSE);
610 g_string_append_printf( client->response_buffer
611 , "%s: %s\r\n"
612 , field
613 , value
617 void ebb_client_write(ebb_client *client, const char *data, int length)
619 assert(client->in_use);
620 if(!client->open) return;
621 g_string_append_len(client->response_buffer, data, length);
622 if(client->began_transmission) {
623 /* restart the watcher if we're streaming */
624 ev_io_start(client->server->loop, &client->write_watcher);
629 void ebb_client_begin_transmission(ebb_client *client)
631 assert(client->in_use);
632 if(!client->open) return;
633 assert(FALSE == ev_is_active(&client->write_watcher));
635 /* assure the socket is still in non-blocking mode */
636 int flags = fcntl(client->fd, F_GETFL, 0);
637 if(0 > fcntl(client->fd, F_SETFL, flags | O_NONBLOCK)) {
638 perror("fcntl()");
639 ebb_client_close(client);
640 return;
643 client->headers_written = TRUE;
644 client->began_transmission = TRUE;
645 client->written = 0;
646 client->write_watcher.data = client;
647 ev_init (&(client->write_watcher), on_client_writable);
648 ev_io_set (&(client->write_watcher), client->fd, EV_WRITE | EV_ERROR);
649 ev_io_start(client->server->loop, &client->write_watcher);
653 /* pass an allocated buffer and the length to read. this function will try to
654 * fill the buffer with that length of data read from the body of the request.
655 * the return value says how much was actually written.
657 int ebb_client_read(ebb_client *client, char *buffer, int length)
659 size_t read;
661 assert(client->in_use);
662 if(!client->open) return -1;
663 assert(client_finished_parsing);
665 if(client->upload_file) {
666 read = fread(buffer, 1, length, client->upload_file);
667 /* TODO error checking! */
668 return read;
669 } else {
670 char* request_body = client->request_buffer + client->parser.nread;
672 read = ramp(min(length, client->content_length - client->nread_from_body));
673 memcpy( buffer
674 , request_body + client->nread_from_body
675 , read
677 client->nread_from_body += read;
678 return read;
682 /* The following socket creation routines are modified and stolen from memcached */
685 static int server_socket_unix(const char *path, int access_mask) {
686 int sfd;
687 struct linger ling = {0, 0};
688 struct sockaddr_un addr;
689 struct stat tstat;
690 int flags =1;
691 int old_umask;
693 if (!path) {
694 return -1;
697 if ((sfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
698 perror("socket()");
699 return -1;
702 if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
703 fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
704 perror("setting O_NONBLOCK");
705 close(sfd);
706 return -1;
710 * Clean up a previous socket file if we left it around
712 if (lstat(path, &tstat) == 0) {
713 if (S_ISSOCK(tstat.st_mode))
714 unlink(path);
717 flags = 1;
718 setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
719 setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
720 setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
723 * the memset call clears nonstandard fields in some impementations
724 * that otherwise mess things up.
726 memset(&addr, 0, sizeof(addr));
728 addr.sun_family = AF_UNIX;
729 strcpy(addr.sun_path, path);
730 old_umask=umask( ~(access_mask&0777));
731 if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
732 perror("bind()");
733 close(sfd);
734 umask(old_umask);
735 return -1;
737 umask(old_umask);
738 if (listen(sfd, EBB_MAX_CLIENTS) == -1) {
739 perror("listen()");
740 close(sfd);
741 return -1;
743 return sfd;