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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +5 -2
- data/ext/agoo/agoo.c +35 -2
- data/ext/agoo/con.c +184 -86
- data/ext/agoo/con.h +4 -2
- data/ext/agoo/debug.c +2 -0
- data/ext/agoo/debug.h +2 -0
- data/ext/agoo/page.c +1 -0
- data/ext/agoo/pub.c +31 -27
- data/ext/agoo/pub.h +10 -11
- data/ext/agoo/request.c +5 -4
- data/ext/agoo/request.h +2 -1
- data/ext/agoo/res.c +3 -1
- data/ext/agoo/res.h +4 -1
- data/ext/agoo/server.c +55 -26
- data/ext/agoo/server.h +5 -3
- data/ext/agoo/subject.c +51 -0
- data/ext/agoo/subject.h +17 -0
- data/ext/agoo/text.c +18 -1
- data/ext/agoo/text.h +1 -0
- data/ext/agoo/upgraded.c +264 -57
- data/ext/agoo/upgraded.h +27 -1
- data/ext/agoo/websocket.c +10 -9
- data/lib/agoo/version.rb +1 -1
- metadata +4 -6
- data/ext/agoo/ccache.c +0 -301
- data/ext/agoo/ccache.h +0 -53
- data/ext/agoo/subscription.c +0 -54
- data/ext/agoo/subscription.h +0 -18
data/ext/agoo/server.h
CHANGED
@@ -9,12 +9,12 @@
|
|
9
9
|
|
10
10
|
#include <ruby.h>
|
11
11
|
|
12
|
-
#include "ccache.h"
|
13
12
|
#include "hook.h"
|
14
13
|
#include "log.h"
|
15
14
|
#include "page.h"
|
16
15
|
#include "queue.h"
|
17
16
|
#include "sub.h"
|
17
|
+
#include "upgraded.h"
|
18
18
|
|
19
19
|
typedef struct _Server {
|
20
20
|
volatile bool inited;
|
@@ -27,12 +27,14 @@ typedef struct _Server {
|
|
27
27
|
atomic_int running;
|
28
28
|
pthread_t listen_thread;
|
29
29
|
pthread_t con_thread;
|
30
|
-
|
30
|
+
|
31
|
+
pthread_mutex_t up_lock;
|
32
|
+
Upgraded up_list;
|
33
|
+
|
31
34
|
struct _Queue con_queue;
|
32
35
|
struct _Queue pub_queue;
|
33
36
|
struct _Cache pages;
|
34
37
|
struct _SubCache sub_cache; // subscription cache
|
35
|
-
struct _CCache con_cache; // Only WebSocket and SSE connections
|
36
38
|
|
37
39
|
Hook hooks;
|
38
40
|
Hook hook404;
|
data/ext/agoo/subject.c
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include <stdio.h>
|
4
|
+
#include <stdlib.h>
|
5
|
+
#include <string.h>
|
6
|
+
|
7
|
+
#include "debug.h"
|
8
|
+
#include "subject.h"
|
9
|
+
|
10
|
+
Subject
|
11
|
+
subject_create(const char *pattern, int plen) {
|
12
|
+
Subject subject = (Subject)malloc(sizeof(struct _Subject) - 7 + plen);
|
13
|
+
|
14
|
+
if (NULL != subject) {
|
15
|
+
DEBUG_ALLOC(mem_subject, subject);
|
16
|
+
subject->next = NULL;
|
17
|
+
memcpy(subject->pattern, pattern, plen);
|
18
|
+
subject->pattern[plen] = '\0';
|
19
|
+
}
|
20
|
+
return subject;
|
21
|
+
}
|
22
|
+
|
23
|
+
void
|
24
|
+
subject_destroy(Subject subject) {
|
25
|
+
DEBUG_FREE(mem_subject, subject);
|
26
|
+
free(subject);
|
27
|
+
}
|
28
|
+
|
29
|
+
bool
|
30
|
+
subject_check(Subject subj, const char *subject) {
|
31
|
+
const char *pat = subj->pattern;
|
32
|
+
|
33
|
+
for (; '\0' != *pat && '\0' != *subject; subject++) {
|
34
|
+
if (*subject == *pat) {
|
35
|
+
pat++;
|
36
|
+
} else if ('*' == *pat) {
|
37
|
+
for (; '\0' != *subject && '.' != *subject; subject++) {
|
38
|
+
}
|
39
|
+
if ('\0' == *subject) {
|
40
|
+
return true;
|
41
|
+
}
|
42
|
+
pat++;
|
43
|
+
} else if ('>' == *pat) {
|
44
|
+
return true;
|
45
|
+
} else {
|
46
|
+
break;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
return '\0' == *pat && '\0' == *subject;
|
50
|
+
}
|
51
|
+
|
data/ext/agoo/subject.h
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
// Copyright (c) 2018, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#ifndef __AGOO_SUBJECT_H__
|
4
|
+
#define __AGOO_SUBJECT_H__
|
5
|
+
|
6
|
+
#include <stdbool.h>
|
7
|
+
|
8
|
+
typedef struct _Subject {
|
9
|
+
struct _Subject *next;
|
10
|
+
char pattern[8];
|
11
|
+
} *Subject;
|
12
|
+
|
13
|
+
extern Subject subject_create(const char *pattern, int plen);
|
14
|
+
extern void subject_destroy(Subject subject);
|
15
|
+
extern bool subject_check(Subject subj, const char *subject);
|
16
|
+
|
17
|
+
#endif // __AGOO_SUBJECT_H__
|
data/ext/agoo/text.c
CHANGED
@@ -23,6 +23,22 @@ text_create(const char *str, int len) {
|
|
23
23
|
return t;
|
24
24
|
}
|
25
25
|
|
26
|
+
Text
|
27
|
+
text_dup(Text t0) {
|
28
|
+
int len = t0->len;
|
29
|
+
Text t = (Text)malloc(sizeof(struct _Text) - TEXT_MIN_SIZE + len + 1);
|
30
|
+
|
31
|
+
if (NULL != t) {
|
32
|
+
DEBUG_ALLOC(mem_text, t)
|
33
|
+
t->len = len;
|
34
|
+
t->alen = len;
|
35
|
+
t->bin = false;
|
36
|
+
atomic_init(&t->ref_cnt, 0);
|
37
|
+
memcpy(t->text, t0->text, len + 1);
|
38
|
+
}
|
39
|
+
return t;
|
40
|
+
}
|
41
|
+
|
26
42
|
Text
|
27
43
|
text_allocate(int len) {
|
28
44
|
Text t = (Text)malloc(sizeof(struct _Text) - TEXT_MIN_SIZE + len + 1);
|
@@ -59,8 +75,9 @@ text_append(Text t, const char *s, int len) {
|
|
59
75
|
if (t->alen <= t->len + len) {
|
60
76
|
long new_len = t->alen + len + t->alen / 2;
|
61
77
|
size_t size = sizeof(struct _Text) - TEXT_MIN_SIZE + new_len + 1;
|
78
|
+
#ifdef MEM_DEBUG
|
62
79
|
Text t0 = t;
|
63
|
-
|
80
|
+
#endif
|
64
81
|
if (NULL == (t = (Text)realloc(t, size))) {
|
65
82
|
return NULL;
|
66
83
|
}
|
data/ext/agoo/text.h
CHANGED
data/ext/agoo/upgraded.c
CHANGED
@@ -4,72 +4,221 @@
|
|
4
4
|
|
5
5
|
#include <ruby/encoding.h>
|
6
6
|
|
7
|
+
#include "con.h"
|
8
|
+
#include "debug.h"
|
7
9
|
#include "pub.h"
|
8
10
|
#include "server.h"
|
11
|
+
#include "subject.h"
|
9
12
|
#include "upgraded.h"
|
10
13
|
|
11
|
-
static VALUE
|
14
|
+
static VALUE upgraded_class = Qundef;
|
15
|
+
|
16
|
+
static VALUE sse_sym;
|
17
|
+
static VALUE websocket_sym;
|
12
18
|
|
13
|
-
static ID cid_id = 0;
|
14
|
-
static ID sid_id = 0;
|
15
19
|
static ID on_open_id = 0;
|
16
20
|
static ID to_s_id = 0;
|
17
21
|
|
22
|
+
static void
|
23
|
+
destroy(Upgraded up) {
|
24
|
+
Subject subject;
|
25
|
+
|
26
|
+
if (Qnil != up->wrap) {
|
27
|
+
DATA_PTR(up->wrap) = NULL;
|
28
|
+
up->wrap = Qnil;
|
29
|
+
}
|
30
|
+
if (NULL == up->prev) {
|
31
|
+
the_server.up_list = up->next;
|
32
|
+
if (NULL != up->next) {
|
33
|
+
up->next->prev = NULL;
|
34
|
+
}
|
35
|
+
} else {
|
36
|
+
up->prev->next = up->next;
|
37
|
+
if (NULL != up->next) {
|
38
|
+
up->next->prev = up->prev;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
while (NULL != (subject = up->subjects)) {
|
42
|
+
up->subjects = up->subjects->next;
|
43
|
+
subject_destroy(subject);
|
44
|
+
}
|
45
|
+
DEBUG_FREE(mem_upgraded, up);
|
46
|
+
free(up);
|
47
|
+
}
|
48
|
+
|
49
|
+
void
|
50
|
+
upgraded_release(Upgraded up) {
|
51
|
+
pthread_mutex_lock(&the_server.up_lock);
|
52
|
+
if (atomic_fetch_sub(&up->ref_cnt, 1) <= 1) {
|
53
|
+
destroy(up);
|
54
|
+
}
|
55
|
+
pthread_mutex_unlock(&the_server.up_lock);
|
56
|
+
}
|
57
|
+
|
58
|
+
void
|
59
|
+
upgraded_release_con(Upgraded up) {
|
60
|
+
pthread_mutex_lock(&the_server.up_lock);
|
61
|
+
up->con = NULL;
|
62
|
+
if (atomic_fetch_sub(&up->ref_cnt, 1) <= 1) {
|
63
|
+
destroy(up);
|
64
|
+
}
|
65
|
+
pthread_mutex_unlock(&the_server.up_lock);
|
66
|
+
}
|
67
|
+
|
68
|
+
// Called from the con_loop thread, no need to lock, this steals the subject
|
69
|
+
// so the pub subject should set to NULL
|
70
|
+
void
|
71
|
+
upgraded_add_subject(Upgraded up, Subject subject) {
|
72
|
+
Subject s;
|
73
|
+
|
74
|
+
for (s = up->subjects; NULL != s; s = s->next) {
|
75
|
+
if (0 == strcmp(subject->pattern, s->pattern)) {
|
76
|
+
subject_destroy(subject);
|
77
|
+
return;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
subject->next = up->subjects;
|
81
|
+
up->subjects = subject;
|
82
|
+
}
|
83
|
+
|
84
|
+
void
|
85
|
+
upgraded_del_subject(Upgraded up, Subject subject) {
|
86
|
+
if (NULL == subject) {
|
87
|
+
while (NULL != (subject = up->subjects)) {
|
88
|
+
up->subjects = up->subjects->next;
|
89
|
+
subject_destroy(subject);
|
90
|
+
}
|
91
|
+
} else {
|
92
|
+
Subject s;
|
93
|
+
Subject prev = NULL;
|
94
|
+
|
95
|
+
for (s = up->subjects; NULL != s; s = s->next) {
|
96
|
+
if (0 == strcmp(subject->pattern, s->pattern)) {
|
97
|
+
if (NULL == prev) {
|
98
|
+
up->subjects = s->next;
|
99
|
+
} else {
|
100
|
+
prev->next = s->next;
|
101
|
+
}
|
102
|
+
subject_destroy(s);
|
103
|
+
break;
|
104
|
+
}
|
105
|
+
prev = s;
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
bool
|
111
|
+
upgraded_match(Upgraded up, const char *subject) {
|
112
|
+
Subject s;
|
113
|
+
|
114
|
+
for (s = up->subjects; NULL != s; s = s->next) {
|
115
|
+
if (subject_check(s, subject)) {
|
116
|
+
return true;
|
117
|
+
}
|
118
|
+
}
|
119
|
+
return false;
|
120
|
+
}
|
121
|
+
|
122
|
+
void
|
123
|
+
upgraded_ref(Upgraded up) {
|
124
|
+
atomic_fetch_add(&up->ref_cnt, 1);
|
125
|
+
}
|
126
|
+
|
127
|
+
static Upgraded
|
128
|
+
get_upgraded(VALUE self) {
|
129
|
+
Upgraded up = NULL;
|
130
|
+
|
131
|
+
if (the_server.active) {
|
132
|
+
pthread_mutex_lock(&the_server.up_lock);
|
133
|
+
if (NULL != (up = DATA_PTR(self))) {
|
134
|
+
atomic_fetch_add(&up->ref_cnt, 1);
|
135
|
+
}
|
136
|
+
pthread_mutex_unlock(&the_server.up_lock);
|
137
|
+
}
|
138
|
+
return up;
|
139
|
+
}
|
140
|
+
|
18
141
|
/* Document-method: write
|
19
142
|
*
|
20
143
|
* call-seq: write(msg)
|
21
144
|
*
|
22
|
-
* Writes a message to the WebSocket or
|
145
|
+
* Writes a message to the WebSocket or SSE connection. Returns true if the
|
146
|
+
* message has been queued and false otherwise. A closed connection or too
|
147
|
+
* many pending messages could cause a value of false to be returned.
|
23
148
|
*/
|
24
149
|
static VALUE
|
25
150
|
up_write(VALUE self, VALUE msg) {
|
26
|
-
|
151
|
+
Upgraded up = get_upgraded(self);
|
27
152
|
Pub p;
|
28
153
|
|
29
|
-
if (
|
30
|
-
|
154
|
+
if (NULL == up) {
|
155
|
+
return Qfalse;
|
31
156
|
}
|
32
|
-
if (0 < the_server.max_push_pending) {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
rb_raise(rb_eIOError, "Too many writes pending. Try again later.");
|
37
|
-
}
|
157
|
+
if (0 < the_server.max_push_pending && the_server.max_push_pending <= atomic_load(&up->pending)) {
|
158
|
+
atomic_fetch_sub(&up->ref_cnt, 1);
|
159
|
+
// Too many pending messages.
|
160
|
+
return Qfalse;
|
38
161
|
}
|
39
162
|
if (T_STRING == rb_type(msg)) {
|
40
163
|
if (RB_ENCODING_IS_ASCII8BIT(msg)) {
|
41
|
-
p = pub_write(
|
164
|
+
p = pub_write(up, StringValuePtr(msg), RSTRING_LEN(msg), true);
|
42
165
|
} else {
|
43
|
-
p = pub_write(
|
166
|
+
p = pub_write(up, StringValuePtr(msg), RSTRING_LEN(msg), false);
|
44
167
|
}
|
45
168
|
} else {
|
46
169
|
volatile VALUE rs = rb_funcall(msg, to_s_id, 0);
|
47
170
|
|
48
|
-
p = pub_write(
|
171
|
+
p = pub_write(up, StringValuePtr(rs), RSTRING_LEN(rs), false);
|
49
172
|
}
|
50
|
-
|
173
|
+
atomic_fetch_add(&up->pending, 1);
|
51
174
|
queue_push(&the_server.pub_queue, p);
|
52
175
|
|
53
|
-
return
|
176
|
+
return Qtrue;
|
54
177
|
}
|
55
178
|
|
56
179
|
/* Document-method: subscribe
|
57
180
|
*
|
58
181
|
* call-seq: subscribe(subject)
|
59
182
|
*
|
60
|
-
* Subscribes to messages published on the specified subject.
|
61
|
-
*
|
183
|
+
* Subscribes to messages published on the specified subject. The subject is a
|
184
|
+
* dot delimited string that can include a '*' character as a wild card that
|
185
|
+
* matches any set of characters. The '>' character matches all remaining
|
186
|
+
* characters. Examples: people.fred.log, people.*.log, people.fred.>
|
62
187
|
*/
|
63
188
|
static VALUE
|
64
189
|
up_subscribe(VALUE self, VALUE subject) {
|
190
|
+
Upgraded up;
|
191
|
+
|
192
|
+
rb_check_type(subject, T_STRING);
|
193
|
+
if (NULL != (up = get_upgraded(self))) {
|
194
|
+
atomic_fetch_add(&up->pending, 1);
|
195
|
+
queue_push(&the_server.pub_queue, pub_subscribe(up, StringValuePtr(subject), RSTRING_LEN(subject)));
|
196
|
+
}
|
197
|
+
return Qnil;
|
198
|
+
}
|
65
199
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
200
|
+
/* Document-method: unsubscribe
|
201
|
+
*
|
202
|
+
* call-seq: unsubscribe(subject=nil)
|
203
|
+
*
|
204
|
+
* Unsubscribes to messages on the provided subject. If the subject is nil
|
205
|
+
* then all subscriptions for the object are removed.
|
206
|
+
*/
|
207
|
+
static VALUE
|
208
|
+
up_unsubscribe(int argc, VALUE *argv, VALUE self) {
|
209
|
+
Upgraded up;
|
210
|
+
const char *subject = NULL;
|
211
|
+
int slen = 0;
|
72
212
|
|
213
|
+
if (0 < argc) {
|
214
|
+
rb_check_type(argv[0], T_STRING);
|
215
|
+
subject = StringValuePtr(argv[0]);
|
216
|
+
slen = (int)RSTRING_LEN(argv[0]);
|
217
|
+
}
|
218
|
+
if (NULL != (up = get_upgraded(self))) {
|
219
|
+
atomic_fetch_add(&up->pending, 1);
|
220
|
+
queue_push(&the_server.pub_queue, pub_unsubscribe(up, subject, slen));
|
221
|
+
}
|
73
222
|
return Qnil;
|
74
223
|
}
|
75
224
|
|
@@ -81,13 +230,12 @@ up_subscribe(VALUE self, VALUE subject) {
|
|
81
230
|
*/
|
82
231
|
static VALUE
|
83
232
|
up_close(VALUE self) {
|
84
|
-
|
233
|
+
Upgraded up = get_upgraded(self);
|
85
234
|
|
86
|
-
if (
|
87
|
-
|
235
|
+
if (NULL != up) {
|
236
|
+
atomic_fetch_add(&up->pending, 1);
|
237
|
+
queue_push(&the_server.pub_queue, pub_close(up));
|
88
238
|
}
|
89
|
-
queue_push(&the_server.pub_queue, pub_close(cid));
|
90
|
-
|
91
239
|
return Qnil;
|
92
240
|
}
|
93
241
|
|
@@ -100,49 +248,108 @@ up_close(VALUE self) {
|
|
100
248
|
*/
|
101
249
|
static VALUE
|
102
250
|
pending(VALUE self) {
|
103
|
-
|
251
|
+
Upgraded up = get_upgraded(self);
|
252
|
+
int pending = -1;
|
253
|
+
|
254
|
+
if (NULL != up) {
|
255
|
+
pending = atomic_load(&up->pending);
|
256
|
+
atomic_fetch_sub(&up->ref_cnt, 1);
|
257
|
+
}
|
258
|
+
return INT2NUM(pending);
|
259
|
+
}
|
104
260
|
|
105
|
-
|
106
|
-
|
261
|
+
/* Document-method: protocol
|
262
|
+
*
|
263
|
+
* call-seq: protocol()
|
264
|
+
*
|
265
|
+
* Returns the protocol of the upgraded connection as either :websocket or
|
266
|
+
* :sse. If not longer connected nil is returned.
|
267
|
+
*/
|
268
|
+
static VALUE
|
269
|
+
protocol(VALUE self) {
|
270
|
+
VALUE pro = Qnil;
|
271
|
+
|
272
|
+
if (the_server.active) {
|
273
|
+
Upgraded up;
|
274
|
+
|
275
|
+
pthread_mutex_lock(&the_server.up_lock);
|
276
|
+
if (NULL != (up = DATA_PTR(self)) && NULL != up->con) {
|
277
|
+
switch (up->con->kind) {
|
278
|
+
case CON_WS:
|
279
|
+
pro = websocket_sym;
|
280
|
+
break;
|
281
|
+
case CON_SSE:
|
282
|
+
pro = sse_sym;
|
283
|
+
break;
|
284
|
+
default:
|
285
|
+
break;
|
286
|
+
}
|
287
|
+
}
|
288
|
+
pthread_mutex_unlock(&the_server.up_lock);
|
107
289
|
}
|
108
|
-
return
|
290
|
+
return pro;
|
109
291
|
}
|
110
292
|
|
111
|
-
|
112
|
-
|
293
|
+
Upgraded
|
294
|
+
upgraded_create(Con c, VALUE obj) {
|
295
|
+
Upgraded up = (Upgraded)malloc(sizeof(struct _Upgraded));
|
296
|
+
|
113
297
|
if (!the_server.active) {
|
114
298
|
rb_raise(rb_eIOError, "Server shutdown.");
|
115
299
|
}
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
300
|
+
if (NULL != up) {
|
301
|
+
DEBUG_ALLOC(mem_upgraded, up);
|
302
|
+
up->con = c;
|
303
|
+
up->handler = obj;
|
304
|
+
atomic_init(&up->pending, 0);
|
305
|
+
atomic_init(&up->ref_cnt, 1); // start with 1 for the Con reference
|
306
|
+
up->on_empty = rb_respond_to(obj, rb_intern("on_drained"));
|
307
|
+
up->on_close = rb_respond_to(obj, rb_intern("on_close"));
|
308
|
+
up->on_shut = rb_respond_to(obj, rb_intern("on_shutdown"));
|
309
|
+
up->on_msg = rb_respond_to(obj, rb_intern("on_message"));
|
310
|
+
up->wrap = Data_Wrap_Struct(upgraded_class, NULL, NULL, up);
|
311
|
+
up->subjects = NULL;
|
312
|
+
up->prev = NULL;
|
313
|
+
pthread_mutex_lock(&the_server.up_lock);
|
314
|
+
if (NULL == the_server.up_list) {
|
315
|
+
up->next = NULL;
|
316
|
+
} else {
|
317
|
+
the_server.up_list->prev = up;
|
318
|
+
}
|
319
|
+
up->next = the_server.up_list;
|
320
|
+
the_server.up_list = up;
|
321
|
+
c->up = up;
|
322
|
+
pthread_mutex_unlock(&the_server.up_lock);
|
323
|
+
|
324
|
+
if (rb_respond_to(obj, on_open_id)) {
|
325
|
+
rb_funcall(obj, on_open_id, 1, up->wrap);
|
326
|
+
}
|
121
327
|
}
|
122
|
-
|
123
|
-
rb_respond_to(obj, rb_intern("on_drained")),
|
124
|
-
rb_respond_to(obj, rb_intern("on_close")),
|
125
|
-
rb_respond_to(obj, rb_intern("on_shutdown")),
|
126
|
-
rb_respond_to(obj, rb_intern("on_message")));
|
127
|
-
rb_funcall(obj, rb_intern("to_s"), 0);
|
328
|
+
return up;
|
128
329
|
}
|
129
330
|
|
331
|
+
// Use the publish from the Agoo module.
|
332
|
+
extern VALUE ragoo_publish(VALUE self, VALUE subject, VALUE message);
|
333
|
+
|
130
334
|
/* Document-module: Agoo::Upgraded
|
131
335
|
*
|
132
|
-
* Adds methods to a handler of WebSocket and
|
336
|
+
* Adds methods to a handler of WebSocket and SSE connections.
|
133
337
|
*/
|
134
338
|
void
|
135
339
|
upgraded_init(VALUE mod) {
|
136
|
-
|
340
|
+
upgraded_class = rb_define_class_under(mod, "Upgraded", rb_cObject);
|
137
341
|
|
138
|
-
rb_define_method(
|
139
|
-
rb_define_method(
|
140
|
-
rb_define_method(
|
141
|
-
rb_define_method(
|
342
|
+
rb_define_method(upgraded_class, "write", up_write, 1);
|
343
|
+
rb_define_method(upgraded_class, "subscribe", up_subscribe, 1);
|
344
|
+
rb_define_method(upgraded_class, "unsubscribe", up_unsubscribe, -1);
|
345
|
+
rb_define_method(upgraded_class, "close", up_close, 0);
|
346
|
+
rb_define_method(upgraded_class, "pending", pending, 0);
|
347
|
+
rb_define_method(upgraded_class, "protocol", protocol, 0);
|
348
|
+
rb_define_method(upgraded_class, "publish", ragoo_publish, 2);
|
142
349
|
|
143
|
-
cid_id = rb_intern("_cid");
|
144
|
-
sid_id = rb_intern("_sid");
|
145
350
|
on_open_id = rb_intern("on_open");
|
146
351
|
to_s_id = rb_intern("to_s");
|
147
|
-
|
352
|
+
|
353
|
+
sse_sym = ID2SYM(rb_intern("sse")); rb_gc_register_address(&sse_sym);
|
354
|
+
websocket_sym = ID2SYM(rb_intern("websocket")); rb_gc_register_address(&websocket_sym);
|
148
355
|
}
|