rbsrt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/rbsrt/rbsrt.c ADDED
@@ -0,0 +1,2270 @@
1
+ /*
2
+ * Ruby SRT - Ruby binding for Secure, Reliable, Transport
3
+ * Copyright (c) 2019 Klaas Speller, Recce.
4
+ *
5
+ * This Source Code Form is subject to the terms of the Mozilla Public
6
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
7
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
+ *
9
+ */
10
+
11
+ /**
12
+ * A Ruby wrapper for SRT (Secure Reliable Transport)
13
+ *
14
+ * @author: Klaas Speller <klaas@recce.nl>
15
+ */
16
+
17
+ // MARK: - Includes
18
+
19
+ // MARK: - System
20
+
21
+ #include <stdio.h>
22
+ #include <stdlib.h>
23
+ #include <unistd.h>
24
+ #include <errno.h>
25
+ #include <string.h>
26
+ #include <sys/types.h>
27
+ #include <sys/socket.h>
28
+ #include <netinet/in.h>
29
+ #include <netdb.h>
30
+ #include <arpa/inet.h>
31
+ #include <sys/wait.h>
32
+ #include <signal.h>
33
+ #include <stdint.h>
34
+
35
+ #include <stdatomic.h>
36
+
37
+
38
+ // MARK: Ruby
39
+
40
+ #include <ruby/ruby.h>
41
+ #include <ruby/util.h>
42
+ #include <ruby/intern.h>
43
+ #include <ruby/thread.h>
44
+ #include <ruby/thread_native.h>
45
+ #include <ruby/io.h>
46
+ #include <ruby/vm.h>
47
+
48
+ // MARK: SRT
49
+
50
+ #include <srt/srt.h>
51
+
52
+
53
+ // MARK: - API
54
+
55
+ #include "rbsrt.h"
56
+ #include "rbstats.h"
57
+
58
+
59
+ // MARK: Network
60
+
61
+ int resolve_address(struct addrinfo *res, char host[], char port[])
62
+ {
63
+ struct addrinfo hints;
64
+
65
+ memset(&hints, 0, sizeof hints);
66
+ hints.ai_family = AF_UNSPEC;
67
+ hints.ai_socktype = SOCK_DGRAM;
68
+
69
+ int status;
70
+
71
+ if ((status = getaddrinfo(host, port, &hints, &res)) != 0)
72
+ {
73
+ DEBUG_ERROR_PRINT("getaddrinfo: %s", gai_strerror(status));
74
+
75
+ return RBSRT_FAILURE;
76
+ }
77
+
78
+ return RBSRT_SUCCESS;
79
+ }
80
+
81
+ void *get_in_addr(struct sockaddr *sa)
82
+ {
83
+ if (sa->sa_family == AF_INET)
84
+ {
85
+ return &(((struct sockaddr_in*)sa)->sin_addr);
86
+ }
87
+
88
+ return &(((struct sockaddr_in6*)sa)->sin6_addr);
89
+ }
90
+
91
+
92
+ // MARK: - Ruby Classes
93
+
94
+ VALUE mSRTModule = Qnil;
95
+ VALUE mSRTSocketKlass = Qnil;
96
+ VALUE mSRTClientKlass = Qnil;
97
+ VALUE mSRTServerKlass = Qnil;
98
+ VALUE mSRTConnectionKlass = Qnil;
99
+ VALUE mSRTPollKlass = Qnil;
100
+
101
+
102
+ // MARK: - Enums
103
+
104
+ typedef enum RBSRTServerFlag
105
+ {
106
+ RBSRT_SERVER_UNINITIALIZED = 0,
107
+ RBSRT_SERVER_INITIALIZED = (1 << 0),
108
+ RBSRT_SERVER_BOUND = (1 << 1),
109
+ RBSRT_SERVER_LISTENING = (1 << 2),
110
+ RBSRT_SERVER_ACCEPTING = (1 << 3),
111
+ RBSRT_SERVER_CLOSED = (1 << 4)
112
+ } rbsrt_server_flag_t;
113
+
114
+ typedef enum RBSRTClientFlag
115
+ {
116
+ RBSRT_CLIENT_UNINITIALIZED = 0,
117
+ RBSRT_CLIENT_INITIALIZED = (1 << 0),
118
+ RBSRT_CLIENT_CONNECTED = (1 << 1),
119
+ RBSRT_CLIENT_CLOSED = (1 << 2)
120
+ } rbsrt_client_flag_t;
121
+
122
+ // MARK: Errors
123
+
124
+ VALUE rbsrt_eStandardError = Qnil;
125
+ VALUE rbstr_eUNKNOWNError = Qnil;
126
+ VALUE rbstr_eCONNSETUPError = Qnil;
127
+ VALUE rbstr_eNOSERVERError = Qnil;
128
+ VALUE rbstr_eCONNREJError = Qnil;
129
+ VALUE rbstr_eSOCKFAILError = Qnil;
130
+ VALUE rbstr_eSECFAILError = Qnil;
131
+ VALUE rbstr_eCONNFAILError = Qnil;
132
+ VALUE rbstr_eCONNLOSTError = Qnil;
133
+ VALUE rbstr_eNOCONNError = Qnil;
134
+ VALUE rbstr_eRESOURCEError = Qnil;
135
+ VALUE rbstr_eTHREADError = Qnil;
136
+ VALUE rbstr_eNOBUFError = Qnil;
137
+ VALUE rbstr_eFILEError = Qnil;
138
+ VALUE rbstr_eINVRDOFFError = Qnil;
139
+ VALUE rbstr_eRDPERMError = Qnil;
140
+ VALUE rbstr_eINVWROFFError = Qnil;
141
+ VALUE rbstr_eWRPERMError = Qnil;
142
+ VALUE rbstr_eINVOPError = Qnil;
143
+ VALUE rbstr_eBOUNDSOCKError = Qnil;
144
+ VALUE rbstr_eCONNSOCKError = Qnil;
145
+ VALUE rbstr_eINVPARAMError = Qnil;
146
+ VALUE rbstr_eINVSOCKError = Qnil;
147
+ VALUE rbstr_eUNBOUNDSOCKError = Qnil;
148
+ VALUE rbstr_eNOLISTENError = Qnil;
149
+ VALUE rbstr_eRDVNOSERVError = Qnil;
150
+ VALUE rbstr_eRDVUNBOUNDError = Qnil;
151
+ VALUE rbstr_eINVALMSGAPIError = Qnil;
152
+ VALUE rbstr_eINVALBUFFERAPIError = Qnil;
153
+ VALUE rbstr_eDUPLISTENError = Qnil;
154
+ VALUE rbstr_eLARGEMSGError = Qnil;
155
+ VALUE rbstr_eINVPOLLIDError = Qnil;
156
+ VALUE rbstr_eASYNCFAILError = Qnil;
157
+ VALUE rbstr_eASYNCSNDError = Qnil;
158
+ VALUE rbstr_eASYNCRCVError = Qnil;
159
+ VALUE rbstr_eTIMEOUTError = Qnil;
160
+ VALUE rbstr_eCONGESTError = Qnil;
161
+ VALUE rbstr_ePEERERRError = Qnil;
162
+
163
+
164
+ VALUE rbsrt_error_get_code(VALUE self)
165
+ {
166
+ VALUE klazz = rb_class_of(self);
167
+
168
+ return rb_const_get(klazz, rb_intern("Code"));
169
+ }
170
+
171
+ VALUE rbstr_error_with_srt_error_code(SRT_ERRNO error_code)
172
+ {
173
+ VALUE error;
174
+
175
+ switch(error_code)
176
+ {
177
+ case SRT_EUNKNOWN:
178
+ error = rbstr_eUNKNOWNError;
179
+ break;
180
+
181
+ case SRT_ECONNSETUP:
182
+ error = rbstr_eCONNSETUPError;
183
+ break;
184
+
185
+ case SRT_ENOSERVER:
186
+ error = rbstr_eNOSERVERError;
187
+ break;
188
+
189
+ case SRT_ECONNREJ:
190
+ error = rbstr_eCONNREJError;
191
+ break;
192
+
193
+ case SRT_ESOCKFAIL:
194
+ error = rbstr_eSOCKFAILError;
195
+ break;
196
+
197
+ case SRT_ESECFAIL:
198
+ error = rbstr_eSECFAILError;
199
+ break;
200
+
201
+ case SRT_ECONNFAIL:
202
+ error = rbstr_eCONNFAILError;
203
+ break;
204
+
205
+ case SRT_ECONNLOST:
206
+ error = rbstr_eCONNLOSTError;
207
+ break;
208
+
209
+ case SRT_ENOCONN:
210
+ error = rbstr_eNOCONNError;
211
+ break;
212
+
213
+ case SRT_ERESOURCE:
214
+ error = rbstr_eRESOURCEError;
215
+ break;
216
+
217
+ case SRT_ETHREAD:
218
+ error = rbstr_eTHREADError;
219
+ break;
220
+
221
+ case SRT_ENOBUF:
222
+ error = rbstr_eNOBUFError;
223
+ break;
224
+
225
+ case SRT_EFILE:
226
+ error = rbstr_eFILEError;
227
+ break;
228
+
229
+ case SRT_EINVRDOFF:
230
+ error = rbstr_eINVRDOFFError;
231
+ break;
232
+
233
+ case SRT_ERDPERM:
234
+ error = rbstr_eRDPERMError;
235
+ break;
236
+
237
+ case SRT_EINVWROFF:
238
+ error = rbstr_eINVWROFFError;
239
+ break;
240
+
241
+ case SRT_EWRPERM:
242
+ error = rbstr_eWRPERMError;
243
+ break;
244
+
245
+ case SRT_EINVOP:
246
+ error = rbstr_eINVOPError;
247
+ break;
248
+
249
+ case SRT_EBOUNDSOCK:
250
+ error = rbstr_eBOUNDSOCKError;
251
+ break;
252
+
253
+ case SRT_ECONNSOCK:
254
+ error = rbstr_eCONNSOCKError;
255
+ break;
256
+
257
+ case SRT_EINVPARAM:
258
+ error = rbstr_eINVPARAMError;
259
+ break;
260
+
261
+ case SRT_EINVSOCK:
262
+ error = rbstr_eINVSOCKError;
263
+ break;
264
+
265
+ case SRT_EUNBOUNDSOCK:
266
+ error = rbstr_eUNBOUNDSOCKError;
267
+ break;
268
+
269
+ case SRT_ENOLISTEN:
270
+ error = rbstr_eNOLISTENError;
271
+ break;
272
+
273
+ case SRT_ERDVNOSERV:
274
+ error = rbstr_eRDVNOSERVError;
275
+ break;
276
+
277
+ case SRT_ERDVUNBOUND:
278
+ error = rbstr_eRDVUNBOUNDError;
279
+ break;
280
+
281
+ case SRT_EINVALMSGAPI:
282
+ error = rbstr_eINVALMSGAPIError;
283
+ break;
284
+
285
+ case SRT_EINVALBUFFERAPI:
286
+ error = rbstr_eINVALBUFFERAPIError;
287
+ break;
288
+
289
+ case SRT_EDUPLISTEN:
290
+ error = rbstr_eDUPLISTENError;
291
+ break;
292
+
293
+ case SRT_ELARGEMSG:
294
+ error = rbstr_eLARGEMSGError;
295
+ break;
296
+
297
+ case SRT_EINVPOLLID:
298
+ error = rbstr_eINVPOLLIDError;
299
+ break;
300
+
301
+ case SRT_EASYNCFAIL:
302
+ error = rbstr_eASYNCFAILError;
303
+ break;
304
+
305
+ case SRT_EASYNCSND:
306
+ error = rbstr_eASYNCSNDError;
307
+ break;
308
+
309
+ case SRT_EASYNCRCV:
310
+ error = rbstr_eASYNCRCVError;
311
+ break;
312
+
313
+ case SRT_ETIMEOUT:
314
+ error = rbstr_eTIMEOUTError;
315
+ break;
316
+
317
+ case SRT_ECONGEST:
318
+ error = rbstr_eCONGESTError;
319
+ break;
320
+
321
+ case SRT_EPEERERR:
322
+ error = rbstr_ePEERERRError;
323
+ break;
324
+
325
+ default:
326
+ error = rbsrt_eStandardError;
327
+ break;
328
+ }
329
+
330
+ return error;
331
+ }
332
+
333
+ _Noreturn void rbsrt_raise_last_srt_error()
334
+ {
335
+ int sys_errno = 0;
336
+ int error_code = srt_getlasterror(&sys_errno);
337
+ VALUE last_error = rbstr_error_with_srt_error_code(error_code);
338
+
339
+ rb_raise(last_error, "%s", srt_getlasterror_str());
340
+ }
341
+
342
+ void rbsrt_init_errors()
343
+ {
344
+ rbsrt_eStandardError = rb_define_class_under(mSRTModule, "Error", rb_eStandardError);
345
+
346
+ rb_define_method(rbsrt_eStandardError, "code", rbsrt_error_get_code, 0);
347
+
348
+
349
+ // Error Types
350
+
351
+ rbstr_eUNKNOWNError = rb_define_class_under(rb_eStandardError, "UNKNOWN", rbsrt_eStandardError);
352
+ rbstr_eCONNSETUPError = rb_define_class_under(rb_eStandardError, "CONNSETUP", rbsrt_eStandardError);
353
+ rbstr_eNOSERVERError = rb_define_class_under(rb_eStandardError, "NOSERVER", rbsrt_eStandardError);
354
+ rbstr_eCONNREJError = rb_define_class_under(rb_eStandardError, "CONNREJ", rbsrt_eStandardError);
355
+ rbstr_eSOCKFAILError = rb_define_class_under(rb_eStandardError, "SOCKFAIL", rbsrt_eStandardError);
356
+ rbstr_eSECFAILError = rb_define_class_under(rb_eStandardError, "SECFAIL", rbsrt_eStandardError);
357
+ rbstr_eCONNFAILError = rb_define_class_under(rb_eStandardError, "CONNFAIL", rbsrt_eStandardError);
358
+ rbstr_eCONNLOSTError = rb_define_class_under(rb_eStandardError, "CONNLOST", rbsrt_eStandardError);
359
+ rbstr_eNOCONNError = rb_define_class_under(rb_eStandardError, "NOCONN", rbsrt_eStandardError);
360
+ rbstr_eRESOURCEError = rb_define_class_under(rb_eStandardError, "RESOURCE", rbsrt_eStandardError);
361
+ rbstr_eTHREADError = rb_define_class_under(rb_eStandardError, "THREAD", rbsrt_eStandardError);
362
+ rbstr_eNOBUFError = rb_define_class_under(rb_eStandardError, "NOBUF", rbsrt_eStandardError);
363
+ rbstr_eFILEError = rb_define_class_under(rb_eStandardError, "FILE", rbsrt_eStandardError);
364
+ rbstr_eINVRDOFFError = rb_define_class_under(rb_eStandardError, "INVRDOFF", rbsrt_eStandardError);
365
+ rbstr_eRDPERMError = rb_define_class_under(rb_eStandardError, "RDPERM", rbsrt_eStandardError);
366
+ rbstr_eINVWROFFError = rb_define_class_under(rb_eStandardError, "INVWROFF", rbsrt_eStandardError);
367
+ rbstr_eWRPERMError = rb_define_class_under(rb_eStandardError, "WRPERM", rbsrt_eStandardError);
368
+ rbstr_eINVOPError = rb_define_class_under(rb_eStandardError, "INVOP", rbsrt_eStandardError);
369
+ rbstr_eBOUNDSOCKError = rb_define_class_under(rb_eStandardError, "BOUNDSOCK", rbsrt_eStandardError);
370
+ rbstr_eCONNSOCKError = rb_define_class_under(rb_eStandardError, "CONNSOCK", rbsrt_eStandardError);
371
+ rbstr_eINVPARAMError = rb_define_class_under(rb_eStandardError, "INVPARAM", rbsrt_eStandardError);
372
+ rbstr_eINVSOCKError = rb_define_class_under(rb_eStandardError, "INVSOCK", rbsrt_eStandardError);
373
+ rbstr_eUNBOUNDSOCKError = rb_define_class_under(rb_eStandardError, "UNBOUNDSOCK", rbsrt_eStandardError);
374
+ rbstr_eNOLISTENError = rb_define_class_under(rb_eStandardError, "NOLISTEN", rbsrt_eStandardError);
375
+ rbstr_eRDVNOSERVError = rb_define_class_under(rb_eStandardError, "RDVNOSERV", rbsrt_eStandardError);
376
+ rbstr_eRDVUNBOUNDError = rb_define_class_under(rb_eStandardError, "RDVUNBOUND", rbsrt_eStandardError);
377
+ rbstr_eINVALMSGAPIError = rb_define_class_under(rb_eStandardError, "INVALMSGAPI", rbsrt_eStandardError);
378
+ rbstr_eINVALBUFFERAPIError = rb_define_class_under(rb_eStandardError, "INVALBUFFERAPI", rbsrt_eStandardError);
379
+ rbstr_eDUPLISTENError = rb_define_class_under(rb_eStandardError, "DUPLISTEN", rbsrt_eStandardError);
380
+ rbstr_eLARGEMSGError = rb_define_class_under(rb_eStandardError, "LARGEMSG", rbsrt_eStandardError);
381
+ rbstr_eINVPOLLIDError = rb_define_class_under(rb_eStandardError, "INVPOLLID", rbsrt_eStandardError);
382
+ rbstr_eASYNCFAILError = rb_define_class_under(rb_eStandardError, "ASYNCFAIL", rbsrt_eStandardError);
383
+ rbstr_eASYNCSNDError = rb_define_class_under(rb_eStandardError, "ASYNCSND", rbsrt_eStandardError);
384
+ rbstr_eASYNCRCVError = rb_define_class_under(rb_eStandardError, "ASYNCRCV", rbsrt_eStandardError);
385
+ rbstr_eTIMEOUTError = rb_define_class_under(rb_eStandardError, "TIMEOUT", rbsrt_eStandardError);
386
+ rbstr_eCONGESTError = rb_define_class_under(rb_eStandardError, "CONGEST", rbsrt_eStandardError);
387
+ rbstr_ePEERERRError = rb_define_class_under(rb_eStandardError, "PEERERR", rbsrt_eStandardError);
388
+
389
+
390
+ // Error Codes
391
+
392
+ rb_define_const(rbsrt_eStandardError, "Code", INT2FIX(0));
393
+ rb_define_const(rbstr_eUNKNOWNError, "Code", INT2FIX(SRT_EUNKNOWN));
394
+ rb_define_const(rbstr_eCONNSETUPError, "Code", INT2FIX(SRT_ECONNSETUP));
395
+ rb_define_const(rbstr_eNOSERVERError, "Code", INT2FIX(SRT_ENOSERVER));
396
+ rb_define_const(rbstr_eCONNREJError, "Code", INT2FIX(SRT_ECONNREJ));
397
+ rb_define_const(rbstr_eSOCKFAILError, "Code", INT2FIX(SRT_ESOCKFAIL));
398
+ rb_define_const(rbstr_eSECFAILError, "Code", INT2FIX(SRT_ESECFAIL));
399
+ rb_define_const(rbstr_eCONNFAILError, "Code", INT2FIX(SRT_ECONNFAIL));
400
+ rb_define_const(rbstr_eCONNLOSTError, "Code", INT2FIX(SRT_ECONNLOST));
401
+ rb_define_const(rbstr_eNOCONNError, "Code", INT2FIX(SRT_ENOCONN));
402
+ rb_define_const(rbstr_eRESOURCEError, "Code", INT2FIX(SRT_ERESOURCE));
403
+ rb_define_const(rbstr_eTHREADError, "Code", INT2FIX(SRT_ETHREAD));
404
+ rb_define_const(rbstr_eNOBUFError, "Code", INT2FIX(SRT_ENOBUF));
405
+ rb_define_const(rbstr_eFILEError, "Code", INT2FIX(SRT_EFILE));
406
+ rb_define_const(rbstr_eINVRDOFFError, "Code", INT2FIX(SRT_EINVRDOFF));
407
+ rb_define_const(rbstr_eRDPERMError, "Code", INT2FIX(SRT_ERDPERM));
408
+ rb_define_const(rbstr_eINVWROFFError, "Code", INT2FIX(SRT_EINVWROFF));
409
+ rb_define_const(rbstr_eWRPERMError, "Code", INT2FIX(SRT_EWRPERM));
410
+ rb_define_const(rbstr_eINVOPError, "Code", INT2FIX(SRT_EINVOP));
411
+ rb_define_const(rbstr_eBOUNDSOCKError, "Code", INT2FIX(SRT_EBOUNDSOCK));
412
+ rb_define_const(rbstr_eCONNSOCKError, "Code", INT2FIX(SRT_ECONNSOCK));
413
+ rb_define_const(rbstr_eINVPARAMError, "Code", INT2FIX(SRT_EINVPARAM));
414
+ rb_define_const(rbstr_eINVSOCKError, "Code", INT2FIX(SRT_EINVSOCK));
415
+ rb_define_const(rbstr_eUNBOUNDSOCKError, "Code", INT2FIX(SRT_EUNBOUNDSOCK));
416
+ rb_define_const(rbstr_eNOLISTENError, "Code", INT2FIX(SRT_ENOLISTEN));
417
+ rb_define_const(rbstr_eRDVNOSERVError, "Code", INT2FIX(SRT_ERDVNOSERV));
418
+ rb_define_const(rbstr_eRDVUNBOUNDError, "Code", INT2FIX(SRT_ERDVUNBOUND));
419
+ rb_define_const(rbstr_eINVALMSGAPIError, "Code", INT2FIX(SRT_EINVALMSGAPI));
420
+ rb_define_const(rbstr_eINVALBUFFERAPIError, "Code", INT2FIX(SRT_EINVALBUFFERAPI));
421
+ rb_define_const(rbstr_eDUPLISTENError, "Code", INT2FIX(SRT_EDUPLISTEN));
422
+ rb_define_const(rbstr_eLARGEMSGError, "Code", INT2FIX(SRT_ELARGEMSG));
423
+ rb_define_const(rbstr_eINVPOLLIDError, "Code", INT2FIX(SRT_EINVPOLLID));
424
+ rb_define_const(rbstr_eASYNCFAILError, "Code", INT2FIX(SRT_EASYNCFAIL));
425
+ rb_define_const(rbstr_eASYNCSNDError, "Code", INT2FIX(SRT_EASYNCSND));
426
+ rb_define_const(rbstr_eASYNCRCVError, "Code", INT2FIX(SRT_EASYNCRCV));
427
+ rb_define_const(rbstr_eTIMEOUTError, "Code", INT2FIX(SRT_ETIMEOUT));
428
+ rb_define_const(rbstr_eCONGESTError, "Code", INT2FIX(SRT_ECONGEST));
429
+ rb_define_const(rbstr_ePEERERRError, "Code", INT2FIX(SRT_EPEERERR));
430
+
431
+ }
432
+
433
+
434
+ // MARK: - SRT Init
435
+
436
+ VALUE rbsrt_srt_startup(void *c)
437
+ {
438
+ RBSRT_DEBUG_PRINT("srt startup");
439
+
440
+ srt_startup();
441
+
442
+ return Qnil;
443
+ }
444
+
445
+ void rbsrt_srt_cleanup(ruby_vm_t *vm)
446
+ {
447
+ RBSRT_DEBUG_PRINT("srt cleanup");
448
+
449
+ srt_cleanup();
450
+ }
451
+
452
+ // MARK: - Socket Base
453
+
454
+ // MARK: Socket State
455
+
456
+ #define RBSRT_SOCKET_STATE_READY_ID rb_intern("ready")
457
+ #define RBSRT_SOCKET_STATE_OPENED_ID rb_intern("opened")
458
+ #define RBSRT_SOCKET_STATE_LISTENING_ID rb_intern("listening")
459
+ #define RBSRT_SOCKET_STATE_CONNECTING_ID rb_intern("connecting")
460
+ #define RBSRT_SOCKET_STATE_CONNECTED_ID rb_intern("connected")
461
+ #define RBSRT_SOCKET_STATE_BROKEN_ID rb_intern("broken")
462
+ #define RBSRT_SOCKET_STATE_CLOSING_ID rb_intern("closing")
463
+ #define RBSRT_SOCKET_STATE_CLOSED_ID rb_intern("closed")
464
+ #define RBSRT_SOCKET_STATE_NONEXIST_ID rb_intern("nonexist")
465
+
466
+ #define RBSRT_SOCKET_STATE_READY_SYM RB_ID2SYM(RBSRT_SOCKET_STATE_READY_ID)
467
+ #define RBSRT_SOCKET_STATE_OPENED_SYM RB_ID2SYM(RBSRT_SOCKET_STATE_OPENED_ID)
468
+ #define RBSRT_SOCKET_STATE_LISTENING_SYM RB_ID2SYM(RBSRT_SOCKET_STATE_LISTENING_ID)
469
+ #define RBSRT_SOCKET_STATE_CONNECTING_SYM RB_ID2SYM(RBSRT_SOCKET_STATE_CONNECTING_ID)
470
+ #define RBSRT_SOCKET_STATE_CONNECTED_SYM RB_ID2SYM(RBSRT_SOCKET_STATE_CONNECTED_ID)
471
+ #define RBSRT_SOCKET_STATE_BROKEN_SYM RB_ID2SYM(RBSRT_SOCKET_STATE_BROKEN_ID)
472
+ #define RBSRT_SOCKET_STATE_CLOSING_SYM RB_ID2SYM(RBSRT_SOCKET_STATE_CLOSING_ID)
473
+ #define RBSRT_SOCKET_STATE_CLOSED_SYM RB_ID2SYM(RBSRT_SOCKET_STATE_CLOSED_ID)
474
+ #define RBSRT_SOCKET_STATE_NONEXIST_SYM RB_ID2SYM(RBSRT_SOCKET_STATE_NONEXIST_ID)
475
+
476
+ VALUE rbsrt_socket_get_socket_state(VALUE self)
477
+ {
478
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
479
+
480
+ RBSRT_DEBUG_PRINT("socket get socket state for %d", socket->socket);
481
+
482
+ SRT_SOCKSTATUS state = srt_getsockstate(socket->socket);
483
+
484
+ VALUE state_sym;
485
+
486
+ switch (state)
487
+ {
488
+ case SRTS_INIT:
489
+ state_sym = RBSRT_SOCKET_STATE_READY_SYM;
490
+ break;
491
+
492
+ case SRTS_OPENED:
493
+ state_sym = RBSRT_SOCKET_STATE_OPENED_SYM;
494
+ break;
495
+
496
+ case SRTS_LISTENING:
497
+ state_sym = RBSRT_SOCKET_STATE_LISTENING_SYM;
498
+ break;
499
+
500
+ case SRTS_CONNECTING:
501
+ state_sym = RBSRT_SOCKET_STATE_CONNECTING_SYM;
502
+ break;
503
+
504
+ case SRTS_CONNECTED:
505
+ state_sym = RBSRT_SOCKET_STATE_CONNECTED_SYM;
506
+ break;
507
+
508
+ case SRTS_BROKEN:
509
+ state_sym = RBSRT_SOCKET_STATE_BROKEN_SYM;
510
+ break;
511
+
512
+ case SRTS_CLOSING:
513
+ state_sym = RBSRT_SOCKET_STATE_CLOSING_SYM;
514
+ break;
515
+
516
+ case SRTS_CLOSED:
517
+ state_sym = RBSRT_SOCKET_STATE_CLOSED_SYM;
518
+ break;
519
+
520
+ case SRTS_NONEXIST:
521
+ state_sym = RBSRT_SOCKET_STATE_NONEXIST_SYM;
522
+ break;
523
+
524
+ default:
525
+ state_sym = Qnil;
526
+ break;
527
+ }
528
+
529
+ return state_sym;
530
+ }
531
+
532
+ VALUE rbsrt_socket_is_ready(VALUE self)
533
+ {
534
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
535
+
536
+ return srt_getsockstate(socket->socket) == SRTS_INIT ? Qtrue : Qfalse;
537
+ }
538
+
539
+ VALUE rbsrt_socket_is_opened(VALUE self)
540
+ {
541
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
542
+
543
+ return srt_getsockstate(socket->socket) == SRTS_OPENED ? Qtrue : Qfalse;
544
+ }
545
+
546
+ VALUE rbsrt_socket_is_listening(VALUE self)
547
+ {
548
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
549
+
550
+ return srt_getsockstate(socket->socket) == SRTS_LISTENING ? Qtrue : Qfalse;
551
+ }
552
+
553
+ VALUE rbsrt_socket_is_connecting(VALUE self)
554
+ {
555
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
556
+
557
+ return srt_getsockstate(socket->socket) == SRTS_CONNECTING ? Qtrue : Qfalse;
558
+ }
559
+
560
+ VALUE rbsrt_socket_is_connected(VALUE self)
561
+ {
562
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
563
+
564
+ return srt_getsockstate(socket->socket) == SRTS_CONNECTED ? Qtrue : Qfalse;
565
+ }
566
+
567
+ VALUE rbsrt_socket_is_broken(VALUE self)
568
+ {
569
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
570
+
571
+ return srt_getsockstate(socket->socket) == SRTS_BROKEN ? Qtrue : Qfalse;
572
+ }
573
+
574
+ VALUE rbsrt_socket_is_closing(VALUE self)
575
+ {
576
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
577
+
578
+ return srt_getsockstate(socket->socket) == SRTS_CLOSING ? Qtrue : Qfalse;
579
+ }
580
+
581
+ VALUE rbsrt_socket_is_closed(VALUE self)
582
+ {
583
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
584
+
585
+ return srt_getsockstate(socket->socket) == SRTS_CLOSED ? Qtrue : Qfalse;
586
+ }
587
+
588
+ VALUE rbsrt_socket_is_nonexist(VALUE self)
589
+ {
590
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
591
+
592
+ return srt_getsockstate(socket->socket) == SRTS_NONEXIST ? Qtrue : Qfalse;
593
+ }
594
+
595
+ void rbsrt_define_socket_state_api(VALUE klass)
596
+ {
597
+ rb_define_method(klass, "state", rbsrt_socket_get_socket_state, 0);
598
+
599
+ rb_define_method(klass, "ready?", rbsrt_socket_is_ready, 0);
600
+ rb_define_method(klass, "opened?", rbsrt_socket_is_opened, 0);
601
+ rb_define_method(klass, "listening?", rbsrt_socket_is_listening, 0);
602
+ rb_define_method(klass, "connecting?", rbsrt_socket_is_connecting, 0);
603
+ rb_define_method(klass, "connected?", rbsrt_socket_is_connected, 0);
604
+ rb_define_method(klass, "broken?", rbsrt_socket_is_broken, 0);
605
+ rb_define_method(klass, "closing?", rbsrt_socket_is_closing, 0);
606
+ rb_define_method(klass, "closed?", rbsrt_socket_is_closed, 0);
607
+ rb_define_method(klass, "nonexist?", rbsrt_socket_is_nonexist, 0);
608
+ }
609
+
610
+
611
+ // MARK: Connecting
612
+
613
+ VALUE rbsrt_socket_connect(VALUE self, VALUE host, VALUE port)
614
+ {
615
+ Check_Type(host, T_STRING);
616
+ Check_Type(port, T_STRING);
617
+
618
+ RBSRT_DEBUG_PRINT("socket connect: host=%s, port=%s", StringValuePtr(host), StringValuePtr(port));
619
+
620
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
621
+
622
+ VALUE retval = Qfalse;
623
+
624
+ int status;
625
+ struct addrinfo hints;
626
+ struct addrinfo *servinfo;
627
+ struct addrinfo *p;
628
+
629
+ int ipv6only = 0;
630
+ int ipv4only = 0;
631
+
632
+
633
+ memset(&hints, 0, sizeof hints);
634
+
635
+ hints.ai_family = AF_UNSPEC;
636
+ hints.ai_socktype = SOCK_DGRAM;
637
+
638
+ if ((status = getaddrinfo(StringValuePtr(host), StringValuePtr(port), &hints, &servinfo)) != 0)
639
+ {
640
+ rb_raise(rbsrt_eStandardError, "failed to get address info: %s", gai_strerror(status));
641
+ }
642
+
643
+ srt_clearlasterror();
644
+
645
+ for(p = servinfo;p != NULL; p = p->ai_next)
646
+ {
647
+ if ((p->ai_family == AF_INET && ipv6only) || (p->ai_family == AF_INET6 && ipv4only))
648
+ {
649
+ continue;
650
+ }
651
+
652
+ if (srt_connect(socket->socket, p->ai_addr, p->ai_addrlen) == SRT_ERROR)
653
+ {
654
+ RBSRT_DEBUG_PRINT("failed to connect socket: %s", srt_getlasterror_str());
655
+
656
+ continue;
657
+ }
658
+
659
+ #if RBSRT_DEBUG
660
+ char ipstr[INET6_ADDRSTRLEN];
661
+ inet_ntop(
662
+ p->ai_family,
663
+ (p->ai_family == AF_INET ? &(((struct sockaddr_in *)p->ai_addr)->sin_addr) : &(((struct sockaddr_in6 *)p->ai_addr)->sin6_addr)),
664
+ ipstr,
665
+ sizeof ipstr);
666
+
667
+ RBSRT_DEBUG_PRINT("socket connected: ip=%s", ipstr);
668
+ #endif
669
+
670
+ // connected
671
+
672
+ retval = Qtrue;
673
+
674
+ break;
675
+ }
676
+
677
+ // complete
678
+
679
+ freeaddrinfo(servinfo);
680
+
681
+ if (retval != Qtrue)
682
+ {
683
+ rbsrt_raise_last_srt_error();
684
+ }
685
+
686
+ return retval;
687
+ }
688
+
689
+ VALUE rbsrt_socket_accept(VALUE self)
690
+ {
691
+ RBSRT_DEBUG_PRINT("server accept");
692
+
693
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
694
+
695
+ struct sockaddr_storage remote_address;
696
+ int addr_size = sizeof(remote_address);
697
+
698
+ SRTSOCKET accepted_socket = srt_accept(socket->socket, (struct sockaddr *)&remote_address, &addr_size);
699
+
700
+ if (accepted_socket == SRT_ERROR)
701
+ {
702
+ rbsrt_raise_last_srt_error();
703
+
704
+ return Qnil;
705
+ }
706
+
707
+ VALUE rbclient = rb_class_new_instance(0, NULL, mSRTSocketKlass);
708
+
709
+ RBSRT_SOCKET_UNWRAP(rbclient, client);
710
+
711
+ client->socket = accepted_socket;
712
+
713
+ return rbclient;
714
+ }
715
+
716
+ VALUE rbsrt_socket_bind(VALUE self, VALUE address, VALUE port)
717
+ {
718
+ int status;
719
+ struct sockaddr_in sa;
720
+ // int livemode = SRTT_LIVE;
721
+
722
+ Check_Type(address, T_STRING);
723
+ Check_Type(port, T_STRING);
724
+
725
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
726
+
727
+ // get address info
728
+ // TODO: Handle domain names
729
+
730
+ sa.sin_family = AF_INET;
731
+ sa.sin_port = htons(atoi(StringValuePtr(port)));
732
+
733
+ if (inet_pton(AF_INET, StringValuePtr(address), &sa.sin_addr) != 1)
734
+ {
735
+ rb_raise(rb_eArgError, "bad adddress: %s", strerror(errno));
736
+
737
+ return Qfalse;
738
+ }
739
+
740
+
741
+ // bind socket
742
+
743
+ status = srt_bind(socket->socket, (struct sockaddr *)&sa, sizeof(sa));
744
+
745
+ if (status == SRT_ERROR)
746
+ {
747
+ rbsrt_raise_last_srt_error();
748
+
749
+ return Qfalse;
750
+ }
751
+
752
+ return Qtrue;
753
+ }
754
+
755
+ VALUE rbsrt_socket_listen(VALUE self, VALUE nbacklog)
756
+ {
757
+ Check_Type(nbacklog, T_FIXNUM);
758
+
759
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
760
+
761
+ int status = srt_listen(socket->socket, FIX2INT(nbacklog));
762
+
763
+ if (status == SRT_ERROR)
764
+ {
765
+ rbsrt_raise_last_srt_error();
766
+
767
+ return Qfalse;
768
+ }
769
+
770
+ return Qtrue;
771
+ }
772
+
773
+
774
+ // MARK: Creating and Configuring
775
+
776
+ VALUE rbsrt_socket_close(VALUE self)
777
+ {
778
+ RBSRT_DEBUG_PRINT("socket close");
779
+
780
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket)
781
+
782
+ if (srt_close(socket->socket) == SRT_ERROR)
783
+ {
784
+ rbsrt_raise_last_srt_error();
785
+
786
+ return Qfalse;
787
+ }
788
+
789
+ return Qtrue;
790
+ }
791
+
792
+
793
+ // MARK: Transmission
794
+
795
+ VALUE rbsrt_socket_sendmsg(VALUE self, VALUE message)
796
+ {
797
+ RBSRT_DEBUG_PRINT("socket sendmsg");
798
+
799
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket)
800
+
801
+ int message_type = rb_type(message);
802
+ const char *buf = NULL;
803
+ int buf_len = 0;
804
+
805
+ switch (message_type)
806
+ {
807
+ case T_STRING:
808
+ buf = StringValuePtr(message);
809
+ buf_len = (int)RSTRING_LEN(message);
810
+ RBSRT_DEBUG_PRINT("sendmsg: %d", buf_len);
811
+ break;
812
+
813
+ case T_OBJECT:
814
+ case T_DATA:
815
+ RBSRT_DEBUG_PRINT("sendmsg DATA");
816
+ // TODO: Support binary
817
+ rb_raise(rb_eArgError, "message must be a string");
818
+ // rdata
819
+ return FIX2INT(SRT_ERROR);
820
+ break;
821
+
822
+ default:
823
+ rb_raise(rb_eArgError, "message must a string");
824
+
825
+ return FIX2INT(SRT_ERROR);
826
+ break;
827
+ }
828
+
829
+
830
+ // send data
831
+
832
+ int packet_size;
833
+ int nbytes;
834
+ int total_nbytes = 0;
835
+ char const *buf_p = buf;
836
+
837
+ do
838
+ {
839
+ packet_size = (buf_len - total_nbytes) > RBSRT_PAYLOAD_SIZE ? RBSRT_PAYLOAD_SIZE : (buf_len - total_nbytes);
840
+
841
+ nbytes = srt_sendmsg2(socket->socket, (buf_p + total_nbytes), packet_size, NULL);
842
+
843
+ if (nbytes == SRT_ERROR)
844
+ {
845
+ DEBUG_ERROR_PRINT("sendmsg error. %s", srt_getlasterror_str());
846
+
847
+ rbsrt_raise_last_srt_error();
848
+
849
+ break;
850
+ }
851
+
852
+ RBSRT_DEBUG_PRINT("send bytes %d", nbytes);
853
+ }
854
+ while ((total_nbytes += nbytes) < buf_len);
855
+
856
+ return INT2FIX(total_nbytes);
857
+ }
858
+
859
+ VALUE rbsrt_socket_recvmsg(VALUE self)
860
+ {
861
+ RBSRT_DEBUG_PRINT("socket recvmsg");
862
+
863
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket)
864
+
865
+ int nbuf = RBSRT_PAYLOAD_SIZE * 2;
866
+ char buf[nbuf];
867
+
868
+ int nbytes = srt_recvmsg2(socket->socket, buf, nbuf, NULL);
869
+
870
+ if (nbytes == SRT_ERROR)
871
+ {
872
+ rbsrt_raise_last_srt_error();
873
+
874
+ return Qnil;
875
+ }
876
+
877
+ else if (nbytes == 0)
878
+ {
879
+ // TODO: Close socket
880
+ return Qnil;
881
+ }
882
+
883
+ VALUE data = rb_str_buf_new((long)nbytes);
884
+ rb_str_buf_cat(data, buf, (long)nbytes);
885
+ rb_obj_taint(data);
886
+
887
+ return data;
888
+ }
889
+
890
+
891
+ // MARK: Socket Options
892
+
893
+ VALUE rbsrt_socket_get_id(VALUE self)
894
+ {
895
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
896
+
897
+ return INT2FIX(socket->socket);
898
+ }
899
+
900
+ VALUE rbsrt_socket_set_rcvsyn(VALUE self, VALUE syn)
901
+ {
902
+ int is_syn = RTEST(syn) ? 1 : 0;
903
+
904
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
905
+
906
+ if (srt_setsockflag(socket->socket, SRTO_RCVSYN, &is_syn, sizeof(is_syn)) == SRT_ERROR)
907
+ {
908
+ rbsrt_raise_last_srt_error();
909
+
910
+ return Qfalse;
911
+ }
912
+
913
+ return Qtrue;
914
+ }
915
+
916
+ VALUE rbsrt_socket_get_rcvsyn(VALUE self)
917
+ {
918
+ int is_syn = 0;
919
+ int is_syn_size = 0;
920
+
921
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
922
+
923
+ if (srt_getsockflag(socket->socket, SRTO_RCVSYN, &is_syn, &is_syn_size) == SRT_ERROR)
924
+ {
925
+ rbsrt_raise_last_srt_error();
926
+
927
+ return Qnil;
928
+ }
929
+
930
+ return is_syn ? Qtrue : Qfalse;
931
+ }
932
+
933
+ VALUE rbsrt_socket_set_sndsyn(VALUE self, VALUE syn)
934
+ {
935
+ int is_syn = RTEST(syn) ? 1 : 0;
936
+
937
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
938
+
939
+ if (srt_setsockflag(socket->socket, SRTO_SNDSYN, &is_syn, sizeof(is_syn)) == SRT_ERROR)
940
+ {
941
+ rbsrt_raise_last_srt_error();
942
+
943
+ return Qfalse;
944
+ }
945
+
946
+ return Qtrue;
947
+ }
948
+
949
+ VALUE rbsrt_socket_get_sndsyn(VALUE self)
950
+ {
951
+ int is_syn = 0;
952
+ int is_syn_size = 0;
953
+
954
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
955
+
956
+ if (srt_getsockflag(socket->socket, SRTO_SNDSYN, &is_syn, &is_syn_size) == SRT_ERROR)
957
+ {
958
+ rbsrt_raise_last_srt_error();
959
+
960
+ return Qnil;
961
+ }
962
+
963
+ return is_syn ? Qtrue : Qfalse;
964
+ }
965
+
966
+ VALUE rbsrt_socket_set_streamid(VALUE self, VALUE streamid)
967
+ {
968
+ Check_Type(streamid, T_STRING);
969
+
970
+ long streamid_llen = rb_str_strlen(streamid);
971
+
972
+ if (streamid_llen > 512)
973
+ {
974
+ rb_raise(rbsrt_eStandardError, "streamid must be 512 characters or less");
975
+
976
+ return Qfalse;
977
+ }
978
+
979
+ int streamid_len = (int)streamid_llen;
980
+ char *streamid_p = StringValuePtr(streamid);
981
+
982
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
983
+
984
+ if (srt_setsockflag(socket->socket, SRTO_STREAMID, streamid_p, streamid_len + 1) == SRT_ERROR)
985
+ {
986
+ rbsrt_raise_last_srt_error();
987
+
988
+ return Qfalse;
989
+ }
990
+
991
+ return Qtrue;
992
+ }
993
+
994
+ VALUE rbsrt_socket_get_streamid(VALUE self)
995
+ {
996
+ char streamid[1024];
997
+ int streamid_len = sizeof(streamid);
998
+
999
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
1000
+
1001
+ if (srt_getsockflag(socket->socket, SRTO_STREAMID, &streamid, &streamid_len) == SRT_ERROR)
1002
+ {
1003
+ rbsrt_raise_last_srt_error();
1004
+
1005
+ return Qfalse;
1006
+ }
1007
+
1008
+ if (streamid_len <= 0)
1009
+ {
1010
+ return Qnil;
1011
+ }
1012
+
1013
+ VALUE result = rb_str_buf_new((long)streamid_len);
1014
+ rb_str_buf_cat(result, streamid, (long)streamid_len);
1015
+ rb_obj_taint(result);
1016
+
1017
+ return result;
1018
+ }
1019
+
1020
+ VALUE rbsrt_socket_set_transtype(VALUE self, VALUE type)
1021
+ {
1022
+ RBSRT_DEBUG_PRINT("socket set transmission type");
1023
+
1024
+ // unwrap type argument
1025
+
1026
+ int type_arg_type = rb_type(type);
1027
+ int srt_transtype;
1028
+ const char *type_name = NULL;
1029
+
1030
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
1031
+
1032
+ switch (type_arg_type)
1033
+ {
1034
+ case T_STRING:
1035
+ type_name = StringValuePtr(type);
1036
+ break;
1037
+
1038
+ case T_SYMBOL:
1039
+ type_name = rb_id2name(SYM2ID(type));
1040
+ break;
1041
+
1042
+ case T_FIXNUM:
1043
+ if (FIX2INT(type) == SRTT_LIVE || FIX2INT(type) == SRTT_FILE)
1044
+ {
1045
+ srt_transtype = FIX2INT(type);
1046
+
1047
+ goto set_flag;
1048
+ }
1049
+
1050
+ else
1051
+ {
1052
+ goto invalid_argument;
1053
+ }
1054
+
1055
+ break;
1056
+
1057
+ default:
1058
+ goto invalid_argument;
1059
+ break;
1060
+ }
1061
+
1062
+ // set option
1063
+
1064
+ if (strncmp(type_name, "live", 5) == 0)
1065
+ {
1066
+ srt_transtype = SRTT_LIVE;
1067
+ }
1068
+
1069
+ else if (strncmp(type_name, "file", 5) == 0)
1070
+ {
1071
+ srt_transtype = SRTT_FILE;
1072
+ }
1073
+
1074
+ else
1075
+ {
1076
+ goto invalid_argument;
1077
+ }
1078
+
1079
+ set_flag:
1080
+
1081
+ if (srt_setsockflag(socket->socket, SRTO_TRANSTYPE, &srt_transtype, sizeof(srt_transtype)) == SRT_ERROR)
1082
+ {
1083
+ rbsrt_raise_last_srt_error();
1084
+
1085
+ return Qfalse;
1086
+ }
1087
+
1088
+ return Qtrue;
1089
+
1090
+ invalid_argument:
1091
+ rb_raise(rb_eArgError, "transmission type must be live (:live, \"live\", %d), or file (:file, \"file\", %d)", SRTT_LIVE, SRTT_FILE);
1092
+ }
1093
+
1094
+
1095
+ VALUE rbsrt_socket_set_tsbpdmode(VALUE self, VALUE val)
1096
+ {
1097
+ // timestamp-based Packet Delivery mode
1098
+
1099
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
1100
+
1101
+ int32_t tsbpdmode = RTEST(val) ? 1 : 0;
1102
+ int tsbpdmode_size = sizeof(tsbpdmode);
1103
+
1104
+ if (srt_setsockflag(socket->socket, SRTO_TSBPDMODE, &tsbpdmode, tsbpdmode_size) == SRT_ERROR)
1105
+ {
1106
+ rbsrt_raise_last_srt_error();
1107
+
1108
+ return Qnil;
1109
+ }
1110
+
1111
+ return val;
1112
+ }
1113
+
1114
+ VALUE rbsrt_socket_get_tsbpdmode(VALUE self)
1115
+ {
1116
+ // timestamp-based Packet Delivery mode
1117
+
1118
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
1119
+
1120
+ int32_t tsbpdmode;
1121
+ int tsbpdmode_size;
1122
+
1123
+ if (srt_getsockflag(socket->socket, SRTO_TSBPDMODE, &tsbpdmode, &tsbpdmode_size) == SRT_ERROR)
1124
+ {
1125
+ rbsrt_raise_last_srt_error();
1126
+
1127
+ return Qnil;
1128
+ }
1129
+
1130
+ return tsbpdmode ? Qtrue : Qfalse;
1131
+ }
1132
+
1133
+
1134
+
1135
+ #ifndef RBSRT_PASSPHRASE_MIN
1136
+ #define RBSRT_PASSPHRASE_MIN 10
1137
+ #endif
1138
+
1139
+ #ifndef RBSRT_PASSPHRASE_MAX
1140
+ #define RBSRT_PASSPHRASE_MAX 79
1141
+ #endif
1142
+
1143
+ VALUE rbsrt_socket_set_passphrase(VALUE self, VALUE passphrase)
1144
+ {
1145
+ int passphrase_type = rb_type(passphrase);
1146
+ char const *passphrase_buf;
1147
+ int passphrase_size;
1148
+
1149
+ switch (passphrase_type)
1150
+ {
1151
+ case T_NIL:
1152
+ passphrase_buf = NULL;
1153
+ passphrase_size = 0;
1154
+ break;
1155
+
1156
+ case T_STRING:
1157
+ passphrase_buf = StringValuePtr(passphrase);
1158
+
1159
+ // long passphrase_length = rb_str_length(passphrase);
1160
+ long passphrase_length = strnlen(passphrase_buf, RBSRT_PASSPHRASE_MAX * 2);
1161
+ passphrase_size = (int)passphrase_length + 1;
1162
+
1163
+ if (passphrase_buf == 0)
1164
+ {
1165
+ passphrase_buf = NULL;
1166
+ passphrase_size = 0;
1167
+ }
1168
+
1169
+ else if (passphrase_length != 0 && (passphrase_length < RBSRT_PASSPHRASE_MIN || passphrase_length > RBSRT_PASSPHRASE_MAX))
1170
+ {
1171
+ printf("PASSPHASE: %s", passphrase_buf);
1172
+ rb_raise(rb_eArgError, "passphrase must be between %d and %d characters or empty (got %ld)", RBSRT_PASSPHRASE_MIN, RBSRT_PASSPHRASE_MAX, passphrase_length);
1173
+
1174
+ return Qfalse;
1175
+ }
1176
+
1177
+
1178
+ break;
1179
+
1180
+ default:
1181
+ Check_Type(passphrase, T_STRING);
1182
+ return Qfalse;
1183
+ break;
1184
+ }
1185
+
1186
+ RBSRT_SOCKET_BASE_UNWRAP(self, socket);
1187
+
1188
+ if (srt_setsockflag(socket->socket, SRTO_PASSPHRASE, passphrase_buf, passphrase_size) == SRT_ERROR)
1189
+ {
1190
+ rbsrt_raise_last_srt_error();
1191
+
1192
+ return Qfalse;
1193
+ }
1194
+
1195
+ return Qtrue;
1196
+ }
1197
+
1198
+
1199
+ // MARK: Base Socket API
1200
+
1201
+ void rbsrt_socket_base_define_base_api(VALUE klass)
1202
+ {
1203
+ rb_define_method(klass, "id", rbsrt_socket_get_id, 0);
1204
+
1205
+ rb_define_method(klass, "read_sync=", rbsrt_socket_set_rcvsyn, 1);
1206
+ rb_define_method(klass, "read_sync?", rbsrt_socket_get_rcvsyn, 0);
1207
+ rb_alias(klass, rb_intern("rcvsyn="), rb_intern("read_sync="));
1208
+ rb_alias(klass, rb_intern("rcvsyn?"), rb_intern("read_sync?"));
1209
+
1210
+ rb_define_method(klass, "passphrase=", rbsrt_socket_set_passphrase, 1);
1211
+ rb_alias(klass, rb_intern("password="), rb_intern("passphrase="));
1212
+ }
1213
+
1214
+ void rbsrt_socket_base_define_option_api(VALUE klass)
1215
+ {
1216
+ rb_define_method(klass, "write_sync=", rbsrt_socket_set_sndsyn, 1);
1217
+ rb_define_method(klass, "write_sync?", rbsrt_socket_get_sndsyn, 0);
1218
+ rb_alias(klass, rb_intern("sndsyn="), rb_intern("write_sync="));
1219
+ rb_alias(klass, rb_intern("sndsyn?"), rb_intern("write_sync?"));
1220
+
1221
+ rb_define_method(klass, "streamid=", rbsrt_socket_set_streamid, 1);
1222
+ rb_define_method(klass, "streamid", rbsrt_socket_get_streamid, 0);
1223
+
1224
+ rb_define_method(klass, "transmission_mode=", rbsrt_socket_set_transtype, 1);
1225
+ rb_alias(klass, rb_intern("trans_mode="), rb_intern("transmission_mode="));
1226
+ rb_alias(klass, rb_intern("transtype="), rb_intern("transmission_mode="));
1227
+
1228
+
1229
+ rb_define_method(klass, "timestamp_based_packet_delivery_mode=", rbsrt_socket_set_tsbpdmode, 1);
1230
+ rb_define_method(klass, "timestamp_based_packet_delivery_mode?", rbsrt_socket_get_tsbpdmode, 0);
1231
+ rb_alias(klass, rb_intern("tsbpdmode="), rb_intern("timestamp_based_packet_delivery_mode="));
1232
+ rb_alias(klass, rb_intern("tsbpdmode?"), rb_intern("timestamp_based_packet_delivery_mode?"));
1233
+ }
1234
+
1235
+ void rbsrt_socket_base_define_basic_api(VALUE klass)
1236
+ {
1237
+ rb_define_method(klass, "close", rbsrt_socket_close, 0);
1238
+ }
1239
+
1240
+ void rbsrt_socket_base_define_connection_api(VALUE klass)
1241
+ {
1242
+ rb_define_method(klass, "connect", rbsrt_socket_connect, 2);
1243
+ }
1244
+
1245
+ void rbsrt_socket_base_define_io_api(VALUE klass)
1246
+ {
1247
+ rb_define_method(klass, "recvmsg", rbsrt_socket_recvmsg, 0);
1248
+ rb_alias(klass, rb_intern("read"), rb_intern("recvmsg"));
1249
+
1250
+ rb_define_method(klass, "sendmsg", rbsrt_socket_sendmsg, 1);
1251
+ rb_alias(klass, rb_intern("write"), rb_intern("sendmsg"));
1252
+ }
1253
+
1254
+
1255
+
1256
+ // MARK: - SRT::Socket Class
1257
+
1258
+ size_t rbsrt_socket_dsize(const void *socket)
1259
+ {
1260
+ RBSRT_DEBUG_PRINT("dsize srt socket");
1261
+
1262
+ return sizeof(rbsrt_client_t);
1263
+ }
1264
+
1265
+ void rbsrt_socket_dmark(void *socket)
1266
+ {
1267
+ RBSRT_DEBUG_PRINT("dmark srt socket");
1268
+ }
1269
+
1270
+
1271
+ // MARK: Initializers
1272
+
1273
+ void rbsrt_socket_deallocate(rbsrt_socket_t *socket)
1274
+ {
1275
+ RBSRT_DEBUG_PRINT("deallocate srt socket");
1276
+
1277
+ srt_close(socket->socket); // TODO: Check socket state before closing
1278
+
1279
+ free(socket);
1280
+ }
1281
+
1282
+ VALUE rbsrt_socket_allocate(VALUE klass)
1283
+ {
1284
+ RBSRT_DEBUG_PRINT("allocate socket");
1285
+
1286
+ rbsrt_socket_t *socket = malloc(sizeof(rbsrt_socket_t));
1287
+
1288
+ memset(socket, 0, sizeof(rbsrt_socket_t));
1289
+
1290
+ return TypedData_Wrap_Struct(klass, &rbsrt_socket_rbtype, socket);
1291
+ }
1292
+
1293
+ VALUE rbsrt_socket_initialize(VALUE self)
1294
+ {
1295
+ RBSRT_DEBUG_PRINT("initialize socket");
1296
+
1297
+ RBSRT_SOCKET_UNWRAP(self, socket);
1298
+
1299
+ socket->socket = srt_create_socket();
1300
+
1301
+ int livemode = SRTT_LIVE;
1302
+
1303
+ srt_setsockflag(socket->socket, SRTO_TRANSTYPE, &livemode, sizeof(livemode)); // set live mode
1304
+
1305
+ return self;
1306
+ }
1307
+
1308
+
1309
+
1310
+ // MARK: - SRT::Connection Class
1311
+
1312
+ // MARK: Ruby Type Helpers
1313
+
1314
+ size_t rbsrt_connection_dsize(const void *server)
1315
+ {
1316
+ RBSRT_DEBUG_PRINT("connection dsize");
1317
+
1318
+ return sizeof(rbsrt_connection_t);
1319
+ }
1320
+
1321
+ void rbsrt_connection_dmark(void *data)
1322
+ {
1323
+ RBSRT_DEBUG_PRINT("connection mark");
1324
+
1325
+ rbsrt_connection_t *connection = (rbsrt_connection_t *)data;
1326
+
1327
+ if (connection->at_data_block)
1328
+ {
1329
+ rb_gc_mark(connection->at_data_block);
1330
+ }
1331
+
1332
+ if (connection->at_close_block)
1333
+ {
1334
+ rb_gc_mark(connection->at_close_block);
1335
+ }
1336
+ }
1337
+
1338
+
1339
+ // MARK: Initializers
1340
+
1341
+ VALUE rbsrt_connection_allocate(VALUE klass)
1342
+ {
1343
+ RBSRT_DEBUG_PRINT("connection allocate");
1344
+
1345
+ rbsrt_connection_t *connection = malloc(sizeof(rbsrt_connection_t));
1346
+
1347
+ memset(connection, 0, sizeof(rbsrt_connection_t));
1348
+
1349
+ return TypedData_Wrap_Struct(klass, &rbsrt_connection_rbtype, connection);
1350
+ }
1351
+
1352
+ void rbsrt_connection_deallocate(rbsrt_connection_t *connection)
1353
+ {
1354
+ RBSRT_DEBUG_PRINT("connection deallocate");
1355
+
1356
+ free(connection);
1357
+ }
1358
+
1359
+
1360
+ // MARK: API
1361
+
1362
+ VALUE rbsrt_connection_set_at_data_block(VALUE self)
1363
+ {
1364
+ RBSRT_DEBUG_PRINT("connection set data block");
1365
+
1366
+ rb_need_block();
1367
+
1368
+ RBSRT_CONNECTION_UNWRAP(self, connection);
1369
+
1370
+ connection->at_data_block = rb_block_proc();
1371
+
1372
+ return Qtrue;
1373
+ }
1374
+
1375
+ VALUE rbsrt_connection_set_at_close_block(VALUE self)
1376
+ {
1377
+ RBSRT_DEBUG_PRINT("connection set close block");
1378
+
1379
+ rb_need_block();
1380
+
1381
+ RBSRT_CONNECTION_UNWRAP(self, connection);
1382
+
1383
+ connection->at_close_block = rb_block_proc();
1384
+
1385
+ return Qtrue;
1386
+ }
1387
+
1388
+ // MARK: - SRT::Server Class
1389
+
1390
+ // MARK: Ruby Type Helpers
1391
+
1392
+ size_t rbsrt_server_dsize(const void *server)
1393
+ {
1394
+ RBSRT_DEBUG_PRINT("server dsize");
1395
+
1396
+ return sizeof(rbsrt_server_t);
1397
+ }
1398
+
1399
+ void rbsrt_server_dmark(void *data)
1400
+ {
1401
+ RBSRT_DEBUG_PRINT("server mark");
1402
+
1403
+ rbsrt_server_t *server = (rbsrt_server_t *)data;
1404
+
1405
+ if (server->acceptor_block)
1406
+ {
1407
+ rb_gc_mark(server->acceptor_block);
1408
+ }
1409
+ }
1410
+
1411
+
1412
+ // MARK: Utils
1413
+
1414
+ #define RBSRT_SERVER_NUM_CONNECTIONS(server) (size_t)atomic_load(&server->num_connections)
1415
+
1416
+
1417
+ // MARK: SRT
1418
+
1419
+ int rbsrt_server_listen_callback(void* context, SRTSOCKET remote_socket, int hs_version, const struct sockaddr* peeraddr, const char* streamid)
1420
+ {
1421
+ // TODO: Call into ruby and allow pre-setup of the socket
1422
+
1423
+ return 1;
1424
+ }
1425
+
1426
+
1427
+ // MARK: Initializers
1428
+
1429
+ void rbsrt_server_deallocate(rbsrt_server_t *server)
1430
+ {
1431
+ RBSRT_DEBUG_PRINT("deallocate srt server");
1432
+
1433
+ SRT_SOCKSTATUS status = srt_getsockstate(server->socket);
1434
+
1435
+ if (status != SRTS_CLOSED || status != SRTS_CLOSING)
1436
+ {
1437
+ srt_close(server->socket);
1438
+ }
1439
+
1440
+ free(server);
1441
+ }
1442
+
1443
+ VALUE rbsrt_server_allocate(VALUE klass)
1444
+ {
1445
+ RBSRT_DEBUG_PRINT("server allocate");
1446
+
1447
+ rbsrt_server_t *server = malloc(sizeof(rbsrt_server_t));
1448
+
1449
+ memset(server, 0, sizeof(rbsrt_server_t));
1450
+
1451
+ return TypedData_Wrap_Struct(klass, &rbsrt_server_rbtype, server);
1452
+ }
1453
+
1454
+ VALUE rbsrt_server_initialize(VALUE self, VALUE address, VALUE port)
1455
+ {
1456
+ RBSRT_DEBUG_PRINT("server initialize");
1457
+
1458
+ rbsrt_server_t *server;
1459
+ int status;
1460
+ struct sockaddr_in sa;
1461
+ int livemode = SRTT_LIVE;
1462
+ int no = 1;
1463
+
1464
+ Check_Type(address, T_STRING);
1465
+ Check_Type(port, T_STRING);
1466
+
1467
+ TypedData_Get_Struct(self, rbsrt_server_t, &rbsrt_server_rbtype, server);
1468
+
1469
+ // Initialize struct
1470
+
1471
+ atomic_init(&server->num_connections, 0);
1472
+
1473
+
1474
+ // Ruby API
1475
+
1476
+ VALUE connections_by_socket = rb_hash_new();
1477
+
1478
+ rb_hash_clear(connections_by_socket);
1479
+
1480
+ rb_ivar_set(self, rb_intern("@connections_by_socket"), connections_by_socket);
1481
+
1482
+
1483
+ // create socket
1484
+
1485
+ server->socket = srt_create_socket();
1486
+
1487
+ if (server->socket == SRT_ERROR)
1488
+ {
1489
+ rb_raise(rb_eStandardError, "%s", srt_getlasterror_str());
1490
+
1491
+ return Qfalse;
1492
+ }
1493
+
1494
+
1495
+ // get address info
1496
+
1497
+ sa.sin_family = AF_INET;
1498
+ sa.sin_port = htons(atoi(StringValuePtr(port)));
1499
+
1500
+ if (inet_pton(AF_INET, StringValuePtr(address), &sa.sin_addr) != 1)
1501
+ {
1502
+ rb_raise(rb_eArgError, "bad adddress: %s", strerror(errno));
1503
+
1504
+ return Qfalse;
1505
+ }
1506
+
1507
+
1508
+ // set up socket
1509
+
1510
+ srt_setsockflag(server->socket, SRTO_TRANSTYPE, &livemode, sizeof(livemode)); // set live mode
1511
+ srt_setsockflag(server->socket, SRTO_RCVSYN, &no, sizeof(no)); // non-blocking mode
1512
+ srt_setsockflag(server->socket, SRTO_SNDSYN, &no, sizeof(no));
1513
+
1514
+
1515
+ // set up callback
1516
+
1517
+ srt_listen_callback(server->socket, rbsrt_server_listen_callback, (void *)self);
1518
+
1519
+
1520
+ // bind server
1521
+
1522
+ status = srt_bind(server->socket, (struct sockaddr *)&sa, sizeof(sa));
1523
+
1524
+ if (status == SRT_ERROR)
1525
+ {
1526
+ rb_raise(rb_eStandardError, "%s", srt_getlasterror_str());
1527
+
1528
+ return Qfalse;
1529
+ }
1530
+
1531
+
1532
+ // listen
1533
+
1534
+ status = srt_listen(server->socket, 6); // TODO: Pass backlog size
1535
+
1536
+ if (status == SRT_ERROR)
1537
+ {
1538
+ rb_raise(rb_eStandardError, "%s", srt_getlasterror_str());
1539
+
1540
+ return Qfalse;
1541
+ }
1542
+
1543
+ return self;
1544
+ }
1545
+
1546
+ VALUE rbsrt_server_close(VALUE self)
1547
+ {
1548
+ RBSRT_DEBUG_PRINT("server close");
1549
+
1550
+ RBSRT_SERVER_UNWRAP(self, server);
1551
+
1552
+ if (srt_close(server->socket) == SRT_ERROR)
1553
+ {
1554
+ rbsrt_raise_last_srt_error();
1555
+ }
1556
+
1557
+ server->flags &= ~ (RBSRT_SERVER_ACCEPTING | RBSRT_SERVER_BOUND | RBSRT_SERVER_LISTENING);
1558
+ server->flags |= RBSRT_SERVER_CLOSED;
1559
+
1560
+ return Qnil;
1561
+ }
1562
+
1563
+ struct rbsrt_server_epoll_wait_args
1564
+ {
1565
+ rbsrt_server_t *server;
1566
+ int64_t timeout;
1567
+ int num_events;
1568
+ SRT_EPOLL_EVENT *events;
1569
+ };
1570
+
1571
+ void *rbsrt_server_epoll_wait(void *args)
1572
+ {
1573
+ struct rbsrt_server_epoll_wait_args *arg = args;
1574
+
1575
+ int num_events = srt_epoll_uwait(arg->server->epollid, arg->events, arg->num_events, arg->timeout);
1576
+
1577
+ return (void *)(uintptr_t)num_events;
1578
+ }
1579
+
1580
+ VALUE rbsrt_server_connection_count(VALUE self)
1581
+ {
1582
+ RBSRT_SERVER_UNWRAP(self, server);
1583
+
1584
+ return SIZET2NUM(RBSRT_SERVER_NUM_CONNECTIONS(server));
1585
+ }
1586
+
1587
+ VALUE rbsrt_server_start(VALUE self)
1588
+ {
1589
+ RBSRT_DEBUG_PRINT("server start");
1590
+
1591
+ rb_need_block();
1592
+
1593
+ RBSRT_SERVER_UNWRAP(self, server);
1594
+
1595
+ // rb_iv_set(self, rb_intern("acceptor_block"), rb_block_proc());
1596
+
1597
+ server->acceptor_block = rb_block_proc();
1598
+
1599
+ server->epollid = srt_epoll_create();
1600
+
1601
+ int event_types = SRT_EPOLL_IN;
1602
+
1603
+ srt_epoll_add_usock(server->epollid, server->socket, &event_types);
1604
+
1605
+ SRT_EPOLL_EVENT events[1024];
1606
+
1607
+ struct rbsrt_server_epoll_wait_args args = {
1608
+ .server = server,
1609
+ .timeout = 100,
1610
+ .num_events = 1024,
1611
+ .events = events
1612
+ };
1613
+
1614
+ struct sockaddr_storage remote_address;
1615
+ int addr_size = sizeof(remote_address);
1616
+ int remote_fd;
1617
+ int running = 1;
1618
+
1619
+ VALUE connections_by_socket = rb_ivar_get(self, rb_intern("@connections_by_socket"));
1620
+
1621
+ while (running)
1622
+ {
1623
+ int num_events = (int)(uintptr_t)rb_thread_call_without_gvl(rbsrt_server_epoll_wait, &args, RUBY_UBF_IO, 0);
1624
+
1625
+ if (num_events <= 0)
1626
+ {
1627
+ continue; // timeout
1628
+ }
1629
+
1630
+ int read_buf_size = RBSRT_PAYLOAD_SIZE * 8;
1631
+ char read_buf[read_buf_size];
1632
+ int nbytes;
1633
+
1634
+ // SRT_MSGCTRL msgctl;
1635
+ SRT_EPOLL_EVENT *event;
1636
+ SRTSOCKET sock;
1637
+ SRT_SOCKSTATUS status;
1638
+ rbsrt_connection_t *connection;
1639
+
1640
+ VALUE rb_connection;
1641
+
1642
+ int no = 0;
1643
+ int no_size = sizeof(no);
1644
+ int connection_epoll_events = SRT_EPOLL_OUT | SRT_EPOLL_IN | SRT_EPOLL_ERR;
1645
+
1646
+ for (int i = 0; i < num_events; i++)
1647
+ {
1648
+ event = &args.events[i];
1649
+ sock = event->fd;
1650
+ status = srt_getsockstate(sock);
1651
+
1652
+ switch (status)
1653
+ {
1654
+ // accept connections
1655
+ case SRTS_LISTENING:
1656
+
1657
+ remote_fd = srt_accept(sock, (struct sockaddr *)&remote_address, &addr_size);
1658
+
1659
+ srt_setsockflag(remote_fd, SRTO_RCVSYN, &no, no_size);
1660
+ srt_setsockflag(remote_fd, SRTO_SNDSYN, &no, no_size);
1661
+
1662
+ connection = malloc(sizeof(rbsrt_connection_t));
1663
+
1664
+ memset(connection, 0, sizeof(rbsrt_connection_t));
1665
+
1666
+ rb_connection = TypedData_Make_Struct(mSRTConnectionKlass, rbsrt_connection_t, &rbsrt_connection_rbtype, connection);
1667
+
1668
+ connection->socket = remote_fd;
1669
+
1670
+ VALUE should_accept = rb_funcall_with_block(self, rb_intern("instance_exec"), 1, &rb_connection, server->acceptor_block);
1671
+
1672
+ if (RTEST(should_accept))
1673
+ {
1674
+ srt_epoll_add_usock(server->epollid, connection->socket, &connection_epoll_events);
1675
+
1676
+ atomic_fetch_add(&server->num_connections, 1);
1677
+
1678
+ rb_hash_aset(connections_by_socket, INT2FIX(connection->socket), rb_connection);
1679
+ }
1680
+
1681
+ else
1682
+ {
1683
+ atomic_fetch_sub(&server->num_connections, 1);
1684
+
1685
+ srt_close(remote_fd);
1686
+ }
1687
+
1688
+ break;
1689
+
1690
+ case SRTS_CLOSED:
1691
+ case SRTS_NONEXIST:
1692
+ case SRTS_BROKEN:
1693
+ RBSRT_DEBUG_PRINT("removing connection with socket: %d", sock);
1694
+
1695
+ srt_epoll_remove_usock(server->epollid, sock);
1696
+
1697
+ rb_connection = rb_hash_delete(connections_by_socket, INT2FIX(sock));
1698
+
1699
+ if (RTEST(rb_connection))
1700
+ {
1701
+ if (atomic_fetch_sub(&server->num_connections, 1) == 0)
1702
+ {
1703
+ DEBUG_ERROR_PRINT("removed to many connections");
1704
+ }
1705
+
1706
+ RBSRT_DEBUG_PRINT("remove connection with socket %d, now %lu sockets", sock, RBSRT_SERVER_NUM_CONNECTIONS(server));
1707
+
1708
+ RBSRT_CONNECTION_UNWRAP(rb_connection, removed_connection);
1709
+
1710
+ if (removed_connection->at_close_block)
1711
+ {
1712
+ rb_funcall(removed_connection->at_close_block, rb_intern("call"), 0);
1713
+
1714
+ removed_connection->at_close_block = 0;
1715
+ }
1716
+
1717
+ if (removed_connection->at_data_block)
1718
+ {
1719
+ removed_connection->at_data_block = 0;
1720
+ }
1721
+ }
1722
+
1723
+ break;
1724
+
1725
+ case SRTS_CONNECTED:
1726
+ if (event->events & SRT_EPOLL_IN)
1727
+ {
1728
+ RBSRT_DEBUG_PRINT("will read from socket %d (max bytes %d)", sock, read_buf_size);
1729
+
1730
+ nbytes = srt_recvmsg2(event->fd, read_buf, read_buf_size, NULL);
1731
+
1732
+ if (nbytes == SRT_ERROR)
1733
+ {
1734
+ RBSRT_DEBUG_PRINT("failed to read from socket %d: %s", sock, srt_getlasterror_str());
1735
+
1736
+ break;
1737
+ }
1738
+
1739
+ if (nbytes > 0)
1740
+ {
1741
+ RBSRT_DEBUG_PRINT("received %d bytes from socket %d", nbytes, sock);
1742
+
1743
+ rb_connection = rb_hash_lookup(connections_by_socket, INT2FIX(sock));
1744
+
1745
+ if (RTEST(rb_connection))
1746
+ {
1747
+ RBSRT_DEBUG_PRINT("found connection for socket %d", sock);
1748
+
1749
+ TypedData_Get_Struct(rb_connection, rbsrt_connection_t, &rbsrt_connection_rbtype, connection);
1750
+
1751
+ if (connection->at_data_block)
1752
+ {
1753
+ RBSRT_DEBUG_PRINT("found data handler for socket %d", sock);
1754
+
1755
+ VALUE data = rb_str_new(read_buf, nbytes);
1756
+
1757
+ rb_funcall(connection->at_data_block, rb_intern("call"), 1, data);
1758
+ }
1759
+ }
1760
+ }
1761
+ }
1762
+
1763
+ // TODO: Handle other events
1764
+ break;
1765
+
1766
+ default:
1767
+ break;
1768
+ }
1769
+ }
1770
+ }
1771
+
1772
+ return Qtrue;
1773
+ }
1774
+
1775
+
1776
+ // MARK: Connections
1777
+
1778
+ VALUE rbsrt_server_accept(VALUE self)
1779
+ {
1780
+ RBSRT_DEBUG_PRINT("server accept");
1781
+
1782
+ RBSRT_SERVER_UNWRAP(self, server);
1783
+
1784
+ // Data_Get_Struct(self, rbsrt_server_t, server);
1785
+ TypedData_Get_Struct(self, rbsrt_server_t, &rbsrt_server_rbtype, server);
1786
+
1787
+ struct sockaddr_storage remote_address;
1788
+ int addr_size = sizeof(remote_address);
1789
+
1790
+ SRTSOCKET socket = srt_accept(server->socket, (struct sockaddr *)&remote_address, &addr_size);
1791
+
1792
+ VALUE rbclient = rb_class_new_instance(0, NULL, mSRTClientKlass);
1793
+
1794
+ rbsrt_client_t *client;
1795
+
1796
+ Data_Get_Struct(rbclient, rbsrt_client_t, client);
1797
+
1798
+ client->socket = socket;
1799
+
1800
+ client->flags |= RBSRT_CLIENT_CONNECTED;
1801
+
1802
+ return rbclient;
1803
+ }
1804
+
1805
+
1806
+
1807
+ // MARK: - SRT::Client Class
1808
+
1809
+ // MARK: Ruby Type Helpers
1810
+
1811
+ size_t rbsrt_client_dsize(const void *client)
1812
+ {
1813
+ RBSRT_DEBUG_PRINT("dsize srt client");
1814
+
1815
+ return sizeof(rbsrt_client_t);
1816
+ }
1817
+
1818
+ void rbsrt_client_dmark(void *client)
1819
+ {
1820
+ RBSRT_DEBUG_PRINT("dmark srt client");
1821
+ }
1822
+
1823
+
1824
+ // MARK: Initializers
1825
+
1826
+ void rbsrt_client_deallocate(rbsrt_client_t *client)
1827
+ {
1828
+ RBSRT_DEBUG_PRINT("deallocate srt client");
1829
+
1830
+ SRT_SOCKSTATUS status = srt_getsockstate(client->socket);
1831
+
1832
+ switch (status)
1833
+ {
1834
+
1835
+ case SRTS_CONNECTED:
1836
+ case SRTS_CONNECTING:
1837
+ case SRTS_OPENED:
1838
+ srt_close(client->socket);
1839
+
1840
+ break;
1841
+
1842
+ default:
1843
+ break;
1844
+ }
1845
+
1846
+ free(client);
1847
+ }
1848
+
1849
+ VALUE rbsrt_client_allocate(VALUE klass)
1850
+ {
1851
+ RBSRT_DEBUG_PRINT("allocate client");
1852
+
1853
+ rbsrt_client_t *client = malloc(sizeof(rbsrt_client_t));
1854
+
1855
+ memset(client, 0, sizeof(rbsrt_client_t));
1856
+
1857
+ return TypedData_Wrap_Struct(klass, &rbsrt_client_rbtype, client);
1858
+ }
1859
+
1860
+ VALUE rbsrt_client_initialize(VALUE self)
1861
+ {
1862
+ RBSRT_DEBUG_PRINT("initialize client");
1863
+
1864
+ RBSRT_CLIENT_UNWRAP(self, client);
1865
+
1866
+ client->socket = srt_create_socket();
1867
+
1868
+ return self;
1869
+ }
1870
+
1871
+
1872
+ // MARK: - SRT::Poll Klass
1873
+
1874
+ size_t rbsrt_poll_dsize(const void *poll)
1875
+ {
1876
+ return sizeof(rbsrt_poll_t);
1877
+ }
1878
+
1879
+ void rbsrt_poll_dmark(void *data)
1880
+ {
1881
+ rbsrt_poll_t *poll = (rbsrt_poll_t *)data;
1882
+
1883
+ if (poll->sockets_by_id)
1884
+ {
1885
+ rb_gc_mark(poll->sockets_by_id);
1886
+ }
1887
+ }
1888
+
1889
+ void rbsrt_poll_deallocate(rbsrt_poll_t *poll)
1890
+ {
1891
+ RBSRT_DEBUG_PRINT("deallocate poll");
1892
+
1893
+ srt_epoll_release(poll->epollid);
1894
+
1895
+ free(poll);
1896
+ }
1897
+
1898
+ int rbsrt_epoll_event_with_splat(VALUE splat, long splat_len)
1899
+ {
1900
+ int events = 0;
1901
+
1902
+ for (long i = 0; i < splat_len; i++)
1903
+ {
1904
+ VALUE event_type = rb_ary_entry(splat, i);
1905
+
1906
+ ID event_id = rb_to_id(event_type);
1907
+
1908
+ if (event_id == rb_intern("in") || event_id == rb_intern("read"))
1909
+ {
1910
+ RBSRT_DEBUG_PRINT("poll add SRT_EPOLL_IN");
1911
+
1912
+ events |= SRT_EPOLL_IN;
1913
+ }
1914
+
1915
+ else if (event_id == rb_intern("out") || event_id == rb_intern("write"))
1916
+ {
1917
+ RBSRT_DEBUG_PRINT("poll add SRT_EPOLL_OUT");
1918
+
1919
+ events |= SRT_EPOLL_OUT;
1920
+ }
1921
+
1922
+ else if (event_id == rb_intern("err") || event_id == rb_intern("error"))
1923
+ {
1924
+ RBSRT_DEBUG_PRINT("poll add SRT_EPOLL_ERR");
1925
+
1926
+ events |= SRT_EPOLL_ERR;
1927
+ }
1928
+
1929
+ else if (event_id == rb_intern("et") || event_id == rb_intern("edge"))
1930
+ {
1931
+ RBSRT_DEBUG_PRINT("poll add SRT_EPOLL_ET");
1932
+
1933
+ events |= SRT_EPOLL_ET;
1934
+ }
1935
+
1936
+ else
1937
+ {
1938
+ rb_raise(rb_eArgError, "poll event must be one of: :in, :out, :err, :edge");
1939
+ }
1940
+ }
1941
+
1942
+ return events;
1943
+ }
1944
+
1945
+ VALUE rbsrt_poll_allocate(VALUE klass)
1946
+ {
1947
+ RBSRT_DEBUG_PRINT("allocate poll");
1948
+
1949
+ rbsrt_poll_t *poll = malloc(sizeof(rbsrt_poll_t));
1950
+
1951
+ memset(poll, 0, sizeof(rbsrt_poll_t));
1952
+
1953
+ return TypedData_Wrap_Struct(klass, &rbsrt_poll_rbtype, poll);
1954
+ }
1955
+
1956
+ VALUE rbsrt_poll_initialize(VALUE self)
1957
+ {
1958
+ RBSRT_DEBUG_PRINT("initialize poll");
1959
+
1960
+ RBSRT_POLL_UNWRAP(self, poll);
1961
+
1962
+ poll->epollid = srt_epoll_create();
1963
+
1964
+ VALUE objects_by_socket = rb_hash_new();
1965
+
1966
+ rb_hash_clear(objects_by_socket);
1967
+
1968
+ rb_ivar_set(self, rb_intern("@sockets"), objects_by_socket);
1969
+
1970
+ return self;
1971
+ }
1972
+
1973
+ VALUE rbsrt_poll_remove_socket(VALUE self, VALUE socket_to_remove)
1974
+ {
1975
+ RBSRT_DEBUG_PRINT("poll remove socket");
1976
+
1977
+ RBSRT_POLL_UNWRAP(self, poll);
1978
+
1979
+ RBSRT_SOCKET_BASE_UNWRAP(socket_to_remove, socket);
1980
+
1981
+ VALUE sockets = rb_ivar_get(self, rb_intern("@sockets"));
1982
+
1983
+ VALUE removed_socket = rb_hash_delete(sockets, INT2FIX(socket->socket));
1984
+
1985
+ if (srt_epoll_remove_usock(poll->epollid, socket->socket) == SRT_ERROR)
1986
+ {
1987
+ rbsrt_raise_last_srt_error();
1988
+ }
1989
+
1990
+ return removed_socket;
1991
+ }
1992
+
1993
+ VALUE rbsrt_poll_add_socket(int argc, VALUE* argv, VALUE self)
1994
+ {
1995
+ RBSRT_DEBUG_PRINT("poll add socket");
1996
+
1997
+ RBSRT_POLL_UNWRAP(self, poll);
1998
+
1999
+ VALUE arg1;
2000
+ VALUE splat;
2001
+
2002
+ rb_scan_args(argc, argv, "1*", &arg1, &splat);
2003
+
2004
+ RBSRT_SOCKET_BASE_UNWRAP(arg1, socket);
2005
+
2006
+ int events = rbsrt_epoll_event_with_splat(splat, rb_array_len(splat));
2007
+
2008
+ if (srt_epoll_add_usock(poll->epollid, socket->socket, &events) == SRT_ERROR)
2009
+ {
2010
+ rbsrt_raise_last_srt_error();
2011
+ }
2012
+
2013
+ VALUE sockets = rb_ivar_get(self, rb_intern("@sockets"));
2014
+
2015
+ rb_hash_aset(sockets, INT2FIX(socket->socket), arg1);
2016
+
2017
+ return self;
2018
+ }
2019
+
2020
+ VALUE rbsrt_poll_update_socket(int argc, VALUE* argv, VALUE self)
2021
+ {
2022
+ RBSRT_DEBUG_PRINT("poll update socket");
2023
+
2024
+ RBSRT_POLL_UNWRAP(self, poll);
2025
+
2026
+ VALUE arg1;
2027
+ VALUE splat;
2028
+
2029
+ rb_scan_args(argc, argv, "1*", &arg1, &splat);
2030
+
2031
+ int events = rbsrt_epoll_event_with_splat(splat, rb_array_len(splat));
2032
+
2033
+ RBSRT_SOCKET_BASE_UNWRAP(arg1, socket);
2034
+
2035
+ if (srt_epoll_update_usock(poll->epollid, socket->socket, &events) == SRT_ERROR)
2036
+ {
2037
+ rbsrt_raise_last_srt_error();
2038
+ }
2039
+
2040
+ return Qnil;
2041
+ }
2042
+
2043
+ typedef struct RBSRTPollWaitArg
2044
+ {
2045
+ int epollid;
2046
+ int timeout;
2047
+ int num_sockets;
2048
+ int num_events;
2049
+ SRT_EPOLL_EVENT *events;
2050
+ } rbsrt_poll_wait_arg_t;
2051
+
2052
+ void *rbsrt_poll_wait_without_gvl(void *context)
2053
+ {
2054
+ rbsrt_poll_wait_arg_t *arg = (rbsrt_poll_wait_arg_t *)context;
2055
+
2056
+ arg->num_events = srt_epoll_uwait(arg->epollid, arg->events, arg->num_sockets, arg->timeout);
2057
+
2058
+ return arg;
2059
+ }
2060
+
2061
+ VALUE rbsrt_poll_wait(int argc, VALUE* argv, VALUE self)
2062
+ {
2063
+ RBSRT_DEBUG_PRINT("poll wait");
2064
+
2065
+ RBSRT_POLL_UNWRAP(self, poll);
2066
+
2067
+ VALUE timeout;
2068
+ VALUE block;
2069
+
2070
+ rb_scan_args(argc, argv, "01&", &timeout, &block);
2071
+
2072
+ int epoll_timeout;
2073
+
2074
+ if (!NIL_P(timeout))
2075
+ {
2076
+ Check_Type(timeout, T_FIXNUM);
2077
+
2078
+ epoll_timeout = FIX2INT(timeout);
2079
+ }
2080
+
2081
+ else
2082
+ {
2083
+ epoll_timeout = -1;
2084
+ }
2085
+
2086
+ VALUE sockets = rb_ivar_get(self, rb_intern("@sockets"));
2087
+ int num_sockets = FIX2INT(rb_hash_size(sockets));
2088
+
2089
+ SRT_EPOLL_EVENT events[num_sockets < 8 ? 8 : num_sockets + 8];
2090
+
2091
+ VALUE readables = rb_ary_new();
2092
+ VALUE writables = rb_ary_new();
2093
+ VALUE errors = rb_ary_new();
2094
+
2095
+ rbsrt_poll_wait_arg_t arg = {
2096
+ .epollid = poll->epollid,
2097
+ .timeout = epoll_timeout,
2098
+ .num_sockets = num_sockets,
2099
+ .num_events = 0,
2100
+ .events = events
2101
+ };
2102
+
2103
+ rb_thread_call_without_gvl(rbsrt_poll_wait_without_gvl, &arg, RUBY_UBF_IO, NULL);
2104
+
2105
+ RBSRT_DEBUG_PRINT("poll did wait");
2106
+
2107
+ for (int i = 0; i < arg.num_events; i++)
2108
+ {
2109
+ SRT_EPOLL_EVENT *event = &events[i];
2110
+
2111
+ VALUE sock = rb_hash_aref(sockets, INT2FIX(event->fd));
2112
+
2113
+ if (!RTEST(sock))
2114
+ {
2115
+ RBSRT_DEBUG_PRINT("poll matched socket not in socket list");
2116
+
2117
+ // TODO: remove unknown socket
2118
+
2119
+ continue;
2120
+ }
2121
+
2122
+ if (event->events & SRT_EPOLL_IN)
2123
+ {
2124
+ RBSRT_DEBUG_PRINT("poll add readables");
2125
+
2126
+ rb_ary_push(readables, sock);
2127
+ }
2128
+
2129
+ if (event->events & SRT_EPOLL_OUT)
2130
+ {
2131
+ RBSRT_DEBUG_PRINT("poll add writables");
2132
+
2133
+ rb_ary_push(writables, sock);
2134
+ }
2135
+
2136
+ if (event->events & SRT_EPOLL_ERR)
2137
+ {
2138
+ RBSRT_DEBUG_PRINT("poll add error");
2139
+
2140
+ rb_ary_push(errors, sock);
2141
+ }
2142
+ }
2143
+
2144
+ if (rb_block_given_p())
2145
+ {
2146
+ rb_yield_values(3, readables, writables, errors);
2147
+
2148
+ return Qtrue;
2149
+ }
2150
+
2151
+ return rb_ary_new_from_args(3, readables, writables, errors);
2152
+ }
2153
+
2154
+
2155
+
2156
+ // MARK: - Ruby Module
2157
+
2158
+ void Init_rbsrt()
2159
+ {
2160
+ // toplevel SRT module
2161
+
2162
+ mSRTModule = rb_define_module("SRT");
2163
+
2164
+ rb_define_const(mSRTModule, "SRT_VERSION", rb_str_new_cstr(SRT_VERSION_STRING));
2165
+
2166
+
2167
+ // SRT::Errors
2168
+
2169
+ rbsrt_init_errors();
2170
+
2171
+
2172
+ // SRT::Socket Class
2173
+
2174
+ mSRTSocketKlass = rb_define_class_under(mSRTModule, "Socket", rb_cObject);
2175
+
2176
+ rb_define_alloc_func(mSRTSocketKlass, rbsrt_socket_allocate);
2177
+
2178
+ rb_define_method(mSRTSocketKlass, "initialize", rbsrt_socket_initialize, 0);
2179
+
2180
+ rbsrt_socket_base_define_basic_api(mSRTSocketKlass);
2181
+ rbsrt_socket_base_define_base_api(mSRTSocketKlass);
2182
+ rbsrt_socket_base_define_option_api(mSRTSocketKlass);
2183
+ rbsrt_socket_base_define_io_api(mSRTSocketKlass);
2184
+ rbsrt_define_socket_state_api(mSRTSocketKlass);
2185
+
2186
+ rb_define_method(mSRTSocketKlass, "accept", rbsrt_socket_accept, 0);
2187
+ rb_define_method(mSRTSocketKlass, "bind", rbsrt_socket_bind, 2);
2188
+ rb_define_method(mSRTSocketKlass, "connect", rbsrt_socket_connect, 2);
2189
+ rb_define_method(mSRTSocketKlass, "listen", rbsrt_socket_listen, 1);
2190
+
2191
+
2192
+
2193
+ // SRT::Server Class
2194
+
2195
+ mSRTServerKlass = rb_define_class_under(mSRTModule, "Server", rb_cObject);
2196
+
2197
+ rb_define_alloc_func(mSRTServerKlass, rbsrt_server_allocate);
2198
+
2199
+ rb_define_method(mSRTServerKlass, "initialize", rbsrt_server_initialize, 2);
2200
+
2201
+ rbsrt_socket_base_define_base_api(mSRTServerKlass);
2202
+ rbsrt_define_socket_state_api(mSRTServerKlass);
2203
+
2204
+ rb_define_method(mSRTServerKlass, "close", rbsrt_server_close, 0);
2205
+ rb_define_method(mSRTServerKlass, "connection_count", rbsrt_server_connection_count, 0);
2206
+ rb_define_method(mSRTServerKlass, "start", rbsrt_server_start, 0);
2207
+
2208
+
2209
+ // SRT::Connection Class
2210
+
2211
+ mSRTConnectionKlass = rb_define_class_under(mSRTModule, "Connection", rb_cObject);
2212
+
2213
+ rb_define_alloc_func(mSRTConnectionKlass, rbsrt_connection_allocate);
2214
+
2215
+ rbsrt_socket_base_define_basic_api(mSRTConnectionKlass);
2216
+ rbsrt_socket_base_define_base_api(mSRTConnectionKlass);
2217
+ rbsrt_socket_base_define_option_api(mSRTConnectionKlass);
2218
+ rbsrt_define_socket_state_api(mSRTConnectionKlass);
2219
+
2220
+ rb_define_method(mSRTConnectionKlass, "sendmsg", rbsrt_socket_sendmsg, 1);
2221
+ rb_alias(mSRTConnectionKlass, rb_intern("write"), rb_intern("sendmsg"));
2222
+
2223
+
2224
+ // calbacks
2225
+
2226
+ rb_define_method(mSRTConnectionKlass, "at_data", rbsrt_connection_set_at_data_block, 0);
2227
+ rb_define_method(mSRTConnectionKlass, "at_close", rbsrt_connection_set_at_close_block, 0);
2228
+
2229
+
2230
+ // SRT::Client Class
2231
+
2232
+ mSRTClientKlass = rb_define_class_under(mSRTModule, "Client", rb_cObject);
2233
+
2234
+ rb_define_alloc_func(mSRTClientKlass, rbsrt_client_allocate);
2235
+
2236
+ // SRT::Client methods
2237
+
2238
+ rb_define_method(mSRTClientKlass, "initialize", rbsrt_client_initialize, 0);
2239
+
2240
+ rbsrt_socket_base_define_basic_api(mSRTClientKlass);
2241
+ rbsrt_socket_base_define_base_api(mSRTClientKlass);
2242
+ rbsrt_socket_base_define_connection_api(mSRTClientKlass);
2243
+ rbsrt_socket_base_define_option_api(mSRTClientKlass);
2244
+ rbsrt_socket_base_define_io_api(mSRTClientKlass);
2245
+ rbsrt_define_socket_state_api(mSRTClientKlass);
2246
+
2247
+
2248
+ // SRT::Poll
2249
+
2250
+ mSRTPollKlass = rb_define_class_under(mSRTModule, "Poll", rb_cObject);
2251
+
2252
+ rb_define_alloc_func(mSRTPollKlass, rbsrt_poll_allocate);
2253
+
2254
+ rb_define_method(mSRTPollKlass, "initialize", rbsrt_poll_initialize, 0);
2255
+ rb_define_method(mSRTPollKlass, "add", rbsrt_poll_add_socket, -1);
2256
+ rb_define_method(mSRTPollKlass, "update", rbsrt_poll_update_socket, -1);
2257
+ rb_define_method(mSRTPollKlass, "remove", rbsrt_poll_remove_socket, 1);
2258
+ rb_define_method(mSRTPollKlass, "wait", rbsrt_poll_wait, -1);
2259
+
2260
+
2261
+ // Init Stats
2262
+
2263
+ RBSRT_stat_init(mSRTModule);
2264
+
2265
+ // Startup SRT
2266
+
2267
+ rbsrt_srt_startup(NULL);
2268
+
2269
+ ruby_vm_at_exit(rbsrt_srt_cleanup);
2270
+ }