ebb 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +53 -62
- data/benchmark/application.rb +3 -9
- data/benchmark/bench_results.rb +30 -17
- data/benchmark/server_test.rb +54 -12
- data/bin/ebb_rails +1 -76
- data/ruby_lib/ebb.rb +136 -107
- data/ruby_lib/ebb/runner.rb +135 -0
- data/ruby_lib/ebb/runner/rails.rb +34 -0
- data/ruby_lib/rack/adapter/rails.rb +2 -0
- data/src/ebb.c +174 -142
- data/src/ebb.h +14 -15
- data/src/ebb_ruby.c +120 -85
- data/src/parser.c +322 -410
- data/test/basic_test.rb +6 -170
- data/test/ebb_rails_test.rb +34 -0
- data/test/env_test.rb +8 -12
- data/test/helper.rb +86 -0
- metadata +21 -11
- data/VERSION +0 -1
- data/ruby_lib/daemonizable.rb +0 -98
- data/test/echo_server.rb +0 -16
- data/test/test.py +0 -15
data/src/ebb.c
CHANGED
@@ -29,7 +29,6 @@
|
|
29
29
|
#define min(a,b) (a < b ? a : b)
|
30
30
|
#define ramp(a) (a > 0 ? a : 0)
|
31
31
|
|
32
|
-
static int server_socket(const int port);
|
33
32
|
static int server_socket_unix(const char *path, int access_mask);
|
34
33
|
|
35
34
|
void env_add(ebb_client *client, const char *field, int flen, const char *value, int vlen)
|
@@ -61,6 +60,7 @@ void env_add_const(ebb_client *client, int type, const char *value, int vlen)
|
|
61
60
|
client->env_size += 1;
|
62
61
|
}
|
63
62
|
|
63
|
+
|
64
64
|
void http_field_cb(void *data, const char *field, size_t flen, const char *value, size_t vlen)
|
65
65
|
{
|
66
66
|
ebb_client *client = (ebb_client*)(data);
|
@@ -116,17 +116,15 @@ void content_length_cb(void *data, const char *at, size_t length)
|
|
116
116
|
{
|
117
117
|
ebb_client *client = (ebb_client*)(data);
|
118
118
|
env_add_const(client, EBB_CONTENT_LENGTH, at, length);
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
client->content_length = atoi(buf);
|
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;
|
125
124
|
}
|
126
125
|
|
127
126
|
|
128
|
-
|
129
|
-
void dispatch(ebb_client *client)
|
127
|
+
static void dispatch(ebb_client *client)
|
130
128
|
{
|
131
129
|
ebb_server *server = client->server;
|
132
130
|
|
@@ -135,20 +133,17 @@ void dispatch(ebb_client *client)
|
|
135
133
|
|
136
134
|
/* Set the env variables */
|
137
135
|
if(server->port) {
|
138
|
-
env_add_const(client, EBB_SERVER_NAME
|
139
|
-
, localhost_str
|
140
|
-
, 7
|
141
|
-
);
|
142
136
|
env_add_const(client, EBB_SERVER_PORT
|
143
137
|
, server->port
|
144
138
|
, strlen(server->port)
|
145
139
|
);
|
146
140
|
}
|
141
|
+
client->in_use = TRUE;
|
147
142
|
server->request_cb(client, server->request_cb_data);
|
148
143
|
}
|
149
144
|
|
150
145
|
|
151
|
-
void on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
|
146
|
+
static void on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
|
152
147
|
{
|
153
148
|
ebb_client *client = (ebb_client*)(watcher->data);
|
154
149
|
|
@@ -164,7 +159,7 @@ void on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents)
|
|
164
159
|
#define client_finished_parsing http_parser_is_finished(&client->parser)
|
165
160
|
#define total_request_size (client->content_length + client->parser.nread)
|
166
161
|
|
167
|
-
void* read_body_into_file(void *_client)
|
162
|
+
static void* read_body_into_file(void *_client)
|
168
163
|
{
|
169
164
|
ebb_client *client = (ebb_client*)_client;
|
170
165
|
static unsigned int id;
|
@@ -199,8 +194,6 @@ void* read_body_into_file(void *_client)
|
|
199
194
|
written += r;
|
200
195
|
}
|
201
196
|
|
202
|
-
// g_debug("wrote request header to file. written: %d, content_length: %d", written, client->content_length);
|
203
|
-
|
204
197
|
int bufsize = 5*1024;
|
205
198
|
char buffer[bufsize];
|
206
199
|
size_t received;
|
@@ -236,10 +229,11 @@ error:
|
|
236
229
|
}
|
237
230
|
|
238
231
|
|
239
|
-
void
|
232
|
+
static void on_client_readable(struct ev_loop *loop, ev_io *watcher, int revents)
|
240
233
|
{
|
241
234
|
ebb_client *client = (ebb_client*)(watcher->data);
|
242
235
|
|
236
|
+
assert(client->in_use == FALSE);
|
243
237
|
assert(client->open);
|
244
238
|
assert(client->server->open);
|
245
239
|
assert(client->server->loop == loop);
|
@@ -250,8 +244,8 @@ void on_readable(struct ev_loop *loop, ev_io *watcher, int revents)
|
|
250
244
|
, EBB_BUFFERSIZE - client->read
|
251
245
|
, 0
|
252
246
|
);
|
253
|
-
if(read < 0) goto error;
|
254
|
-
if(read == 0)
|
247
|
+
if(read < 0) goto error;
|
248
|
+
if(read == 0) goto error; /* XXX is this the right action to take for read==0 ? */
|
255
249
|
client->read += read;
|
256
250
|
ev_timer_again(loop, &client->timeout_watcher);
|
257
251
|
|
@@ -288,42 +282,10 @@ error:
|
|
288
282
|
ebb_client_close(client);
|
289
283
|
}
|
290
284
|
|
291
|
-
|
285
|
+
static client_init(ebb_server *server, ebb_client *client)
|
292
286
|
{
|
293
|
-
|
294
|
-
assert(server->open);
|
295
|
-
assert(server->loop == loop);
|
296
|
-
assert(&server->request_watcher == watcher);
|
297
|
-
|
298
|
-
if(EV_ERROR & revents) {
|
299
|
-
g_message("on_request() got error event, closing server.");
|
300
|
-
ebb_server_unlisten(server);
|
301
|
-
return;
|
302
|
-
}
|
303
|
-
/* Now we're going to initialize the client
|
304
|
-
* and set up her callbacks for read and write
|
305
|
-
* the client won't get passed back to the user, however,
|
306
|
-
* until the request is complete and parsed.
|
307
|
-
*/
|
308
|
-
int i;
|
309
|
-
ebb_client *client;
|
310
|
-
/* Get next availible peer */
|
311
|
-
for(i=0; i < EBB_MAX_CLIENTS; i++)
|
312
|
-
if(!server->clients[i].open) {
|
313
|
-
client = &(server->clients[i]);
|
314
|
-
break;
|
315
|
-
}
|
316
|
-
if(client == NULL) {
|
317
|
-
g_message("Too many peers. Refusing connections.");
|
318
|
-
return;
|
319
|
-
}
|
320
|
-
|
287
|
+
assert(client->in_use == FALSE);
|
321
288
|
#ifdef DEBUG
|
322
|
-
int count = 0;
|
323
|
-
for(i = 0; i < EBB_MAX_CLIENTS; i++)
|
324
|
-
if(server->clients[i].open) count += 1;
|
325
|
-
g_debug("%d open connections", count);
|
326
|
-
|
327
289
|
/* does ragel fuck up if request buffer isn't null? */
|
328
290
|
for(i=0; i< EBB_BUFFERSIZE; i++)
|
329
291
|
client->request_buffer[i] = 'A';
|
@@ -335,7 +297,12 @@ void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
|
|
335
297
|
/* DO SOCKET STUFF */
|
336
298
|
socklen_t len;
|
337
299
|
client->fd = accept(server->fd, (struct sockaddr*)&(server->sockaddr), &len);
|
338
|
-
|
300
|
+
if(client->fd < 0) {
|
301
|
+
perror("accept()");
|
302
|
+
client->open = FALSE;
|
303
|
+
return;
|
304
|
+
}
|
305
|
+
|
339
306
|
int flags = fcntl(client->fd, F_GETFL, 0);
|
340
307
|
assert(0 <= fcntl(client->fd, F_SETFL, flags | O_NONBLOCK));
|
341
308
|
|
@@ -352,19 +319,22 @@ void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
|
|
352
319
|
client->parser.content_length = content_length_cb;
|
353
320
|
|
354
321
|
/* OTHER */
|
355
|
-
|
356
322
|
client->env_size = 0;
|
357
323
|
client->read = client->nread_from_body = 0;
|
358
324
|
client->response_buffer->len = 0; /* see note in ebb_client_close */
|
359
325
|
client->content_length = 0;
|
326
|
+
if(client->request_buffer == NULL) {
|
327
|
+
client->request_buffer = (char*)malloc(EBB_BUFFERSIZE);
|
328
|
+
}
|
360
329
|
|
361
|
-
client->
|
362
|
-
client->
|
363
|
-
client->
|
330
|
+
client->status_written = FALSE;
|
331
|
+
client->headers_written = FALSE;
|
332
|
+
client->body_written = FALSE;
|
333
|
+
client->began_transmission = FALSE;
|
364
334
|
|
365
335
|
/* SETUP READ AND TIMEOUT WATCHERS */
|
366
336
|
client->read_watcher.data = client;
|
367
|
-
ev_init(&client->read_watcher,
|
337
|
+
ev_init(&client->read_watcher, on_client_readable);
|
368
338
|
ev_io_set(&client->read_watcher, client->fd, EV_READ | EV_ERROR);
|
369
339
|
ev_io_start(server->loop, &client->read_watcher);
|
370
340
|
|
@@ -373,6 +343,46 @@ void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
|
|
373
343
|
ev_timer_start(server->loop, &client->timeout_watcher);
|
374
344
|
}
|
375
345
|
|
346
|
+
static void on_request(struct ev_loop *loop, ev_io *watcher, int revents)
|
347
|
+
{
|
348
|
+
ebb_server *server = (ebb_server*)(watcher->data);
|
349
|
+
assert(server->open);
|
350
|
+
assert(server->loop == loop);
|
351
|
+
assert(&server->request_watcher == watcher);
|
352
|
+
|
353
|
+
if(EV_ERROR & revents) {
|
354
|
+
g_message("on_request() got error event, closing server.");
|
355
|
+
ebb_server_unlisten(server);
|
356
|
+
return;
|
357
|
+
}
|
358
|
+
/* Now we're going to initialize the client
|
359
|
+
* and set up her callbacks for read and write
|
360
|
+
* the client won't get passed back to the user, however,
|
361
|
+
* until the request is complete and parsed.
|
362
|
+
*/
|
363
|
+
int i;
|
364
|
+
ebb_client *client;
|
365
|
+
/* Get next availible peer */
|
366
|
+
for(i=0; i < EBB_MAX_CLIENTS; i++)
|
367
|
+
if(!server->clients[i].in_use && !server->clients[i].open) {
|
368
|
+
client = &(server->clients[i]);
|
369
|
+
break;
|
370
|
+
}
|
371
|
+
if(client == NULL) {
|
372
|
+
g_message("Too many peers. Refusing connections.");
|
373
|
+
return;
|
374
|
+
}
|
375
|
+
|
376
|
+
#ifdef DEBUG
|
377
|
+
int count = 0;
|
378
|
+
for(i = 0; i < EBB_MAX_CLIENTS; i++)
|
379
|
+
if(server->clients[i].open) count += 1;
|
380
|
+
g_debug("%d open connections", count);
|
381
|
+
#endif
|
382
|
+
|
383
|
+
client_init(server, client);
|
384
|
+
}
|
385
|
+
|
376
386
|
|
377
387
|
ebb_server* ebb_server_alloc()
|
378
388
|
{
|
@@ -388,8 +398,12 @@ void ebb_server_init( ebb_server *server
|
|
388
398
|
)
|
389
399
|
{
|
390
400
|
int i;
|
391
|
-
for(i=0; i < EBB_MAX_CLIENTS; i++)
|
401
|
+
for(i=0; i < EBB_MAX_CLIENTS; i++) {
|
402
|
+
server->clients[i].request_buffer = NULL;
|
392
403
|
server->clients[i].response_buffer = g_string_new("");
|
404
|
+
server->clients[i].open = FALSE;
|
405
|
+
server->clients[i].in_use = FALSE;
|
406
|
+
}
|
393
407
|
|
394
408
|
server->request_cb = request_cb;
|
395
409
|
server->request_cb_data = request_cb_data;
|
@@ -431,11 +445,51 @@ void ebb_server_unlisten(ebb_server *server)
|
|
431
445
|
}
|
432
446
|
}
|
433
447
|
|
434
|
-
|
435
|
-
void ebb_server_listen(ebb_server *server)
|
448
|
+
int ebb_server_listen_on_port(ebb_server *server, const int port)
|
436
449
|
{
|
437
|
-
int
|
438
|
-
|
450
|
+
int sfd = -1;
|
451
|
+
struct linger ling = {0, 0};
|
452
|
+
struct sockaddr_in addr;
|
453
|
+
int flags = 1;
|
454
|
+
|
455
|
+
if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
456
|
+
perror("socket()");
|
457
|
+
goto error;
|
458
|
+
}
|
459
|
+
|
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
|
+
flags = 1;
|
467
|
+
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
|
468
|
+
setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
|
469
|
+
setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
|
470
|
+
setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
|
471
|
+
|
472
|
+
/*
|
473
|
+
* the memset call clears nonstandard fields in some impementations
|
474
|
+
* that otherwise mess things up.
|
475
|
+
*/
|
476
|
+
memset(&addr, 0, sizeof(addr));
|
477
|
+
|
478
|
+
addr.sin_family = AF_INET;
|
479
|
+
addr.sin_port = htons(port);
|
480
|
+
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
481
|
+
|
482
|
+
if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
483
|
+
perror("bind()");
|
484
|
+
goto error;
|
485
|
+
}
|
486
|
+
if (listen(sfd, EBB_MAX_CLIENTS) < 0) {
|
487
|
+
perror("listen()");
|
488
|
+
goto error;
|
489
|
+
}
|
490
|
+
server->fd = sfd;
|
491
|
+
server->port = malloc(sizeof(char)*8); /* for easy access to the port */
|
492
|
+
sprintf(server->port, "%d", port);
|
439
493
|
assert(server->open == FALSE);
|
440
494
|
server->open = TRUE;
|
441
495
|
|
@@ -443,29 +497,31 @@ void ebb_server_listen(ebb_server *server)
|
|
443
497
|
ev_init (&server->request_watcher, on_request);
|
444
498
|
ev_io_set (&server->request_watcher, server->fd, EV_READ | EV_ERROR);
|
445
499
|
ev_io_start (server->loop, &server->request_watcher);
|
500
|
+
|
501
|
+
return server->fd;
|
502
|
+
error:
|
503
|
+
if(sfd > 0) close(sfd);
|
504
|
+
return -1;
|
446
505
|
}
|
447
506
|
|
448
507
|
|
449
|
-
int
|
508
|
+
int ebb_server_listen_on_socket(ebb_server *server, const char *socketpath)
|
450
509
|
{
|
451
|
-
int fd =
|
452
|
-
if(fd < 0) return 0;
|
453
|
-
server->
|
454
|
-
|
455
|
-
server
|
456
|
-
|
457
|
-
return fd;
|
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;
|
458
516
|
}
|
459
517
|
|
460
518
|
|
461
|
-
|
519
|
+
void ebb_client_release(ebb_client *client)
|
462
520
|
{
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
ebb_server_listen(server);
|
468
|
-
return fd;
|
521
|
+
assert(client->in_use);
|
522
|
+
client->in_use = FALSE;
|
523
|
+
if(client->written == client->response_buffer->len)
|
524
|
+
ebb_client_close(client);
|
469
525
|
}
|
470
526
|
|
471
527
|
|
@@ -494,13 +550,18 @@ void ebb_client_close(ebb_client *client)
|
|
494
550
|
}
|
495
551
|
|
496
552
|
|
497
|
-
void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
|
553
|
+
static void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
|
498
554
|
{
|
499
555
|
ebb_client *client = (ebb_client*)(watcher->data);
|
500
556
|
ssize_t sent;
|
501
557
|
|
558
|
+
assert(client->status_written);
|
559
|
+
assert(client->headers_written);
|
560
|
+
assert(client->began_transmission);
|
561
|
+
|
502
562
|
if(EV_ERROR & revents) {
|
503
563
|
g_message("on_client_writable() got error event, closing peer");
|
564
|
+
ebb_client_close(client);
|
504
565
|
return;
|
505
566
|
}
|
506
567
|
|
@@ -518,6 +579,9 @@ void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
|
|
518
579
|
#endif
|
519
580
|
ebb_client_close(client);
|
520
581
|
return;
|
582
|
+
} else if(sent == 0) {
|
583
|
+
g_message("Sent zero bytes? Closing connection");
|
584
|
+
ebb_client_close(client);
|
521
585
|
}
|
522
586
|
client->written += sent;
|
523
587
|
|
@@ -526,25 +590,32 @@ void on_client_writable(struct ev_loop *loop, ev_io *watcher, int revents)
|
|
526
590
|
|
527
591
|
ev_timer_again(loop, &(client->timeout_watcher));
|
528
592
|
|
529
|
-
if(client->written == client->response_buffer->len)
|
530
|
-
|
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
|
+
}
|
531
598
|
}
|
532
599
|
|
533
600
|
void ebb_client_write_status(ebb_client *client, int status, const char *human_status)
|
534
601
|
{
|
535
|
-
assert(client->
|
602
|
+
assert(client->in_use);
|
603
|
+
if(!client->open) return;
|
604
|
+
assert(client->status_written == FALSE);
|
536
605
|
g_string_append_printf( client->response_buffer
|
537
606
|
, "HTTP/1.1 %d %s\r\n"
|
538
607
|
, status
|
539
608
|
, human_status
|
540
609
|
);
|
541
|
-
client->
|
610
|
+
client->status_written = TRUE;
|
542
611
|
}
|
543
612
|
|
544
613
|
void ebb_client_write_header(ebb_client *client, const char *field, const char *value)
|
545
614
|
{
|
546
|
-
assert(client->
|
547
|
-
|
615
|
+
assert(client->in_use);
|
616
|
+
if(!client->open) return;
|
617
|
+
assert(client->status_written == TRUE);
|
618
|
+
assert(client->headers_written == FALSE);
|
548
619
|
g_string_append_printf( client->response_buffer
|
549
620
|
, "%s: %s\r\n"
|
550
621
|
, field
|
@@ -554,18 +625,23 @@ void ebb_client_write_header(ebb_client *client, const char *field, const char *
|
|
554
625
|
|
555
626
|
void ebb_client_write(ebb_client *client, const char *data, int length)
|
556
627
|
{
|
628
|
+
assert(client->in_use);
|
629
|
+
if(!client->open) return;
|
557
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
|
+
}
|
558
635
|
}
|
559
636
|
|
560
637
|
|
561
|
-
void
|
638
|
+
void ebb_client_begin_transmission(ebb_client *client)
|
562
639
|
{
|
563
|
-
assert(client->
|
564
|
-
|
640
|
+
assert(client->in_use);
|
641
|
+
if(!client->open) return;
|
642
|
+
assert(FALSE == ev_is_active(&client->write_watcher));
|
565
643
|
|
566
|
-
/* assure the socket is still in non-blocking mode
|
567
|
-
* in the ruby binding, for example, i change this flag
|
568
|
-
*/
|
644
|
+
/* assure the socket is still in non-blocking mode */
|
569
645
|
int flags = fcntl(client->fd, F_GETFL, 0);
|
570
646
|
if(0 > fcntl(client->fd, F_SETFL, flags | O_NONBLOCK)) {
|
571
647
|
perror("fcntl()");
|
@@ -573,11 +649,13 @@ void ebb_client_finished(ebb_client *client)
|
|
573
649
|
return;
|
574
650
|
}
|
575
651
|
|
652
|
+
client->headers_written = TRUE;
|
653
|
+
client->began_transmission = TRUE;
|
576
654
|
client->written = 0;
|
577
655
|
client->write_watcher.data = client;
|
578
656
|
ev_init (&(client->write_watcher), on_client_writable);
|
579
657
|
ev_io_set (&(client->write_watcher), client->fd, EV_WRITE | EV_ERROR);
|
580
|
-
ev_io_start(client->server->loop, &
|
658
|
+
ev_io_start(client->server->loop, &client->write_watcher);
|
581
659
|
}
|
582
660
|
|
583
661
|
|
@@ -589,7 +667,8 @@ int ebb_client_read(ebb_client *client, char *buffer, int length)
|
|
589
667
|
{
|
590
668
|
size_t read;
|
591
669
|
|
592
|
-
assert(client->
|
670
|
+
assert(client->in_use);
|
671
|
+
if(!client->open) return -1;
|
593
672
|
assert(client_finished_parsing);
|
594
673
|
|
595
674
|
if(client->upload_file) {
|
@@ -611,53 +690,6 @@ int ebb_client_read(ebb_client *client, char *buffer, int length)
|
|
611
690
|
|
612
691
|
/* The following socket creation routines are modified and stolen from memcached */
|
613
692
|
|
614
|
-
static int server_socket(const int port) {
|
615
|
-
int sfd;
|
616
|
-
struct linger ling = {0, 0};
|
617
|
-
struct sockaddr_in addr;
|
618
|
-
int flags =1;
|
619
|
-
|
620
|
-
if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
621
|
-
perror("socket()");
|
622
|
-
return -1;
|
623
|
-
}
|
624
|
-
|
625
|
-
if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
|
626
|
-
fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
627
|
-
perror("setting O_NONBLOCK");
|
628
|
-
close(sfd);
|
629
|
-
return -1;
|
630
|
-
}
|
631
|
-
|
632
|
-
flags = 1;
|
633
|
-
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
|
634
|
-
setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
|
635
|
-
setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
|
636
|
-
setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags));
|
637
|
-
|
638
|
-
/*
|
639
|
-
* the memset call clears nonstandard fields in some impementations
|
640
|
-
* that otherwise mess things up.
|
641
|
-
*/
|
642
|
-
memset(&addr, 0, sizeof(addr));
|
643
|
-
|
644
|
-
addr.sin_family = AF_INET;
|
645
|
-
addr.sin_port = htons(port);
|
646
|
-
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
647
|
-
|
648
|
-
if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
649
|
-
perror("bind()");
|
650
|
-
close(sfd);
|
651
|
-
return -1;
|
652
|
-
}
|
653
|
-
if (listen(sfd, EBB_MAX_CLIENTS) == -1) {
|
654
|
-
perror("listen()");
|
655
|
-
close(sfd);
|
656
|
-
return -1;
|
657
|
-
}
|
658
|
-
return sfd;
|
659
|
-
}
|
660
|
-
|
661
693
|
|
662
694
|
static int server_socket_unix(const char *path, int access_mask) {
|
663
695
|
int sfd;
|