sctp-socket 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.gitignore +1 -0
- data/CHANGES.md +9 -0
- data/MANIFEST.md +39 -2
- data/README.md +1 -1
- data/Rakefile +3 -5
- data/ext/sctp/extconf.rb +33 -24
- data/ext/sctp/sctp_compat.h +369 -0
- data/ext/sctp/socket.c +909 -382
- data/sctp-socket.gemspec +1 -1
- data.tar.gz.sig +0 -0
- metadata +4 -6
- metadata.gz.sig +0 -0
data/ext/sctp/socket.c
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
#include "ruby.h"
|
|
2
|
+
#include <ruby/thread.h>
|
|
2
3
|
#include <string.h>
|
|
3
4
|
#include <errno.h>
|
|
4
5
|
#include <arpa/inet.h>
|
|
5
|
-
#include <netinet/sctp.h>
|
|
6
6
|
|
|
7
7
|
#ifdef HAVE_SYS_PARAM_H
|
|
8
8
|
#include <sys/param.h>
|
|
9
9
|
#endif
|
|
10
10
|
|
|
11
|
+
#include "sctp_compat.h"
|
|
12
|
+
|
|
11
13
|
VALUE mSCTP;
|
|
12
14
|
VALUE cSocket;
|
|
13
15
|
VALUE v_sndrcv_struct;
|
|
@@ -41,7 +43,7 @@ VALUE v_sctp_initmsg_struct;
|
|
|
41
43
|
|
|
42
44
|
// Memory safety and error handling macros
|
|
43
45
|
#define CHECK_FILENO_VALID(fileno) do { \
|
|
44
|
-
if ((fileno)
|
|
46
|
+
if (SCTP_FD_INVALID(fileno)) { \
|
|
45
47
|
rb_raise(rb_eSystemCallError, "invalid file descriptor"); \
|
|
46
48
|
} \
|
|
47
49
|
} while(0)
|
|
@@ -54,8 +56,7 @@ VALUE v_sctp_initmsg_struct;
|
|
|
54
56
|
} while(0)
|
|
55
57
|
|
|
56
58
|
#define CHECK_SOCKET_CLOSED(self) do { \
|
|
57
|
-
|
|
58
|
-
if (NIL_P(v_fileno) || NUM2INT(v_fileno) < 0) { \
|
|
59
|
+
if (NIL_P(rb_iv_get((self), "@fileno"))) { \
|
|
59
60
|
rb_raise(rb_eIOError, "socket is closed"); \
|
|
60
61
|
} \
|
|
61
62
|
} while(0)
|
|
@@ -63,6 +64,65 @@ VALUE v_sctp_initmsg_struct;
|
|
|
63
64
|
#define MAX_IP_ADDRESSES 8
|
|
64
65
|
#define DEFAULT_BUFFER_SIZE 1024
|
|
65
66
|
#define IP_BUFFER_SIZE INET6_ADDRSTRLEN
|
|
67
|
+
#define MAX_NOTIFICATION_DATA 8192
|
|
68
|
+
|
|
69
|
+
/*
|
|
70
|
+
* Helper function to parse an IP address string and fill a sockaddr_in or sockaddr_in6 structure.
|
|
71
|
+
* Supports both IPv4 and IPv6 addresses.
|
|
72
|
+
*
|
|
73
|
+
* @param addr_str The IP address string to parse
|
|
74
|
+
* @param port The port number (in host byte order)
|
|
75
|
+
* @param sin Pointer to sockaddr_in to fill (for IPv4)
|
|
76
|
+
* @param sin6 Pointer to sockaddr_in6 to fill (for IPv6)
|
|
77
|
+
* @param domain The address family (AF_INET or AF_INET6)
|
|
78
|
+
*/
|
|
79
|
+
static void parse_ip_address_v4(const char* addr_str, int port, struct sockaddr_in* sin){
|
|
80
|
+
bzero(sin, sizeof(*sin));
|
|
81
|
+
sin->sin_family = AF_INET;
|
|
82
|
+
sin->sin_port = htons(port);
|
|
83
|
+
if(inet_pton(AF_INET, addr_str, &sin->sin_addr) != 1)
|
|
84
|
+
rb_raise(rb_eArgError, "invalid IPv4 address: %s", addr_str);
|
|
85
|
+
#ifdef BSD
|
|
86
|
+
sin->sin_len = sizeof(struct sockaddr_in);
|
|
87
|
+
#endif
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static void parse_ip_address_v6(const char* addr_str, int port, struct sockaddr_in6* sin6){
|
|
91
|
+
bzero(sin6, sizeof(*sin6));
|
|
92
|
+
sin6->sin6_family = AF_INET6;
|
|
93
|
+
sin6->sin6_port = htons(port);
|
|
94
|
+
if(inet_pton(AF_INET6, addr_str, &sin6->sin6_addr) != 1)
|
|
95
|
+
rb_raise(rb_eArgError, "invalid IPv6 address: %s", addr_str);
|
|
96
|
+
#ifdef BSD
|
|
97
|
+
sin6->sin6_len = sizeof(struct sockaddr_in6);
|
|
98
|
+
#endif
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
* Helper function to set INADDR_ANY for IPv4.
|
|
103
|
+
*/
|
|
104
|
+
static void set_any_address_v4(int port, struct sockaddr_in* sin){
|
|
105
|
+
bzero(sin, sizeof(*sin));
|
|
106
|
+
sin->sin_family = AF_INET;
|
|
107
|
+
sin->sin_port = htons(port);
|
|
108
|
+
sin->sin_addr.s_addr = htonl(INADDR_ANY);
|
|
109
|
+
#ifdef BSD
|
|
110
|
+
sin->sin_len = sizeof(struct sockaddr_in);
|
|
111
|
+
#endif
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
* Helper function to set IN6ADDR_ANY for IPv6.
|
|
116
|
+
*/
|
|
117
|
+
static void set_any_address_v6(int port, struct sockaddr_in6* sin6){
|
|
118
|
+
bzero(sin6, sizeof(*sin6));
|
|
119
|
+
sin6->sin6_family = AF_INET6;
|
|
120
|
+
sin6->sin6_port = htons(port);
|
|
121
|
+
sin6->sin6_addr = in6addr_any;
|
|
122
|
+
#ifdef BSD
|
|
123
|
+
sin6->sin6_len = sizeof(struct sockaddr_in6);
|
|
124
|
+
#endif
|
|
125
|
+
}
|
|
66
126
|
|
|
67
127
|
/*
|
|
68
128
|
* Convert a sockaddr_in structure to a Ruby struct.
|
|
@@ -197,12 +257,18 @@ VALUE get_notification_info(char* buffer){
|
|
|
197
257
|
v_str = rb_str_new2("unknown");
|
|
198
258
|
}
|
|
199
259
|
|
|
200
|
-
|
|
201
|
-
(
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
260
|
+
{
|
|
261
|
+
struct sockaddr* sa = (struct sockaddr*)&snp->sn_paddr_change.spc_aaddr;
|
|
262
|
+
|
|
263
|
+
if(sa->sa_family == AF_INET6){
|
|
264
|
+
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
|
|
265
|
+
inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str));
|
|
266
|
+
}
|
|
267
|
+
else{
|
|
268
|
+
struct sockaddr_in* sin = (struct sockaddr_in*)sa;
|
|
269
|
+
inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
206
272
|
|
|
207
273
|
v_notification = rb_struct_new(v_peeraddr_change_struct,
|
|
208
274
|
UINT2NUM(snp->sn_paddr_change.spc_type),
|
|
@@ -215,83 +281,150 @@ VALUE get_notification_info(char* buffer){
|
|
|
215
281
|
);
|
|
216
282
|
break;
|
|
217
283
|
case SCTP_REMOTE_ERROR:
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
284
|
+
{
|
|
285
|
+
size_t data_len = 0;
|
|
286
|
+
VALUE v_data_ary;
|
|
287
|
+
|
|
288
|
+
// Calculate actual data length (total length minus fixed header)
|
|
289
|
+
if(snp->sn_remote_error.sre_length > offsetof(struct sctp_remote_error, sre_data))
|
|
290
|
+
data_len = snp->sn_remote_error.sre_length - offsetof(struct sctp_remote_error, sre_data);
|
|
291
|
+
|
|
292
|
+
// Bounds check to prevent stack overflow
|
|
293
|
+
if(data_len > MAX_NOTIFICATION_DATA)
|
|
294
|
+
data_len = MAX_NOTIFICATION_DATA;
|
|
295
|
+
|
|
296
|
+
if(data_len > 0){
|
|
297
|
+
v_temp = ALLOCA_N(VALUE, data_len);
|
|
298
|
+
for(i = 0; i < data_len; i++){
|
|
299
|
+
v_temp[i] = UINT2NUM(snp->sn_remote_error.sre_data[i]);
|
|
300
|
+
}
|
|
301
|
+
v_data_ary = rb_ary_new4(data_len, v_temp);
|
|
302
|
+
}
|
|
303
|
+
else{
|
|
304
|
+
v_data_ary = rb_ary_new();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
v_notification = rb_struct_new(v_remote_error_struct,
|
|
308
|
+
UINT2NUM(snp->sn_remote_error.sre_type),
|
|
309
|
+
UINT2NUM(snp->sn_remote_error.sre_flags),
|
|
310
|
+
UINT2NUM(snp->sn_remote_error.sre_length),
|
|
311
|
+
UINT2NUM(snp->sn_remote_error.sre_error),
|
|
312
|
+
UINT2NUM(snp->sn_remote_error.sre_assoc_id),
|
|
313
|
+
v_data_ary
|
|
314
|
+
);
|
|
222
315
|
}
|
|
223
|
-
|
|
224
|
-
v_notification = rb_struct_new(v_remote_error_struct,
|
|
225
|
-
UINT2NUM(snp->sn_remote_error.sre_type),
|
|
226
|
-
UINT2NUM(snp->sn_remote_error.sre_flags),
|
|
227
|
-
UINT2NUM(snp->sn_remote_error.sre_length),
|
|
228
|
-
UINT2NUM(snp->sn_remote_error.sre_error),
|
|
229
|
-
UINT2NUM(snp->sn_remote_error.sre_assoc_id),
|
|
230
|
-
rb_ary_new4(snp->sn_remote_error.sre_length, v_temp)
|
|
231
|
-
);
|
|
232
316
|
break;
|
|
233
317
|
#ifdef SCTP_SEND_FAILED_EVENT
|
|
234
318
|
case SCTP_SEND_FAILED_EVENT:
|
|
235
|
-
|
|
236
|
-
|
|
319
|
+
{
|
|
320
|
+
size_t data_len = 0;
|
|
321
|
+
VALUE v_data_ary;
|
|
237
322
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
323
|
+
#ifdef HAVE_STRUCT_SCTP_SEND_FAILED_EVENT_SSFE_LENGTH
|
|
324
|
+
// Calculate actual data length (total length minus fixed header)
|
|
325
|
+
if(snp->sn_send_failed_event.ssfe_length > offsetof(struct sctp_send_failed_event, ssfe_data))
|
|
326
|
+
data_len = snp->sn_send_failed_event.ssfe_length - offsetof(struct sctp_send_failed_event, ssfe_data);
|
|
327
|
+
|
|
328
|
+
// Bounds check to prevent stack overflow
|
|
329
|
+
if(data_len > MAX_NOTIFICATION_DATA)
|
|
330
|
+
data_len = MAX_NOTIFICATION_DATA;
|
|
331
|
+
|
|
332
|
+
if(data_len > 0){
|
|
333
|
+
v_temp = ALLOCA_N(VALUE, data_len);
|
|
334
|
+
for(i = 0; i < data_len; i++){
|
|
335
|
+
v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssfe_data[i]);
|
|
336
|
+
}
|
|
337
|
+
v_data_ary = rb_ary_new4(data_len, v_temp);
|
|
338
|
+
}
|
|
339
|
+
else{
|
|
340
|
+
v_data_ary = rb_ary_new();
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
v_notification = rb_struct_new(v_send_failed_event_struct,
|
|
344
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_type),
|
|
345
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_length),
|
|
346
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_error),
|
|
347
|
+
rb_struct_new(v_sndinfo_struct,
|
|
348
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
|
|
349
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
|
|
350
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
|
|
351
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
|
|
352
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
|
|
353
|
+
),
|
|
354
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_assoc_id),
|
|
355
|
+
v_data_ary
|
|
356
|
+
);
|
|
256
357
|
#else
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
358
|
+
// Calculate actual data length (total length minus fixed header)
|
|
359
|
+
if(snp->sn_send_failed_event.ssf_length > offsetof(struct sctp_send_failed_event, ssf_data))
|
|
360
|
+
data_len = snp->sn_send_failed_event.ssf_length - offsetof(struct sctp_send_failed_event, ssf_data);
|
|
361
|
+
|
|
362
|
+
// Bounds check to prevent stack overflow
|
|
363
|
+
if(data_len > MAX_NOTIFICATION_DATA)
|
|
364
|
+
data_len = MAX_NOTIFICATION_DATA;
|
|
365
|
+
|
|
366
|
+
if(data_len > 0){
|
|
367
|
+
v_temp = ALLOCA_N(VALUE, data_len);
|
|
368
|
+
for(i = 0; i < data_len; i++){
|
|
369
|
+
v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssf_data[i]);
|
|
370
|
+
}
|
|
371
|
+
v_data_ary = rb_ary_new4(data_len, v_temp);
|
|
372
|
+
}
|
|
373
|
+
else{
|
|
374
|
+
v_data_ary = rb_ary_new();
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
v_notification = rb_struct_new(v_send_failed_event_struct,
|
|
378
|
+
UINT2NUM(snp->sn_send_failed_event.ssf_type),
|
|
379
|
+
UINT2NUM(snp->sn_send_failed_event.ssf_length),
|
|
380
|
+
UINT2NUM(snp->sn_send_failed_event.ssf_error),
|
|
381
|
+
rb_struct_new(v_sndinfo_struct,
|
|
382
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
|
|
383
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
|
|
384
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
|
|
385
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
|
|
386
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
|
|
387
|
+
),
|
|
388
|
+
UINT2NUM(snp->sn_send_failed_event.ssf_assoc_id),
|
|
389
|
+
v_data_ary
|
|
390
|
+
);
|
|
277
391
|
#endif
|
|
392
|
+
}
|
|
278
393
|
break;
|
|
279
394
|
#else
|
|
280
395
|
case SCTP_SEND_FAILED:
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
396
|
+
{
|
|
397
|
+
size_t data_len = 0;
|
|
398
|
+
VALUE v_data_ary;
|
|
399
|
+
|
|
400
|
+
// Calculate actual data length (total length minus fixed header)
|
|
401
|
+
if(snp->sn_send_failed.ssf_length > offsetof(struct sctp_send_failed, ssf_data))
|
|
402
|
+
data_len = snp->sn_send_failed.ssf_length - offsetof(struct sctp_send_failed, ssf_data);
|
|
403
|
+
|
|
404
|
+
// Bounds check to prevent stack overflow
|
|
405
|
+
if(data_len > MAX_NOTIFICATION_DATA)
|
|
406
|
+
data_len = MAX_NOTIFICATION_DATA;
|
|
407
|
+
|
|
408
|
+
if(data_len > 0){
|
|
409
|
+
v_temp = ALLOCA_N(VALUE, data_len);
|
|
410
|
+
for(i = 0; i < data_len; i++){
|
|
411
|
+
v_temp[i] = UINT2NUM(snp->sn_send_failed.ssf_data[i]);
|
|
412
|
+
}
|
|
413
|
+
v_data_ary = rb_ary_new4(data_len, v_temp);
|
|
414
|
+
}
|
|
415
|
+
else{
|
|
416
|
+
v_data_ary = rb_ary_new();
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
v_notification = rb_struct_new(v_send_failed_event_struct,
|
|
420
|
+
UINT2NUM(snp->sn_send_failed.ssf_type),
|
|
421
|
+
UINT2NUM(snp->sn_send_failed.ssf_length),
|
|
422
|
+
UINT2NUM(snp->sn_send_failed.ssf_error),
|
|
423
|
+
Qnil,
|
|
424
|
+
UINT2NUM(snp->sn_send_failed.ssf_assoc_id),
|
|
425
|
+
v_data_ary
|
|
426
|
+
);
|
|
285
427
|
}
|
|
286
|
-
|
|
287
|
-
v_notification = rb_struct_new(v_send_failed_event_struct,
|
|
288
|
-
UINT2NUM(snp->sn_send_failed.ssf_type),
|
|
289
|
-
UINT2NUM(snp->sn_send_failed.ssf_length),
|
|
290
|
-
UINT2NUM(snp->sn_send_failed.ssf_error),
|
|
291
|
-
Qnil,
|
|
292
|
-
UINT2NUM(snp->sn_send_failed.ssf_assoc_id),
|
|
293
|
-
rb_ary_new4(snp->sn_send_failed.ssf_length, v_temp)
|
|
294
|
-
);
|
|
295
428
|
break;
|
|
296
429
|
#endif
|
|
297
430
|
case SCTP_SHUTDOWN_EVENT:
|
|
@@ -370,7 +503,7 @@ VALUE get_notification_info(char* buffer){
|
|
|
370
503
|
* socket2 = SCTP::Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
|
|
371
504
|
*/
|
|
372
505
|
static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
|
|
373
|
-
|
|
506
|
+
sctp_sock_t fileno;
|
|
374
507
|
VALUE v_domain, v_type;
|
|
375
508
|
|
|
376
509
|
rb_scan_args(argc, argv, "02", &v_domain, &v_type);
|
|
@@ -394,14 +527,14 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
|
|
|
394
527
|
rb_raise(rb_eArgError, "unsupported socket type: %d", type);
|
|
395
528
|
}
|
|
396
529
|
|
|
397
|
-
fileno =
|
|
530
|
+
fileno = sctp_sys_socket(NUM2INT(v_domain), NUM2INT(v_type), IPPROTO_SCTP);
|
|
398
531
|
|
|
399
|
-
if(fileno
|
|
532
|
+
if(SCTP_FD_INVALID(fileno))
|
|
400
533
|
rb_raise(rb_eSystemCallError, "socket: %s", strerror(errno));
|
|
401
534
|
|
|
402
535
|
rb_iv_set(self, "@domain", v_domain);
|
|
403
536
|
rb_iv_set(self, "@type", v_type);
|
|
404
|
-
rb_iv_set(self, "@fileno",
|
|
537
|
+
rb_iv_set(self, "@fileno", SCTP_FD_TO_NUM(fileno));
|
|
405
538
|
rb_iv_set(self, "@association_id", INT2NUM(0));
|
|
406
539
|
|
|
407
540
|
return self;
|
|
@@ -451,14 +584,12 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
|
|
|
451
584
|
* Returns the port that it was bound to.
|
|
452
585
|
*/
|
|
453
586
|
static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
|
454
|
-
|
|
455
|
-
int i,
|
|
587
|
+
sctp_sock_t fileno;
|
|
588
|
+
int i, num_ip, flags, domain, port, on;
|
|
456
589
|
VALUE v_addresses, v_port, v_flags, v_address, v_reuse_addr, v_options;
|
|
457
590
|
|
|
458
591
|
rb_scan_args(argc, argv, "01", &v_options);
|
|
459
592
|
|
|
460
|
-
bzero(&addrs, sizeof(addrs));
|
|
461
|
-
|
|
462
593
|
if(NIL_P(v_options))
|
|
463
594
|
v_options = rb_hash_new();
|
|
464
595
|
|
|
@@ -485,44 +616,63 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
|
|
485
616
|
if(num_ip > MAX_IP_ADDRESSES)
|
|
486
617
|
rb_raise(rb_eArgError, "too many IP addresses to bind, maximum is eight");
|
|
487
618
|
|
|
619
|
+
CHECK_SOCKET_CLOSED(self);
|
|
620
|
+
|
|
488
621
|
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
|
489
|
-
fileno =
|
|
622
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
490
623
|
|
|
491
|
-
if(
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
624
|
+
if(v_reuse_addr == Qtrue){
|
|
625
|
+
on = 1;
|
|
626
|
+
#ifdef HAVE_USRSCTP_H
|
|
627
|
+
/* usrsctp runs in userspace; address reuse is not needed/supported. Silently skip. */
|
|
628
|
+
(void)on;
|
|
629
|
+
#else
|
|
630
|
+
if(sctp_sys_setsockopt(fileno, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
|
|
631
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
499
632
|
#endif
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
if(domain == AF_INET6){
|
|
636
|
+
struct sockaddr_in6 addrs6[MAX_IP_ADDRESSES];
|
|
637
|
+
bzero(&addrs6, sizeof(addrs6));
|
|
638
|
+
|
|
639
|
+
if(!NIL_P(v_addresses)){
|
|
640
|
+
for(i = 0; i < num_ip; i++){
|
|
641
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
642
|
+
parse_ip_address_v6(StringValueCStr(v_address), port, &addrs6[i]);
|
|
643
|
+
}
|
|
500
644
|
}
|
|
645
|
+
else{
|
|
646
|
+
set_any_address_v6(port, &addrs6[0]);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if(sctp_sys_bindx(fileno, (struct sockaddr *)addrs6, num_ip, flags) != 0)
|
|
650
|
+
rb_raise(rb_eSystemCallError, "sctp_bindx: %s", strerror(errno));
|
|
501
651
|
}
|
|
502
652
|
else{
|
|
503
|
-
addrs[
|
|
504
|
-
addrs
|
|
505
|
-
addrs[0].sin_addr.s_addr = htonl(INADDR_ANY);
|
|
506
|
-
#ifdef BSD
|
|
507
|
-
addrs[0].sin_len = sizeof(struct sockaddr_in);
|
|
508
|
-
#endif
|
|
509
|
-
}
|
|
653
|
+
struct sockaddr_in addrs[MAX_IP_ADDRESSES];
|
|
654
|
+
bzero(&addrs, sizeof(addrs));
|
|
510
655
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
656
|
+
if(!NIL_P(v_addresses)){
|
|
657
|
+
for(i = 0; i < num_ip; i++){
|
|
658
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
659
|
+
parse_ip_address_v4(StringValueCStr(v_address), port, &addrs[i]);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
else{
|
|
663
|
+
set_any_address_v4(port, &addrs[0]);
|
|
664
|
+
}
|
|
516
665
|
|
|
517
|
-
|
|
518
|
-
|
|
666
|
+
if(sctp_sys_bindx(fileno, (struct sockaddr *)addrs, num_ip, flags) != 0)
|
|
667
|
+
rb_raise(rb_eSystemCallError, "sctp_bindx: %s", strerror(errno));
|
|
668
|
+
}
|
|
519
669
|
|
|
520
670
|
if(port == 0){
|
|
521
671
|
struct sockaddr_in sin;
|
|
522
672
|
socklen_t len = sizeof(sin);
|
|
523
673
|
bzero(&sin, len);
|
|
524
674
|
|
|
525
|
-
if(
|
|
675
|
+
if(sctp_sys_getsockname(fileno, (struct sockaddr *)&sin, &len) == -1)
|
|
526
676
|
rb_raise(rb_eSystemCallError, "getsockname: %s", strerror(errno));
|
|
527
677
|
|
|
528
678
|
port = sin.sin_port;
|
|
@@ -550,10 +700,10 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
|
|
550
700
|
* methods will automatically establish associations.
|
|
551
701
|
*/
|
|
552
702
|
static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
|
|
553
|
-
|
|
554
|
-
int i, num_ip,
|
|
703
|
+
sctp_sock_t fileno;
|
|
704
|
+
int i, num_ip, domain, port;
|
|
555
705
|
sctp_assoc_t assoc;
|
|
556
|
-
VALUE v_address,
|
|
706
|
+
VALUE v_address, v_options, v_addresses, v_port;
|
|
557
707
|
|
|
558
708
|
rb_scan_args(argc, argv, "01", &v_options);
|
|
559
709
|
|
|
@@ -571,25 +721,41 @@ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
|
|
|
571
721
|
if(NIL_P(v_port))
|
|
572
722
|
rb_raise(rb_eArgError, "you must specify a port");
|
|
573
723
|
|
|
574
|
-
|
|
724
|
+
CHECK_SOCKET_CLOSED(self);
|
|
725
|
+
|
|
726
|
+
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
|
727
|
+
port = NUM2INT(v_port);
|
|
728
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
575
729
|
|
|
576
730
|
num_ip = (int)RARRAY_LEN(v_addresses);
|
|
577
|
-
bzero(&addrs, sizeof(addrs));
|
|
578
731
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
732
|
+
if(num_ip > MAX_IP_ADDRESSES)
|
|
733
|
+
rb_raise(rb_eArgError, "too many IP addresses, maximum is eight");
|
|
734
|
+
|
|
735
|
+
if(domain == AF_INET6){
|
|
736
|
+
struct sockaddr_in6 addrs6[MAX_IP_ADDRESSES];
|
|
737
|
+
bzero(&addrs6, sizeof(addrs6));
|
|
738
|
+
|
|
739
|
+
for(i = 0; i < num_ip; i++){
|
|
740
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
741
|
+
parse_ip_address_v6(StringValueCStr(v_address), port, &addrs6[i]);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
if(sctp_sys_connectx(fileno, (struct sockaddr *)addrs6, num_ip, &assoc) < 0)
|
|
745
|
+
rb_raise(rb_eSystemCallError, "sctp_connectx: %s", strerror(errno));
|
|
587
746
|
}
|
|
747
|
+
else{
|
|
748
|
+
struct sockaddr_in addrs[MAX_IP_ADDRESSES];
|
|
749
|
+
bzero(&addrs, sizeof(addrs));
|
|
588
750
|
|
|
589
|
-
|
|
751
|
+
for(i = 0; i < num_ip; i++){
|
|
752
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
753
|
+
parse_ip_address_v4(StringValueCStr(v_address), port, &addrs[i]);
|
|
754
|
+
}
|
|
590
755
|
|
|
591
|
-
|
|
592
|
-
|
|
756
|
+
if(sctp_sys_connectx(fileno, (struct sockaddr *)addrs, num_ip, &assoc) < 0)
|
|
757
|
+
rb_raise(rb_eSystemCallError, "sctp_connectx: %s", strerror(errno));
|
|
758
|
+
}
|
|
593
759
|
|
|
594
760
|
rb_iv_set(self, "@association_id", INT2NUM(assoc));
|
|
595
761
|
|
|
@@ -619,7 +785,7 @@ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
|
|
|
619
785
|
*/
|
|
620
786
|
static VALUE rsctp_close(int argc, VALUE* argv, VALUE self){
|
|
621
787
|
VALUE v_options, v_linger, v_fileno;
|
|
622
|
-
|
|
788
|
+
sctp_sock_t fileno;
|
|
623
789
|
|
|
624
790
|
rb_scan_args(argc, argv, "01", &v_options);
|
|
625
791
|
|
|
@@ -634,9 +800,13 @@ static VALUE rsctp_close(int argc, VALUE* argv, VALUE self){
|
|
|
634
800
|
if(NIL_P(v_fileno)) // Already closed
|
|
635
801
|
return self;
|
|
636
802
|
|
|
637
|
-
fileno =
|
|
803
|
+
fileno = NUM_TO_SCTP_FD(v_fileno);
|
|
638
804
|
|
|
639
805
|
if(!NIL_P(v_linger)){
|
|
806
|
+
#ifdef HAVE_USRSCTP_H
|
|
807
|
+
/* usrsctp doesn't support SOL_SOCKET options; linger is not available */
|
|
808
|
+
(void)v_linger;
|
|
809
|
+
#else
|
|
640
810
|
struct linger lin;
|
|
641
811
|
int linger_time = NUM2INT(v_linger);
|
|
642
812
|
|
|
@@ -646,11 +816,12 @@ static VALUE rsctp_close(int argc, VALUE* argv, VALUE self){
|
|
|
646
816
|
lin.l_onoff = 1;
|
|
647
817
|
lin.l_linger = linger_time;
|
|
648
818
|
|
|
649
|
-
if(
|
|
819
|
+
if(sctp_sys_setsockopt(fileno, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0)
|
|
650
820
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
821
|
+
#endif
|
|
651
822
|
}
|
|
652
823
|
|
|
653
|
-
if(
|
|
824
|
+
if(sctp_sys_close(fileno) < 0)
|
|
654
825
|
rb_raise(rb_eSystemCallError, "close: %s", strerror(errno));
|
|
655
826
|
|
|
656
827
|
// Mark socket as closed
|
|
@@ -700,7 +871,8 @@ static VALUE rsctp_closed_p(VALUE self){
|
|
|
700
871
|
static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
|
|
701
872
|
sctp_assoc_t assoc_id;
|
|
702
873
|
struct sockaddr* addrs = NULL;
|
|
703
|
-
|
|
874
|
+
sctp_sock_t fileno;
|
|
875
|
+
int i, num_addrs;
|
|
704
876
|
char str[IP_BUFFER_SIZE];
|
|
705
877
|
VALUE v_fileno, v_association_id;
|
|
706
878
|
VALUE v_array = rb_ary_new();
|
|
@@ -709,10 +881,10 @@ static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
|
|
|
709
881
|
|
|
710
882
|
if(NIL_P(v_fileno)){
|
|
711
883
|
CHECK_SOCKET_CLOSED(self);
|
|
712
|
-
fileno =
|
|
884
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
713
885
|
}
|
|
714
886
|
else{
|
|
715
|
-
fileno =
|
|
887
|
+
fileno = NUM_TO_SCTP_FD(v_fileno);
|
|
716
888
|
CHECK_FILENO_VALID(fileno);
|
|
717
889
|
}
|
|
718
890
|
|
|
@@ -721,22 +893,32 @@ static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
|
|
|
721
893
|
else
|
|
722
894
|
assoc_id = NUM2INT(v_association_id);
|
|
723
895
|
|
|
724
|
-
num_addrs =
|
|
896
|
+
num_addrs = sctp_sys_getpaddrs(fileno, assoc_id, &addrs);
|
|
725
897
|
|
|
726
898
|
if(num_addrs < 0){
|
|
727
899
|
if(addrs != NULL)
|
|
728
|
-
|
|
900
|
+
sctp_sys_freepaddrs(addrs);
|
|
729
901
|
|
|
730
902
|
rb_raise(rb_eSystemCallError, "sctp_getpaddrs: %s", strerror(errno));
|
|
731
903
|
}
|
|
732
904
|
|
|
733
905
|
for(i = 0; i < num_addrs; i++){
|
|
906
|
+
struct sockaddr* sa = &addrs[i];
|
|
734
907
|
bzero(&str, sizeof(str));
|
|
735
|
-
|
|
908
|
+
|
|
909
|
+
if(sa->sa_family == AF_INET6){
|
|
910
|
+
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
|
|
911
|
+
inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str));
|
|
912
|
+
}
|
|
913
|
+
else{
|
|
914
|
+
struct sockaddr_in* sin = (struct sockaddr_in*)sa;
|
|
915
|
+
inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str));
|
|
916
|
+
}
|
|
917
|
+
|
|
736
918
|
rb_ary_push(v_array, rb_str_new2(str));
|
|
737
919
|
}
|
|
738
920
|
|
|
739
|
-
|
|
921
|
+
sctp_sys_freepaddrs(addrs);
|
|
740
922
|
|
|
741
923
|
return v_array;
|
|
742
924
|
}
|
|
@@ -761,7 +943,8 @@ static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
|
|
|
761
943
|
static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
|
|
762
944
|
sctp_assoc_t assoc_id;
|
|
763
945
|
struct sockaddr* addrs = NULL;
|
|
764
|
-
|
|
946
|
+
sctp_sock_t fileno;
|
|
947
|
+
int i, num_addrs;
|
|
765
948
|
char str[IP_BUFFER_SIZE];
|
|
766
949
|
VALUE v_assoc_fileno, v_assoc_id;
|
|
767
950
|
VALUE v_array = rb_ary_new();
|
|
@@ -770,10 +953,10 @@ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
|
|
|
770
953
|
|
|
771
954
|
if(NIL_P(v_assoc_fileno)){
|
|
772
955
|
CHECK_SOCKET_CLOSED(self);
|
|
773
|
-
fileno =
|
|
956
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
774
957
|
}
|
|
775
958
|
else{
|
|
776
|
-
fileno =
|
|
959
|
+
fileno = NUM_TO_SCTP_FD(v_assoc_fileno);
|
|
777
960
|
CHECK_FILENO_VALID(fileno);
|
|
778
961
|
}
|
|
779
962
|
|
|
@@ -782,22 +965,32 @@ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
|
|
|
782
965
|
else
|
|
783
966
|
assoc_id = NUM2INT(v_assoc_id);
|
|
784
967
|
|
|
785
|
-
num_addrs =
|
|
968
|
+
num_addrs = sctp_sys_getladdrs(fileno, assoc_id, &addrs);
|
|
786
969
|
|
|
787
970
|
if(num_addrs < 0){
|
|
788
971
|
if(addrs != NULL)
|
|
789
|
-
|
|
972
|
+
sctp_sys_freeladdrs(addrs);
|
|
790
973
|
|
|
791
974
|
rb_raise(rb_eSystemCallError, "sctp_getladdrs: %s", strerror(errno));
|
|
792
975
|
}
|
|
793
976
|
|
|
794
977
|
for(i = 0; i < num_addrs; i++){
|
|
978
|
+
struct sockaddr* sa = &addrs[i];
|
|
795
979
|
bzero(&str, sizeof(str));
|
|
796
|
-
|
|
980
|
+
|
|
981
|
+
if(sa->sa_family == AF_INET6){
|
|
982
|
+
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
|
|
983
|
+
inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str));
|
|
984
|
+
}
|
|
985
|
+
else{
|
|
986
|
+
struct sockaddr_in* sin = (struct sockaddr_in*)sa;
|
|
987
|
+
inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str));
|
|
988
|
+
}
|
|
989
|
+
|
|
797
990
|
rb_ary_push(v_array, rb_str_new2(str));
|
|
798
991
|
}
|
|
799
992
|
|
|
800
|
-
|
|
993
|
+
sctp_sys_freeladdrs(addrs);
|
|
801
994
|
|
|
802
995
|
return v_array;
|
|
803
996
|
}
|
|
@@ -832,9 +1025,9 @@ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
|
|
|
832
1025
|
static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
833
1026
|
VALUE v_msg, v_message, v_addresses;
|
|
834
1027
|
struct iovec iov[IOV_MAX];
|
|
835
|
-
struct sockaddr_in* addrs;
|
|
836
1028
|
struct sctp_sendv_spa spa;
|
|
837
|
-
|
|
1029
|
+
sctp_sock_t fileno;
|
|
1030
|
+
int i, size, num_ip, domain, port;
|
|
838
1031
|
ssize_t num_bytes;
|
|
839
1032
|
|
|
840
1033
|
Check_Type(v_options, T_HASH);
|
|
@@ -856,14 +1049,15 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
|
856
1049
|
if(!NIL_P(v_addresses)){
|
|
857
1050
|
Check_Type(v_addresses, T_ARRAY);
|
|
858
1051
|
num_ip = (int)RARRAY_LEN(v_addresses);
|
|
859
|
-
|
|
1052
|
+
|
|
1053
|
+
if(num_ip > MAX_IP_ADDRESSES)
|
|
1054
|
+
rb_raise(rb_eArgError, "too many IP addresses, maximum is eight");
|
|
860
1055
|
}
|
|
861
1056
|
else{
|
|
862
|
-
addrs = NULL;
|
|
863
1057
|
num_ip = 0;
|
|
864
1058
|
}
|
|
865
1059
|
|
|
866
|
-
fileno =
|
|
1060
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
867
1061
|
size = (int)RARRAY_LEN(v_message);
|
|
868
1062
|
|
|
869
1063
|
if(!size)
|
|
@@ -877,8 +1071,15 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
|
877
1071
|
spa.sendv_sndinfo.snd_flags = SCTP_UNORDERED;
|
|
878
1072
|
spa.sendv_sndinfo.snd_assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
879
1073
|
|
|
880
|
-
|
|
881
|
-
|
|
1074
|
+
for(i = 0; i < size; i++){
|
|
1075
|
+
v_msg = RARRAY_AREF(v_message, i);
|
|
1076
|
+
iov[i].iov_base = StringValueCStr(v_msg);
|
|
1077
|
+
iov[i].iov_len = RSTRING_LEN(v_msg);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
|
1081
|
+
|
|
1082
|
+
if(num_ip > 0){
|
|
882
1083
|
VALUE v_address, v_port;
|
|
883
1084
|
|
|
884
1085
|
v_port = rb_iv_get(self, "@port");
|
|
@@ -888,36 +1089,62 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
|
888
1089
|
else
|
|
889
1090
|
port = NUM2INT(v_port);
|
|
890
1091
|
|
|
891
|
-
domain
|
|
1092
|
+
if(domain == AF_INET6){
|
|
1093
|
+
struct sockaddr_in6* addrs6 = (struct sockaddr_in6*)alloca(num_ip * sizeof(struct sockaddr_in6));
|
|
1094
|
+
bzero(addrs6, num_ip * sizeof(struct sockaddr_in6));
|
|
892
1095
|
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
1096
|
+
for(i = 0; i < num_ip; i++){
|
|
1097
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
1098
|
+
parse_ip_address_v6(StringValueCStr(v_address), port, &addrs6[i]);
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
num_bytes = (ssize_t)sctp_sys_sendv(
|
|
1102
|
+
fileno,
|
|
1103
|
+
iov,
|
|
1104
|
+
size,
|
|
1105
|
+
(struct sockaddr*)addrs6,
|
|
1106
|
+
num_ip,
|
|
1107
|
+
&spa,
|
|
1108
|
+
sizeof(spa),
|
|
1109
|
+
SCTP_SENDV_SPA,
|
|
1110
|
+
0
|
|
1111
|
+
);
|
|
901
1112
|
}
|
|
902
|
-
|
|
1113
|
+
else{
|
|
1114
|
+
struct sockaddr_in* addrs = (struct sockaddr_in*)alloca(num_ip * sizeof(struct sockaddr_in));
|
|
1115
|
+
bzero(addrs, num_ip * sizeof(struct sockaddr_in));
|
|
903
1116
|
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
}
|
|
1117
|
+
for(i = 0; i < num_ip; i++){
|
|
1118
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
1119
|
+
parse_ip_address_v4(StringValueCStr(v_address), port, &addrs[i]);
|
|
1120
|
+
}
|
|
909
1121
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1122
|
+
num_bytes = (ssize_t)sctp_sys_sendv(
|
|
1123
|
+
fileno,
|
|
1124
|
+
iov,
|
|
1125
|
+
size,
|
|
1126
|
+
(struct sockaddr*)addrs,
|
|
1127
|
+
num_ip,
|
|
1128
|
+
&spa,
|
|
1129
|
+
sizeof(spa),
|
|
1130
|
+
SCTP_SENDV_SPA,
|
|
1131
|
+
0
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
else{
|
|
1136
|
+
num_bytes = (ssize_t)sctp_sys_sendv(
|
|
1137
|
+
fileno,
|
|
1138
|
+
iov,
|
|
1139
|
+
size,
|
|
1140
|
+
NULL,
|
|
1141
|
+
0,
|
|
1142
|
+
&spa,
|
|
1143
|
+
sizeof(spa),
|
|
1144
|
+
SCTP_SENDV_SPA,
|
|
1145
|
+
0
|
|
1146
|
+
);
|
|
1147
|
+
}
|
|
921
1148
|
|
|
922
1149
|
if(num_bytes < 0)
|
|
923
1150
|
rb_raise(rb_eSystemCallError, "sctp_sendv: %s", strerror(errno));
|
|
@@ -926,6 +1153,80 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
|
926
1153
|
}
|
|
927
1154
|
#endif
|
|
928
1155
|
|
|
1156
|
+
/*
|
|
1157
|
+
* GVL-release helpers for blocking receive calls.
|
|
1158
|
+
*
|
|
1159
|
+
* usrsctp_recvv blocks on internal userspace locks, not real system calls,
|
|
1160
|
+
* so Ruby's signal-handling thread never gets a chance to run. By releasing
|
|
1161
|
+
* the GVL around the blocking call, other Ruby threads (including the signal
|
|
1162
|
+
* thread) can execute. The UBF (unblock function) is invoked by Ruby when
|
|
1163
|
+
* it needs to interrupt the blocking call (e.g. Ctrl-C).
|
|
1164
|
+
*
|
|
1165
|
+
* For native SCTP we use RUBY_UBF_IO which sends a signal that interrupts
|
|
1166
|
+
* the real recvmsg() syscall. For usrsctp we shut down the read side of
|
|
1167
|
+
* the socket, which causes usrsctp_recvv to return with an error.
|
|
1168
|
+
*/
|
|
1169
|
+
|
|
1170
|
+
/* --- recvmsg (sctp_recvmsg / usrsctp_recvv via sctp_sys_recvmsg) --- */
|
|
1171
|
+
|
|
1172
|
+
struct recvmsg_nogvl_args {
|
|
1173
|
+
sctp_sock_t fd;
|
|
1174
|
+
void *buf;
|
|
1175
|
+
size_t len;
|
|
1176
|
+
struct sockaddr *from;
|
|
1177
|
+
socklen_t *fromlen;
|
|
1178
|
+
struct sctp_sndrcvinfo *sinfo;
|
|
1179
|
+
int *msg_flags;
|
|
1180
|
+
ssize_t result;
|
|
1181
|
+
int saved_errno;
|
|
1182
|
+
};
|
|
1183
|
+
|
|
1184
|
+
static void *recvmsg_nogvl(void *arg){
|
|
1185
|
+
struct recvmsg_nogvl_args *a = (struct recvmsg_nogvl_args *)arg;
|
|
1186
|
+
a->result = sctp_sys_recvmsg(a->fd, a->buf, a->len,
|
|
1187
|
+
a->from, a->fromlen, a->sinfo, a->msg_flags);
|
|
1188
|
+
a->saved_errno = errno;
|
|
1189
|
+
return NULL;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
#ifdef HAVE_USRSCTP_H
|
|
1193
|
+
static void recvmsg_ubf(void *arg){
|
|
1194
|
+
struct recvmsg_nogvl_args *a = (struct recvmsg_nogvl_args *)arg;
|
|
1195
|
+
usrsctp_shutdown(a->fd, SHUT_RD);
|
|
1196
|
+
}
|
|
1197
|
+
#endif
|
|
1198
|
+
|
|
1199
|
+
/* --- recvv (sctp_recvv / usrsctp_recvv via sctp_sys_recvv) --- */
|
|
1200
|
+
|
|
1201
|
+
struct recvv_nogvl_args {
|
|
1202
|
+
sctp_sock_t fd;
|
|
1203
|
+
const struct iovec *iov;
|
|
1204
|
+
int iovcnt;
|
|
1205
|
+
struct sockaddr *from;
|
|
1206
|
+
socklen_t *fromlen;
|
|
1207
|
+
void *info;
|
|
1208
|
+
socklen_t *infolen;
|
|
1209
|
+
unsigned int *infotype;
|
|
1210
|
+
int *flags;
|
|
1211
|
+
ssize_t result;
|
|
1212
|
+
int saved_errno;
|
|
1213
|
+
};
|
|
1214
|
+
|
|
1215
|
+
static void *recvv_nogvl(void *arg){
|
|
1216
|
+
struct recvv_nogvl_args *a = (struct recvv_nogvl_args *)arg;
|
|
1217
|
+
a->result = sctp_sys_recvv(a->fd, a->iov, a->iovcnt,
|
|
1218
|
+
a->from, a->fromlen, a->info, a->infolen, a->infotype, a->flags);
|
|
1219
|
+
a->saved_errno = errno;
|
|
1220
|
+
return NULL;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
#ifdef HAVE_USRSCTP_H
|
|
1224
|
+
static void recvv_ubf(void *arg){
|
|
1225
|
+
struct recvv_nogvl_args *a = (struct recvv_nogvl_args *)arg;
|
|
1226
|
+
usrsctp_shutdown(a->fd, SHUT_RD);
|
|
1227
|
+
}
|
|
1228
|
+
#endif
|
|
1229
|
+
|
|
929
1230
|
#ifdef HAVE_SCTP_RECVV
|
|
930
1231
|
/*
|
|
931
1232
|
* call-seq:
|
|
@@ -957,7 +1258,8 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
|
957
1258
|
*/
|
|
958
1259
|
static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
|
|
959
1260
|
VALUE v_flags, v_buffer_size;
|
|
960
|
-
|
|
1261
|
+
sctp_sock_t fileno;
|
|
1262
|
+
int flags, on, buffer_size;
|
|
961
1263
|
ssize_t bytes;
|
|
962
1264
|
uint infotype;
|
|
963
1265
|
socklen_t infolen;
|
|
@@ -970,7 +1272,9 @@ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
|
|
|
970
1272
|
|
|
971
1273
|
rb_scan_args(argc, argv, "02", &v_flags, &v_buffer_size);
|
|
972
1274
|
|
|
973
|
-
|
|
1275
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1276
|
+
|
|
1277
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
974
1278
|
|
|
975
1279
|
if(NIL_P(v_flags))
|
|
976
1280
|
flags = 0;
|
|
@@ -995,7 +1299,7 @@ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
|
|
|
995
1299
|
iov->iov_len = buffer_size;
|
|
996
1300
|
|
|
997
1301
|
on = 1;
|
|
998
|
-
if(
|
|
1302
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(on)) < 0){
|
|
999
1303
|
free(buffer);
|
|
1000
1304
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
1001
1305
|
}
|
|
@@ -1003,17 +1307,27 @@ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
|
|
|
1003
1307
|
infolen = sizeof(struct sctp_rcvinfo);
|
|
1004
1308
|
infotype = 0;
|
|
1005
1309
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
NULL
|
|
1012
|
-
|
|
1013
|
-
&
|
|
1014
|
-
&
|
|
1015
|
-
&
|
|
1016
|
-
|
|
1310
|
+
{
|
|
1311
|
+
struct recvv_nogvl_args recv_args;
|
|
1312
|
+
recv_args.fd = fileno;
|
|
1313
|
+
recv_args.iov = iov;
|
|
1314
|
+
recv_args.iovcnt = 1;
|
|
1315
|
+
recv_args.from = NULL;
|
|
1316
|
+
recv_args.fromlen = NULL;
|
|
1317
|
+
recv_args.info = &info;
|
|
1318
|
+
recv_args.infolen = &infolen;
|
|
1319
|
+
recv_args.infotype = &infotype;
|
|
1320
|
+
recv_args.flags = &flags;
|
|
1321
|
+
|
|
1322
|
+
#ifdef HAVE_USRSCTP_H
|
|
1323
|
+
rb_thread_call_without_gvl(recvv_nogvl, &recv_args, recvv_ubf, &recv_args);
|
|
1324
|
+
#else
|
|
1325
|
+
rb_thread_call_without_gvl(recvv_nogvl, &recv_args, RUBY_UBF_IO, NULL);
|
|
1326
|
+
#endif
|
|
1327
|
+
|
|
1328
|
+
bytes = recv_args.result;
|
|
1329
|
+
errno = recv_args.saved_errno;
|
|
1330
|
+
}
|
|
1017
1331
|
|
|
1018
1332
|
if(bytes < 0){
|
|
1019
1333
|
free(buffer);
|
|
@@ -1062,7 +1376,7 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
|
|
|
1062
1376
|
uint16_t stream;
|
|
1063
1377
|
uint32_t ppid, send_flags, ctrl_flags, ttl, context;
|
|
1064
1378
|
ssize_t num_bytes;
|
|
1065
|
-
|
|
1379
|
+
sctp_sock_t fileno;
|
|
1066
1380
|
sctp_assoc_t assoc_id;
|
|
1067
1381
|
struct sctp_sndrcvinfo info;
|
|
1068
1382
|
VALUE v_msg, v_stream, v_ppid, v_context, v_send_flags, v_ctrl_flags, v_ttl, v_assoc_id;
|
|
@@ -1116,6 +1430,8 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
|
|
|
1116
1430
|
else
|
|
1117
1431
|
assoc_id = NUM2INT(v_assoc_id);
|
|
1118
1432
|
|
|
1433
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1434
|
+
|
|
1119
1435
|
info.sinfo_stream = stream;
|
|
1120
1436
|
info.sinfo_flags = send_flags;
|
|
1121
1437
|
info.sinfo_ppid = ppid;
|
|
@@ -1123,9 +1439,9 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
|
|
|
1123
1439
|
info.sinfo_timetolive = ttl;
|
|
1124
1440
|
info.sinfo_assoc_id = assoc_id;
|
|
1125
1441
|
|
|
1126
|
-
fileno =
|
|
1442
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1127
1443
|
|
|
1128
|
-
num_bytes = (ssize_t)
|
|
1444
|
+
num_bytes = (ssize_t)sctp_sys_send(
|
|
1129
1445
|
fileno,
|
|
1130
1446
|
StringValueCStr(v_msg),
|
|
1131
1447
|
RSTRING_LEN(v_msg),
|
|
@@ -1176,13 +1492,11 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
|
1176
1492
|
uint16_t stream;
|
|
1177
1493
|
uint32_t ppid, flags, ttl, context;
|
|
1178
1494
|
ssize_t num_bytes;
|
|
1179
|
-
|
|
1180
|
-
int
|
|
1495
|
+
sctp_sock_t fileno;
|
|
1496
|
+
int num_ip, domain;
|
|
1181
1497
|
|
|
1182
1498
|
Check_Type(v_options, T_HASH);
|
|
1183
1499
|
|
|
1184
|
-
bzero(&addrs, sizeof(addrs));
|
|
1185
|
-
|
|
1186
1500
|
v_msg = rb_hash_aref2(v_options, "message");
|
|
1187
1501
|
v_stream = rb_hash_aref2(v_options, "stream");
|
|
1188
1502
|
v_ppid = rb_hash_aref2(v_options, "ppid");
|
|
@@ -1222,12 +1536,21 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
|
1222
1536
|
else
|
|
1223
1537
|
context = NUM2INT(v_context);
|
|
1224
1538
|
|
|
1539
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1540
|
+
|
|
1541
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1542
|
+
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
|
1543
|
+
|
|
1225
1544
|
if(!NIL_P(v_addresses)){
|
|
1226
1545
|
int i, port;
|
|
1227
1546
|
VALUE v_address, v_port;
|
|
1228
1547
|
|
|
1229
1548
|
Check_Type(v_addresses, T_ARRAY);
|
|
1230
1549
|
num_ip = (int)RARRAY_LEN(v_addresses);
|
|
1550
|
+
|
|
1551
|
+
if(num_ip > MAX_IP_ADDRESSES)
|
|
1552
|
+
rb_raise(rb_eArgError, "too many IP addresses, maximum is eight");
|
|
1553
|
+
|
|
1231
1554
|
v_port = rb_hash_aref2(v_options, "port");
|
|
1232
1555
|
|
|
1233
1556
|
if(NIL_P(v_port))
|
|
@@ -1235,47 +1558,62 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
|
1235
1558
|
else
|
|
1236
1559
|
port = NUM2INT(v_port);
|
|
1237
1560
|
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1561
|
+
if(domain == AF_INET6){
|
|
1562
|
+
struct sockaddr_in6 addrs6[MAX_IP_ADDRESSES];
|
|
1563
|
+
|
|
1564
|
+
bzero(&addrs6, sizeof(addrs6));
|
|
1565
|
+
|
|
1566
|
+
for(i = 0; i < num_ip; i++){
|
|
1567
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
1568
|
+
parse_ip_address_v6(StringValueCStr(v_address), port, &addrs6[i]);
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
num_bytes = (ssize_t)sctp_sys_sendmsg(
|
|
1572
|
+
fileno,
|
|
1573
|
+
StringValueCStr(v_msg),
|
|
1574
|
+
RSTRING_LEN(v_msg),
|
|
1575
|
+
(struct sockaddr*)addrs6,
|
|
1576
|
+
num_ip,
|
|
1577
|
+
ppid,
|
|
1578
|
+
flags,
|
|
1579
|
+
stream,
|
|
1580
|
+
ttl,
|
|
1581
|
+
context
|
|
1582
|
+
);
|
|
1246
1583
|
}
|
|
1584
|
+
else{
|
|
1585
|
+
struct sockaddr_in addrs[MAX_IP_ADDRESSES];
|
|
1247
1586
|
|
|
1248
|
-
|
|
1249
|
-
}
|
|
1250
|
-
else{
|
|
1251
|
-
num_ip = 0;
|
|
1252
|
-
size = 0;
|
|
1253
|
-
}
|
|
1587
|
+
bzero(&addrs, sizeof(addrs));
|
|
1254
1588
|
|
|
1255
|
-
|
|
1589
|
+
for(i = 0; i < num_ip; i++){
|
|
1590
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
1591
|
+
parse_ip_address_v4(StringValueCStr(v_address), port, &addrs[i]);
|
|
1592
|
+
}
|
|
1256
1593
|
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
);
|
|
1594
|
+
num_bytes = (ssize_t)sctp_sys_sendmsg(
|
|
1595
|
+
fileno,
|
|
1596
|
+
StringValueCStr(v_msg),
|
|
1597
|
+
RSTRING_LEN(v_msg),
|
|
1598
|
+
(struct sockaddr*)addrs,
|
|
1599
|
+
num_ip,
|
|
1600
|
+
ppid,
|
|
1601
|
+
flags,
|
|
1602
|
+
stream,
|
|
1603
|
+
ttl,
|
|
1604
|
+
context
|
|
1605
|
+
);
|
|
1606
|
+
}
|
|
1271
1607
|
}
|
|
1272
1608
|
else{
|
|
1273
|
-
|
|
1609
|
+
// No addresses - use empty addrs
|
|
1610
|
+
num_ip = 0;
|
|
1611
|
+
num_bytes = (ssize_t)sctp_sys_sendmsg(
|
|
1274
1612
|
fileno,
|
|
1275
1613
|
StringValueCStr(v_msg),
|
|
1276
1614
|
RSTRING_LEN(v_msg),
|
|
1277
|
-
|
|
1278
|
-
|
|
1615
|
+
NULL,
|
|
1616
|
+
0,
|
|
1279
1617
|
ppid,
|
|
1280
1618
|
flags,
|
|
1281
1619
|
stream,
|
|
@@ -1283,31 +1621,9 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
|
1283
1621
|
context
|
|
1284
1622
|
);
|
|
1285
1623
|
}
|
|
1286
|
-
#else
|
|
1287
|
-
num_bytes = (ssize_t)sctp_sendmsg(
|
|
1288
|
-
fileno,
|
|
1289
|
-
StringValueCStr(v_msg),
|
|
1290
|
-
RSTRING_LEN(v_msg),
|
|
1291
|
-
(struct sockaddr*)addrs,
|
|
1292
|
-
size,
|
|
1293
|
-
ppid,
|
|
1294
|
-
flags,
|
|
1295
|
-
stream,
|
|
1296
|
-
ttl,
|
|
1297
|
-
context
|
|
1298
|
-
);
|
|
1299
|
-
#endif
|
|
1300
1624
|
|
|
1301
|
-
if(num_bytes < 0)
|
|
1302
|
-
#ifdef BSD
|
|
1303
|
-
if(num_ip > 0)
|
|
1304
|
-
rb_raise(rb_eSystemCallError, "sctp_sendmsgx: %s", strerror(errno));
|
|
1305
|
-
else
|
|
1306
|
-
rb_raise(rb_eSystemCallError, "sctp_sendmsg: %s", strerror(errno));
|
|
1307
|
-
#else
|
|
1625
|
+
if(num_bytes < 0)
|
|
1308
1626
|
rb_raise(rb_eSystemCallError, "sctp_sendmsg: %s", strerror(errno));
|
|
1309
|
-
#endif
|
|
1310
|
-
}
|
|
1311
1627
|
|
|
1312
1628
|
return LONG2NUM(num_bytes);
|
|
1313
1629
|
}
|
|
@@ -1345,7 +1661,8 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
|
1345
1661
|
VALUE v_flags, v_buffer_size, v_notification, v_message;
|
|
1346
1662
|
struct sctp_sndrcvinfo sndrcvinfo;
|
|
1347
1663
|
struct sockaddr_in clientaddr;
|
|
1348
|
-
|
|
1664
|
+
sctp_sock_t fileno;
|
|
1665
|
+
int flags, buffer_size;
|
|
1349
1666
|
ssize_t bytes;
|
|
1350
1667
|
char *buffer;
|
|
1351
1668
|
socklen_t length;
|
|
@@ -1369,22 +1686,34 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
|
1369
1686
|
if(buffer == NULL)
|
|
1370
1687
|
rb_raise(rb_eNoMemError, "failed to allocate buffer");
|
|
1371
1688
|
|
|
1372
|
-
|
|
1689
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1690
|
+
|
|
1691
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1373
1692
|
length = sizeof(struct sockaddr_in);
|
|
1374
1693
|
|
|
1375
1694
|
bzero(buffer, buffer_size);
|
|
1376
1695
|
bzero(&clientaddr, sizeof(clientaddr));
|
|
1377
1696
|
bzero(&sndrcvinfo, sizeof(sndrcvinfo));
|
|
1378
1697
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
&
|
|
1385
|
-
&
|
|
1386
|
-
&
|
|
1387
|
-
|
|
1698
|
+
{
|
|
1699
|
+
struct recvmsg_nogvl_args recv_args;
|
|
1700
|
+
recv_args.fd = fileno;
|
|
1701
|
+
recv_args.buf = buffer;
|
|
1702
|
+
recv_args.len = buffer_size;
|
|
1703
|
+
recv_args.from = (struct sockaddr*)&clientaddr;
|
|
1704
|
+
recv_args.fromlen = &length;
|
|
1705
|
+
recv_args.sinfo = &sndrcvinfo;
|
|
1706
|
+
recv_args.msg_flags = &flags;
|
|
1707
|
+
|
|
1708
|
+
#ifdef HAVE_USRSCTP_H
|
|
1709
|
+
rb_thread_call_without_gvl(recvmsg_nogvl, &recv_args, recvmsg_ubf, &recv_args);
|
|
1710
|
+
#else
|
|
1711
|
+
rb_thread_call_without_gvl(recvmsg_nogvl, &recv_args, RUBY_UBF_IO, NULL);
|
|
1712
|
+
#endif
|
|
1713
|
+
|
|
1714
|
+
bytes = recv_args.result;
|
|
1715
|
+
errno = recv_args.saved_errno;
|
|
1716
|
+
}
|
|
1388
1717
|
|
|
1389
1718
|
if(bytes < 0){
|
|
1390
1719
|
free(buffer);
|
|
@@ -1437,18 +1766,20 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
|
1437
1766
|
* By default these values are set to zero (i.e. ignored).
|
|
1438
1767
|
*/
|
|
1439
1768
|
static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
|
|
1440
|
-
|
|
1769
|
+
sctp_sock_t fileno;
|
|
1441
1770
|
struct sctp_initmsg initmsg;
|
|
1442
1771
|
VALUE v_output, v_input, v_attempts, v_timeout;
|
|
1443
1772
|
|
|
1444
1773
|
bzero(&initmsg, sizeof(initmsg));
|
|
1445
1774
|
|
|
1775
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1776
|
+
|
|
1446
1777
|
v_output = rb_hash_aref2(v_options, "output_streams");
|
|
1447
1778
|
v_input = rb_hash_aref2(v_options, "input_streams");
|
|
1448
1779
|
v_attempts = rb_hash_aref2(v_options, "max_attempts");
|
|
1449
1780
|
v_timeout = rb_hash_aref2(v_options, "timeout");
|
|
1450
1781
|
|
|
1451
|
-
fileno =
|
|
1782
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1452
1783
|
|
|
1453
1784
|
if(!NIL_P(v_output))
|
|
1454
1785
|
initmsg.sinit_num_ostreams = NUM2INT(v_output);
|
|
@@ -1462,7 +1793,7 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
|
|
|
1462
1793
|
if(!NIL_P(v_timeout))
|
|
1463
1794
|
initmsg.sinit_max_init_timeo = NUM2INT(v_timeout);
|
|
1464
1795
|
|
|
1465
|
-
if(
|
|
1796
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg)) < 0)
|
|
1466
1797
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
1467
1798
|
|
|
1468
1799
|
return self;
|
|
@@ -1507,13 +1838,15 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
|
|
|
1507
1838
|
* socket.subscribe(:data_io => true, :shutdown => true, :send_failure => true)
|
|
1508
1839
|
*/
|
|
1509
1840
|
static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
|
|
1510
|
-
|
|
1841
|
+
sctp_sock_t fileno;
|
|
1511
1842
|
struct sctp_event_subscribe events;
|
|
1512
1843
|
|
|
1513
1844
|
bzero(&events, sizeof(events));
|
|
1514
1845
|
Check_Type(v_options, T_HASH);
|
|
1515
1846
|
|
|
1516
|
-
|
|
1847
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1848
|
+
|
|
1849
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1517
1850
|
|
|
1518
1851
|
if(RTEST(rb_hash_aref2(v_options, "data_io")))
|
|
1519
1852
|
events.sctp_data_io_event = 1;
|
|
@@ -1549,8 +1882,43 @@ static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
|
|
|
1549
1882
|
if(RTEST(rb_hash_aref2(v_options, "sender_dry")))
|
|
1550
1883
|
events.sctp_sender_dry_event = 1;
|
|
1551
1884
|
|
|
1552
|
-
|
|
1885
|
+
#ifdef HAVE_USRSCTP_H
|
|
1886
|
+
/* usrsctp uses SCTP_EVENT + struct sctp_event for per-event subscription */
|
|
1887
|
+
{
|
|
1888
|
+
struct sctp_event se;
|
|
1889
|
+
memset(&se, 0, sizeof(se));
|
|
1890
|
+
se.se_assoc_id = 0;
|
|
1891
|
+
|
|
1892
|
+
/* data_io: enable via SCTP_RECVRCVINFO sockopt */
|
|
1893
|
+
if(events.sctp_data_io_event){
|
|
1894
|
+
int on = 1;
|
|
1895
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(on)) < 0)
|
|
1896
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
#define SUBSCRIBE_EVENT(field, type) \
|
|
1900
|
+
if(events.field){ \
|
|
1901
|
+
se.se_type = (type); se.se_on = 1; \
|
|
1902
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_EVENT, &se, sizeof(se)) < 0) \
|
|
1903
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno)); \
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
SUBSCRIBE_EVENT(sctp_association_event, SCTP_ASSOC_CHANGE)
|
|
1907
|
+
SUBSCRIBE_EVENT(sctp_address_event, SCTP_PEER_ADDR_CHANGE)
|
|
1908
|
+
SUBSCRIBE_EVENT(sctp_send_failure_event, SCTP_SEND_FAILED)
|
|
1909
|
+
SUBSCRIBE_EVENT(sctp_peer_error_event, SCTP_REMOTE_ERROR)
|
|
1910
|
+
SUBSCRIBE_EVENT(sctp_shutdown_event, SCTP_SHUTDOWN_EVENT)
|
|
1911
|
+
SUBSCRIBE_EVENT(sctp_partial_delivery_event, SCTP_PARTIAL_DELIVERY_EVENT)
|
|
1912
|
+
SUBSCRIBE_EVENT(sctp_adaptation_layer_event, SCTP_ADAPTATION_INDICATION)
|
|
1913
|
+
SUBSCRIBE_EVENT(sctp_authentication_event, SCTP_AUTHENTICATION_EVENT)
|
|
1914
|
+
SUBSCRIBE_EVENT(sctp_sender_dry_event, SCTP_SENDER_DRY_EVENT)
|
|
1915
|
+
|
|
1916
|
+
#undef SUBSCRIBE_EVENT
|
|
1917
|
+
}
|
|
1918
|
+
#else
|
|
1919
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)) < 0)
|
|
1553
1920
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
1921
|
+
#endif
|
|
1554
1922
|
|
|
1555
1923
|
return self;
|
|
1556
1924
|
}
|
|
@@ -1581,7 +1949,8 @@ static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
|
|
|
1581
1949
|
*/
|
|
1582
1950
|
static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
|
|
1583
1951
|
VALUE v_backlog;
|
|
1584
|
-
|
|
1952
|
+
sctp_sock_t fileno;
|
|
1953
|
+
int backlog;
|
|
1585
1954
|
|
|
1586
1955
|
rb_scan_args(argc, argv, "01", &v_backlog);
|
|
1587
1956
|
|
|
@@ -1593,9 +1962,11 @@ static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
|
|
|
1593
1962
|
if(backlog > SOMAXCONN)
|
|
1594
1963
|
rb_raise(rb_eArgError, "backlog value exceeds maximum value of: %i", SOMAXCONN);
|
|
1595
1964
|
|
|
1596
|
-
|
|
1965
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1597
1966
|
|
|
1598
|
-
|
|
1967
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1968
|
+
|
|
1969
|
+
if(sctp_sys_listen(fileno, backlog) < 0)
|
|
1599
1970
|
rb_raise(rb_eSystemCallError, "listen: %s", strerror(errno));
|
|
1600
1971
|
|
|
1601
1972
|
return self;
|
|
@@ -1620,18 +1991,20 @@ static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
|
|
|
1620
1991
|
* end
|
|
1621
1992
|
*/
|
|
1622
1993
|
static VALUE rsctp_peeloff(VALUE self, VALUE v_assoc_id){
|
|
1623
|
-
|
|
1994
|
+
sctp_sock_t fileno, assoc_fileno;
|
|
1624
1995
|
sctp_assoc_t assoc_id;
|
|
1625
1996
|
|
|
1626
|
-
|
|
1997
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1998
|
+
|
|
1999
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1627
2000
|
assoc_id = NUM2INT(v_assoc_id);
|
|
1628
2001
|
|
|
1629
|
-
assoc_fileno =
|
|
2002
|
+
assoc_fileno = sctp_sys_peeloff(fileno, assoc_id);
|
|
1630
2003
|
|
|
1631
|
-
if(assoc_fileno
|
|
2004
|
+
if(SCTP_FD_INVALID(assoc_fileno))
|
|
1632
2005
|
rb_raise(rb_eSystemCallError, "sctp_peeloff: %s", strerror(errno));
|
|
1633
2006
|
|
|
1634
|
-
return
|
|
2007
|
+
return SCTP_FD_TO_NUM(assoc_fileno);
|
|
1635
2008
|
}
|
|
1636
2009
|
|
|
1637
2010
|
/*
|
|
@@ -1653,32 +2026,60 @@ static VALUE rsctp_peeloff(VALUE self, VALUE v_assoc_id){
|
|
|
1653
2026
|
* * association_id
|
|
1654
2027
|
*/
|
|
1655
2028
|
static VALUE rsctp_get_default_send_params(VALUE self){
|
|
1656
|
-
|
|
2029
|
+
sctp_sock_t fileno;
|
|
1657
2030
|
socklen_t size;
|
|
1658
2031
|
sctp_assoc_t assoc_id;
|
|
1659
|
-
struct sctp_sndrcvinfo sndrcv;
|
|
1660
2032
|
|
|
1661
|
-
|
|
2033
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1662
2034
|
|
|
1663
|
-
fileno =
|
|
2035
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1664
2036
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
1665
|
-
size = sizeof(struct sctp_sndrcvinfo);
|
|
1666
2037
|
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
2038
|
+
#ifdef HAVE_USRSCTP_H
|
|
2039
|
+
{
|
|
2040
|
+
struct sctp_sndinfo sndinfo;
|
|
2041
|
+
bzero(&sndinfo, sizeof(sndinfo));
|
|
2042
|
+
size = sizeof(sndinfo);
|
|
2043
|
+
|
|
2044
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_DEFAULT_SNDINFO, (void*)&sndinfo, &size) < 0)
|
|
2045
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
2046
|
+
|
|
2047
|
+
return rb_struct_new(
|
|
2048
|
+
v_sctp_default_send_params_struct,
|
|
2049
|
+
INT2NUM(sndinfo.snd_sid),
|
|
2050
|
+
INT2NUM(0), /* ssn - not available via sndinfo */
|
|
2051
|
+
INT2NUM(sndinfo.snd_flags),
|
|
2052
|
+
INT2NUM(sndinfo.snd_ppid),
|
|
2053
|
+
INT2NUM(sndinfo.snd_context),
|
|
2054
|
+
INT2NUM(0), /* timetolive - not available via sndinfo */
|
|
2055
|
+
INT2NUM(0), /* tsn - not available via sndinfo */
|
|
2056
|
+
INT2NUM(0), /* cumtsn - not available via sndinfo */
|
|
2057
|
+
INT2NUM(sndinfo.snd_assoc_id)
|
|
2058
|
+
);
|
|
2059
|
+
}
|
|
2060
|
+
#else
|
|
2061
|
+
{
|
|
2062
|
+
struct sctp_sndrcvinfo sndrcv;
|
|
2063
|
+
bzero(&sndrcv, sizeof(sndrcv));
|
|
2064
|
+
size = sizeof(struct sctp_sndrcvinfo);
|
|
2065
|
+
|
|
2066
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_DEFAULT_SEND_PARAM, (void*)&sndrcv, &size) < 0)
|
|
2067
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
2068
|
+
|
|
2069
|
+
return rb_struct_new(
|
|
2070
|
+
v_sctp_default_send_params_struct,
|
|
2071
|
+
INT2NUM(sndrcv.sinfo_stream),
|
|
2072
|
+
INT2NUM(sndrcv.sinfo_ssn),
|
|
2073
|
+
INT2NUM(sndrcv.sinfo_flags),
|
|
2074
|
+
INT2NUM(sndrcv.sinfo_ppid),
|
|
2075
|
+
INT2NUM(sndrcv.sinfo_context),
|
|
2076
|
+
INT2NUM(sndrcv.sinfo_timetolive),
|
|
2077
|
+
INT2NUM(sndrcv.sinfo_tsn),
|
|
2078
|
+
INT2NUM(sndrcv.sinfo_cumtsn),
|
|
2079
|
+
INT2NUM(sndrcv.sinfo_assoc_id)
|
|
2080
|
+
);
|
|
2081
|
+
}
|
|
2082
|
+
#endif
|
|
1682
2083
|
}
|
|
1683
2084
|
|
|
1684
2085
|
/*
|
|
@@ -1698,18 +2099,20 @@ static VALUE rsctp_get_default_send_params(VALUE self){
|
|
|
1698
2099
|
* All values that refer to time values are measured in milliseconds.
|
|
1699
2100
|
*/
|
|
1700
2101
|
static VALUE rsctp_get_association_info(VALUE self){
|
|
1701
|
-
|
|
2102
|
+
sctp_sock_t fileno;
|
|
1702
2103
|
socklen_t size;
|
|
1703
2104
|
sctp_assoc_t assoc_id;
|
|
1704
2105
|
struct sctp_assocparams assoc;
|
|
1705
2106
|
|
|
1706
2107
|
bzero(&assoc, sizeof(assoc));
|
|
1707
2108
|
|
|
1708
|
-
|
|
2109
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2110
|
+
|
|
2111
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1709
2112
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
1710
2113
|
size = sizeof(struct sctp_assocparams);
|
|
1711
2114
|
|
|
1712
|
-
if(
|
|
2115
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_ASSOCINFO, (void*)&assoc, &size) < 0)
|
|
1713
2116
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
1714
2117
|
|
|
1715
2118
|
return rb_struct_new(
|
|
@@ -1741,13 +2144,15 @@ static VALUE rsctp_get_association_info(VALUE self){
|
|
|
1741
2144
|
*/
|
|
1742
2145
|
static VALUE rsctp_set_association_info(VALUE self, VALUE v_options){
|
|
1743
2146
|
VALUE v_assoc_id, v_max_rxt, v_nbr_peer, v_peer_rw, v_local_rw, v_cookie;
|
|
1744
|
-
|
|
2147
|
+
sctp_sock_t fileno;
|
|
1745
2148
|
sctp_assoc_t assoc_id;
|
|
1746
2149
|
struct sctp_assocparams assoc;
|
|
1747
2150
|
|
|
1748
2151
|
bzero(&assoc, sizeof(assoc));
|
|
1749
2152
|
|
|
1750
|
-
|
|
2153
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2154
|
+
|
|
2155
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1751
2156
|
|
|
1752
2157
|
v_assoc_id = rb_hash_aref2(v_options, "association_id");
|
|
1753
2158
|
v_max_rxt = rb_hash_aref2(v_options, "max_retransmission_count");
|
|
@@ -1778,7 +2183,7 @@ static VALUE rsctp_set_association_info(VALUE self, VALUE v_options){
|
|
|
1778
2183
|
if(!NIL_P(v_cookie))
|
|
1779
2184
|
assoc.sasoc_cookie_life = NUM2INT(v_cookie);
|
|
1780
2185
|
|
|
1781
|
-
if(
|
|
2186
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, sizeof(assoc)) < 0)
|
|
1782
2187
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
1783
2188
|
|
|
1784
2189
|
return rb_struct_new(
|
|
@@ -1808,10 +2213,13 @@ static VALUE rsctp_set_association_info(VALUE self, VALUE v_options){
|
|
|
1808
2213
|
* The default is SHUT_RDWR.
|
|
1809
2214
|
*/
|
|
1810
2215
|
static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
|
|
1811
|
-
|
|
2216
|
+
sctp_sock_t fileno;
|
|
2217
|
+
int how;
|
|
1812
2218
|
VALUE v_how;
|
|
1813
2219
|
|
|
1814
|
-
|
|
2220
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2221
|
+
|
|
2222
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1815
2223
|
|
|
1816
2224
|
rb_scan_args(argc, argv, "01", &v_how);
|
|
1817
2225
|
|
|
@@ -1823,7 +2231,7 @@ static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
|
|
|
1823
2231
|
how = NUM2INT(v_how);
|
|
1824
2232
|
}
|
|
1825
2233
|
|
|
1826
|
-
if(
|
|
2234
|
+
if(sctp_sys_shutdown(fileno, how) < 0)
|
|
1827
2235
|
rb_raise(rb_eSystemCallError, "shutdown: %s", strerror(errno));
|
|
1828
2236
|
|
|
1829
2237
|
return self;
|
|
@@ -1843,18 +2251,20 @@ static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
|
|
|
1843
2251
|
* * min
|
|
1844
2252
|
*/
|
|
1845
2253
|
static VALUE rsctp_get_retransmission_info(VALUE self){
|
|
1846
|
-
|
|
2254
|
+
sctp_sock_t fileno;
|
|
1847
2255
|
socklen_t size;
|
|
1848
2256
|
sctp_assoc_t assoc_id;
|
|
1849
2257
|
struct sctp_rtoinfo rto;
|
|
1850
2258
|
|
|
1851
2259
|
bzero(&rto, sizeof(rto));
|
|
1852
2260
|
|
|
1853
|
-
|
|
2261
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2262
|
+
|
|
2263
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1854
2264
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
1855
2265
|
size = sizeof(struct sctp_rtoinfo);
|
|
1856
2266
|
|
|
1857
|
-
if(
|
|
2267
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_RTOINFO, (void*)&rto, &size) < 0)
|
|
1858
2268
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
1859
2269
|
|
|
1860
2270
|
return rb_struct_new(
|
|
@@ -1883,13 +2293,15 @@ static VALUE rsctp_get_retransmission_info(VALUE self){
|
|
|
1883
2293
|
*/
|
|
1884
2294
|
static VALUE rsctp_set_retransmission_info(VALUE self, VALUE v_options){
|
|
1885
2295
|
VALUE v_assoc_id, v_initial, v_max, v_min;
|
|
1886
|
-
|
|
2296
|
+
sctp_sock_t fileno;
|
|
1887
2297
|
sctp_assoc_t assoc_id;
|
|
1888
2298
|
struct sctp_rtoinfo rto;
|
|
1889
2299
|
|
|
1890
2300
|
bzero(&rto, sizeof(rto));
|
|
1891
2301
|
|
|
1892
|
-
|
|
2302
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2303
|
+
|
|
2304
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1893
2305
|
|
|
1894
2306
|
v_assoc_id = rb_hash_aref2(v_options, "association_id");
|
|
1895
2307
|
v_initial = rb_hash_aref2(v_options, "initial");
|
|
@@ -1912,7 +2324,7 @@ static VALUE rsctp_set_retransmission_info(VALUE self, VALUE v_options){
|
|
|
1912
2324
|
if(!NIL_P(v_min))
|
|
1913
2325
|
rto.srto_min = NUM2INT(v_min);
|
|
1914
2326
|
|
|
1915
|
-
if(
|
|
2327
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_RTOINFO, &rto, sizeof(rto)) < 0)
|
|
1916
2328
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
1917
2329
|
|
|
1918
2330
|
return rb_struct_new(
|
|
@@ -1949,20 +2361,22 @@ static VALUE rsctp_set_retransmission_info(VALUE self, VALUE v_options){
|
|
|
1949
2361
|
* * primary (IP)
|
|
1950
2362
|
*/
|
|
1951
2363
|
static VALUE rsctp_get_status(VALUE self){
|
|
1952
|
-
|
|
2364
|
+
sctp_sock_t fileno;
|
|
1953
2365
|
socklen_t size;
|
|
1954
2366
|
sctp_assoc_t assoc_id;
|
|
1955
2367
|
struct sctp_status status;
|
|
1956
2368
|
struct sctp_paddrinfo* spinfo;
|
|
1957
|
-
char tmpname[
|
|
2369
|
+
char tmpname[INET6_ADDRSTRLEN];
|
|
1958
2370
|
|
|
1959
2371
|
bzero(&status, sizeof(status));
|
|
1960
2372
|
|
|
1961
|
-
|
|
2373
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2374
|
+
|
|
2375
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
1962
2376
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
1963
2377
|
size = sizeof(struct sctp_status);
|
|
1964
2378
|
|
|
1965
|
-
if(
|
|
2379
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_STATUS, (void*)&status, &size) < 0)
|
|
1966
2380
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
1967
2381
|
|
|
1968
2382
|
spinfo = &status.sstat_primary;
|
|
@@ -2015,19 +2429,64 @@ static VALUE rsctp_get_status(VALUE self){
|
|
|
2015
2429
|
* * send_failure_event
|
|
2016
2430
|
*/
|
|
2017
2431
|
static VALUE rsctp_get_subscriptions(VALUE self){
|
|
2018
|
-
|
|
2019
|
-
socklen_t size;
|
|
2432
|
+
sctp_sock_t fileno;
|
|
2020
2433
|
sctp_assoc_t assoc_id;
|
|
2021
2434
|
struct sctp_event_subscribe events;
|
|
2435
|
+
#ifndef HAVE_USRSCTP_H
|
|
2436
|
+
socklen_t size;
|
|
2437
|
+
#endif
|
|
2022
2438
|
|
|
2023
2439
|
bzero(&events, sizeof(events));
|
|
2024
2440
|
|
|
2025
|
-
|
|
2441
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2442
|
+
|
|
2443
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2026
2444
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
2027
|
-
size = sizeof(struct sctp_event_subscribe);
|
|
2028
2445
|
|
|
2029
|
-
|
|
2446
|
+
#ifdef HAVE_USRSCTP_H
|
|
2447
|
+
/* usrsctp uses SCTP_EVENT + struct sctp_event for per-event query */
|
|
2448
|
+
{
|
|
2449
|
+
struct sctp_event se;
|
|
2450
|
+
socklen_t se_size;
|
|
2451
|
+
|
|
2452
|
+
memset(&events, 0, sizeof(events));
|
|
2453
|
+
|
|
2454
|
+
/* data_io: check SCTP_RECVRCVINFO sockopt */
|
|
2455
|
+
{
|
|
2456
|
+
int on = 0;
|
|
2457
|
+
socklen_t on_size = sizeof(on);
|
|
2458
|
+
if(sctp_sys_getsockopt(fileno, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, &on_size) == 0 && on)
|
|
2459
|
+
events.sctp_data_io_event = 1;
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
#define QUERY_EVENT(field, type) \
|
|
2463
|
+
memset(&se, 0, sizeof(se)); \
|
|
2464
|
+
se.se_assoc_id = assoc_id; \
|
|
2465
|
+
se.se_type = (type); \
|
|
2466
|
+
se_size = sizeof(se); \
|
|
2467
|
+
if(sctp_sys_getsockopt(fileno, IPPROTO_SCTP, SCTP_EVENT, &se, &se_size) == 0 && se.se_on) \
|
|
2468
|
+
events.field = 1;
|
|
2469
|
+
|
|
2470
|
+
QUERY_EVENT(sctp_association_event, SCTP_ASSOC_CHANGE)
|
|
2471
|
+
QUERY_EVENT(sctp_address_event, SCTP_PEER_ADDR_CHANGE)
|
|
2472
|
+
QUERY_EVENT(sctp_send_failure_event, SCTP_SEND_FAILED)
|
|
2473
|
+
QUERY_EVENT(sctp_peer_error_event, SCTP_REMOTE_ERROR)
|
|
2474
|
+
QUERY_EVENT(sctp_shutdown_event, SCTP_SHUTDOWN_EVENT)
|
|
2475
|
+
QUERY_EVENT(sctp_partial_delivery_event, SCTP_PARTIAL_DELIVERY_EVENT)
|
|
2476
|
+
QUERY_EVENT(sctp_adaptation_layer_event, SCTP_ADAPTATION_INDICATION)
|
|
2477
|
+
QUERY_EVENT(sctp_authentication_event, SCTP_AUTHENTICATION_EVENT)
|
|
2478
|
+
QUERY_EVENT(sctp_sender_dry_event, SCTP_SENDER_DRY_EVENT)
|
|
2479
|
+
#ifdef HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_STREAM_RESET_EVENT
|
|
2480
|
+
QUERY_EVENT(sctp_stream_reset_event, SCTP_STREAM_RESET_EVENT)
|
|
2481
|
+
#endif
|
|
2482
|
+
|
|
2483
|
+
#undef QUERY_EVENT
|
|
2484
|
+
}
|
|
2485
|
+
#else
|
|
2486
|
+
size = sizeof(struct sctp_event_subscribe);
|
|
2487
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_EVENTS, (void*)&events, &size) < 0)
|
|
2030
2488
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
2489
|
+
#endif
|
|
2031
2490
|
|
|
2032
2491
|
return rb_struct_new(
|
|
2033
2492
|
v_sctp_event_subscribe_struct,
|
|
@@ -2078,7 +2537,7 @@ static VALUE rsctp_get_subscriptions(VALUE self){
|
|
|
2078
2537
|
* * ipv6_flowlabel
|
|
2079
2538
|
*/
|
|
2080
2539
|
static VALUE rsctp_get_peer_address_params(VALUE self){
|
|
2081
|
-
|
|
2540
|
+
sctp_sock_t fileno;
|
|
2082
2541
|
char str[IP_BUFFER_SIZE];
|
|
2083
2542
|
socklen_t size;
|
|
2084
2543
|
sctp_assoc_t assoc_id;
|
|
@@ -2087,14 +2546,27 @@ static VALUE rsctp_get_peer_address_params(VALUE self){
|
|
|
2087
2546
|
bzero(&paddr, sizeof(paddr));
|
|
2088
2547
|
bzero(&str, sizeof(str));
|
|
2089
2548
|
|
|
2090
|
-
|
|
2549
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2550
|
+
|
|
2551
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2091
2552
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
2092
2553
|
size = sizeof(struct sctp_paddrparams);
|
|
2093
2554
|
|
|
2094
|
-
if(
|
|
2555
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_PEER_ADDR_PARAMS, (void*)&paddr, &size) < 0)
|
|
2095
2556
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
2096
2557
|
|
|
2097
|
-
|
|
2558
|
+
{
|
|
2559
|
+
struct sockaddr* sa = (struct sockaddr*)&paddr.spp_address;
|
|
2560
|
+
|
|
2561
|
+
if(sa->sa_family == AF_INET6){
|
|
2562
|
+
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
|
|
2563
|
+
inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str));
|
|
2564
|
+
}
|
|
2565
|
+
else{
|
|
2566
|
+
struct sockaddr_in* sin = (struct sockaddr_in*)sa;
|
|
2567
|
+
inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str));
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2098
2570
|
|
|
2099
2571
|
return rb_struct_new(
|
|
2100
2572
|
v_sctp_peer_addr_params_struct,
|
|
@@ -2127,18 +2599,20 @@ static VALUE rsctp_get_peer_address_params(VALUE self){
|
|
|
2127
2599
|
* (in milliseconds) to use in attempting an INIT.
|
|
2128
2600
|
*/
|
|
2129
2601
|
static VALUE rsctp_get_init_msg(VALUE self){
|
|
2130
|
-
|
|
2602
|
+
sctp_sock_t fileno;
|
|
2131
2603
|
socklen_t size;
|
|
2132
2604
|
sctp_assoc_t assoc_id;
|
|
2133
2605
|
struct sctp_initmsg initmsg;
|
|
2134
2606
|
|
|
2135
2607
|
bzero(&initmsg, sizeof(initmsg));
|
|
2136
2608
|
|
|
2137
|
-
|
|
2609
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2610
|
+
|
|
2611
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2138
2612
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
2139
2613
|
size = sizeof(struct sctp_initmsg);
|
|
2140
2614
|
|
|
2141
|
-
if(
|
|
2615
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_INITMSG, (void*)&initmsg, &size) < 0)
|
|
2142
2616
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
2143
2617
|
|
|
2144
2618
|
return rb_struct_new(
|
|
@@ -2157,16 +2631,18 @@ static VALUE rsctp_get_init_msg(VALUE self){
|
|
|
2157
2631
|
* Returns whether or not the nodelay option has been set.
|
|
2158
2632
|
*/
|
|
2159
2633
|
static VALUE rsctp_get_nodelay(VALUE self){
|
|
2160
|
-
|
|
2634
|
+
sctp_sock_t fileno;
|
|
2161
2635
|
socklen_t size;
|
|
2162
2636
|
sctp_assoc_t assoc_id;
|
|
2163
2637
|
int value;
|
|
2164
2638
|
|
|
2165
|
-
|
|
2639
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2640
|
+
|
|
2641
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2166
2642
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
2167
2643
|
size = sizeof(int);
|
|
2168
2644
|
|
|
2169
|
-
if(
|
|
2645
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_NODELAY, (void*)&value, &size) < 0)
|
|
2170
2646
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
2171
2647
|
|
|
2172
2648
|
if(value)
|
|
@@ -2184,11 +2660,13 @@ static VALUE rsctp_get_nodelay(VALUE self){
|
|
|
2184
2660
|
* cost of more packets in the network.
|
|
2185
2661
|
*/
|
|
2186
2662
|
static VALUE rsctp_set_nodelay(VALUE self, VALUE v_bool){
|
|
2187
|
-
|
|
2663
|
+
sctp_sock_t fileno;
|
|
2188
2664
|
socklen_t size;
|
|
2189
2665
|
int value;
|
|
2190
2666
|
|
|
2191
|
-
|
|
2667
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2668
|
+
|
|
2669
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2192
2670
|
size = sizeof(int);
|
|
2193
2671
|
|
|
2194
2672
|
if(NIL_P(v_bool) || v_bool == Qfalse)
|
|
@@ -2196,7 +2674,7 @@ static VALUE rsctp_set_nodelay(VALUE self, VALUE v_bool){
|
|
|
2196
2674
|
else
|
|
2197
2675
|
value = 1;
|
|
2198
2676
|
|
|
2199
|
-
if(
|
|
2677
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_NODELAY, &value, size) < 0)
|
|
2200
2678
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
2201
2679
|
|
|
2202
2680
|
if(value)
|
|
@@ -2216,12 +2694,14 @@ static VALUE rsctp_set_nodelay(VALUE self, VALUE v_bool){
|
|
|
2216
2694
|
* instead a error will be indicated to the user.
|
|
2217
2695
|
*/
|
|
2218
2696
|
static VALUE rsctp_disable_fragments(VALUE self, VALUE v_bool){
|
|
2219
|
-
|
|
2697
|
+
sctp_sock_t fileno;
|
|
2220
2698
|
socklen_t size;
|
|
2221
2699
|
sctp_assoc_t assoc_id;
|
|
2222
2700
|
int value;
|
|
2223
2701
|
|
|
2224
|
-
|
|
2702
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2703
|
+
|
|
2704
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2225
2705
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
2226
2706
|
size = sizeof(int);
|
|
2227
2707
|
|
|
@@ -2230,7 +2710,7 @@ static VALUE rsctp_disable_fragments(VALUE self, VALUE v_bool){
|
|
|
2230
2710
|
else
|
|
2231
2711
|
value = 1;
|
|
2232
2712
|
|
|
2233
|
-
if(
|
|
2713
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_DISABLE_FRAGMENTS, (void*)&value, &size) < 0)
|
|
2234
2714
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
2235
2715
|
|
|
2236
2716
|
if(value)
|
|
@@ -2247,16 +2727,18 @@ static VALUE rsctp_disable_fragments(VALUE self, VALUE v_bool){
|
|
|
2247
2727
|
* shut down.
|
|
2248
2728
|
*/
|
|
2249
2729
|
static VALUE rsctp_get_autoclose(VALUE self){
|
|
2250
|
-
|
|
2730
|
+
sctp_sock_t fileno;
|
|
2251
2731
|
socklen_t size;
|
|
2252
2732
|
sctp_assoc_t assoc_id;
|
|
2253
2733
|
int value;
|
|
2254
2734
|
|
|
2255
|
-
|
|
2735
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2736
|
+
|
|
2737
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2256
2738
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
2257
2739
|
size = sizeof(int);
|
|
2258
2740
|
|
|
2259
|
-
if(
|
|
2741
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_AUTOCLOSE, (void*)&value, &size) < 0)
|
|
2260
2742
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
2261
2743
|
|
|
2262
2744
|
return INT2NUM(value);
|
|
@@ -2285,13 +2767,15 @@ static VALUE rsctp_get_autoclose(VALUE self){
|
|
|
2285
2767
|
* This socket option is applicable to the one-to-many style socket only.
|
|
2286
2768
|
*/
|
|
2287
2769
|
static VALUE rsctp_set_autoclose(VALUE self, VALUE v_seconds){
|
|
2288
|
-
|
|
2770
|
+
sctp_sock_t fileno;
|
|
2289
2771
|
int value;
|
|
2290
2772
|
|
|
2773
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2774
|
+
|
|
2291
2775
|
value = NUM2INT(v_seconds);
|
|
2292
|
-
fileno =
|
|
2776
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2293
2777
|
|
|
2294
|
-
if(
|
|
2778
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_AUTOCLOSE, &value, sizeof(value)) < 0)
|
|
2295
2779
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
2296
2780
|
|
|
2297
2781
|
return INT2NUM(value);
|
|
@@ -2304,7 +2788,7 @@ static VALUE rsctp_set_autoclose(VALUE self, VALUE v_seconds){
|
|
|
2304
2788
|
* Enables auth for future associations.
|
|
2305
2789
|
*/
|
|
2306
2790
|
static VALUE rsctp_enable_auth_support(int argc, VALUE* argv, VALUE self){
|
|
2307
|
-
|
|
2791
|
+
sctp_sock_t fileno;
|
|
2308
2792
|
socklen_t size;
|
|
2309
2793
|
sctp_assoc_t assoc_id;
|
|
2310
2794
|
struct sctp_assoc_value assoc_value;
|
|
@@ -2314,7 +2798,7 @@ static VALUE rsctp_enable_auth_support(int argc, VALUE* argv, VALUE self){
|
|
|
2314
2798
|
|
|
2315
2799
|
CHECK_SOCKET_CLOSED(self);
|
|
2316
2800
|
|
|
2317
|
-
fileno =
|
|
2801
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2318
2802
|
size = sizeof(struct sctp_assoc_value);
|
|
2319
2803
|
|
|
2320
2804
|
if(NIL_P(v_assoc_id))
|
|
@@ -2325,7 +2809,7 @@ static VALUE rsctp_enable_auth_support(int argc, VALUE* argv, VALUE self){
|
|
|
2325
2809
|
assoc_value.assoc_id = assoc_id;
|
|
2326
2810
|
assoc_value.assoc_value = 1;
|
|
2327
2811
|
|
|
2328
|
-
if(
|
|
2812
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_AUTH_SUPPORTED, (void*)&assoc_value, size) < 0)
|
|
2329
2813
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
2330
2814
|
|
|
2331
2815
|
return self;
|
|
@@ -2339,7 +2823,7 @@ static VALUE rsctp_enable_auth_support(int argc, VALUE* argv, VALUE self){
|
|
|
2339
2823
|
* Returns true if auth support is enabled, false otherwise.
|
|
2340
2824
|
*/
|
|
2341
2825
|
static VALUE rsctp_get_auth_support(int argc, VALUE* argv, VALUE self){
|
|
2342
|
-
|
|
2826
|
+
sctp_sock_t fileno;
|
|
2343
2827
|
socklen_t size;
|
|
2344
2828
|
sctp_assoc_t assoc_id;
|
|
2345
2829
|
struct sctp_assoc_value assoc_value;
|
|
@@ -2349,7 +2833,7 @@ static VALUE rsctp_get_auth_support(int argc, VALUE* argv, VALUE self){
|
|
|
2349
2833
|
|
|
2350
2834
|
CHECK_SOCKET_CLOSED(self);
|
|
2351
2835
|
|
|
2352
|
-
fileno =
|
|
2836
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2353
2837
|
size = sizeof(struct sctp_assoc_value);
|
|
2354
2838
|
|
|
2355
2839
|
if(NIL_P(v_assoc_id))
|
|
@@ -2359,7 +2843,7 @@ static VALUE rsctp_get_auth_support(int argc, VALUE* argv, VALUE self){
|
|
|
2359
2843
|
|
|
2360
2844
|
assoc_value.assoc_id = assoc_id;
|
|
2361
2845
|
|
|
2362
|
-
if(
|
|
2846
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_AUTH_SUPPORTED, (void*)&assoc_value, &size) < 0)
|
|
2363
2847
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
2364
2848
|
|
|
2365
2849
|
if(assoc_value.assoc_value)
|
|
@@ -2395,7 +2879,7 @@ static VALUE rsctp_get_auth_support(int argc, VALUE* argv, VALUE self){
|
|
|
2395
2879
|
* otherwise this will set a key on the endpoint.
|
|
2396
2880
|
*/
|
|
2397
2881
|
static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
|
|
2398
|
-
|
|
2882
|
+
sctp_sock_t fileno;
|
|
2399
2883
|
size_t len;
|
|
2400
2884
|
char* key;
|
|
2401
2885
|
uint keynum;
|
|
@@ -2408,7 +2892,7 @@ static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2408
2892
|
|
|
2409
2893
|
CHECK_SOCKET_CLOSED(self);
|
|
2410
2894
|
|
|
2411
|
-
fileno =
|
|
2895
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2412
2896
|
key = StringValuePtr(v_key);
|
|
2413
2897
|
len = RSTRING_LEN(v_key); // Use Ruby's string length, not strlen
|
|
2414
2898
|
|
|
@@ -2423,7 +2907,7 @@ static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2423
2907
|
keynum = NUM2INT(v_keynumber);
|
|
2424
2908
|
|
|
2425
2909
|
// Allocate the structure with space for the key
|
|
2426
|
-
size = sizeof(struct sctp_authkey) + len;
|
|
2910
|
+
size = (socklen_t)(sizeof(struct sctp_authkey) + len);
|
|
2427
2911
|
auth_key = malloc(size);
|
|
2428
2912
|
|
|
2429
2913
|
if (auth_key == NULL)
|
|
@@ -2434,7 +2918,7 @@ static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2434
2918
|
auth_key->sca_keylength = len;
|
|
2435
2919
|
memcpy(auth_key->sca_key, key, len);
|
|
2436
2920
|
|
|
2437
|
-
if(
|
|
2921
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_AUTH_KEY, (void*)auth_key, size) < 0) {
|
|
2438
2922
|
int err = errno;
|
|
2439
2923
|
free(auth_key);
|
|
2440
2924
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(err));
|
|
@@ -2451,7 +2935,7 @@ static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2451
2935
|
* Gets the active shared key to be used to build the association shared key.
|
|
2452
2936
|
*/
|
|
2453
2937
|
static VALUE rsctp_get_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
2454
|
-
|
|
2938
|
+
sctp_sock_t fileno;
|
|
2455
2939
|
socklen_t size;
|
|
2456
2940
|
struct sctp_authkeyid authkey;
|
|
2457
2941
|
sctp_assoc_t assoc_id;
|
|
@@ -2460,6 +2944,8 @@ static VALUE rsctp_get_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2460
2944
|
|
|
2461
2945
|
rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
|
|
2462
2946
|
|
|
2947
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2948
|
+
|
|
2463
2949
|
bzero(&authkey, sizeof(authkey));
|
|
2464
2950
|
|
|
2465
2951
|
// Cast it later, we want to force a validity check.
|
|
@@ -2468,7 +2954,7 @@ static VALUE rsctp_get_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2468
2954
|
if(keynum < 0)
|
|
2469
2955
|
rb_raise(rb_eArgError, "invalid keynum value");
|
|
2470
2956
|
|
|
2471
|
-
fileno =
|
|
2957
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2472
2958
|
|
|
2473
2959
|
if(NIL_P(v_assoc_id))
|
|
2474
2960
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
@@ -2480,7 +2966,7 @@ static VALUE rsctp_get_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2480
2966
|
|
|
2481
2967
|
size = sizeof(struct sctp_authkeyid);
|
|
2482
2968
|
|
|
2483
|
-
if(
|
|
2969
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_AUTH_ACTIVE_KEY, (void*)&authkey, &size) < 0)
|
|
2484
2970
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
2485
2971
|
|
|
2486
2972
|
return INT2NUM(authkey.scact_keynumber);
|
|
@@ -2509,7 +2995,7 @@ static VALUE rsctp_get_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2509
2995
|
* By default, the association_id is the result of SCTP::Socket#association_id.
|
|
2510
2996
|
*/
|
|
2511
2997
|
static VALUE rsctp_set_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
2512
|
-
|
|
2998
|
+
sctp_sock_t fileno;
|
|
2513
2999
|
socklen_t size;
|
|
2514
3000
|
struct sctp_authkeyid authkey;
|
|
2515
3001
|
sctp_assoc_t assoc_id;
|
|
@@ -2518,12 +3004,14 @@ static VALUE rsctp_set_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2518
3004
|
|
|
2519
3005
|
rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
|
|
2520
3006
|
|
|
3007
|
+
CHECK_SOCKET_CLOSED(self);
|
|
3008
|
+
|
|
2521
3009
|
keynum = FIX2INT(v_keynum);
|
|
2522
3010
|
|
|
2523
3011
|
if(keynum < 0)
|
|
2524
3012
|
rb_raise(rb_eArgError, "invalid keynum value");
|
|
2525
3013
|
|
|
2526
|
-
fileno =
|
|
3014
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2527
3015
|
|
|
2528
3016
|
if(NIL_P(v_assoc_id))
|
|
2529
3017
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
@@ -2534,7 +3022,7 @@ static VALUE rsctp_set_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2534
3022
|
authkey.scact_keynumber = (uint)keynum;
|
|
2535
3023
|
size = sizeof(struct sctp_authkeyid);
|
|
2536
3024
|
|
|
2537
|
-
if(
|
|
3025
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, (void*)&authkey, size) < 0)
|
|
2538
3026
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
2539
3027
|
|
|
2540
3028
|
return self;
|
|
@@ -2566,7 +3054,7 @@ static VALUE rsctp_set_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2566
3054
|
* otherwise this will delete the key from the endpoint.
|
|
2567
3055
|
*/
|
|
2568
3056
|
static VALUE rsctp_delete_shared_key(int argc, VALUE* argv, VALUE self){
|
|
2569
|
-
|
|
3057
|
+
sctp_sock_t fileno;
|
|
2570
3058
|
socklen_t size;
|
|
2571
3059
|
struct sctp_authkeyid authkey;
|
|
2572
3060
|
sctp_assoc_t assoc_id;
|
|
@@ -2579,7 +3067,7 @@ static VALUE rsctp_delete_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2579
3067
|
|
|
2580
3068
|
bzero(&authkey, sizeof(authkey));
|
|
2581
3069
|
|
|
2582
|
-
fileno =
|
|
3070
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2583
3071
|
keynum = NUM2UINT(v_keynum);
|
|
2584
3072
|
|
|
2585
3073
|
if(NIL_P(v_assoc_id))
|
|
@@ -2592,7 +3080,7 @@ static VALUE rsctp_delete_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2592
3080
|
|
|
2593
3081
|
size = sizeof(struct sctp_authkeyid);
|
|
2594
3082
|
|
|
2595
|
-
if(
|
|
3083
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY, (void*)&authkey, size) < 0)
|
|
2596
3084
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
2597
3085
|
|
|
2598
3086
|
return INT2NUM(authkey.scact_keynumber);
|
|
@@ -2612,15 +3100,18 @@ static VALUE rsctp_delete_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2612
3100
|
* a no-op.
|
|
2613
3101
|
*/
|
|
2614
3102
|
static VALUE rsctp_map_ipv4(VALUE self, VALUE v_bool){
|
|
2615
|
-
|
|
3103
|
+
sctp_sock_t fileno;
|
|
3104
|
+
int boolean;
|
|
3105
|
+
|
|
3106
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2616
3107
|
|
|
2617
3108
|
boolean = 0;
|
|
2618
|
-
fileno =
|
|
3109
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2619
3110
|
|
|
2620
3111
|
if(v_bool == Qtrue)
|
|
2621
3112
|
boolean = 1;
|
|
2622
3113
|
|
|
2623
|
-
if(
|
|
3114
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, (void*)&boolean, sizeof(boolean)) < 0)
|
|
2624
3115
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
2625
3116
|
|
|
2626
3117
|
return v_bool;
|
|
@@ -2634,18 +3125,18 @@ static VALUE rsctp_map_ipv4(VALUE self, VALUE v_bool){
|
|
|
2634
3125
|
* for PF_INET6 sockets. Returns true if mapping is enabled, false otherwise.
|
|
2635
3126
|
*/
|
|
2636
3127
|
static VALUE rsctp_get_map_ipv4(VALUE self){
|
|
2637
|
-
|
|
3128
|
+
sctp_sock_t fileno;
|
|
2638
3129
|
socklen_t size;
|
|
2639
3130
|
sctp_assoc_t assoc_id;
|
|
2640
3131
|
int value;
|
|
2641
3132
|
|
|
2642
3133
|
CHECK_SOCKET_CLOSED(self);
|
|
2643
3134
|
|
|
2644
|
-
fileno =
|
|
3135
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2645
3136
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
2646
3137
|
size = sizeof(int);
|
|
2647
3138
|
|
|
2648
|
-
if(
|
|
3139
|
+
if(sctp_sys_opt_info(fileno, assoc_id, SCTP_I_WANT_MAPPED_V4_ADDR, (void*)&value, &size) < 0)
|
|
2649
3140
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
2650
3141
|
|
|
2651
3142
|
if(value)
|
|
@@ -2679,7 +3170,7 @@ static VALUE rsctp_get_map_ipv4(VALUE self){
|
|
|
2679
3170
|
*/
|
|
2680
3171
|
static VALUE rsctp_set_default_send_params(VALUE self, VALUE v_options){
|
|
2681
3172
|
VALUE v_stream, v_ssn, v_flags, v_ppid, v_context, v_ttl, v_tsn, v_cumtsn, v_assoc_id;
|
|
2682
|
-
|
|
3173
|
+
sctp_sock_t fileno;
|
|
2683
3174
|
sctp_assoc_t assoc_id;
|
|
2684
3175
|
struct sctp_sndrcvinfo sndrcv;
|
|
2685
3176
|
|
|
@@ -2688,7 +3179,9 @@ static VALUE rsctp_set_default_send_params(VALUE self, VALUE v_options){
|
|
|
2688
3179
|
|
|
2689
3180
|
bzero(&sndrcv, sizeof(sndrcv));
|
|
2690
3181
|
|
|
2691
|
-
|
|
3182
|
+
CHECK_SOCKET_CLOSED(self);
|
|
3183
|
+
|
|
3184
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
2692
3185
|
|
|
2693
3186
|
v_stream = rb_hash_aref2(v_options, "stream");
|
|
2694
3187
|
v_ssn = rb_hash_aref2(v_options, "ssn");
|
|
@@ -2730,8 +3223,23 @@ static VALUE rsctp_set_default_send_params(VALUE self, VALUE v_options){
|
|
|
2730
3223
|
if(!NIL_P(v_cumtsn))
|
|
2731
3224
|
sndrcv.sinfo_cumtsn = NUM2INT(v_cumtsn);
|
|
2732
3225
|
|
|
2733
|
-
|
|
3226
|
+
#ifdef HAVE_USRSCTP_H
|
|
3227
|
+
{
|
|
3228
|
+
struct sctp_sndinfo sndinfo;
|
|
3229
|
+
bzero(&sndinfo, sizeof(sndinfo));
|
|
3230
|
+
sndinfo.snd_sid = sndrcv.sinfo_stream;
|
|
3231
|
+
sndinfo.snd_flags = sndrcv.sinfo_flags;
|
|
3232
|
+
sndinfo.snd_ppid = sndrcv.sinfo_ppid;
|
|
3233
|
+
sndinfo.snd_context = sndrcv.sinfo_context;
|
|
3234
|
+
sndinfo.snd_assoc_id = sndrcv.sinfo_assoc_id;
|
|
3235
|
+
|
|
3236
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, &sndinfo, sizeof(sndinfo)) < 0)
|
|
3237
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
3238
|
+
}
|
|
3239
|
+
#else
|
|
3240
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_DEFAULT_SEND_PARAM, &sndrcv, sizeof(sndrcv)) < 0)
|
|
2734
3241
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
3242
|
+
#endif
|
|
2735
3243
|
|
|
2736
3244
|
return rb_struct_new(
|
|
2737
3245
|
v_sctp_default_send_params_struct,
|
|
@@ -2771,17 +3279,20 @@ static VALUE rsctp_set_default_send_params(VALUE self, VALUE v_options){
|
|
|
2771
3279
|
*/
|
|
2772
3280
|
static VALUE rsctp_set_peer_address_params(VALUE self, VALUE v_options){
|
|
2773
3281
|
VALUE v_assoc_id, v_address, v_hbinterval, v_pathmaxrxt, v_pathmtu, v_flags, v_ipv6_flowlabel;
|
|
2774
|
-
|
|
3282
|
+
sctp_sock_t fileno;
|
|
3283
|
+
int domain;
|
|
2775
3284
|
sctp_assoc_t assoc_id;
|
|
2776
3285
|
struct sctp_paddrparams paddr;
|
|
2777
|
-
struct sockaddr_in* sin;
|
|
2778
3286
|
|
|
2779
3287
|
if(!RB_TYPE_P(v_options, T_HASH))
|
|
2780
3288
|
rb_raise(rb_eTypeError, "options must be a hash");
|
|
2781
3289
|
|
|
2782
3290
|
bzero(&paddr, sizeof(paddr));
|
|
2783
3291
|
|
|
2784
|
-
|
|
3292
|
+
CHECK_SOCKET_CLOSED(self);
|
|
3293
|
+
|
|
3294
|
+
fileno = NUM_TO_SCTP_FD(rb_iv_get(self, "@fileno"));
|
|
3295
|
+
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
|
2785
3296
|
|
|
2786
3297
|
v_assoc_id = rb_hash_aref2(v_options, "association_id");
|
|
2787
3298
|
v_address = rb_hash_aref2(v_options, "address");
|
|
@@ -2797,12 +3308,28 @@ static VALUE rsctp_set_peer_address_params(VALUE self, VALUE v_options){
|
|
|
2797
3308
|
assoc_id = NUM2INT(v_assoc_id);
|
|
2798
3309
|
paddr.spp_assoc_id = assoc_id;
|
|
2799
3310
|
|
|
2800
|
-
// If address is provided, set up the sockaddr structure
|
|
3311
|
+
// If address is provided, set up the sockaddr structure based on domain
|
|
2801
3312
|
if(!NIL_P(v_address)){
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
if(
|
|
2805
|
-
|
|
3313
|
+
const char* addr_str = StringValueCStr(v_address);
|
|
3314
|
+
|
|
3315
|
+
if(domain == AF_INET6){
|
|
3316
|
+
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&paddr.spp_address;
|
|
3317
|
+
sin6->sin6_family = AF_INET6;
|
|
3318
|
+
if(inet_pton(AF_INET6, addr_str, &sin6->sin6_addr) <= 0)
|
|
3319
|
+
rb_raise(rb_eArgError, "invalid IPv6 address: %s", addr_str);
|
|
3320
|
+
#ifdef BSD
|
|
3321
|
+
sin6->sin6_len = sizeof(struct sockaddr_in6);
|
|
3322
|
+
#endif
|
|
3323
|
+
}
|
|
3324
|
+
else{
|
|
3325
|
+
struct sockaddr_in* sin = (struct sockaddr_in*)&paddr.spp_address;
|
|
3326
|
+
sin->sin_family = AF_INET;
|
|
3327
|
+
if(inet_pton(AF_INET, addr_str, &sin->sin_addr) <= 0)
|
|
3328
|
+
rb_raise(rb_eArgError, "invalid IPv4 address: %s", addr_str);
|
|
3329
|
+
#ifdef BSD
|
|
3330
|
+
sin->sin_len = sizeof(struct sockaddr_in);
|
|
3331
|
+
#endif
|
|
3332
|
+
}
|
|
2806
3333
|
}
|
|
2807
3334
|
|
|
2808
3335
|
if(!NIL_P(v_hbinterval))
|
|
@@ -2820,7 +3347,7 @@ static VALUE rsctp_set_peer_address_params(VALUE self, VALUE v_options){
|
|
|
2820
3347
|
if(!NIL_P(v_ipv6_flowlabel))
|
|
2821
3348
|
paddr.spp_ipv6_flowlabel = NUM2INT(v_ipv6_flowlabel);
|
|
2822
3349
|
|
|
2823
|
-
if(
|
|
3350
|
+
if(sctp_sys_setsockopt(fileno, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &paddr, sizeof(paddr)) < 0)
|
|
2824
3351
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
2825
3352
|
|
|
2826
3353
|
return rb_struct_new(
|
|
@@ -2920,7 +3447,7 @@ void Init_socket(void){
|
|
|
2920
3447
|
|
|
2921
3448
|
v_sctp_receive_info_struct = rb_struct_define(
|
|
2922
3449
|
"ReceiveInfo", "message", "sid", "ssn", "flags", "ppid", "tsn",
|
|
2923
|
-
"cumtsn", "context", "
|
|
3450
|
+
"cumtsn", "context", "association_id", NULL
|
|
2924
3451
|
);
|
|
2925
3452
|
|
|
2926
3453
|
v_sctp_peer_addr_params_struct = rb_struct_define(
|
|
@@ -2993,8 +3520,8 @@ void Init_socket(void){
|
|
|
2993
3520
|
rb_define_attr(cSocket, "association_id", 1, 1);
|
|
2994
3521
|
rb_define_attr(cSocket, "port", 1, 1);
|
|
2995
3522
|
|
|
2996
|
-
/* 0.
|
|
2997
|
-
rb_define_const(cSocket, "VERSION", rb_str_new2("0.
|
|
3523
|
+
/* 0.3.0: The version of this library */
|
|
3524
|
+
rb_define_const(cSocket, "VERSION", rb_str_new2("0.3.0"));
|
|
2998
3525
|
|
|
2999
3526
|
/* send flags */
|
|
3000
3527
|
|