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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/ext/agoo/agoo.c +4 -3
- data/ext/agoo/bind.c +275 -0
- data/ext/agoo/bind.h +35 -0
- data/ext/agoo/con.c +22 -25
- data/ext/agoo/debug.c +2 -0
- data/ext/agoo/debug.h +1 -0
- data/ext/agoo/error_stream.c +1 -0
- data/ext/agoo/hook.c +16 -6
- data/ext/agoo/hook.h +3 -1
- data/ext/agoo/http.c +7 -7
- data/ext/agoo/http.h +3 -1
- data/ext/agoo/log.h +1 -0
- data/ext/agoo/page.c +231 -104
- data/ext/agoo/page.h +10 -38
- data/ext/agoo/request.c +5 -1
- data/ext/agoo/request.h +1 -2
- data/ext/agoo/response.c +5 -1
- data/ext/agoo/rhook.c +2 -2
- data/ext/agoo/rhook.h +1 -1
- data/ext/agoo/rserver.c +991 -0
- data/ext/agoo/rserver.h +42 -0
- data/ext/agoo/server.c +95 -978
- data/ext/agoo/server.h +16 -27
- data/ext/agoo/upgraded.c +28 -20
- data/ext/agoo/websocket.c +4 -7
- data/lib/agoo/version.rb +1 -1
- data/test/bind_test.rb +134 -0
- data/test/named_client.rb +7 -0
- data/test/named_server.rb +13 -0
- metadata +12 -2
data/ext/agoo/server.h
CHANGED
@@ -7,50 +7,39 @@
|
|
7
7
|
#include <stdbool.h>
|
8
8
|
#include <stdatomic.h>
|
9
9
|
|
10
|
-
#include
|
11
|
-
|
12
|
-
#include "
|
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
|
48
|
-
|
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
|
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__
|
data/ext/agoo/upgraded.c
CHANGED
@@ -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
|
-
|
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(&
|
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(&
|
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(&
|
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(&
|
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(&
|
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(&
|
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 <
|
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(&
|
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(&
|
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(&
|
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(&
|
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(&
|
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(&
|
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(&
|
359
|
-
if (NULL ==
|
359
|
+
pthread_mutex_lock(&the_rserver.up_lock);
|
360
|
+
if (NULL == the_rserver.up_list) {
|
360
361
|
up->next = NULL;
|
361
362
|
} else {
|
362
|
-
|
363
|
+
the_rserver.up_list->prev = up;
|
363
364
|
}
|
364
|
-
up->next =
|
365
|
-
|
365
|
+
up->next = the_rserver.up_list;
|
366
|
+
the_rserver.up_list = up;
|
366
367
|
c->up = up;
|
367
|
-
pthread_mutex_unlock(&
|
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);
|
data/ext/agoo/websocket.c
CHANGED
@@ -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->
|
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->
|
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(&
|
204
|
+
queue_push(&the_rserver.eval_queue, (void*)req);
|
208
205
|
}
|
209
206
|
}
|
210
207
|
|
data/lib/agoo/version.rb
CHANGED
data/test/bind_test.rb
ADDED
@@ -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
|
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
|
+
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-
|
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
|