agoo 2.0.5 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of agoo might be problematic. Click here for more details.

@@ -15,9 +15,10 @@
15
15
 
16
16
  #define MAX_HEADER_SIZE 8192
17
17
 
18
- struct _CSlot;
18
+ struct _Upgraded;
19
19
 
20
20
  typedef struct _Con {
21
+ struct _Con *next;
21
22
  int sock;
22
23
  ConKind kind;
23
24
  struct pollfd *pp;
@@ -30,11 +31,12 @@ typedef struct _Con {
30
31
 
31
32
  double timeout;
32
33
  bool closing;
34
+ bool dead;
33
35
  Req req;
34
36
  Res res_head;
35
37
  Res res_tail;
36
38
 
37
- struct _CSlot *slot; // only set for push connections
39
+ struct _Upgraded *up; // only set for push connections
38
40
  } *Con;
39
41
 
40
42
  extern Con con_create(Err err, int sock, uint64_t id);
@@ -44,8 +44,10 @@ atomic_int mem_req = 0;
44
44
  atomic_int mem_res = 0;
45
45
  atomic_int mem_res_body = 0;
46
46
  atomic_int mem_response = 0;
47
+ atomic_int mem_subject = 0;
47
48
  atomic_int mem_text = 0;
48
49
  atomic_int mem_to_s = 0;
50
+ atomic_int mem_upgraded = 0;
49
51
 
50
52
  #ifdef MEM_DEBUG
51
53
  static void
@@ -39,8 +39,10 @@ extern atomic_int mem_req;
39
39
  extern atomic_int mem_res;
40
40
  extern atomic_int mem_res_body;
41
41
  extern atomic_int mem_response;
42
+ extern atomic_int mem_subject;
42
43
  extern atomic_int mem_text;
43
44
  extern atomic_int mem_to_s;
45
+ extern atomic_int mem_upgraded;
44
46
 
45
47
  extern void debug_add(void *ptr, const char *type, const char *file, int line);
46
48
  extern void debug_update(void *orig, void *ptr, const char *type, const char *file, int line);
@@ -353,6 +353,7 @@ update_contents(Cache cache, Page p) {
353
353
  if (NULL == (f = fopen(path, "rb"))) {
354
354
  return false;
355
355
  }
356
+ mime = "text/html";
356
357
  } else {
357
358
  return false;
358
359
  }
@@ -6,74 +6,79 @@
6
6
 
7
7
  #include "debug.h"
8
8
  #include "pub.h"
9
+ #include "subject.h"
9
10
  #include "text.h"
11
+ #include "upgraded.h"
10
12
 
11
13
  Pub
12
- pub_close(uint64_t cid) {
14
+ pub_close(Upgraded up) {
13
15
  Pub p = (Pub)malloc(sizeof(struct _Pub));
14
16
 
15
17
  if (NULL != p) {
16
18
  DEBUG_ALLOC(mem_pub, p);
17
19
  p->next = NULL;
18
20
  p->kind = PUB_CLOSE;
19
- p->cid = cid;
20
- p->sid = 0;
21
+ p->up = up;
21
22
  p->subject = NULL;
23
+ p->msg = NULL;
22
24
  }
23
25
  return p;
24
26
  }
25
27
 
26
28
  Pub
27
- pub_subscribe(uint64_t cid, uint64_t sid, const char *subject) {
29
+ pub_subscribe(Upgraded up, const char *subject, int slen) {
28
30
  Pub p = (Pub)malloc(sizeof(struct _Pub));
29
31
 
30
32
  if (NULL != p) {
31
33
  DEBUG_ALLOC(mem_pub, p);
32
34
  p->next = NULL;
33
35
  p->kind = PUB_SUB;
34
- p->cid = cid;
35
- p->sid = sid;
36
- p->subject = strdup(subject);
36
+ p->up = up;
37
+ p->subject = subject_create(subject, slen);
38
+ p->msg = NULL;
37
39
  }
38
40
  return p;
39
41
  }
40
42
 
41
43
  Pub
42
- pub_unsubscribe(uint64_t cid, uint64_t sid) {
44
+ pub_unsubscribe(Upgraded up, const char *subject, int slen) {
43
45
  Pub p = (Pub)malloc(sizeof(struct _Pub));
44
46
 
45
47
  if (NULL != p) {
46
48
  DEBUG_ALLOC(mem_pub, p);
47
49
  p->next = NULL;
48
50
  p->kind = PUB_UN;
49
- p->cid = cid;
50
- p->sid = sid;
51
- p->subject = NULL;
51
+ p->up = up;
52
+ if (NULL != subject) {
53
+ p->subject = subject_create(subject, slen);
54
+ } else {
55
+ p->subject = NULL;
56
+ }
57
+ p->msg = NULL;
52
58
  }
53
59
  return p;
54
60
  }
55
61
 
56
62
  Pub
57
- pub_publish(char *subject, const char *message, size_t mlen, bool bin) {
63
+ pub_publish(char *subject, int slen, const char *message, size_t mlen) {
58
64
  Pub p = (Pub)malloc(sizeof(struct _Pub));
59
65
 
60
66
  if (NULL != p) {
61
67
  DEBUG_ALLOC(mem_pub, p);
62
68
  p->next = NULL;
63
69
  p->kind = PUB_MSG;
64
- p->cid = 0;
65
- p->subject = strdup(subject);
70
+ p->up = NULL;
71
+ p->subject = subject_create(subject, slen);
66
72
  // Allocate an extra 24 bytes so the message can be expanded in place
67
73
  // if a WebSocket or SSE write.
68
- p->msg = text_allocate((int)mlen + 24);
69
- p->msg = text_append(text_allocate((int)mlen + 16), message, (int)mlen);
74
+ p->msg = text_append(text_allocate((int)mlen + 24), message, (int)mlen);
70
75
  text_ref(p->msg);
71
76
  }
72
77
  return p;
73
78
  }
74
79
 
75
80
  Pub
76
- pub_write(uint64_t cid, const char *message, size_t mlen, bool bin) {
81
+ pub_write(Upgraded up, const char *message, size_t mlen, bool bin) {
77
82
  // Allocate an extra 16 bytes so the message can be expanded in place if a
78
83
  // WebSocket write.
79
84
  Pub p = (Pub)malloc(sizeof(struct _Pub));
@@ -82,7 +87,7 @@ pub_write(uint64_t cid, const char *message, size_t mlen, bool bin) {
82
87
  DEBUG_ALLOC(mem_pub, p);
83
88
  p->next = NULL;
84
89
  p->kind = PUB_WRITE;
85
- p->cid = cid;
90
+ p->up = up;
86
91
  p->subject = NULL;
87
92
  // Allocate an extra 16 bytes so the message can be expanded in place
88
93
  // if a WebSocket write.
@@ -95,15 +100,14 @@ pub_write(uint64_t cid, const char *message, size_t mlen, bool bin) {
95
100
 
96
101
  void
97
102
  pub_destroy(Pub pub) {
98
- switch (pub->kind) {
99
- case PUB_MSG:
100
- case PUB_WRITE:
101
- if (NULL != pub->msg) {
102
- text_release(pub->msg);
103
- }
104
- break;
105
- default:
106
- break;
103
+ if (NULL != pub->msg) {
104
+ text_release(pub->msg);
105
+ }
106
+ if (NULL != pub->subject) {
107
+ subject_destroy(pub->subject);
108
+ }
109
+ if (NULL != pub->up) {
110
+ upgraded_release(pub->up);
107
111
  }
108
112
  DEBUG_FREE(mem_pub, pub);
109
113
  free(pub);
@@ -8,6 +8,8 @@
8
8
  #include <stdlib.h>
9
9
 
10
10
  struct _Text;
11
+ struct _Upgraded;
12
+ struct _Subject;
11
13
 
12
14
  typedef enum {
13
15
  PUB_SUB = 'S',
@@ -22,19 +24,16 @@ typedef enum {
22
24
  typedef struct _Pub {
23
25
  struct _Pub *next;
24
26
  PubKind kind;
25
- uint64_t cid;
26
- char *subject;
27
- union {
28
- uint64_t sid;
29
- struct _Text *msg;
30
- };
27
+ struct _Upgraded *up;
28
+ struct _Subject *subject;
29
+ struct _Text *msg;
31
30
  } *Pub;
32
31
 
33
- extern Pub pub_close(uint64_t cid);
34
- extern Pub pub_subscribe(uint64_t cid, uint64_t sid, const char *subject);
35
- extern Pub pub_unsubscribe(uint64_t cid, uint64_t sid);
36
- extern Pub pub_publish(char *subject, const char *message, size_t mlen, bool bin);
37
- extern Pub pub_write(uint64_t cid, const char *message, size_t mlen, bool bin);
32
+ extern Pub pub_close(struct _Upgraded *up);
33
+ extern Pub pub_subscribe(struct _Upgraded *up, const char *subject, int slen);
34
+ extern Pub pub_unsubscribe(struct _Upgraded *up, const char *subject, int slen);
35
+ extern Pub pub_publish(char *subject, int slen, const char *message, size_t mlen);
36
+ extern Pub pub_write(struct _Upgraded *up, const char *message, size_t mlen, bool bin);
38
37
  extern void pub_destroy(Pub pub);
39
38
 
40
39
  #endif // __AGOO_PUB_H__
@@ -383,8 +383,9 @@ add_header_value(VALUE hh, const char *key, int klen, const char *val, int vlen)
383
383
  } else if (sizeof(content_length) - 1 == klen && 0 == strncasecmp(key, content_length, sizeof(content_length) - 1)) {
384
384
  rb_hash_aset(hh, content_length_val, rb_str_new(val, vlen));
385
385
  } else {
386
- char hkey[1024];
387
- char *k = hkey;
386
+ char hkey[1024];
387
+ char *k = hkey;
388
+ volatile VALUE sval = rb_str_new(val, vlen);
388
389
 
389
390
  strcpy(hkey, "HTTP_");
390
391
  k = hkey + 5;
@@ -394,12 +395,12 @@ add_header_value(VALUE hh, const char *key, int klen, const char *val, int vlen)
394
395
  strncpy(k, key, klen);
395
396
  hkey[klen + 5] = '\0';
396
397
 
397
- rb_hash_aset(hh, rb_str_new(hkey, klen + 5), rb_str_new(val, vlen));
398
+ rb_hash_aset(hh, rb_str_new(hkey, klen + 5), sval);
398
399
  // Contrary to the Rack spec, Rails expects all upper case keys so add those as well.
399
400
  for (k = hkey + 5; '\0' != *k; k++) {
400
401
  *k = toupper(*k);
401
402
  }
402
- rb_hash_aset(hh, rb_str_new(hkey, klen + 5), rb_str_new(val, vlen));
403
+ rb_hash_aset(hh, rb_str_new(hkey, klen + 5), sval);
403
404
  }
404
405
  }
405
406
 
@@ -12,6 +12,7 @@
12
12
  #include "types.h"
13
13
 
14
14
  struct _Server;
15
+ struct _Upgraded;
15
16
 
16
17
  typedef enum {
17
18
  UP_NONE = '\0',
@@ -27,7 +28,7 @@ typedef struct _Str {
27
28
  typedef struct _Req {
28
29
  Method method;
29
30
  Upgrade upgrade;
30
- uint64_t cid;
31
+ struct _Upgraded *up;
31
32
  struct _Str path;
32
33
  struct _Str query;
33
34
  struct _Str header;
@@ -2,17 +2,19 @@
2
2
 
3
3
  #include <stdlib.h>
4
4
 
5
+ #include "con.h"
5
6
  #include "debug.h"
6
7
  #include "res.h"
7
8
 
8
9
  Res
9
- res_create() {
10
+ res_create(Con con) {
10
11
  Res res = (Res)malloc(sizeof(struct _Res));
11
12
 
12
13
  if (NULL != res) {
13
14
  DEBUG_ALLOC(mem_res, res)
14
15
  res->next = NULL;
15
16
  atomic_init(&res->message, NULL);
17
+ res->con = con;
16
18
  res->con_kind = CON_HTTP;
17
19
  res->close = false;
18
20
  res->ping = false;
@@ -11,8 +11,11 @@
11
11
  #include "text.h"
12
12
  #include "types.h"
13
13
 
14
+ struct _Con;
15
+
14
16
  typedef struct _Res {
15
17
  struct _Res *next;
18
+ struct _Con *con;
16
19
  _Atomic(Text) message;
17
20
  ConKind con_kind;
18
21
  bool close;
@@ -20,7 +23,7 @@ typedef struct _Res {
20
23
  bool pong;
21
24
  } *Res;
22
25
 
23
- extern Res res_create();
26
+ extern Res res_create(struct _Con *con);
24
27
  extern void res_destroy(Res res);
25
28
  extern void res_set_message(Res res, Text t);
26
29
 
@@ -25,6 +25,7 @@
25
25
  #include "dtime.h"
26
26
  #include "err.h"
27
27
  #include "http.h"
28
+ #include "pub.h"
28
29
  #include "response.h"
29
30
  #include "request.h"
30
31
  #include "server.h"
@@ -46,6 +47,8 @@ static VALUE post_sym;
46
47
  static VALUE push_env_key;
47
48
  static VALUE put_sym;
48
49
 
50
+ static VALUE rserver;
51
+
49
52
  static ID call_id;
50
53
  static ID each_id;
51
54
  static ID on_close_id;
@@ -58,6 +61,23 @@ static const char err500[] = "HTTP/1.1 500 Internal Server Error\r\n";
58
61
 
59
62
  struct _Server the_server = {false};
60
63
 
64
+ static void
65
+ server_mark(void *ptr) {
66
+ Upgraded up;
67
+
68
+ rb_gc_mark(rserver);
69
+ pthread_mutex_lock(&the_server.up_lock);
70
+ for (up = the_server.up_list; NULL != up; up = up->next) {
71
+ if (Qnil != up->handler) {
72
+ rb_gc_mark(up->handler);
73
+ }
74
+ if (Qnil != up->wrap) {
75
+ rb_gc_mark(up->wrap);
76
+ }
77
+ }
78
+ pthread_mutex_unlock(&the_server.up_lock);
79
+ }
80
+
61
81
  void
62
82
  server_shutdown() {
63
83
  if (the_server.inited) {
@@ -74,7 +94,6 @@ server_shutdown() {
74
94
  the_server.con_thread = 0;
75
95
  }
76
96
  sub_cleanup(&the_server.sub_cache);
77
- cc_cleanup(&the_server.con_cache);
78
97
  // The preferred method to of waiting for the ruby threads would
79
98
  // be either a join or even a kill but since we may not have the
80
99
  // gvl here that would cause a segfault. Instead we set a timeout
@@ -89,7 +108,7 @@ server_shutdown() {
89
108
  dsleep(0.02);
90
109
  }
91
110
  DEBUG_FREE(mem_eval_threads, the_server.eval_threads);
92
- free(the_server.eval_threads); // TBD use regular malloc and free
111
+ free(the_server.eval_threads);
93
112
  the_server.eval_threads = NULL;
94
113
  }
95
114
  while (NULL != the_server.hooks) {
@@ -217,8 +236,10 @@ rserver_init(int argc, VALUE *argv, VALUE self) {
217
236
  queue_multi_init(&the_server.eval_queue, 1024, false, true);
218
237
 
219
238
  cache_init(&the_server.pages);
220
- cc_init(&the_server.con_cache);
221
239
  sub_init(&the_server.sub_cache);
240
+
241
+ pthread_mutex_init(&the_server.up_lock, 0);
242
+ the_server.up_list = NULL;
222
243
 
223
244
  the_server.inited = true;
224
245
 
@@ -320,21 +341,25 @@ rescue_error(VALUE x) {
320
341
  volatile VALUE msg = rb_funcall(info, rb_intern("message"), 0);
321
342
  const char *classname = rb_obj_classname(info);
322
343
  const char *ms = rb_string_value_ptr(&msg);
323
- char buf[1024];
324
- int len = (int)(strlen(classname) + 2 + strlen(ms));
325
- int cnt;
326
- Text message;
327
344
 
328
- if ((int)(sizeof(buf) - sizeof(bad500) + 7) <= len) {
329
- len = sizeof(buf) - sizeof(bad500) + 7;
330
- }
331
- cnt = snprintf(buf, sizeof(buf), "%s%d\r\n\r\n%s: %s", bad500, len, classname, ms);
332
- message = text_create(buf, cnt);
345
+ if (NULL == req->up) {
346
+ char buf[1024];
347
+ int len = (int)(strlen(classname) + 2 + strlen(ms));
348
+ int cnt;
349
+ Text message;
333
350
 
334
- req->res->close = true;
335
- res_set_message(req->res, message);
336
- queue_wakeup(&the_server.con_queue);
351
+ if ((int)(sizeof(buf) - sizeof(bad500) + 7) <= len) {
352
+ len = sizeof(buf) - sizeof(bad500) + 7;
353
+ }
354
+ cnt = snprintf(buf, sizeof(buf), "%s%d\r\n\r\n%s: %s", bad500, len, classname, ms);
355
+ message = text_create(buf, cnt);
337
356
 
357
+ req->res->close = true;
358
+ res_set_message(req->res, message);
359
+ queue_wakeup(&the_server.con_queue);
360
+ } else {
361
+ log_cat(&error_cat, "%s: %s", classname, ms);
362
+ }
338
363
  return Qfalse;
339
364
  }
340
365
 
@@ -495,7 +520,7 @@ handle_rack_inner(void *x) {
495
520
  break;
496
521
  }
497
522
  req->handler_type = PUSH_HOOK;
498
- upgraded_extend(req->cid, req->handler);
523
+ upgraded_create(req->res->con, req->handler);
499
524
  t->len = snprintf(t->text, 1024, "HTTP/1.1 101 %s\r\n", status_msg);
500
525
  t = ws_add_headers(req, t);
501
526
  break;
@@ -507,7 +532,7 @@ handle_rack_inner(void *x) {
507
532
  break;
508
533
  }
509
534
  req->handler_type = PUSH_HOOK;
510
- upgraded_extend(req->cid, req->handler);
535
+ upgraded_create(req->res->con, req->handler);
511
536
  t = sse_upgrade(req, t);
512
537
  res_set_message(req->res, t);
513
538
  queue_wakeup(&the_server.con_queue);
@@ -548,9 +573,6 @@ handle_rack_inner(void *x) {
548
573
 
549
574
  static void*
550
575
  handle_rack(void *x) {
551
- // Disable GC. The handle_rack function or rather the env seems to get
552
- // collected even though it is volatile so for now turn off GC
553
- // temporarily.
554
576
  //rb_gc_disable();
555
577
  rb_rescue2(handle_rack_inner, (VALUE)x, rescue_error, (VALUE)x, rb_eException, 0);
556
578
  //rb_gc_enable();
@@ -587,27 +609,31 @@ handle_push_inner(void *x) {
587
609
 
588
610
  switch (req->method) {
589
611
  case ON_MSG:
590
- rb_funcall(req->handler, on_message_id, 1, rb_str_new(req->msg, req->mlen));
612
+ rb_funcall(req->handler, on_message_id, 2, req->up->wrap, rb_str_new(req->msg, req->mlen));
591
613
  break;
592
614
  case ON_BIN: {
593
615
  volatile VALUE rstr = rb_str_new(req->msg, req->mlen);
594
616
 
595
617
  rb_enc_associate(rstr, rb_ascii8bit_encoding());
596
- rb_funcall(req->handler, on_message_id, 1, rstr);
618
+ rb_funcall(req->handler, on_message_id, 2, req->up->wrap, rstr);
597
619
  break;
598
620
  }
599
621
  case ON_CLOSE:
600
- rb_funcall(req->handler, on_close_id, 0);
622
+ upgraded_ref(req->up);
623
+ queue_push(&the_server.pub_queue, pub_close(req->up));
624
+ rb_funcall(req->handler, on_close_id, 1, req->up->wrap);
601
625
  break;
602
626
  case ON_SHUTDOWN:
603
- rb_funcall(req->handler, rb_intern("on_shutdown"), 0);
627
+ rb_funcall(req->handler, rb_intern("on_shutdown"), 1, req->up->wrap);
604
628
  break;
605
629
  case ON_EMPTY:
606
- rb_funcall(req->handler, on_drained_id, 0);
630
+ rb_funcall(req->handler, on_drained_id, 1, req->up->wrap);
607
631
  break;
608
632
  default:
609
633
  break;
610
634
  }
635
+ upgraded_release(req->up);
636
+
611
637
  return Qfalse;
612
638
  }
613
639
 
@@ -652,7 +678,7 @@ handle_protected(Req req, bool gvi) {
652
678
  char buf[256];
653
679
  int cnt = snprintf(buf, sizeof(buf), "HTTP/1.1 500 Internal Error\r\nConnection: Close\r\nContent-Length: 0\r\n\r\n");
654
680
  Text message = text_create(buf, cnt);
655
-
681
+
656
682
  req->res->close = true;
657
683
  res_set_message(req->res, message);
658
684
  queue_wakeup(&the_server.con_queue);
@@ -881,5 +907,8 @@ server_init(VALUE mod) {
881
907
 
882
908
  push_env_key = rb_str_new_cstr("rack.upgrade"); rb_gc_register_address(&push_env_key);
883
909
 
910
+ rserver = Data_Wrap_Struct(rb_cObject, server_mark, NULL, strdup("dummy"));
911
+ rb_gc_register_address(&rserver);
912
+
884
913
  http_init();
885
914
  }