opal-up 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -3
- data/ext/up_ext/up_ext.c +65 -19
- data/lib/up/bun/server.rb +17 -0
- data/lib/up/cli.rb +6 -3
- data/lib/up/client.rb +2 -3
- data/lib/up/ruby/cluster.rb +1 -0
- data/lib/up/u_web_socket/cluster.rb +22 -2
- data/lib/up/u_web_socket/server.rb +19 -2
- data/lib/up/version.rb +1 -1
- metadata +4 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e47b86e6f54cbdb8ecf23cf5b6c759127ac30a8f4f00764e39eeca57ca94e52d
|
4
|
+
data.tar.gz: 6d93f3b96474fb1c18fadeb5a46083241947691470a0c3f7d36dc7025e1116de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25d3c86c354d50656b266995a0d235460e6d9c45b1853d33d363636e1bead3b4539b8a068fee0cbfd58b27d2160759b2f1823ae039c2ce0c15793f6a95fd0541
|
7
|
+
data.tar.gz: d3a6dd3a8e854a1ba75cfc297ecb5b4153c04b3814185add67424bcfd7574538d4365aebbd1006967e798d7af155ad0b98582955eb4f8c2e1f5633448d474433
|
data/README.md
CHANGED
@@ -84,15 +84,16 @@ Available with `bundle exec` within the example apps or if this gem is included
|
|
84
84
|
Usage: up [options]
|
85
85
|
|
86
86
|
-h, --help Show this message
|
87
|
-
-p, --port PORT Port number the server will listen to
|
88
|
-
-b, --bind ADDRESS Address the server will listen to
|
87
|
+
-p, --port PORT Port number the server will listen to. Default: 3000
|
88
|
+
-b, --bind ADDRESS Address the server will listen to. Default: localhost
|
89
89
|
-s, --secure Use secure sockets.
|
90
90
|
When using secure sockets, the -a, -c and -k options must be provided
|
91
91
|
-a, --ca-file FILE File with CA certs
|
92
92
|
-c, --cert-file FILE File with the servers certificate
|
93
93
|
-k, --key-file FILE File with the servers certificate
|
94
|
+
-l, --log-file FILE Log file
|
94
95
|
-v, --version Show version
|
95
|
-
|
96
|
+
-w, --workers NUMBER For clusters, the number of workers to run. Default: number of processors
|
96
97
|
```
|
97
98
|
## Supported Features
|
98
99
|
|
data/ext/up_ext/up_ext.c
CHANGED
@@ -22,7 +22,9 @@ static VALUE cLogger;
|
|
22
22
|
|
23
23
|
static ID at_env;
|
24
24
|
static ID at_handler;
|
25
|
+
static ID at_instance;
|
25
26
|
static ID at_member_id;
|
27
|
+
static ID at_members;
|
26
28
|
static ID at_open;
|
27
29
|
static ID at_protocol;
|
28
30
|
static ID at_secret;
|
@@ -40,6 +42,7 @@ static ID id_on_drained;
|
|
40
42
|
static ID id_on_message;
|
41
43
|
static ID id_on_open;
|
42
44
|
static ID id_port;
|
45
|
+
static ID id_publish;
|
43
46
|
|
44
47
|
static rb_encoding *utf8_encoding;
|
45
48
|
static rb_encoding *binary_encoding;
|
@@ -411,14 +414,14 @@ static VALUE up_client_pending(VALUE self) {
|
|
411
414
|
return INT2FIX(0);
|
412
415
|
}
|
413
416
|
|
414
|
-
static void up_client_cluster_publish(
|
417
|
+
static void up_client_cluster_publish(char *scrt, int st, VALUE channel,
|
415
418
|
VALUE message) {
|
416
419
|
const char *opening_line = "POST " INTERNAL_PUBLISH_PATH " HTTP/1.1\r\n";
|
417
420
|
const char *host_header = "Host: localhost\r\n";
|
418
421
|
const char *secret = "Secret: ";
|
419
422
|
char secret_header[50];
|
420
423
|
memcpy(secret_header, secret, 8);
|
421
|
-
memcpy(secret_header + 8,
|
424
|
+
memcpy(secret_header + 8, scrt, 36);
|
422
425
|
memcpy(secret_header + 8 + 36, "\r\n", 2);
|
423
426
|
const char *content_type = "Content-Type: text/plain\r\n";
|
424
427
|
long c_length = RSTRING_LEN(channel) + RSTRING_LEN(message) + 2;
|
@@ -447,12 +450,25 @@ static void up_client_cluster_publish(server_s *s, int st, VALUE channel,
|
|
447
450
|
// fprintf(stderr, "read: %s\n", read_buf);
|
448
451
|
}
|
449
452
|
|
450
|
-
static
|
453
|
+
static void up_internal_publish_to_member(server_s *s, VALUE channel,
|
454
|
+
VALUE message, int member_idx) {
|
455
|
+
struct sockaddr_in member_addr = {.sin_addr.s_addr = inet_addr("127.0.0.1"),
|
456
|
+
.sin_family = AF_INET};
|
457
|
+
int st = socket(AF_INET, SOCK_STREAM, 0);
|
458
|
+
if (st) {
|
459
|
+
member_addr.sin_port = htons(FIX2INT(s->port) + member_idx);
|
460
|
+
if (connect(st, (struct sockaddr *)&member_addr,
|
461
|
+
sizeof(struct sockaddr_in)) == 0) {
|
462
|
+
up_client_cluster_publish(s->secret, st, channel, message);
|
463
|
+
close(st);
|
464
|
+
}
|
465
|
+
}
|
466
|
+
}
|
467
|
+
|
468
|
+
static VALUE up_client_publish(VALUE self, VALUE channel, VALUE message) {
|
451
469
|
uws_websocket_t *ws = DATA_PTR(self);
|
452
470
|
if (!ws)
|
453
471
|
return Qnil;
|
454
|
-
VALUE channel, message, engine;
|
455
|
-
rb_scan_args(argc, argv, "21", &channel, &message, &engine);
|
456
472
|
if (TYPE(channel) != T_STRING)
|
457
473
|
channel = rb_obj_as_string(channel);
|
458
474
|
if (TYPE(message) != T_STRING)
|
@@ -467,20 +483,9 @@ static VALUE up_client_publish(int argc, VALUE *argv, VALUE self) {
|
|
467
483
|
|
468
484
|
// publish to cluster members
|
469
485
|
int i;
|
470
|
-
struct sockaddr_in member_addr = {
|
471
|
-
.sin_addr.s_addr = inet_addr("127.0.0.1"), .sin_family = AF_INET};
|
472
486
|
for (i = 1; i <= s->workers; i++) {
|
473
|
-
if (i != s->member_id)
|
474
|
-
|
475
|
-
if (st) {
|
476
|
-
member_addr.sin_port = htons(FIX2INT(s->port) + i);
|
477
|
-
if (connect(st, (struct sockaddr *)&member_addr,
|
478
|
-
sizeof(struct sockaddr_in)) == 0) {
|
479
|
-
up_client_cluster_publish(s, st, channel, message);
|
480
|
-
close(st);
|
481
|
-
}
|
482
|
-
}
|
483
|
-
}
|
487
|
+
if (i != s->member_id)
|
488
|
+
up_internal_publish_to_member(s, channel, message, i);
|
484
489
|
}
|
485
490
|
}
|
486
491
|
return res ? Qtrue : Qfalse;
|
@@ -747,6 +752,7 @@ static void up_internal_close_sockets(int signal) {
|
|
747
752
|
static VALUE up_server_listen(VALUE self) {
|
748
753
|
server_s *s = DATA_PTR(self);
|
749
754
|
up_internal_check_arg_types(s->rapp, &s->host, &s->port);
|
755
|
+
rb_ivar_set(mUp, at_instance, self);
|
750
756
|
|
751
757
|
s->env_template = rb_hash_dup(rack_env_template);
|
752
758
|
// When combined with SCRIPT_NAME and PATH_INFO, these variables can be used
|
@@ -820,6 +826,33 @@ static VALUE up_server_listen(VALUE self) {
|
|
820
826
|
return self;
|
821
827
|
}
|
822
828
|
|
829
|
+
static VALUE up_server_publish(VALUE self, VALUE channel, VALUE message) {
|
830
|
+
if (TYPE(channel) != T_STRING)
|
831
|
+
channel = rb_obj_as_string(channel);
|
832
|
+
if (TYPE(message) != T_STRING)
|
833
|
+
message = rb_obj_as_string(message);
|
834
|
+
server_s *s = DATA_PTR(self);
|
835
|
+
VALUE members = rb_ivar_get(self, at_members);
|
836
|
+
if (members != Qnil) {
|
837
|
+
long i, mb_cnt = RARRAY_LEN(members);
|
838
|
+
for (i = 0; i < mb_cnt; i++) {
|
839
|
+
up_internal_publish_to_member(s, channel, message, i);
|
840
|
+
}
|
841
|
+
} else {
|
842
|
+
uws_publish(USE_SSL, s->app, RSTRING_PTR(channel), RSTRING_LEN(channel),
|
843
|
+
RSTRING_PTR(message), RSTRING_LEN(message), TEXT, false);
|
844
|
+
if (s->member_id > 0) {
|
845
|
+
// publish to cluster members
|
846
|
+
int i;
|
847
|
+
for (i = 1; i <= s->workers; i++) {
|
848
|
+
if (i != s->member_id)
|
849
|
+
up_internal_publish_to_member(s, channel, message, i);
|
850
|
+
}
|
851
|
+
}
|
852
|
+
}
|
853
|
+
return Qtrue;
|
854
|
+
}
|
855
|
+
|
823
856
|
static VALUE up_server_stop(VALUE self) {
|
824
857
|
server_s *s = DATA_PTR(self);
|
825
858
|
if (!s->app)
|
@@ -891,10 +924,19 @@ void up_setup_rack_env_template(void) {
|
|
891
924
|
rb_hash_aset(rack_env_template, HTTP_VERSION, http11);
|
892
925
|
}
|
893
926
|
|
927
|
+
static VALUE up_publish(VALUE self, VALUE channel, VALUE message) {
|
928
|
+
VALUE instance = rb_ivar_get(mUp, at_instance);
|
929
|
+
if (instance != Qnil)
|
930
|
+
return rb_funcall(instance, id_publish, 2, channel, message);
|
931
|
+
return Qfalse;
|
932
|
+
}
|
933
|
+
|
894
934
|
void Init_up_ext(void) {
|
895
935
|
at_env = rb_intern("@env");
|
896
936
|
at_handler = rb_intern("@handler");
|
937
|
+
at_instance = rb_intern("@instance");
|
897
938
|
at_member_id = rb_intern("@member_id");
|
939
|
+
at_members = rb_intern("@members");
|
898
940
|
at_open = rb_intern("@open");
|
899
941
|
at_protocol = rb_intern("@protocol");
|
900
942
|
at_secret = rb_intern("@secret");
|
@@ -912,6 +954,7 @@ void Init_up_ext(void) {
|
|
912
954
|
id_on_message = rb_intern("on_message");
|
913
955
|
id_on_open = rb_intern("on_open");
|
914
956
|
id_port = rb_intern("port");
|
957
|
+
id_publish = rb_intern("publish");
|
915
958
|
|
916
959
|
utf8_encoding = rb_enc_find("UTF-8");
|
917
960
|
binary_encoding = rb_enc_find("binary");
|
@@ -949,11 +992,13 @@ void Init_up_ext(void) {
|
|
949
992
|
up_setup_rack_env_template();
|
950
993
|
|
951
994
|
mUp = rb_define_module("Up");
|
995
|
+
rb_define_singleton_method(mUp, "publish", up_publish, 2);
|
996
|
+
|
952
997
|
cClient = rb_define_class_under(mUp, "Client", rb_cObject);
|
953
998
|
rb_define_alloc_func(cClient, up_client_alloc);
|
954
999
|
rb_define_method(cClient, "close", up_client_close, 0);
|
955
1000
|
rb_define_method(cClient, "pending", up_client_pending, 0);
|
956
|
-
rb_define_method(cClient, "publish", up_client_publish,
|
1001
|
+
rb_define_method(cClient, "publish", up_client_publish, 2);
|
957
1002
|
rb_define_method(cClient, "subscribe", up_client_subscribe, -1);
|
958
1003
|
rb_define_method(cClient, "unsubscribe", up_client_unsubscribe, -1);
|
959
1004
|
rb_define_method(cClient, "write", up_client_write, 1);
|
@@ -964,5 +1009,6 @@ void Init_up_ext(void) {
|
|
964
1009
|
rb_define_alloc_func(cServer, up_server_alloc);
|
965
1010
|
rb_define_method(cServer, "initialize", up_server_init, -1);
|
966
1011
|
rb_define_method(cServer, "listen", up_server_listen, 0);
|
1012
|
+
rb_define_method(cServer, "publish", up_server_publish, 2);
|
967
1013
|
rb_define_method(cServer, "stop", up_server_stop, 0);
|
968
1014
|
}
|
data/lib/up/bun/server.rb
CHANGED
@@ -4,6 +4,13 @@ require 'up/cli'
|
|
4
4
|
require 'up/client'
|
5
5
|
|
6
6
|
module Up
|
7
|
+
class << self
|
8
|
+
def publish(channel, message)
|
9
|
+
raise 'no instance running' unless @instance
|
10
|
+
@instance&.publish(channel, message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
7
14
|
module Bun
|
8
15
|
class Server
|
9
16
|
def initialize(app:, host: 'localhost', port: 3000, scheme: 'http', ca_file: nil, cert_file: nil, key_file: nil, logger: Logger.new(STDERR))
|
@@ -49,6 +56,7 @@ module Up
|
|
49
56
|
}
|
50
57
|
def listen
|
51
58
|
raise "already running" if @server
|
59
|
+
::Up.instance_variable_set(:@instance, self)
|
52
60
|
%x{
|
53
61
|
const oubs = Opal.Up.Bun.Server;
|
54
62
|
const ouwc = Opal.Up.Client;
|
@@ -152,6 +160,15 @@ module Up
|
|
152
160
|
}
|
153
161
|
end
|
154
162
|
|
163
|
+
def publish(channel, message)
|
164
|
+
%x{
|
165
|
+
if (!message.$$is_string) {
|
166
|
+
message = JSON.stringify(message);
|
167
|
+
}
|
168
|
+
#@server.publish(channel, message);
|
169
|
+
}
|
170
|
+
end
|
171
|
+
|
155
172
|
def stop
|
156
173
|
if Up::CLI::stoppable?
|
157
174
|
`#@server.stop()`
|
data/lib/up/cli.rb
CHANGED
@@ -14,10 +14,10 @@ module Up
|
|
14
14
|
puts self
|
15
15
|
exit
|
16
16
|
end
|
17
|
-
on('-p', '--port PORT', String, 'Port number the server will listen to') do |port|
|
17
|
+
on('-p', '--port PORT', String, 'Port number the server will listen to. Default: 3000') do |port|
|
18
18
|
options[:port] = port.to_i
|
19
19
|
end
|
20
|
-
on('-b', '--bind ADDRESS', String, 'Address the server will listen to') do |host|
|
20
|
+
on('-b', '--bind ADDRESS', String, 'Address the server will listen to. Default: localhost') do |host|
|
21
21
|
options[:host] = host
|
22
22
|
end
|
23
23
|
on('-s', '--secure', "Use secure sockets.\nWhen using secure sockets, the -a, -c and -k options must be provided") do
|
@@ -32,13 +32,16 @@ module Up
|
|
32
32
|
on('-k', '--key-file FILE', String, 'File with the servers certificate') do |key_file|
|
33
33
|
options[:key_file] = key_file
|
34
34
|
end
|
35
|
-
on('-l', '--log-file FILE', String, '
|
35
|
+
on('-l', '--log-file FILE', String, 'Log file') do |log_file|
|
36
36
|
options[:logger] = Logger.new(File.new(log_file, 'a+'))
|
37
37
|
end
|
38
38
|
on('-v', '--version', 'Show version') do
|
39
39
|
puts "Up! v#{Up::VERSION}"
|
40
40
|
exit
|
41
41
|
end
|
42
|
+
on('-w', '--workers NUMBER', 'For clusters, the number of workers to run. Default: number of processors') do |workers|
|
43
|
+
options[:workers] = workers.to_i
|
44
|
+
end
|
42
45
|
end
|
43
46
|
|
44
47
|
def parse!
|
data/lib/up/client.rb
CHANGED
@@ -36,15 +36,14 @@ module Up
|
|
36
36
|
`#@ws?.getBufferedAmount()`
|
37
37
|
end
|
38
38
|
|
39
|
-
def publish(channel, message
|
39
|
+
def publish(channel, message)
|
40
40
|
res = false
|
41
|
-
raise 'publish engine not supported' if engine
|
42
41
|
%x{
|
43
42
|
if (!message.$$is_string) {
|
44
43
|
message = JSON.stringify(message);
|
45
44
|
}
|
46
45
|
res = #@server?.publish(channel, message);
|
47
|
-
if (
|
46
|
+
if (#@worker) {
|
48
47
|
process.send({c: channel, m: message});
|
49
48
|
}
|
50
49
|
}
|
data/lib/up/ruby/cluster.rb
CHANGED
@@ -18,6 +18,7 @@ module Up
|
|
18
18
|
|
19
19
|
def listen
|
20
20
|
raise "already running" unless @members.empty?
|
21
|
+
::Up.instance_variable_set(:@instance, self)
|
21
22
|
%x{
|
22
23
|
if (cluster.isPrimary) {
|
23
24
|
cluster.on('message', (worker, message, handle) => {
|
@@ -33,9 +34,9 @@ module Up
|
|
33
34
|
#@members[i] = cluster.fork();
|
34
35
|
}
|
35
36
|
} else {
|
36
|
-
|
37
|
+
#@worker = true;
|
37
38
|
function process_message_handler(message, handle) {
|
38
|
-
|
39
|
+
#@server.publish(message.c, message.m);
|
39
40
|
}
|
40
41
|
process.on('message', process_message_handler);
|
41
42
|
#{super}
|
@@ -43,6 +44,25 @@ module Up
|
|
43
44
|
}
|
44
45
|
end
|
45
46
|
|
47
|
+
def publish(channel, message)
|
48
|
+
%x{
|
49
|
+
if (!message.$$is_string) {
|
50
|
+
message = JSON.stringify(message);
|
51
|
+
}
|
52
|
+
if (#@worker ) {
|
53
|
+
#@server?.publish(channel, message);
|
54
|
+
process.send({c: channel, m: message});
|
55
|
+
} else if (#@members) {
|
56
|
+
for (let member of #@members) {
|
57
|
+
if (member !== worker) {
|
58
|
+
member.send(message);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
46
66
|
def stop
|
47
67
|
if Up::CLI::stoppable?
|
48
68
|
@members.each { |m| `m.kill()` }
|
@@ -10,6 +10,13 @@ require 'up/client'
|
|
10
10
|
}
|
11
11
|
|
12
12
|
module Up
|
13
|
+
class << self
|
14
|
+
def publish(channel, message)
|
15
|
+
raise 'no instance running' unless @instance
|
16
|
+
@instance&.publish(channel, message)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
13
20
|
module UWebSocket
|
14
21
|
class Server
|
15
22
|
def initialize(app:, host: 'localhost', port: 3000, scheme: 'http', ca_file: nil, cert_file: nil, key_file: nil, logger: Logger.new(STDERR))
|
@@ -74,6 +81,7 @@ module Up
|
|
74
81
|
|
75
82
|
def listen
|
76
83
|
raise "already running" if @server
|
84
|
+
::Up.instance_variable_set(:@instance, self)
|
77
85
|
%x{
|
78
86
|
const ouws = Opal.Up.UWebSocket.Server;
|
79
87
|
const ouwc = Opal.Up.Client;
|
@@ -138,9 +146,9 @@ module Up
|
|
138
146
|
client.open = false;
|
139
147
|
client.handler = handler
|
140
148
|
client.protocol = #{:websocket};
|
141
|
-
client.server =
|
149
|
+
client.server = #@server;
|
142
150
|
client.timeout = 120;
|
143
|
-
if (
|
151
|
+
if (#@worker) {
|
144
152
|
client.worker = true;
|
145
153
|
}
|
146
154
|
res.upgrade({ client: client },
|
@@ -164,6 +172,15 @@ module Up
|
|
164
172
|
}
|
165
173
|
end
|
166
174
|
|
175
|
+
def publish(channel, message)
|
176
|
+
%x{
|
177
|
+
if (!message.$$is_string) {
|
178
|
+
message = JSON.stringify(message);
|
179
|
+
}
|
180
|
+
#@server.publish(channel, message);
|
181
|
+
}
|
182
|
+
end
|
183
|
+
|
167
184
|
def stop
|
168
185
|
if Up::CLI::stoppable?
|
169
186
|
`#@server.close()`
|
data/lib/up/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opal-up
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Biedermann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logger
|
@@ -58,26 +58,6 @@ dependencies:
|
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: 3.0.9
|
61
|
-
- !ruby/object:Gem::Dependency
|
62
|
-
name: rackup
|
63
|
-
requirement: !ruby/object:Gem::Requirement
|
64
|
-
requirements:
|
65
|
-
- - ">="
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: 0.2.2
|
68
|
-
- - "<"
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
version: 3.0.0
|
71
|
-
type: :runtime
|
72
|
-
prerelease: false
|
73
|
-
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
requirements:
|
75
|
-
- - ">="
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: 0.2.2
|
78
|
-
- - "<"
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
version: 3.0.0
|
81
61
|
- !ruby/object:Gem::Dependency
|
82
62
|
name: rake
|
83
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -201,7 +181,7 @@ files:
|
|
201
181
|
- lib/up/u_web_socket/server.rb
|
202
182
|
- lib/up/u_web_socket/server_cli.rb
|
203
183
|
- lib/up/version.rb
|
204
|
-
homepage:
|
184
|
+
homepage: https://github.com/janbiedermann/up
|
205
185
|
licenses:
|
206
186
|
- MIT
|
207
187
|
metadata: {}
|
@@ -223,5 +203,5 @@ requirements: []
|
|
223
203
|
rubygems_version: 3.5.3
|
224
204
|
signing_key:
|
225
205
|
specification_version: 4
|
226
|
-
summary: Rack server for Opal
|
206
|
+
summary: Rack server for Opal and Ruby
|
227
207
|
test_files: []
|