ebb 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,10 +11,7 @@ module Ebb
11
11
  # defaults for ebb_rails
12
12
  @options.update(
13
13
  :environment => 'development',
14
- :port => 3000,
15
- # rails has a mutex lock around each request - threaded processing
16
- # will only slow things down
17
- :threaded_processing => false
14
+ :port => 3000
18
15
  )
19
16
 
20
17
  @parser.on("-e", "--env ENV",
@@ -66,6 +66,11 @@ module Rack
66
66
  serve_rails(env)
67
67
  end
68
68
  end
69
+
70
+ # Never spawn threads for a request
71
+ def deferred?(env)
72
+ false
73
+ end
69
74
 
70
75
  protected
71
76
 
data/src/ebb.c CHANGED
@@ -17,11 +17,9 @@
17
17
  #include <signal.h>
18
18
  #include <assert.h>
19
19
 
20
- #include <pthread.h>
21
- #include <glib.h>
22
-
23
20
  #define EV_STANDALONE 1
24
21
  #include <ev.c>
22
+ #include <glib.h>
25
23
 
26
24
  #include "parser.h"
27
25
  #include "ebb.h"
@@ -29,7 +27,14 @@
29
27
  #define min(a,b) (a < b ? a : b)
30
28
  #define ramp(a) (a > 0 ? a : 0)
31
29
 
32
- static int server_socket_unix(const char *path, int access_mask);
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
+
33
38
 
34
39
  void env_add(ebb_client *client, const char *field, int flen, const char *value, int vlen)
35
40
  {
@@ -37,7 +42,7 @@ void env_add(ebb_client *client, const char *field, int flen, const char *value,
37
42
  client->parser.overflow_error = TRUE;
38
43
  return;
39
44
  }
40
- client->env[client->env_size].type = EBB_FIELD_VALUE_PAIR;
45
+ client->env[client->env_size].type = -1;
41
46
  client->env[client->env_size].field = field;
42
47
  client->env[client->env_size].field_length = flen;
43
48
  client->env[client->env_size].value = value;
@@ -70,75 +75,22 @@ void http_field_cb(void *data, const char *field, size_t flen, const char *value
70
75
  }
71
76
 
72
77
 
73
- void request_method_cb(void *data, const char *at, size_t length)
74
- {
75
- ebb_client *client = (ebb_client*)(data);
76
- env_add_const(client, EBB_REQUEST_METHOD, at, length);
77
- }
78
-
79
-
80
- void request_uri_cb(void *data, const char *at, size_t length)
81
- {
82
- ebb_client *client = (ebb_client*)(data);
83
- env_add_const(client, EBB_REQUEST_URI, at, length);
84
- }
85
-
86
-
87
- void fragment_cb(void *data, const char *at, size_t length)
88
- {
89
- ebb_client *client = (ebb_client*)(data);
90
- env_add_const(client, EBB_FRAGMENT, at, length);
91
- }
92
-
93
-
94
- void request_path_cb(void *data, const char *at, size_t length)
95
- {
96
- ebb_client *client = (ebb_client*)(data);
97
- env_add_const(client, EBB_REQUEST_PATH, at, length);
98
- }
99
-
100
-
101
- void query_string_cb(void *data, const char *at, size_t length)
102
- {
103
- ebb_client *client = (ebb_client*)(data);
104
- env_add_const(client, EBB_QUERY_STRING, at, length);
105
- }
106
-
107
-
108
- void http_version_cb(void *data, const char *at, size_t length)
109
- {
110
- ebb_client *client = (ebb_client*)(data);
111
- env_add_const(client, EBB_HTTP_VERSION, at, length);
112
- }
113
-
114
-
115
- void content_length_cb(void *data, const char *at, size_t length)
78
+ void on_element(void *data, int type, const char *at, size_t length)
116
79
  {
117
80
  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;
81
+ env_add_const(client, type, at, length);
124
82
  }
125
83
 
126
84
 
127
85
  static void dispatch(ebb_client *client)
128
86
  {
129
87
  ebb_server *server = client->server;
130
-
131
88
  if(client->open == FALSE)
132
89
  return;
133
-
134
- /* Set the env variables */
135
- if(server->port) {
136
- env_add_const(client, EBB_SERVER_PORT
137
- , server->port
138
- , strlen(server->port)
139
- );
140
- }
141
90
  client->in_use = TRUE;
91
+
92
+ /* XXX decide if to use keep-alive or not? */
93
+
142
94
  server->request_cb(client, server->request_cb_data);
143
95
  }
144
96
 
@@ -157,77 +109,7 @@ static void on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
157
109
  }
158
110
 
159
111
  #define client_finished_parsing http_parser_is_finished(&client->parser)
160
- #define total_request_size (client->content_length + client->parser.nread)
161
-
162
- static void* read_body_into_file(void *_client)
163
- {
164
- ebb_client *client = (ebb_client*)_client;
165
- static unsigned int id;
166
- FILE *tmpfile;
167
-
168
- assert(client->open);
169
- assert(client->server->open);
170
- assert(client->content_length > 0);
171
- assert(client_finished_parsing);
172
-
173
- /* set blocking socket */
174
- int flags = fcntl(client->fd, F_GETFL, 0);
175
- assert(0 <= fcntl(client->fd, F_SETFL, flags & ~O_NONBLOCK));
176
-
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;
181
-
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
189
- );
190
- if(r <= 0) {
191
- ebb_client_close(client);
192
- return NULL;
193
- }
194
- written += r;
195
- }
196
-
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)
204
- , 0
205
- );
206
- if(received < 0) goto error;
207
- client->read += received;
208
-
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
216
- );
217
- if(rv <= 0) goto error;
218
- w += rv;
219
- }
220
- written += received;
221
- }
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;
229
- }
230
-
112
+ #define total_request_size (client->parser.content_length + client->parser.nread)
231
113
 
232
114
  static void on_client_readable(struct ev_loop *loop, ev_io *watcher, int revents)
233
115
  {
@@ -244,12 +126,12 @@ static void on_client_readable(struct ev_loop *loop, ev_io *watcher, int revents
244
126
  , EBB_BUFFERSIZE - client->read
245
127
  , 0
246
128
  );
247
- if(read < 0) goto error;
129
+ if(read < 0) goto error;
248
130
  if(read == 0) goto error; /* XXX is this the right action to take for read==0 ? */
249
131
  client->read += read;
250
132
  ev_timer_again(loop, &client->timeout_watcher);
251
133
 
252
- if(client->read == EBB_BUFFERSIZE) goto error;
134
+ // if(client->read == EBB_BUFFERSIZE) goto error;
253
135
 
254
136
  if(FALSE == client_finished_parsing) {
255
137
  http_parser_execute( &client->parser
@@ -261,88 +143,144 @@ static void on_client_readable(struct ev_loop *loop, ev_io *watcher, int revents
261
143
  }
262
144
 
263
145
  if(client_finished_parsing) {
264
- if(total_request_size == client->read) {
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;
265
150
  ev_io_stop(loop, watcher);
266
- client->nread_from_body = 0;
267
151
  dispatch(client);
268
152
  return;
269
153
  }
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;
277
- }
278
154
  }
279
155
  return;
280
156
  error:
157
+ #ifdef DEBUG
281
158
  if(read < 0) g_message("Error recving data: %s", strerror(errno));
159
+ #endif
282
160
  ebb_client_close(client);
283
161
  }
284
162
 
285
- static client_init(ebb_server *server, ebb_client *client)
163
+
164
+ static void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
286
165
  {
287
- assert(client->in_use == FALSE);
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) {
288
188
  #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';
189
+ g_message("Error writing: %s", strerror(errno));
292
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;
293
198
 
294
- client->open = TRUE;
295
- client->server = server;
199
+ assert(client->written <= client->response_buffer->len);
200
+ //g_message("wrote %d bytes. total: %d", (int)sent, (int)(client->written));
296
201
 
297
- /* DO SOCKET STUFF */
298
- socklen_t len;
299
- client->fd = accept(server->fd, (struct sockaddr*)&(server->sockaddr), &len);
300
- if(client->fd < 0) {
301
- perror("accept()");
302
- client->open = FALSE;
303
- return;
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;
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;
304
237
  }
305
238
 
306
- int flags = fcntl(client->fd, F_GETFL, 0);
307
- assert(0 <= fcntl(client->fd, F_SETFL, flags | O_NONBLOCK));
239
+ set_nonblock(client->fd);
240
+
241
+ /* IP Address */
242
+ if(client->server->port)
243
+ client->ip = inet_ntoa(client->sockaddr.sin_addr);
308
244
 
309
245
  /* INITIALIZE http_parser */
310
- http_parser_init(&(client->parser));
246
+ http_parser_init(&client->parser);
311
247
  client->parser.data = client;
312
- client->parser.http_field = http_field_cb;
313
- client->parser.request_method = request_method_cb;
314
- client->parser.request_uri = request_uri_cb;
315
- client->parser.fragment = fragment_cb;
316
- client->parser.request_path = request_path_cb;
317
- client->parser.query_string = query_string_cb;
318
- client->parser.http_version = http_version_cb;
319
- client->parser.content_length = content_length_cb;
248
+ client->parser.http_field = http_field_cb;
249
+ client->parser.on_element = on_element;
320
250
 
321
251
  /* OTHER */
322
252
  client->env_size = 0;
323
- client->read = client->nread_from_body = 0;
324
- client->response_buffer->len = 0; /* see note in ebb_client_close */
325
- client->content_length = 0;
253
+ client->read = 0;
326
254
  if(client->request_buffer == NULL) {
255
+ /* Only allocate the request_buffer once */
327
256
  client->request_buffer = (char*)malloc(EBB_BUFFERSIZE);
328
257
  }
258
+ client->keep_alive = FALSE;
259
+ client->status_written = client->headers_written = client->body_written = FALSE;
260
+ client->written = 0;
329
261
 
330
- client->status_written = FALSE;
331
- client->headers_written = FALSE;
332
- client->body_written = FALSE;
333
- client->began_transmission = FALSE;
262
+ if(client->response_buffer != NULL)
263
+ g_string_free(client->response_buffer, TRUE);
264
+ client->response_buffer = g_string_new("");
334
265
 
335
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
+
336
273
  client->read_watcher.data = client;
337
274
  ev_init(&client->read_watcher, on_client_readable);
338
275
  ev_io_set(&client->read_watcher, client->fd, EV_READ | EV_ERROR);
339
- ev_io_start(server->loop, &client->read_watcher);
276
+ ev_io_start(client->server->loop, &client->read_watcher);
340
277
 
341
278
  client->timeout_watcher.data = client;
342
279
  ev_timer_init(&client->timeout_watcher, on_timeout, EBB_TIMEOUT, EBB_TIMEOUT);
343
- ev_timer_start(server->loop, &client->timeout_watcher);
280
+ ev_timer_start(client->server->loop, &client->timeout_watcher);
344
281
  }
345
282
 
283
+
346
284
  static void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
347
285
  {
348
286
  ebb_server *server = (ebb_server*)(watcher->data);
@@ -380,7 +318,7 @@ static void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
380
318
  g_debug("%d open connections", count);
381
319
  #endif
382
320
 
383
- client_init(server, client);
321
+ client_init(client);
384
322
  }
385
323
 
386
324
 
@@ -400,9 +338,10 @@ void ebb_server_init( ebb_server *server
400
338
  int i;
401
339
  for(i=0; i < EBB_MAX_CLIENTS; i++) {
402
340
  server->clients[i].request_buffer = NULL;
403
- server->clients[i].response_buffer = g_string_new("");
341
+ server->clients[i].response_buffer = NULL;
404
342
  server->clients[i].open = FALSE;
405
343
  server->clients[i].in_use = FALSE;
344
+ server->clients[i].server = server;
406
345
  }
407
346
 
408
347
  server->request_cb = request_cb;
@@ -421,9 +360,6 @@ void ebb_server_free(ebb_server *server)
421
360
  {
422
361
  ebb_server_unlisten(server);
423
362
 
424
- int i;
425
- for(i=0; i < EBB_MAX_CLIENTS; i++)
426
- g_string_free(server->clients[i].response_buffer, TRUE);
427
363
  if(server->port)
428
364
  free(server->port);
429
365
  if(server->socketpath)
@@ -439,12 +375,43 @@ void ebb_server_unlisten(ebb_server *server)
439
375
  ebb_client *client;
440
376
  ev_io_stop(server->loop, &server->request_watcher);
441
377
  close(server->fd);
442
- if(server->socketpath)
378
+ if(server->socketpath) {
443
379
  unlink(server->socketpath);
380
+ server->socketpath = NULL;
381
+ }
382
+ if(server->port) {
383
+ free(server->port);
384
+ server->port = NULL;
385
+ }
444
386
  server->open = FALSE;
445
387
  }
446
388
  }
447
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
+
448
415
  int ebb_server_listen_on_port(ebb_server *server, const int port)
449
416
  {
450
417
  int sfd = -1;
@@ -457,12 +424,6 @@ int ebb_server_listen_on_port(ebb_server *server, const int port)
457
424
  goto error;
458
425
  }
459
426
 
460
- flags = fcntl(sfd, F_GETFL, 0);
461
- if(fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
462
- perror("setting O_NONBLOCK");
463
- goto error;
464
- }
465
-
466
427
  flags = 1;
467
428
  setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
468
429
  setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
@@ -483,36 +444,79 @@ int ebb_server_listen_on_port(ebb_server *server, const int port)
483
444
  perror("bind()");
484
445
  goto error;
485
446
  }
486
- if (listen(sfd, EBB_MAX_CLIENTS) < 0) {
487
- perror("listen()");
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()");
488
473
  goto error;
489
474
  }
490
- server->fd = sfd;
491
- server->port = malloc(sizeof(char)*8); /* for easy access to the port */
492
- sprintf(server->port, "%d", port);
493
- assert(server->open == FALSE);
494
- server->open = TRUE;
495
475
 
496
- server->request_watcher.data = server;
497
- ev_init (&server->request_watcher, on_request);
498
- ev_io_set (&server->request_watcher, server->fd, EV_READ | EV_ERROR);
499
- ev_io_start (server->loop, &server->request_watcher);
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
+ }
500
480
 
501
- return server->fd;
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;
502
508
  error:
503
509
  if(sfd > 0) close(sfd);
504
510
  return -1;
505
511
  }
506
512
 
507
513
 
508
- int ebb_server_listen_on_socket(ebb_server *server, const char *socketpath)
514
+ int ebb_server_clients_in_use_p(ebb_server *server)
509
515
  {
510
- // int fd = server_socket_unix(socketpath, 0755);
511
- // if(fd < 0) return 0;
512
- // server->socketpath = strdup(socketpath);
513
- // server->fd = fd;
514
- // server_listen(server);
515
- // return fd;
516
+ int i;
517
+ for(i = 0; i < EBB_MAX_CLIENTS; i++)
518
+ if(server->clients[i].in_use) return TRUE;
519
+ return FALSE;
516
520
  }
517
521
 
518
522
 
@@ -520,6 +524,21 @@ void ebb_client_release(ebb_client *client)
520
524
  {
521
525
  assert(client->in_use);
522
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
+
523
542
  if(client->written == client->response_buffer->len)
524
543
  ebb_client_close(client);
525
544
  }
@@ -532,17 +551,10 @@ void ebb_client_close(ebb_client *client)
532
551
  ev_io_stop(client->server->loop, &client->write_watcher);
533
552
  ev_timer_stop(client->server->loop, &client->timeout_watcher);
534
553
 
535
- if(client->upload_file) {
536
- fclose(client->upload_file);
537
- unlink(client->upload_file_filename);
538
- }
554
+ client->ip = NULL;
539
555
 
540
- /* here we do not free the already allocated GString client->response_buffer
541
- * that we're holding the response in. we reuse it again -
542
- * presumably because the backend is going to keep sending such long
543
- * requests.
544
- */
545
- client->response_buffer->len = 0;
556
+ g_string_free(client->response_buffer, TRUE);
557
+ client->response_buffer = NULL;
546
558
 
547
559
  close(client->fd);
548
560
  client->open = FALSE;
@@ -550,54 +562,7 @@ void ebb_client_close(ebb_client *client)
550
562
  }
551
563
 
552
564
 
553
- static void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
554
- {
555
- ebb_client *client = (ebb_client*)(watcher->data);
556
- ssize_t sent;
557
-
558
- assert(client->status_written);
559
- assert(client->headers_written);
560
- assert(client->began_transmission);
561
-
562
- if(EV_ERROR & revents) {
563
- g_message("on_client_writable() got error event, closing peer");
564
- ebb_client_close(client);
565
- return;
566
- }
567
-
568
- //if(client->written != 0)
569
- // g_debug("total written: %d", (int)(client->written));
570
-
571
- sent = send( client->fd
572
- , client->response_buffer->str + sizeof(gchar)*(client->written)
573
- , client->response_buffer->len - client->written
574
- , 0
575
- );
576
- if(sent < 0) {
577
- #ifdef DEBUG
578
- g_message("Error writing: %s", strerror(errno));
579
- #endif
580
- ebb_client_close(client);
581
- return;
582
- } else if(sent == 0) {
583
- g_message("Sent zero bytes? Closing connection");
584
- ebb_client_close(client);
585
- }
586
- client->written += sent;
587
-
588
- assert(client->written <= client->response_buffer->len);
589
- //g_message("wrote %d bytes. total: %d", (int)sent, (int)(client->written));
590
-
591
- ev_timer_again(loop, &(client->timeout_watcher));
592
-
593
- if(client->written == client->response_buffer->len) {
594
- ev_io_stop(loop, watcher);
595
- if(client->body_written)
596
- ebb_client_close(client);
597
- }
598
- }
599
-
600
- void ebb_client_write_status(ebb_client *client, int status, const char *human_status)
565
+ void ebb_client_write_status(ebb_client *client, int status, const char *reason_phrase)
601
566
  {
602
567
  assert(client->in_use);
603
568
  if(!client->open) return;
@@ -605,17 +570,22 @@ void ebb_client_write_status(ebb_client *client, int status, const char *human_s
605
570
  g_string_append_printf( client->response_buffer
606
571
  , "HTTP/1.1 %d %s\r\n"
607
572
  , status
608
- , human_status
573
+ , reason_phrase
609
574
  );
610
575
  client->status_written = TRUE;
611
576
  }
612
577
 
578
+
613
579
  void ebb_client_write_header(ebb_client *client, const char *field, const char *value)
614
580
  {
615
581
  assert(client->in_use);
616
582
  if(!client->open) return;
617
583
  assert(client->status_written == TRUE);
618
584
  assert(client->headers_written == FALSE);
585
+
586
+ if(strcmp(field, "Connection") == 0 && strcmp(value, "Keep-Alive") == 0) {
587
+ client->keep_alive = TRUE;
588
+ }
619
589
  g_string_append_printf( client->response_buffer
620
590
  , "%s: %s\r\n"
621
591
  , field
@@ -623,131 +593,35 @@ void ebb_client_write_header(ebb_client *client, const char *field, const char *
623
593
  );
624
594
  }
625
595
 
626
- void ebb_client_write(ebb_client *client, const char *data, int length)
627
- {
628
- assert(client->in_use);
629
- if(!client->open) return;
630
- g_string_append_len(client->response_buffer, data, length);
631
- if(client->began_transmission) {
632
- /* restart the watcher if we're streaming */
633
- ev_io_start(client->server->loop, &client->write_watcher);
634
- }
635
- }
636
-
637
596
 
638
- void ebb_client_begin_transmission(ebb_client *client)
597
+ void ebb_client_write_body(ebb_client *client, const char *data, int length)
639
598
  {
640
599
  assert(client->in_use);
641
600
  if(!client->open) return;
642
- assert(FALSE == ev_is_active(&client->write_watcher));
643
601
 
644
- /* assure the socket is still in non-blocking mode */
645
- int flags = fcntl(client->fd, F_GETFL, 0);
646
- if(0 > fcntl(client->fd, F_SETFL, flags | O_NONBLOCK)) {
647
- perror("fcntl()");
648
- ebb_client_close(client);
649
- return;
602
+ if(client->headers_written == FALSE) {
603
+ g_string_append(client->response_buffer, "\r\n");
604
+ client->headers_written = TRUE;
650
605
  }
651
606
 
652
- client->headers_written = TRUE;
653
- client->began_transmission = TRUE;
654
- client->written = 0;
655
- client->write_watcher.data = client;
656
- ev_init (&(client->write_watcher), on_client_writable);
657
- ev_io_set (&(client->write_watcher), client->fd, EV_WRITE | EV_ERROR);
658
- ev_io_start(client->server->loop, &client->write_watcher);
659
- }
660
-
661
-
662
- /* pass an allocated buffer and the length to read. this function will try to
663
- * fill the buffer with that length of data read from the body of the request.
664
- * the return value says how much was actually written.
665
- */
666
- int ebb_client_read(ebb_client *client, char *buffer, int length)
667
- {
668
- size_t read;
607
+ g_string_append_len(client->response_buffer, data, length);
669
608
 
670
- assert(client->in_use);
671
- if(!client->open) return -1;
672
- assert(client_finished_parsing);
673
-
674
- if(client->upload_file) {
675
- read = fread(buffer, 1, length, client->upload_file);
676
- /* TODO error checking! */
677
- return read;
678
- } else {
679
- char* request_body = client->request_buffer + client->parser.nread;
680
-
681
- read = ramp(min(length, client->content_length - client->nread_from_body));
682
- memcpy( buffer
683
- , request_body + client->nread_from_body
684
- , read
685
- );
686
- client->nread_from_body += read;
687
- return read;
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);
688
615
  }
689
616
  }
690
617
 
691
- /* The following socket creation routines are modified and stolen from memcached */
692
-
693
-
694
- static int server_socket_unix(const char *path, int access_mask) {
695
- int sfd;
696
- struct linger ling = {0, 0};
697
- struct sockaddr_un addr;
698
- struct stat tstat;
699
- int flags =1;
700
- int old_umask;
701
-
702
- if (!path) {
703
- return -1;
704
- }
705
-
706
- if ((sfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
707
- perror("socket()");
708
- return -1;
709
- }
710
-
711
- if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
712
- fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
713
- perror("setting O_NONBLOCK");
714
- close(sfd);
715
- return -1;
716
- }
717
-
718
- /*
719
- * Clean up a previous socket file if we left it around
720
- */
721
- if (lstat(path, &tstat) == 0) {
722
- if (S_ISSOCK(tstat.st_mode))
723
- unlink(path);
724
- }
725
-
726
- flags = 1;
727
- setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
728
- setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
729
- setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
730
-
731
- /*
732
- * the memset call clears nonstandard fields in some impementations
733
- * that otherwise mess things up.
734
- */
735
- memset(&addr, 0, sizeof(addr));
736
-
737
- addr.sun_family = AF_UNIX;
738
- strcpy(addr.sun_path, path);
739
- old_umask=umask( ~(access_mask&0777));
740
- if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
741
- perror("bind()");
742
- close(sfd);
743
- umask(old_umask);
744
- return -1;
745
- }
746
- umask(old_umask);
747
- if (listen(sfd, EBB_MAX_CLIENTS) == -1) {
748
- perror("listen()");
749
- close(sfd);
750
- return -1;
751
- }
752
- return sfd;
753
- }
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
+ // }