ebb 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/src/ebb.c DELETED
@@ -1,627 +0,0 @@
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>
12
-
13
- #include <stdio.h>
14
- #include <string.h>
15
- #include <stdlib.h>
16
- #include <errno.h>
17
- #include <signal.h>
18
- #include <assert.h>
19
-
20
- #define EV_STANDALONE 1
21
- #include <ev.c>
22
- #include <glib.h>
23
-
24
- #include "parser.h"
25
- #include "ebb.h"
26
-
27
- #define min(a,b) (a < b ? a : b)
28
- #define ramp(a) (a > 0 ? a : 0)
29
-
30
- static void client_init(ebb_client *client);
31
-
32
- static void set_nonblock(int fd)
33
- {
34
- int flags = fcntl(fd, F_GETFL, 0);
35
- assert(0 <= fcntl(fd, F_SETFL, flags | O_NONBLOCK) && "Setting socket non-block failed!");
36
- }
37
-
38
-
39
- void env_add(ebb_client *client, const char *field, int flen, const char *value, int vlen)
40
- {
41
- if(client->env_size >= EBB_MAX_ENV) {
42
- client->parser.overflow_error = TRUE;
43
- return;
44
- }
45
- struct ebb_env_item * const item = &client->env[client->env_size++];
46
- item->type = -1;
47
- item->field_length = flen;
48
- item->value_length = vlen;
49
- item->field = field;
50
- item->value = value;
51
- }
52
-
53
-
54
- void env_add_const(ebb_client *client, int type, const char *value, int vlen)
55
- {
56
- if(client->env_size >= EBB_MAX_ENV) {
57
- client->parser.overflow_error = TRUE;
58
- return;
59
- }
60
- struct ebb_env_item * const item = &client->env[client->env_size++];
61
- item->type = type;
62
- item->field_length = -1;
63
- item->value_length = vlen;
64
- item->field = NULL;
65
- item->value = value;
66
- }
67
-
68
-
69
- void http_field_cb(void *data, const char *field, size_t flen, const char *value, size_t vlen)
70
- {
71
- ebb_client *client = (ebb_client*)(data);
72
- assert(field != NULL);
73
- assert(value != NULL);
74
- env_add(client, field, flen, value, vlen);
75
- }
76
-
77
-
78
- void on_element(void *data, int type, const char *at, size_t length)
79
- {
80
- ebb_client *client = (ebb_client*)(data);
81
- env_add_const(client, type, at, length);
82
- }
83
-
84
-
85
- static void dispatch(ebb_client *client)
86
- {
87
- ebb_server *server = client->server;
88
- if(client->open == FALSE)
89
- return;
90
- client->in_use = TRUE;
91
-
92
- /* XXX decide if to use keep-alive or not? */
93
-
94
- server->request_cb(client, server->request_cb_data);
95
- }
96
-
97
-
98
- static void on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
99
- {
100
- ebb_client *client = (ebb_client*)(watcher->data);
101
-
102
- assert(client->server->loop == loop);
103
- assert(&(client->timeout_watcher) == watcher);
104
-
105
- ebb_client_close(client);
106
- #ifdef DEBUG
107
- g_message("peer timed out");
108
- #endif
109
- }
110
-
111
- #define client_finished_parsing http_parser_is_finished(&client->parser)
112
- #define total_request_size (client->parser.content_length + client->parser.nread)
113
-
114
- static void on_client_readable(struct ev_loop *loop, ev_io *watcher, int revents)
115
- {
116
- ebb_client *client = (ebb_client*)(watcher->data);
117
-
118
- assert(client->in_use == FALSE);
119
- assert(client->open);
120
- assert(client->server->open);
121
- assert(client->server->loop == loop);
122
- assert(&client->read_watcher == watcher);
123
-
124
- ssize_t read = recv( client->fd
125
- , client->request_buffer + client->read
126
- , EBB_BUFFERSIZE - client->read
127
- , 0
128
- );
129
- if(read < 0) goto error;
130
- if(read == 0) goto error; /* XXX is this the right action to take for read==0 ? */
131
- client->read += read;
132
- ev_timer_again(loop, &client->timeout_watcher);
133
-
134
- // if(client->read == EBB_BUFFERSIZE) goto error;
135
-
136
- if(FALSE == client_finished_parsing) {
137
- http_parser_execute( &client->parser
138
- , client->request_buffer
139
- , client->read
140
- , client->parser.nread
141
- );
142
- if(http_parser_has_error(&client->parser)) goto error;
143
- }
144
-
145
- if(client_finished_parsing) {
146
- assert(client->read <= total_request_size);
147
- if(total_request_size == client->read || total_request_size > EBB_BUFFERSIZE) {
148
- client->body_head = client->request_buffer + client->parser.nread;
149
- client->body_head_len = client->read - client->parser.nread;
150
- ev_io_stop(loop, watcher);
151
- dispatch(client);
152
- return;
153
- }
154
- }
155
- return;
156
- error:
157
- #ifdef DEBUG
158
- if(read < 0) g_message("Error recving data: %s", strerror(errno));
159
- #endif
160
- ebb_client_close(client);
161
- }
162
-
163
-
164
- static void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
165
- {
166
- ebb_client *client = (ebb_client*)(watcher->data);
167
- ssize_t sent;
168
-
169
- if(client->status_written == FALSE || client->headers_written == FALSE) {
170
- g_message("no status or headers - closing connection.");
171
- goto error;
172
- }
173
-
174
- if(EV_ERROR & revents) {
175
- g_message("on_client_writable() got error event, closing peer");
176
- goto error;
177
- }
178
-
179
- //if(client->written != 0)
180
- // g_debug("total written: %d", (int)(client->written));
181
-
182
- sent = send( client->fd
183
- , client->response_buffer->str + sizeof(gchar)*(client->written)
184
- , client->response_buffer->len - client->written
185
- , 0
186
- );
187
- if(sent < 0) {
188
- #ifdef DEBUG
189
- g_message("Error writing: %s", strerror(errno));
190
- #endif
191
- goto error;
192
- } else if(sent == 0) {
193
- /* is this the wrong thing to do? */
194
- g_message("Sent zero bytes? Closing connection");
195
- goto error;
196
- }
197
- client->written += sent;
198
-
199
- assert(client->written <= client->response_buffer->len);
200
- //g_message("wrote %d bytes. total: %d", (int)sent, (int)(client->written));
201
-
202
- ev_timer_again(loop, &client->timeout_watcher);
203
-
204
- if(client->written == client->response_buffer->len) {
205
- /* stop the write watcher. to be restarted by the next call to ebb_client_write_body
206
- * or if client->body_written is set (by using ebb_client_release) then
207
- * we close the connection
208
- */
209
- ev_io_stop(loop, watcher);
210
- if(client->body_written) {
211
- client->keep_alive ? client_init(client) : ebb_client_close(client);
212
- }
213
- }
214
- return;
215
- error:
216
- ebb_client_close(client);
217
- }
218
-
219
-
220
- static void client_init(ebb_client *client)
221
- {
222
- assert(client->in_use == FALSE);
223
-
224
- /* If the client is already open, reuse the fd, just reset all the parameters
225
- * this would happen in the case of a keep_alive request
226
- */
227
- if(!client->open) {
228
- /* DO SOCKET STUFF */
229
- socklen_t len = sizeof(struct sockaddr);
230
- int fd = accept(client->server->fd, (struct sockaddr*)&(client->sockaddr), &len);
231
- if(fd < 0) {
232
- perror("accept()");
233
- return;
234
- }
235
- client->open = TRUE;
236
- client->fd = fd;
237
- }
238
-
239
- set_nonblock(client->fd);
240
-
241
- /* IP Address */
242
- if(client->server->port)
243
- client->ip = inet_ntoa(client->sockaddr.sin_addr);
244
-
245
- /* INITIALIZE http_parser */
246
- http_parser_init(&client->parser);
247
- client->parser.data = client;
248
- client->parser.http_field = http_field_cb;
249
- client->parser.on_element = on_element;
250
-
251
- /* OTHER */
252
- client->env_size = 0;
253
- client->read = 0;
254
- if(client->request_buffer == NULL) {
255
- /* Only allocate the request_buffer once */
256
- client->request_buffer = (char*)malloc(EBB_BUFFERSIZE);
257
- }
258
- client->keep_alive = FALSE;
259
- client->status_written = client->headers_written = client->body_written = FALSE;
260
- client->written = 0;
261
-
262
- if(client->response_buffer != NULL)
263
- g_string_free(client->response_buffer, TRUE);
264
- client->response_buffer = g_string_new("");
265
-
266
- /* SETUP READ AND TIMEOUT WATCHERS */
267
- client->write_watcher.data = client;
268
- ev_init (&client->write_watcher, on_client_writable);
269
- ev_io_set (&client->write_watcher, client->fd, EV_WRITE | EV_ERROR);
270
- /* Note, do not start write_watcher until there is something to be written.
271
- * See ebb_client_write_body() */
272
-
273
- client->read_watcher.data = client;
274
- ev_init(&client->read_watcher, on_client_readable);
275
- ev_io_set(&client->read_watcher, client->fd, EV_READ | EV_ERROR);
276
- ev_io_start(client->server->loop, &client->read_watcher);
277
-
278
- client->timeout_watcher.data = client;
279
- ev_timer_init(&client->timeout_watcher, on_timeout, EBB_TIMEOUT, 0);
280
- ev_timer_start(client->server->loop, &client->timeout_watcher);
281
- }
282
-
283
-
284
- static void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
285
- {
286
- ebb_server *server = (ebb_server*)(watcher->data);
287
- assert(server->open);
288
- assert(server->loop == loop);
289
- assert(&server->request_watcher == watcher);
290
-
291
- if(EV_ERROR & revents) {
292
- g_message("on_request() got error event, closing server.");
293
- ebb_server_unlisten(server);
294
- return;
295
- }
296
- /* Now we're going to initialize the client
297
- * and set up her callbacks for read and write
298
- * the client won't get passed back to the user, however,
299
- * until the request is complete and parsed.
300
- */
301
- int i;
302
- ebb_client *client = NULL;
303
- /* Get next availible peer */
304
- for(i=0; i < EBB_MAX_CLIENTS; i++)
305
- if(!server->clients[i].in_use && !server->clients[i].open) {
306
- client = &(server->clients[i]);
307
- break;
308
- }
309
- if(client == NULL) {
310
- g_message("Too many peers. Refusing connections.");
311
- return;
312
- }
313
-
314
- #ifdef DEBUG
315
- int count = 0;
316
- for(i = 0; i < EBB_MAX_CLIENTS; i++)
317
- if(server->clients[i].open) count += 1;
318
- g_debug("%d open connections", count);
319
- #endif
320
-
321
- client_init(client);
322
- }
323
-
324
-
325
- ebb_server* ebb_server_alloc()
326
- {
327
- ebb_server *server = g_new0(ebb_server, 1);
328
- return server;
329
- }
330
-
331
-
332
- void ebb_server_init( ebb_server *server
333
- , struct ev_loop *loop
334
- , ebb_request_cb request_cb
335
- , void *request_cb_data
336
- )
337
- {
338
- int i;
339
- for(i=0; i < EBB_MAX_CLIENTS; i++) {
340
- server->clients[i].request_buffer = NULL;
341
- server->clients[i].response_buffer = NULL;
342
- server->clients[i].open = FALSE;
343
- server->clients[i].in_use = FALSE;
344
- server->clients[i].server = server;
345
- }
346
-
347
- server->request_cb = request_cb;
348
- server->request_cb_data = request_cb_data;
349
- server->loop = loop;
350
- server->open = FALSE;
351
- server->fd = -1;
352
- return;
353
- error:
354
- ebb_server_free(server);
355
- return;
356
- }
357
-
358
-
359
- void ebb_server_free(ebb_server *server)
360
- {
361
- ebb_server_unlisten(server);
362
-
363
- if(server->port)
364
- free(server->port);
365
- if(server->socketpath)
366
- free(server->socketpath);
367
- free(server);
368
- }
369
-
370
-
371
- void ebb_server_unlisten(ebb_server *server)
372
- {
373
- if(server->open) {
374
- int i;
375
- ebb_client *client;
376
- ev_io_stop(server->loop, &server->request_watcher);
377
- close(server->fd);
378
- if(server->socketpath) {
379
- unlink(server->socketpath);
380
- server->socketpath = NULL;
381
- }
382
- if(server->port) {
383
- free(server->port);
384
- server->port = NULL;
385
- }
386
- server->open = FALSE;
387
- }
388
- }
389
-
390
-
391
- int ebb_server_listen_on_fd(ebb_server *server, const int sfd)
392
- {
393
- if (listen(sfd, EBB_MAX_CLIENTS) < 0) {
394
- perror("listen()");
395
- return -1;
396
- }
397
-
398
- set_nonblock(sfd); /* XXX: superfluous? */
399
-
400
- server->fd = sfd;
401
- assert(server->port == NULL);
402
- assert(server->socketpath == NULL);
403
- assert(server->open == FALSE);
404
- server->open = TRUE;
405
-
406
- server->request_watcher.data = server;
407
- ev_init (&server->request_watcher, on_request);
408
- ev_io_set (&server->request_watcher, server->fd, EV_READ | EV_ERROR);
409
- ev_io_start (server->loop, &server->request_watcher);
410
-
411
- return server->fd;
412
- }
413
-
414
-
415
- int ebb_server_listen_on_port(ebb_server *server, const int port)
416
- {
417
- int sfd = -1;
418
- struct linger ling = {0, 0};
419
- struct sockaddr_in addr;
420
- int flags = 1;
421
-
422
- if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
423
- perror("socket()");
424
- goto error;
425
- }
426
-
427
- flags = 1;
428
- setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
429
- setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
430
- setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
431
- setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
432
-
433
- /*
434
- * the memset call clears nonstandard fields in some impementations
435
- * that otherwise mess things up.
436
- */
437
- memset(&addr, 0, sizeof(addr));
438
-
439
- addr.sin_family = AF_INET;
440
- addr.sin_port = htons(port);
441
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
442
-
443
- if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
444
- perror("bind()");
445
- goto error;
446
- }
447
-
448
- int ret = ebb_server_listen_on_fd(server, sfd);
449
- if (ret >= 0) {
450
- assert(server->port == NULL);
451
- server->port = malloc(sizeof(char)*8); /* for easy access to the port */
452
- sprintf(server->port, "%d", port);
453
- }
454
- return ret;
455
- error:
456
- if(sfd > 0) close(sfd);
457
- return -1;
458
- }
459
-
460
-
461
- int ebb_server_listen_on_unix_socket(ebb_server *server, const char *socketpath)
462
- {
463
- int sfd = -1;
464
- struct linger ling = {0, 0};
465
- struct sockaddr_un addr;
466
- struct stat tstat;
467
- int flags =1;
468
- int old_umask = -1;
469
- int access_mask = 0777;
470
-
471
- if(( sfd = socket(AF_UNIX, SOCK_STREAM, 0) ) == -1) {
472
- perror("socket()");
473
- goto error;
474
- }
475
-
476
- /* Clean up a previous socket file if we left it around */
477
- if(lstat(socketpath, &tstat) == 0 && S_ISSOCK(tstat.st_mode)) {
478
- unlink(socketpath);
479
- }
480
-
481
- flags = 1;
482
- setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
483
- setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
484
- setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
485
-
486
- /*
487
- * the memset call clears nonstandard fields in some impementations
488
- * that otherwise mess things up.
489
- */
490
- memset(&addr, 0, sizeof(addr));
491
-
492
- addr.sun_family = AF_UNIX;
493
- strcpy(addr.sun_path, socketpath);
494
- old_umask = umask( ~(access_mask & 0777) );
495
-
496
- if(bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
497
- perror("bind()");
498
- goto error;
499
- }
500
- umask(old_umask);
501
-
502
- int ret = ebb_server_listen_on_fd(server, sfd);
503
- if (ret >= 0) {
504
- assert(server->socketpath == NULL);
505
- server->socketpath = strdup(socketpath);
506
- }
507
- return ret;
508
- error:
509
- if(sfd > 0) close(sfd);
510
- return -1;
511
- }
512
-
513
-
514
- int ebb_server_clients_in_use_p(ebb_server *server)
515
- {
516
- int i;
517
- for(i = 0; i < EBB_MAX_CLIENTS; i++)
518
- if(server->clients[i].in_use) return TRUE;
519
- return FALSE;
520
- }
521
-
522
-
523
- void ebb_client_release(ebb_client *client)
524
- {
525
- assert(client->in_use);
526
- client->in_use = FALSE;
527
-
528
- if(client->headers_written == FALSE) {
529
- g_string_append(client->response_buffer, "\r\n");
530
- client->headers_written = TRUE;
531
- }
532
- client->body_written = TRUE;
533
-
534
- /* If the write_watcher isn't yet active, then start it. It could be that
535
- * we're streaming and the watcher has been stopped. In that case we
536
- * start it again since we have more to write. */
537
- if(ev_is_active(&client->write_watcher) == FALSE) {
538
- set_nonblock(client->fd);
539
- ev_io_start(client->server->loop, &client->write_watcher);
540
- }
541
-
542
- if(client->written == client->response_buffer->len)
543
- ebb_client_close(client);
544
- }
545
-
546
-
547
- void ebb_client_close(ebb_client *client)
548
- {
549
- if(client->open) {
550
- ev_io_stop(client->server->loop, &client->read_watcher);
551
- ev_io_stop(client->server->loop, &client->write_watcher);
552
- ev_timer_stop(client->server->loop, &client->timeout_watcher);
553
-
554
- client->ip = NULL;
555
-
556
- g_string_free(client->response_buffer, TRUE);
557
- client->response_buffer = NULL;
558
-
559
- close(client->fd);
560
- client->open = FALSE;
561
- }
562
- }
563
-
564
-
565
- void ebb_client_write_status(ebb_client *client, int status, const char *reason_phrase)
566
- {
567
- assert(client->in_use);
568
- if(!client->open) return;
569
- assert(client->status_written == FALSE);
570
- g_string_append_printf( client->response_buffer
571
- , "HTTP/1.1 %d %s\r\n"
572
- , status
573
- , reason_phrase
574
- );
575
- client->status_written = TRUE;
576
- }
577
-
578
-
579
- void ebb_client_write_header(ebb_client *client, const char *field, const char *value)
580
- {
581
- assert(client->in_use);
582
- if(!client->open) return;
583
- assert(client->status_written == TRUE);
584
- assert(client->headers_written == FALSE);
585
-
586
- if(strcmp(field, "Connection") == 0 && strcmp(value, "Keep-Alive") == 0) {
587
- client->keep_alive = TRUE;
588
- }
589
- g_string_append_printf( client->response_buffer
590
- , "%s: %s\r\n"
591
- , field
592
- , value
593
- );
594
- }
595
-
596
-
597
- void ebb_client_write_body(ebb_client *client, const char *data, int length)
598
- {
599
- assert(client->in_use);
600
- if(!client->open) return;
601
-
602
- if(client->headers_written == FALSE) {
603
- g_string_append(client->response_buffer, "\r\n");
604
- client->headers_written = TRUE;
605
- }
606
-
607
- g_string_append_len(client->response_buffer, data, length);
608
-
609
- /* If the write_watcher isn't yet active, then start it. It could be that
610
- * we're streaming and the watcher has been stopped. In that case we
611
- * start it again since we have more to write. */
612
- if(ev_is_active(&client->write_watcher) == FALSE) {
613
- set_nonblock(client->fd);
614
- ev_io_start(client->server->loop, &client->write_watcher);
615
- }
616
- }
617
-
618
- // int ebb_client_should_keep_alive(ebb_client*)
619
- // {
620
- // /* TODO - return boolean */
621
- // if env['HTTP_VERSION'] == 'HTTP/1.0'
622
- // return true if env['HTTP_CONNECTION'] =~ /Keep-Alive/i
623
- // else
624
- // return true unless env['HTTP_CONNECTION'] =~ /close/i
625
- // end
626
- // false
627
- // }