agoo 2.4.0 → 2.5.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.

Potentially problematic release.


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

@@ -7,50 +7,39 @@
7
7
  #include <stdbool.h>
8
8
  #include <stdatomic.h>
9
9
 
10
- #include <ruby.h>
11
-
12
- #include "rhook.h"
13
- #include "log.h"
14
- #include "page.h"
10
+ #include "bind.h"
11
+ #include "err.h"
12
+ #include "hook.h"
15
13
  #include "queue.h"
16
- #include "sub.h"
17
- #include "upgraded.h"
18
-
19
- #define MAX_WORKERS 32
20
14
 
21
15
  typedef struct _Server {
22
16
  volatile bool inited;
23
17
  volatile bool active;
24
18
  int thread_cnt;
25
- int worker_cnt;
26
- int max_push_pending;
27
- int port;
28
- int fd;
29
19
  bool pedantic;
30
20
  bool root_first;
31
- atomic_int running;
32
21
  pthread_t listen_thread;
33
22
  pthread_t con_thread;
34
-
35
- pthread_mutex_t up_lock;
36
- Upgraded up_list;
37
-
38
23
  struct _Queue con_queue;
39
- struct _Queue pub_queue;
40
- struct _Cache pages;
41
- struct _SubCache sub_cache; // subscription cache
42
-
43
24
  Hook hooks;
44
25
  Hook hook404;
45
- struct _Queue eval_queue;
46
26
 
47
- int worker_pids[MAX_WORKERS];
48
- VALUE *eval_threads; // Qnil terminated
27
+ //int port; // TBD remove
28
+ //int fd; // TBD remove
29
+ Bind binds;
30
+
31
+ // A count of the running threads from the wrapper or the server managed
32
+ // threads.
33
+ atomic_int running;
49
34
  } *Server;
50
35
 
51
36
  extern struct _Server the_server;
52
37
 
53
- extern void server_init(VALUE mod);
54
- extern void server_shutdown();
38
+ extern void server_setup();
39
+ extern void server_shutdown(const char *app_name, void (*stop)());
40
+ extern void server_bind(Bind b);
41
+
42
+ extern int setup_listen(Err err);
43
+ extern int server_start(Err err, const char *app_name, const char *version);
55
44
 
56
45
  #endif // __AGOO_SERVER_H__
@@ -7,6 +7,7 @@
7
7
  #include "con.h"
8
8
  #include "debug.h"
9
9
  #include "pub.h"
10
+ #include "rserver.h"
10
11
  #include "server.h"
11
12
  #include "subject.h"
12
13
  #include "upgraded.h"
@@ -28,7 +29,7 @@ destroy(Upgraded up) {
28
29
  up->wrap = Qnil;
29
30
  }
30
31
  if (NULL == up->prev) {
31
- the_server.up_list = up->next;
32
+ the_rserver.up_list = up->next;
32
33
  if (NULL != up->next) {
33
34
  up->next->prev = NULL;
34
35
  }
@@ -70,21 +71,21 @@ extract_subject(VALUE subject, int *slen) {
70
71
 
71
72
  void
72
73
  upgraded_release(Upgraded up) {
73
- pthread_mutex_lock(&the_server.up_lock);
74
+ pthread_mutex_lock(&the_rserver.up_lock);
74
75
  if (atomic_fetch_sub(&up->ref_cnt, 1) <= 1) {
75
76
  destroy(up);
76
77
  }
77
- pthread_mutex_unlock(&the_server.up_lock);
78
+ pthread_mutex_unlock(&the_rserver.up_lock);
78
79
  }
79
80
 
80
81
  void
81
82
  upgraded_release_con(Upgraded up) {
82
- pthread_mutex_lock(&the_server.up_lock);
83
+ pthread_mutex_lock(&the_rserver.up_lock);
83
84
  up->con = NULL;
84
85
  if (atomic_fetch_sub(&up->ref_cnt, 1) <= 1) {
85
86
  destroy(up);
86
87
  }
87
- pthread_mutex_unlock(&the_server.up_lock);
88
+ pthread_mutex_unlock(&the_rserver.up_lock);
88
89
  }
89
90
 
90
91
  // Called from the con_loop thread, no need to lock, this steals the subject
@@ -151,11 +152,11 @@ get_upgraded(VALUE self) {
151
152
  Upgraded up = NULL;
152
153
 
153
154
  if (the_server.active) {
154
- pthread_mutex_lock(&the_server.up_lock);
155
+ pthread_mutex_lock(&the_rserver.up_lock);
155
156
  if (NULL != (up = DATA_PTR(self))) {
156
157
  atomic_fetch_add(&up->ref_cnt, 1);
157
158
  }
158
- pthread_mutex_unlock(&the_server.up_lock);
159
+ pthread_mutex_unlock(&the_rserver.up_lock);
159
160
  }
160
161
  return up;
161
162
  }
@@ -176,7 +177,7 @@ up_write(VALUE self, VALUE msg) {
176
177
  if (NULL == up) {
177
178
  return Qfalse;
178
179
  }
179
- if (0 < the_server.max_push_pending && the_server.max_push_pending <= atomic_load(&up->pending)) {
180
+ if (0 < the_rserver.max_push_pending && the_rserver.max_push_pending <= atomic_load(&up->pending)) {
180
181
  atomic_fetch_sub(&up->ref_cnt, 1);
181
182
  // Too many pending messages.
182
183
  return Qfalse;
@@ -193,7 +194,7 @@ up_write(VALUE self, VALUE msg) {
193
194
  p = pub_write(up, StringValuePtr(rs), RSTRING_LEN(rs), false);
194
195
  }
195
196
  atomic_fetch_add(&up->pending, 1);
196
- queue_push(&the_server.pub_queue, p);
197
+ queue_push(&the_rserver.pub_queue, p);
197
198
 
198
199
  return Qtrue;
199
200
  }
@@ -217,7 +218,7 @@ up_subscribe(VALUE self, VALUE subject) {
217
218
 
218
219
  if (NULL != (up = get_upgraded(self))) {
219
220
  atomic_fetch_add(&up->pending, 1);
220
- queue_push(&the_server.pub_queue, pub_subscribe(up, subj, slen));
221
+ queue_push(&the_rserver.pub_queue, pub_subscribe(up, subj, slen));
221
222
  }
222
223
  return Qnil;
223
224
  }
@@ -242,7 +243,7 @@ up_unsubscribe(int argc, VALUE *argv, VALUE self) {
242
243
  }
243
244
  if (NULL != (up = get_upgraded(self))) {
244
245
  atomic_fetch_add(&up->pending, 1);
245
- queue_push(&the_server.pub_queue, pub_unsubscribe(up, subject, slen));
246
+ queue_push(&the_rserver.pub_queue, pub_unsubscribe(up, subject, slen));
246
247
  }
247
248
  return Qnil;
248
249
  }
@@ -259,7 +260,7 @@ up_close(VALUE self) {
259
260
 
260
261
  if (NULL != up) {
261
262
  atomic_fetch_add(&up->pending, 1);
262
- queue_push(&the_server.pub_queue, pub_close(up));
263
+ queue_push(&the_rserver.pub_queue, pub_close(up));
263
264
  }
264
265
  return Qnil;
265
266
  }
@@ -315,7 +316,7 @@ protocol(VALUE self) {
315
316
  if (the_server.active) {
316
317
  Upgraded up;
317
318
 
318
- pthread_mutex_lock(&the_server.up_lock);
319
+ pthread_mutex_lock(&the_rserver.up_lock);
319
320
  if (NULL != (up = DATA_PTR(self)) && NULL != up->con) {
320
321
  switch (up->con->kind) {
321
322
  case CON_WS:
@@ -328,7 +329,7 @@ protocol(VALUE self) {
328
329
  break;
329
330
  }
330
331
  }
331
- pthread_mutex_unlock(&the_server.up_lock);
332
+ pthread_mutex_unlock(&the_rserver.up_lock);
332
333
  }
333
334
  return pro;
334
335
  }
@@ -355,16 +356,16 @@ upgraded_create(Con c, VALUE obj, VALUE env) {
355
356
  up->wrap = Data_Wrap_Struct(upgraded_class, NULL, NULL, up);
356
357
  up->subjects = NULL;
357
358
  up->prev = NULL;
358
- pthread_mutex_lock(&the_server.up_lock);
359
- if (NULL == the_server.up_list) {
359
+ pthread_mutex_lock(&the_rserver.up_lock);
360
+ if (NULL == the_rserver.up_list) {
360
361
  up->next = NULL;
361
362
  } else {
362
- the_server.up_list->prev = up;
363
+ the_rserver.up_list->prev = up;
363
364
  }
364
- up->next = the_server.up_list;
365
- the_server.up_list = up;
365
+ up->next = the_rserver.up_list;
366
+ the_rserver.up_list = up;
366
367
  c->up = up;
367
- pthread_mutex_unlock(&the_server.up_lock);
368
+ pthread_mutex_unlock(&the_rserver.up_lock);
368
369
 
369
370
  if (rb_respond_to(obj, on_open_id)) {
370
371
  rb_funcall(obj, on_open_id, 1, up->wrap);
@@ -376,6 +377,13 @@ upgraded_create(Con c, VALUE obj, VALUE env) {
376
377
  // Use the publish from the Agoo module.
377
378
  extern VALUE ragoo_publish(VALUE self, VALUE subject, VALUE message);
378
379
 
380
+ /* Document-method: env
381
+ *
382
+ * call-seq: env()
383
+ *
384
+ * Returns the environment passed to the call method that initiated the
385
+ * Upgraded Object creation.
386
+ */
379
387
  static VALUE
380
388
  env(VALUE self) {
381
389
  Upgraded up = get_upgraded(self);
@@ -6,6 +6,7 @@
6
6
  #include "con.h"
7
7
  #include "debug.h"
8
8
  #include "request.h"
9
+ #include "rserver.h"
9
10
  #include "sha1.h"
10
11
  #include "text.h"
11
12
  #include "websocket.h"
@@ -185,11 +186,8 @@ ws_create_req(Con c, long mlen) {
185
186
  c->req->upgrade = UP_NONE;
186
187
  c->req->up = c->up;
187
188
  c->req->res = NULL;
188
- c->req->handler_type = PUSH_HOOK;
189
189
  if (c->up->on_msg) {
190
- c->req->handler = c->up->handler;
191
- } else {
192
- c->req->handler = Qnil;
190
+ c->req->hook = hook_create(NONE, NULL, (void*)c->up->handler, PUSH_HOOK, &the_rserver.eval_queue);
193
191
  }
194
192
  return false;
195
193
  }
@@ -201,10 +199,9 @@ ws_req_close(Con c) {
201
199
 
202
200
  req->up = c->up;
203
201
  req->method = ON_CLOSE;
204
- req->handler_type = PUSH_HOOK;
205
- req->handler = c->up->handler;
202
+ req->hook = hook_create(NONE, NULL, (void*)c->up->handler, PUSH_HOOK, &the_rserver.eval_queue);
206
203
  atomic_fetch_add(&c->up->ref_cnt, 1);
207
- queue_push(&the_server.eval_queue, (void*)req);
204
+ queue_push(&the_rserver.eval_queue, (void*)req);
208
205
  }
209
206
  }
210
207
 
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Agoo
3
3
  # Agoo version.
4
- VERSION = '2.4.0'
4
+ VERSION = '2.5.0'
5
5
  end
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.dirname(__FILE__)
4
+ $root_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
5
+ %w(lib ext).each do |dir|
6
+ $: << File.join($root_dir, dir)
7
+ end
8
+
9
+ require 'minitest'
10
+ require 'minitest/autorun'
11
+ require 'net/http'
12
+ require 'socket'
13
+
14
+ require 'agoo'
15
+
16
+ class BindTest < Minitest::Test
17
+
18
+ # Run all the tests in one test to avoid creating the server multiple times.
19
+ def test_static
20
+ begin
21
+ Agoo::Log.configure(dir: '',
22
+ console: true,
23
+ classic: true,
24
+ colorize: true,
25
+ states: {
26
+ INFO: false,
27
+ DEBUG: false,
28
+ connect: false,
29
+ request: false,
30
+ response: false,
31
+ eval: true,
32
+ })
33
+
34
+ addr = ''
35
+ Socket.ip_address_list.each { |ai|
36
+ if ai.ipv4? && '127.0.0.1' != ai.ip_address
37
+ addr = ai.ip_address
38
+ break
39
+ end
40
+ }
41
+ addr6 = '::1'
42
+ name = '/tmp/agoo_test.socket'
43
+ Agoo::Server.init(6471, 'root', thread_count: 1,
44
+ bind: ['http://127.0.0.1:6472',
45
+ "http://#{addr}:6473",
46
+ "http://[#{addr6}]:6474",
47
+ "unix://#{name}",
48
+ ])
49
+ Agoo::Server.start()
50
+
51
+ port_test
52
+ localhost_test
53
+ ipv4_test(addr)
54
+ ipv6_test(addr6)
55
+ restrict_test
56
+ named_test(name)
57
+ ensure
58
+ Agoo::shutdown
59
+ end
60
+ end
61
+
62
+ def port_test
63
+ uri = URI('http://localhost:6471/index.html')
64
+ request(uri)
65
+ end
66
+
67
+ def localhost_test
68
+ uri = URI('http://localhost:6472/index.html')
69
+ request(uri)
70
+ end
71
+
72
+ def ipv4_test(addr)
73
+ uri = URI("http://#{addr}:6473/index.html")
74
+ request(uri)
75
+ end
76
+
77
+ def ipv6_test(addr)
78
+ uri = URI("http://[#{addr}]:6474/index.html")
79
+ request(uri)
80
+ end
81
+
82
+ def restrict_test
83
+ uri = URI("http://127.0.0.1:6473/index.html")
84
+ assert_raises Exception do
85
+ Net::HTTP.get(uri)
86
+ end
87
+ end
88
+
89
+ def named_test(name)
90
+ content = ''
91
+ UNIXSocket.open(name) {|c|
92
+ c.print(%|GET /index.html HTTP/1.1\r
93
+ Accept-Encoding: *\r
94
+ Accept: */*\r
95
+ User-Agent: Ruby\r
96
+ \r
97
+ |)
98
+ rcnt = 0
99
+ c.each_line { |line|
100
+ rcnt = line.split(':')[1].to_i if line.start_with?("Content-Length: ")
101
+ break if line.length <= 2 # \r\n
102
+ }
103
+ if 0 < rcnt
104
+ content = c.read(rcnt)
105
+ end
106
+ }
107
+ expect = %|<!DOCTYPE html>
108
+ <html>
109
+ <head><title>Agoo Test</title></head>
110
+ <body>Agoo</body>
111
+ </html>
112
+ |
113
+ assert_equal(expect, content)
114
+ end
115
+
116
+ def request(uri)
117
+ expect = %|<!DOCTYPE html>
118
+ <html>
119
+ <head><title>Agoo Test</title></head>
120
+ <body>Agoo</body>
121
+ </html>
122
+ |
123
+ req = Net::HTTP::Get.new(uri)
124
+ req['Accept-Encoding'] = '*'
125
+ req['User-Agent'] = 'Ruby'
126
+ res = Net::HTTP.start(uri.hostname, uri.port) { |h|
127
+ h.request(req)
128
+ }
129
+ content = res.body
130
+ assert_equal('text/html', res['Content-Type'])
131
+ assert_equal(expect, content)
132
+ end
133
+
134
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'socket'
4
+
5
+ UNIXSocket.open("/tmp/sockme") {|c|
6
+ p c.read #=> "hi\n"
7
+ }
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'socket'
4
+
5
+ serv = UNIXServer.new("/tmp/sockme")
6
+ begin
7
+ sock = serv.accept_nonblock
8
+ sock.puts "hello"
9
+ sock.flush()
10
+ rescue IO::WaitReadable, Errno::EINTR
11
+ IO.select([serv])
12
+ retry
13
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: agoo
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-04 00:00:00.000000000 Z
11
+ date: 2018-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -48,6 +48,8 @@ files:
48
48
  - ext/agoo/agoo.c
49
49
  - ext/agoo/base64.c
50
50
  - ext/agoo/base64.h
51
+ - ext/agoo/bind.c
52
+ - ext/agoo/bind.h
51
53
  - ext/agoo/con.c
52
54
  - ext/agoo/con.h
53
55
  - ext/agoo/debug.c
@@ -85,6 +87,8 @@ files:
85
87
  - ext/agoo/rhook.h
86
88
  - ext/agoo/rlog.c
87
89
  - ext/agoo/rlog.h
90
+ - ext/agoo/rserver.c
91
+ - ext/agoo/rserver.h
88
92
  - ext/agoo/seg.h
89
93
  - ext/agoo/server.c
90
94
  - ext/agoo/server.h
@@ -107,8 +111,11 @@ files:
107
111
  - lib/agoo/version.rb
108
112
  - lib/rack/handler/agoo.rb
109
113
  - test/base_handler_test.rb
114
+ - test/bind_test.rb
110
115
  - test/hijack_test.rb
111
116
  - test/log_test.rb
117
+ - test/named_client.rb
118
+ - test/named_server.rb
112
119
  - test/rack_handler_test.rb
113
120
  - test/static_test.rb
114
121
  homepage: https://github.com/ohler55/agoo
@@ -147,8 +154,11 @@ signing_key:
147
154
  specification_version: 4
148
155
  summary: An HTTP server
149
156
  test_files:
157
+ - test/named_client.rb
150
158
  - test/log_test.rb
151
159
  - test/rack_handler_test.rb
152
160
  - test/hijack_test.rb
161
+ - test/named_server.rb
153
162
  - test/base_handler_test.rb
154
163
  - test/static_test.rb
164
+ - test/bind_test.rb