sctp-socket 0.2.0 → 0.2.2
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/CHANGES.md +14 -0
- data/README.md +1 -1
- data/Rakefile +3 -1
- data/ext/sctp/socket.c +679 -256
- data/sctp-socket.gemspec +2 -2
- data.tar.gz.sig +0 -0
- metadata +3 -8
- metadata.gz.sig +0 -0
- data/.github/FUNDING.yml +0 -4
- data/.github/workflows/ruby.yml +0 -59
data/ext/sctp/socket.c
CHANGED
|
@@ -63,6 +63,65 @@ VALUE v_sctp_initmsg_struct;
|
|
|
63
63
|
#define MAX_IP_ADDRESSES 8
|
|
64
64
|
#define DEFAULT_BUFFER_SIZE 1024
|
|
65
65
|
#define IP_BUFFER_SIZE INET6_ADDRSTRLEN
|
|
66
|
+
#define MAX_NOTIFICATION_DATA 8192
|
|
67
|
+
|
|
68
|
+
/*
|
|
69
|
+
* Helper function to parse an IP address string and fill a sockaddr_in or sockaddr_in6 structure.
|
|
70
|
+
* Supports both IPv4 and IPv6 addresses.
|
|
71
|
+
*
|
|
72
|
+
* @param addr_str The IP address string to parse
|
|
73
|
+
* @param port The port number (in host byte order)
|
|
74
|
+
* @param sin Pointer to sockaddr_in to fill (for IPv4)
|
|
75
|
+
* @param sin6 Pointer to sockaddr_in6 to fill (for IPv6)
|
|
76
|
+
* @param domain The address family (AF_INET or AF_INET6)
|
|
77
|
+
*/
|
|
78
|
+
static void parse_ip_address_v4(const char* addr_str, int port, struct sockaddr_in* sin){
|
|
79
|
+
bzero(sin, sizeof(*sin));
|
|
80
|
+
sin->sin_family = AF_INET;
|
|
81
|
+
sin->sin_port = htons(port);
|
|
82
|
+
if(inet_pton(AF_INET, addr_str, &sin->sin_addr) != 1)
|
|
83
|
+
rb_raise(rb_eArgError, "invalid IPv4 address: %s", addr_str);
|
|
84
|
+
#ifdef BSD
|
|
85
|
+
sin->sin_len = sizeof(struct sockaddr_in);
|
|
86
|
+
#endif
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
static void parse_ip_address_v6(const char* addr_str, int port, struct sockaddr_in6* sin6){
|
|
90
|
+
bzero(sin6, sizeof(*sin6));
|
|
91
|
+
sin6->sin6_family = AF_INET6;
|
|
92
|
+
sin6->sin6_port = htons(port);
|
|
93
|
+
if(inet_pton(AF_INET6, addr_str, &sin6->sin6_addr) != 1)
|
|
94
|
+
rb_raise(rb_eArgError, "invalid IPv6 address: %s", addr_str);
|
|
95
|
+
#ifdef BSD
|
|
96
|
+
sin6->sin6_len = sizeof(struct sockaddr_in6);
|
|
97
|
+
#endif
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/*
|
|
101
|
+
* Helper function to set INADDR_ANY for IPv4.
|
|
102
|
+
*/
|
|
103
|
+
static void set_any_address_v4(int port, struct sockaddr_in* sin){
|
|
104
|
+
bzero(sin, sizeof(*sin));
|
|
105
|
+
sin->sin_family = AF_INET;
|
|
106
|
+
sin->sin_port = htons(port);
|
|
107
|
+
sin->sin_addr.s_addr = htonl(INADDR_ANY);
|
|
108
|
+
#ifdef BSD
|
|
109
|
+
sin->sin_len = sizeof(struct sockaddr_in);
|
|
110
|
+
#endif
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/*
|
|
114
|
+
* Helper function to set IN6ADDR_ANY for IPv6.
|
|
115
|
+
*/
|
|
116
|
+
static void set_any_address_v6(int port, struct sockaddr_in6* sin6){
|
|
117
|
+
bzero(sin6, sizeof(*sin6));
|
|
118
|
+
sin6->sin6_family = AF_INET6;
|
|
119
|
+
sin6->sin6_port = htons(port);
|
|
120
|
+
sin6->sin6_addr = in6addr_any;
|
|
121
|
+
#ifdef BSD
|
|
122
|
+
sin6->sin6_len = sizeof(struct sockaddr_in6);
|
|
123
|
+
#endif
|
|
124
|
+
}
|
|
66
125
|
|
|
67
126
|
/*
|
|
68
127
|
* Convert a sockaddr_in structure to a Ruby struct.
|
|
@@ -197,12 +256,18 @@ VALUE get_notification_info(char* buffer){
|
|
|
197
256
|
v_str = rb_str_new2("unknown");
|
|
198
257
|
}
|
|
199
258
|
|
|
200
|
-
|
|
201
|
-
(
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
259
|
+
{
|
|
260
|
+
struct sockaddr* sa = (struct sockaddr*)&snp->sn_paddr_change.spc_aaddr;
|
|
261
|
+
|
|
262
|
+
if(sa->sa_family == AF_INET6){
|
|
263
|
+
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
|
|
264
|
+
inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str));
|
|
265
|
+
}
|
|
266
|
+
else{
|
|
267
|
+
struct sockaddr_in* sin = (struct sockaddr_in*)sa;
|
|
268
|
+
inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str));
|
|
269
|
+
}
|
|
270
|
+
}
|
|
206
271
|
|
|
207
272
|
v_notification = rb_struct_new(v_peeraddr_change_struct,
|
|
208
273
|
UINT2NUM(snp->sn_paddr_change.spc_type),
|
|
@@ -215,83 +280,150 @@ VALUE get_notification_info(char* buffer){
|
|
|
215
280
|
);
|
|
216
281
|
break;
|
|
217
282
|
case SCTP_REMOTE_ERROR:
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
283
|
+
{
|
|
284
|
+
size_t data_len = 0;
|
|
285
|
+
VALUE v_data_ary;
|
|
286
|
+
|
|
287
|
+
// Calculate actual data length (total length minus fixed header)
|
|
288
|
+
if(snp->sn_remote_error.sre_length > offsetof(struct sctp_remote_error, sre_data))
|
|
289
|
+
data_len = snp->sn_remote_error.sre_length - offsetof(struct sctp_remote_error, sre_data);
|
|
290
|
+
|
|
291
|
+
// Bounds check to prevent stack overflow
|
|
292
|
+
if(data_len > MAX_NOTIFICATION_DATA)
|
|
293
|
+
data_len = MAX_NOTIFICATION_DATA;
|
|
294
|
+
|
|
295
|
+
if(data_len > 0){
|
|
296
|
+
v_temp = ALLOCA_N(VALUE, data_len);
|
|
297
|
+
for(i = 0; i < data_len; i++){
|
|
298
|
+
v_temp[i] = UINT2NUM(snp->sn_remote_error.sre_data[i]);
|
|
299
|
+
}
|
|
300
|
+
v_data_ary = rb_ary_new4(data_len, v_temp);
|
|
301
|
+
}
|
|
302
|
+
else{
|
|
303
|
+
v_data_ary = rb_ary_new();
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
v_notification = rb_struct_new(v_remote_error_struct,
|
|
307
|
+
UINT2NUM(snp->sn_remote_error.sre_type),
|
|
308
|
+
UINT2NUM(snp->sn_remote_error.sre_flags),
|
|
309
|
+
UINT2NUM(snp->sn_remote_error.sre_length),
|
|
310
|
+
UINT2NUM(snp->sn_remote_error.sre_error),
|
|
311
|
+
UINT2NUM(snp->sn_remote_error.sre_assoc_id),
|
|
312
|
+
v_data_ary
|
|
313
|
+
);
|
|
222
314
|
}
|
|
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
315
|
break;
|
|
233
316
|
#ifdef SCTP_SEND_FAILED_EVENT
|
|
234
317
|
case SCTP_SEND_FAILED_EVENT:
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
for(i = 0; i < snp->sn_send_failed_event.ssfe_length; i++){
|
|
239
|
-
v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssfe_data[i]);
|
|
240
|
-
}
|
|
318
|
+
{
|
|
319
|
+
size_t data_len = 0;
|
|
320
|
+
VALUE v_data_ary;
|
|
241
321
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
322
|
+
#ifdef HAVE_STRUCT_SCTP_SEND_FAILED_EVENT_SSFE_LENGTH
|
|
323
|
+
// Calculate actual data length (total length minus fixed header)
|
|
324
|
+
if(snp->sn_send_failed_event.ssfe_length > offsetof(struct sctp_send_failed_event, ssfe_data))
|
|
325
|
+
data_len = snp->sn_send_failed_event.ssfe_length - offsetof(struct sctp_send_failed_event, ssfe_data);
|
|
326
|
+
|
|
327
|
+
// Bounds check to prevent stack overflow
|
|
328
|
+
if(data_len > MAX_NOTIFICATION_DATA)
|
|
329
|
+
data_len = MAX_NOTIFICATION_DATA;
|
|
330
|
+
|
|
331
|
+
if(data_len > 0){
|
|
332
|
+
v_temp = ALLOCA_N(VALUE, data_len);
|
|
333
|
+
for(i = 0; i < data_len; i++){
|
|
334
|
+
v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssfe_data[i]);
|
|
335
|
+
}
|
|
336
|
+
v_data_ary = rb_ary_new4(data_len, v_temp);
|
|
337
|
+
}
|
|
338
|
+
else{
|
|
339
|
+
v_data_ary = rb_ary_new();
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
v_notification = rb_struct_new(v_send_failed_event_struct,
|
|
343
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_type),
|
|
344
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_length),
|
|
345
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_error),
|
|
346
|
+
rb_struct_new(v_sndinfo_struct,
|
|
347
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
|
|
348
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
|
|
349
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
|
|
350
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
|
|
351
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
|
|
352
|
+
),
|
|
353
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_assoc_id),
|
|
354
|
+
v_data_ary
|
|
355
|
+
);
|
|
256
356
|
#else
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
357
|
+
// Calculate actual data length (total length minus fixed header)
|
|
358
|
+
if(snp->sn_send_failed_event.ssf_length > offsetof(struct sctp_send_failed_event, ssf_data))
|
|
359
|
+
data_len = snp->sn_send_failed_event.ssf_length - offsetof(struct sctp_send_failed_event, ssf_data);
|
|
360
|
+
|
|
361
|
+
// Bounds check to prevent stack overflow
|
|
362
|
+
if(data_len > MAX_NOTIFICATION_DATA)
|
|
363
|
+
data_len = MAX_NOTIFICATION_DATA;
|
|
364
|
+
|
|
365
|
+
if(data_len > 0){
|
|
366
|
+
v_temp = ALLOCA_N(VALUE, data_len);
|
|
367
|
+
for(i = 0; i < data_len; i++){
|
|
368
|
+
v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssf_data[i]);
|
|
369
|
+
}
|
|
370
|
+
v_data_ary = rb_ary_new4(data_len, v_temp);
|
|
371
|
+
}
|
|
372
|
+
else{
|
|
373
|
+
v_data_ary = rb_ary_new();
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
v_notification = rb_struct_new(v_send_failed_event_struct,
|
|
377
|
+
UINT2NUM(snp->sn_send_failed_event.ssf_type),
|
|
378
|
+
UINT2NUM(snp->sn_send_failed_event.ssf_length),
|
|
379
|
+
UINT2NUM(snp->sn_send_failed_event.ssf_error),
|
|
380
|
+
rb_struct_new(v_sndinfo_struct,
|
|
381
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
|
|
382
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
|
|
383
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
|
|
384
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
|
|
385
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
|
|
386
|
+
),
|
|
387
|
+
UINT2NUM(snp->sn_send_failed_event.ssf_assoc_id),
|
|
388
|
+
v_data_ary
|
|
389
|
+
);
|
|
277
390
|
#endif
|
|
391
|
+
}
|
|
278
392
|
break;
|
|
279
393
|
#else
|
|
280
394
|
case SCTP_SEND_FAILED:
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
395
|
+
{
|
|
396
|
+
size_t data_len = 0;
|
|
397
|
+
VALUE v_data_ary;
|
|
398
|
+
|
|
399
|
+
// Calculate actual data length (total length minus fixed header)
|
|
400
|
+
if(snp->sn_send_failed.ssf_length > offsetof(struct sctp_send_failed, ssf_data))
|
|
401
|
+
data_len = snp->sn_send_failed.ssf_length - offsetof(struct sctp_send_failed, ssf_data);
|
|
402
|
+
|
|
403
|
+
// Bounds check to prevent stack overflow
|
|
404
|
+
if(data_len > MAX_NOTIFICATION_DATA)
|
|
405
|
+
data_len = MAX_NOTIFICATION_DATA;
|
|
406
|
+
|
|
407
|
+
if(data_len > 0){
|
|
408
|
+
v_temp = ALLOCA_N(VALUE, data_len);
|
|
409
|
+
for(i = 0; i < data_len; i++){
|
|
410
|
+
v_temp[i] = UINT2NUM(snp->sn_send_failed.ssf_data[i]);
|
|
411
|
+
}
|
|
412
|
+
v_data_ary = rb_ary_new4(data_len, v_temp);
|
|
413
|
+
}
|
|
414
|
+
else{
|
|
415
|
+
v_data_ary = rb_ary_new();
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
v_notification = rb_struct_new(v_send_failed_event_struct,
|
|
419
|
+
UINT2NUM(snp->sn_send_failed.ssf_type),
|
|
420
|
+
UINT2NUM(snp->sn_send_failed.ssf_length),
|
|
421
|
+
UINT2NUM(snp->sn_send_failed.ssf_error),
|
|
422
|
+
Qnil,
|
|
423
|
+
UINT2NUM(snp->sn_send_failed.ssf_assoc_id),
|
|
424
|
+
v_data_ary
|
|
425
|
+
);
|
|
285
426
|
}
|
|
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
427
|
break;
|
|
296
428
|
#endif
|
|
297
429
|
case SCTP_SHUTDOWN_EVENT:
|
|
@@ -451,14 +583,11 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
|
|
|
451
583
|
* Returns the port that it was bound to.
|
|
452
584
|
*/
|
|
453
585
|
static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
|
454
|
-
struct sockaddr_in addrs[MAX_IP_ADDRESSES];
|
|
455
586
|
int i, fileno, num_ip, flags, domain, port, on;
|
|
456
587
|
VALUE v_addresses, v_port, v_flags, v_address, v_reuse_addr, v_options;
|
|
457
588
|
|
|
458
589
|
rb_scan_args(argc, argv, "01", &v_options);
|
|
459
590
|
|
|
460
|
-
bzero(&addrs, sizeof(addrs));
|
|
461
|
-
|
|
462
591
|
if(NIL_P(v_options))
|
|
463
592
|
v_options = rb_hash_new();
|
|
464
593
|
|
|
@@ -485,37 +614,51 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
|
|
485
614
|
if(num_ip > MAX_IP_ADDRESSES)
|
|
486
615
|
rb_raise(rb_eArgError, "too many IP addresses to bind, maximum is eight");
|
|
487
616
|
|
|
617
|
+
CHECK_SOCKET_CLOSED(self);
|
|
618
|
+
|
|
488
619
|
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
|
489
620
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
490
621
|
|
|
491
|
-
if(!NIL_P(v_addresses)){
|
|
492
|
-
for(i = 0; i < num_ip; i++){
|
|
493
|
-
v_address = RARRAY_PTR(v_addresses)[i];
|
|
494
|
-
addrs[i].sin_family = domain;
|
|
495
|
-
addrs[i].sin_port = htons(port);
|
|
496
|
-
addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
|
|
497
|
-
#ifdef BSD
|
|
498
|
-
addrs[i].sin_len = sizeof(struct sockaddr_in);
|
|
499
|
-
#endif
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
else{
|
|
503
|
-
addrs[0].sin_family = domain;
|
|
504
|
-
addrs[0].sin_port = htons(port);
|
|
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
|
-
}
|
|
510
|
-
|
|
511
622
|
if(v_reuse_addr == Qtrue){
|
|
512
623
|
on = 1;
|
|
513
624
|
if(setsockopt(fileno, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
|
|
514
625
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
515
626
|
}
|
|
516
627
|
|
|
517
|
-
if(
|
|
518
|
-
|
|
628
|
+
if(domain == AF_INET6){
|
|
629
|
+
struct sockaddr_in6 addrs6[MAX_IP_ADDRESSES];
|
|
630
|
+
bzero(&addrs6, sizeof(addrs6));
|
|
631
|
+
|
|
632
|
+
if(!NIL_P(v_addresses)){
|
|
633
|
+
for(i = 0; i < num_ip; i++){
|
|
634
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
635
|
+
parse_ip_address_v6(StringValueCStr(v_address), port, &addrs6[i]);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
else{
|
|
639
|
+
set_any_address_v6(port, &addrs6[0]);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
if(sctp_bindx(fileno, (struct sockaddr *)addrs6, num_ip, flags) != 0)
|
|
643
|
+
rb_raise(rb_eSystemCallError, "sctp_bindx: %s", strerror(errno));
|
|
644
|
+
}
|
|
645
|
+
else{
|
|
646
|
+
struct sockaddr_in addrs[MAX_IP_ADDRESSES];
|
|
647
|
+
bzero(&addrs, sizeof(addrs));
|
|
648
|
+
|
|
649
|
+
if(!NIL_P(v_addresses)){
|
|
650
|
+
for(i = 0; i < num_ip; i++){
|
|
651
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
652
|
+
parse_ip_address_v4(StringValueCStr(v_address), port, &addrs[i]);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
else{
|
|
656
|
+
set_any_address_v4(port, &addrs[0]);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
if(sctp_bindx(fileno, (struct sockaddr *)addrs, num_ip, flags) != 0)
|
|
660
|
+
rb_raise(rb_eSystemCallError, "sctp_bindx: %s", strerror(errno));
|
|
661
|
+
}
|
|
519
662
|
|
|
520
663
|
if(port == 0){
|
|
521
664
|
struct sockaddr_in sin;
|
|
@@ -550,10 +693,9 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
|
|
550
693
|
* methods will automatically establish associations.
|
|
551
694
|
*/
|
|
552
695
|
static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
|
|
553
|
-
|
|
554
|
-
int i, num_ip, fileno;
|
|
696
|
+
int i, num_ip, fileno, domain, port;
|
|
555
697
|
sctp_assoc_t assoc;
|
|
556
|
-
VALUE v_address,
|
|
698
|
+
VALUE v_address, v_options, v_addresses, v_port;
|
|
557
699
|
|
|
558
700
|
rb_scan_args(argc, argv, "01", &v_options);
|
|
559
701
|
|
|
@@ -571,25 +713,41 @@ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
|
|
|
571
713
|
if(NIL_P(v_port))
|
|
572
714
|
rb_raise(rb_eArgError, "you must specify a port");
|
|
573
715
|
|
|
574
|
-
|
|
716
|
+
CHECK_SOCKET_CLOSED(self);
|
|
717
|
+
|
|
718
|
+
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
|
719
|
+
port = NUM2INT(v_port);
|
|
720
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
575
721
|
|
|
576
722
|
num_ip = (int)RARRAY_LEN(v_addresses);
|
|
577
|
-
bzero(&addrs, sizeof(addrs));
|
|
578
723
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
724
|
+
if(num_ip > MAX_IP_ADDRESSES)
|
|
725
|
+
rb_raise(rb_eArgError, "too many IP addresses, maximum is eight");
|
|
726
|
+
|
|
727
|
+
if(domain == AF_INET6){
|
|
728
|
+
struct sockaddr_in6 addrs6[MAX_IP_ADDRESSES];
|
|
729
|
+
bzero(&addrs6, sizeof(addrs6));
|
|
730
|
+
|
|
731
|
+
for(i = 0; i < num_ip; i++){
|
|
732
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
733
|
+
parse_ip_address_v6(StringValueCStr(v_address), port, &addrs6[i]);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
if(sctp_connectx(fileno, (struct sockaddr *)addrs6, num_ip, &assoc) < 0)
|
|
737
|
+
rb_raise(rb_eSystemCallError, "sctp_connectx: %s", strerror(errno));
|
|
587
738
|
}
|
|
739
|
+
else{
|
|
740
|
+
struct sockaddr_in addrs[MAX_IP_ADDRESSES];
|
|
741
|
+
bzero(&addrs, sizeof(addrs));
|
|
588
742
|
|
|
589
|
-
|
|
743
|
+
for(i = 0; i < num_ip; i++){
|
|
744
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
745
|
+
parse_ip_address_v4(StringValueCStr(v_address), port, &addrs[i]);
|
|
746
|
+
}
|
|
590
747
|
|
|
591
|
-
|
|
592
|
-
|
|
748
|
+
if(sctp_connectx(fileno, (struct sockaddr *)addrs, num_ip, &assoc) < 0)
|
|
749
|
+
rb_raise(rb_eSystemCallError, "sctp_connectx: %s", strerror(errno));
|
|
750
|
+
}
|
|
593
751
|
|
|
594
752
|
rb_iv_set(self, "@association_id", INT2NUM(assoc));
|
|
595
753
|
|
|
@@ -731,8 +889,18 @@ static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
|
|
|
731
889
|
}
|
|
732
890
|
|
|
733
891
|
for(i = 0; i < num_addrs; i++){
|
|
892
|
+
struct sockaddr* sa = &addrs[i];
|
|
734
893
|
bzero(&str, sizeof(str));
|
|
735
|
-
|
|
894
|
+
|
|
895
|
+
if(sa->sa_family == AF_INET6){
|
|
896
|
+
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
|
|
897
|
+
inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str));
|
|
898
|
+
}
|
|
899
|
+
else{
|
|
900
|
+
struct sockaddr_in* sin = (struct sockaddr_in*)sa;
|
|
901
|
+
inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str));
|
|
902
|
+
}
|
|
903
|
+
|
|
736
904
|
rb_ary_push(v_array, rb_str_new2(str));
|
|
737
905
|
}
|
|
738
906
|
|
|
@@ -792,8 +960,18 @@ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
|
|
|
792
960
|
}
|
|
793
961
|
|
|
794
962
|
for(i = 0; i < num_addrs; i++){
|
|
963
|
+
struct sockaddr* sa = &addrs[i];
|
|
795
964
|
bzero(&str, sizeof(str));
|
|
796
|
-
|
|
965
|
+
|
|
966
|
+
if(sa->sa_family == AF_INET6){
|
|
967
|
+
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
|
|
968
|
+
inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str));
|
|
969
|
+
}
|
|
970
|
+
else{
|
|
971
|
+
struct sockaddr_in* sin = (struct sockaddr_in*)sa;
|
|
972
|
+
inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str));
|
|
973
|
+
}
|
|
974
|
+
|
|
797
975
|
rb_ary_push(v_array, rb_str_new2(str));
|
|
798
976
|
}
|
|
799
977
|
|
|
@@ -832,9 +1010,8 @@ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
|
|
|
832
1010
|
static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
833
1011
|
VALUE v_msg, v_message, v_addresses;
|
|
834
1012
|
struct iovec iov[IOV_MAX];
|
|
835
|
-
struct sockaddr_in* addrs;
|
|
836
1013
|
struct sctp_sendv_spa spa;
|
|
837
|
-
int i, fileno, size, num_ip;
|
|
1014
|
+
int i, fileno, size, num_ip, domain, port;
|
|
838
1015
|
ssize_t num_bytes;
|
|
839
1016
|
|
|
840
1017
|
Check_Type(v_options, T_HASH);
|
|
@@ -851,13 +1028,16 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
|
851
1028
|
|
|
852
1029
|
Check_Type(v_message, T_ARRAY);
|
|
853
1030
|
|
|
1031
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1032
|
+
|
|
854
1033
|
if(!NIL_P(v_addresses)){
|
|
855
1034
|
Check_Type(v_addresses, T_ARRAY);
|
|
856
1035
|
num_ip = (int)RARRAY_LEN(v_addresses);
|
|
857
|
-
|
|
1036
|
+
|
|
1037
|
+
if(num_ip > MAX_IP_ADDRESSES)
|
|
1038
|
+
rb_raise(rb_eArgError, "too many IP addresses, maximum is eight");
|
|
858
1039
|
}
|
|
859
1040
|
else{
|
|
860
|
-
addrs = NULL;
|
|
861
1041
|
num_ip = 0;
|
|
862
1042
|
}
|
|
863
1043
|
|
|
@@ -875,8 +1055,15 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
|
875
1055
|
spa.sendv_sndinfo.snd_flags = SCTP_UNORDERED;
|
|
876
1056
|
spa.sendv_sndinfo.snd_assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
877
1057
|
|
|
878
|
-
|
|
879
|
-
|
|
1058
|
+
for(i = 0; i < size; i++){
|
|
1059
|
+
v_msg = RARRAY_AREF(v_message, i);
|
|
1060
|
+
iov[i].iov_base = StringValueCStr(v_msg);
|
|
1061
|
+
iov[i].iov_len = RSTRING_LEN(v_msg);
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
|
1065
|
+
|
|
1066
|
+
if(num_ip > 0){
|
|
880
1067
|
VALUE v_address, v_port;
|
|
881
1068
|
|
|
882
1069
|
v_port = rb_iv_get(self, "@port");
|
|
@@ -886,36 +1073,62 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
|
886
1073
|
else
|
|
887
1074
|
port = NUM2INT(v_port);
|
|
888
1075
|
|
|
889
|
-
domain
|
|
1076
|
+
if(domain == AF_INET6){
|
|
1077
|
+
struct sockaddr_in6* addrs6 = (struct sockaddr_in6*)alloca(num_ip * sizeof(struct sockaddr_in6));
|
|
1078
|
+
bzero(addrs6, num_ip * sizeof(struct sockaddr_in6));
|
|
890
1079
|
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
1080
|
+
for(i = 0; i < num_ip; i++){
|
|
1081
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
1082
|
+
parse_ip_address_v6(StringValueCStr(v_address), port, &addrs6[i]);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
num_bytes = (ssize_t)sctp_sendv(
|
|
1086
|
+
fileno,
|
|
1087
|
+
iov,
|
|
1088
|
+
size,
|
|
1089
|
+
(struct sockaddr*)addrs6,
|
|
1090
|
+
num_ip,
|
|
1091
|
+
&spa,
|
|
1092
|
+
sizeof(spa),
|
|
1093
|
+
SCTP_SENDV_SPA,
|
|
1094
|
+
0
|
|
1095
|
+
);
|
|
899
1096
|
}
|
|
900
|
-
|
|
1097
|
+
else{
|
|
1098
|
+
struct sockaddr_in* addrs = (struct sockaddr_in*)alloca(num_ip * sizeof(struct sockaddr_in));
|
|
1099
|
+
bzero(addrs, num_ip * sizeof(struct sockaddr_in));
|
|
901
1100
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
}
|
|
1101
|
+
for(i = 0; i < num_ip; i++){
|
|
1102
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
1103
|
+
parse_ip_address_v4(StringValueCStr(v_address), port, &addrs[i]);
|
|
1104
|
+
}
|
|
907
1105
|
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
1106
|
+
num_bytes = (ssize_t)sctp_sendv(
|
|
1107
|
+
fileno,
|
|
1108
|
+
iov,
|
|
1109
|
+
size,
|
|
1110
|
+
(struct sockaddr*)addrs,
|
|
1111
|
+
num_ip,
|
|
1112
|
+
&spa,
|
|
1113
|
+
sizeof(spa),
|
|
1114
|
+
SCTP_SENDV_SPA,
|
|
1115
|
+
0
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
else{
|
|
1120
|
+
num_bytes = (ssize_t)sctp_sendv(
|
|
1121
|
+
fileno,
|
|
1122
|
+
iov,
|
|
1123
|
+
size,
|
|
1124
|
+
NULL,
|
|
1125
|
+
0,
|
|
1126
|
+
&spa,
|
|
1127
|
+
sizeof(spa),
|
|
1128
|
+
SCTP_SENDV_SPA,
|
|
1129
|
+
0
|
|
1130
|
+
);
|
|
1131
|
+
}
|
|
919
1132
|
|
|
920
1133
|
if(num_bytes < 0)
|
|
921
1134
|
rb_raise(rb_eSystemCallError, "sctp_sendv: %s", strerror(errno));
|
|
@@ -925,24 +1138,50 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
|
925
1138
|
#endif
|
|
926
1139
|
|
|
927
1140
|
#ifdef HAVE_SCTP_RECVV
|
|
1141
|
+
/*
|
|
1142
|
+
* call-seq:
|
|
1143
|
+
* SCTP::Socket#recvv(flags=0, buffer_size=1024)
|
|
1144
|
+
*
|
|
1145
|
+
* Receive a message using sctp_recvv from another SCTP endpoint.
|
|
1146
|
+
*
|
|
1147
|
+
* The optional buffer_size parameter specifies the size of the receive buffer
|
|
1148
|
+
* in bytes. Defaults to 1024 bytes if not specified.
|
|
1149
|
+
*
|
|
1150
|
+
* Example:
|
|
1151
|
+
*
|
|
1152
|
+
* begin
|
|
1153
|
+
* socket = SCTP::Socket.new
|
|
1154
|
+
* socket.bind(:port => 62534, :addresses => ['10.0.4.5', '10.0.5.5'])
|
|
1155
|
+
* socket.listen
|
|
1156
|
+
*
|
|
1157
|
+
* while true
|
|
1158
|
+
* info = socket.recvv
|
|
1159
|
+
* puts "Received message: #{info.message}"
|
|
1160
|
+
*
|
|
1161
|
+
* # Or with custom buffer size
|
|
1162
|
+
* info = socket.recvv(0, 4096)
|
|
1163
|
+
* puts "Received message: #{info.message}"
|
|
1164
|
+
* end
|
|
1165
|
+
* ensure
|
|
1166
|
+
* socket.close
|
|
1167
|
+
* end
|
|
1168
|
+
*/
|
|
928
1169
|
static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
|
|
929
|
-
VALUE v_flags;
|
|
930
|
-
int fileno, flags, on;
|
|
1170
|
+
VALUE v_flags, v_buffer_size;
|
|
1171
|
+
int fileno, flags, on, buffer_size;
|
|
931
1172
|
ssize_t bytes;
|
|
932
1173
|
uint infotype;
|
|
933
1174
|
socklen_t infolen;
|
|
934
1175
|
struct iovec iov[1];
|
|
935
1176
|
struct sctp_rcvinfo info;
|
|
936
|
-
char buffer
|
|
1177
|
+
char *buffer;
|
|
937
1178
|
|
|
938
1179
|
bzero(&iov, sizeof(iov));
|
|
939
1180
|
bzero(&info, sizeof(info));
|
|
940
|
-
bzero(&buffer, sizeof(buffer));
|
|
941
1181
|
|
|
942
|
-
|
|
943
|
-
iov->iov_len = sizeof(buffer);
|
|
1182
|
+
rb_scan_args(argc, argv, "02", &v_flags, &v_buffer_size);
|
|
944
1183
|
|
|
945
|
-
|
|
1184
|
+
CHECK_SOCKET_CLOSED(self);
|
|
946
1185
|
|
|
947
1186
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
948
1187
|
|
|
@@ -951,9 +1190,28 @@ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
|
|
|
951
1190
|
else
|
|
952
1191
|
flags = NUM2INT(v_flags);
|
|
953
1192
|
|
|
1193
|
+
if(NIL_P(v_buffer_size))
|
|
1194
|
+
buffer_size = 1024;
|
|
1195
|
+
else
|
|
1196
|
+
buffer_size = NUM2INT(v_buffer_size);
|
|
1197
|
+
|
|
1198
|
+
if(buffer_size <= 0)
|
|
1199
|
+
rb_raise(rb_eArgError, "buffer size must be positive");
|
|
1200
|
+
|
|
1201
|
+
buffer = (char*)malloc(buffer_size);
|
|
1202
|
+
if(buffer == NULL)
|
|
1203
|
+
rb_raise(rb_eNoMemError, "failed to allocate buffer");
|
|
1204
|
+
|
|
1205
|
+
bzero(buffer, buffer_size);
|
|
1206
|
+
|
|
1207
|
+
iov->iov_base = buffer;
|
|
1208
|
+
iov->iov_len = buffer_size;
|
|
1209
|
+
|
|
954
1210
|
on = 1;
|
|
955
|
-
if(setsockopt(fileno, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(on)) < 0)
|
|
1211
|
+
if(setsockopt(fileno, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(on)) < 0){
|
|
1212
|
+
free(buffer);
|
|
956
1213
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
1214
|
+
}
|
|
957
1215
|
|
|
958
1216
|
infolen = sizeof(struct sctp_rcvinfo);
|
|
959
1217
|
infotype = 0;
|
|
@@ -970,16 +1228,19 @@ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
|
|
|
970
1228
|
&flags
|
|
971
1229
|
);
|
|
972
1230
|
|
|
973
|
-
if(bytes < 0)
|
|
1231
|
+
if(bytes < 0){
|
|
1232
|
+
free(buffer);
|
|
974
1233
|
rb_raise(rb_eSystemCallError, "sctp_recvv: %s", strerror(errno));
|
|
1234
|
+
}
|
|
975
1235
|
|
|
976
1236
|
if(infotype != SCTP_RECVV_RCVINFO){
|
|
1237
|
+
free(buffer);
|
|
977
1238
|
return Qnil;
|
|
978
1239
|
}
|
|
979
1240
|
else{
|
|
980
|
-
|
|
1241
|
+
VALUE result = rb_struct_new(
|
|
981
1242
|
v_sctp_receive_info_struct,
|
|
982
|
-
|
|
1243
|
+
rb_str_new(iov->iov_base, bytes),
|
|
983
1244
|
UINT2NUM(info.rcv_sid),
|
|
984
1245
|
UINT2NUM(info.rcv_ssn),
|
|
985
1246
|
UINT2NUM(info.rcv_flags),
|
|
@@ -989,6 +1250,8 @@ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
|
|
|
989
1250
|
UINT2NUM(info.rcv_context),
|
|
990
1251
|
UINT2NUM(info.rcv_assoc_id)
|
|
991
1252
|
);
|
|
1253
|
+
free(buffer);
|
|
1254
|
+
return result;
|
|
992
1255
|
}
|
|
993
1256
|
}
|
|
994
1257
|
#endif
|
|
@@ -1066,6 +1329,8 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
|
|
|
1066
1329
|
else
|
|
1067
1330
|
assoc_id = NUM2INT(v_assoc_id);
|
|
1068
1331
|
|
|
1332
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1333
|
+
|
|
1069
1334
|
info.sinfo_stream = stream;
|
|
1070
1335
|
info.sinfo_flags = send_flags;
|
|
1071
1336
|
info.sinfo_ppid = ppid;
|
|
@@ -1126,13 +1391,10 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
|
1126
1391
|
uint16_t stream;
|
|
1127
1392
|
uint32_t ppid, flags, ttl, context;
|
|
1128
1393
|
ssize_t num_bytes;
|
|
1129
|
-
|
|
1130
|
-
int fileno, size, num_ip;
|
|
1394
|
+
int fileno, num_ip, domain;
|
|
1131
1395
|
|
|
1132
1396
|
Check_Type(v_options, T_HASH);
|
|
1133
1397
|
|
|
1134
|
-
bzero(&addrs, sizeof(addrs));
|
|
1135
|
-
|
|
1136
1398
|
v_msg = rb_hash_aref2(v_options, "message");
|
|
1137
1399
|
v_stream = rb_hash_aref2(v_options, "stream");
|
|
1138
1400
|
v_ppid = rb_hash_aref2(v_options, "ppid");
|
|
@@ -1172,12 +1434,21 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
|
1172
1434
|
else
|
|
1173
1435
|
context = NUM2INT(v_context);
|
|
1174
1436
|
|
|
1437
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1438
|
+
|
|
1439
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1440
|
+
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
|
1441
|
+
|
|
1175
1442
|
if(!NIL_P(v_addresses)){
|
|
1176
1443
|
int i, port;
|
|
1177
1444
|
VALUE v_address, v_port;
|
|
1178
1445
|
|
|
1179
1446
|
Check_Type(v_addresses, T_ARRAY);
|
|
1180
1447
|
num_ip = (int)RARRAY_LEN(v_addresses);
|
|
1448
|
+
|
|
1449
|
+
if(num_ip > MAX_IP_ADDRESSES)
|
|
1450
|
+
rb_raise(rb_eArgError, "too many IP addresses, maximum is eight");
|
|
1451
|
+
|
|
1181
1452
|
v_port = rb_hash_aref2(v_options, "port");
|
|
1182
1453
|
|
|
1183
1454
|
if(NIL_P(v_port))
|
|
@@ -1185,47 +1456,92 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
|
1185
1456
|
else
|
|
1186
1457
|
port = NUM2INT(v_port);
|
|
1187
1458
|
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1459
|
+
if(domain == AF_INET6){
|
|
1460
|
+
struct sockaddr_in6 addrs6[MAX_IP_ADDRESSES];
|
|
1461
|
+
|
|
1462
|
+
bzero(&addrs6, sizeof(addrs6));
|
|
1463
|
+
|
|
1464
|
+
for(i = 0; i < num_ip; i++){
|
|
1465
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
1466
|
+
parse_ip_address_v6(StringValueCStr(v_address), port, &addrs6[i]);
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1193
1469
|
#ifdef BSD
|
|
1194
|
-
|
|
1470
|
+
num_bytes = (ssize_t)sctp_sendmsgx(
|
|
1471
|
+
fileno,
|
|
1472
|
+
StringValueCStr(v_msg),
|
|
1473
|
+
RSTRING_LEN(v_msg),
|
|
1474
|
+
(struct sockaddr*)addrs6,
|
|
1475
|
+
num_ip,
|
|
1476
|
+
ppid,
|
|
1477
|
+
flags,
|
|
1478
|
+
stream,
|
|
1479
|
+
ttl,
|
|
1480
|
+
context
|
|
1481
|
+
);
|
|
1482
|
+
#else
|
|
1483
|
+
num_bytes = (ssize_t)sctp_sendmsg(
|
|
1484
|
+
fileno,
|
|
1485
|
+
StringValueCStr(v_msg),
|
|
1486
|
+
RSTRING_LEN(v_msg),
|
|
1487
|
+
(struct sockaddr*)addrs6,
|
|
1488
|
+
num_ip * sizeof(struct sockaddr_in6),
|
|
1489
|
+
ppid,
|
|
1490
|
+
flags,
|
|
1491
|
+
stream,
|
|
1492
|
+
ttl,
|
|
1493
|
+
context
|
|
1494
|
+
);
|
|
1195
1495
|
#endif
|
|
1196
1496
|
}
|
|
1497
|
+
else{
|
|
1498
|
+
struct sockaddr_in addrs[MAX_IP_ADDRESSES];
|
|
1197
1499
|
|
|
1198
|
-
|
|
1199
|
-
}
|
|
1200
|
-
else{
|
|
1201
|
-
num_ip = 0;
|
|
1202
|
-
size = 0;
|
|
1203
|
-
}
|
|
1500
|
+
bzero(&addrs, sizeof(addrs));
|
|
1204
1501
|
|
|
1205
|
-
|
|
1502
|
+
for(i = 0; i < num_ip; i++){
|
|
1503
|
+
v_address = RARRAY_AREF(v_addresses, i);
|
|
1504
|
+
parse_ip_address_v4(StringValueCStr(v_address), port, &addrs[i]);
|
|
1505
|
+
}
|
|
1206
1506
|
|
|
1207
1507
|
#ifdef BSD
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1508
|
+
num_bytes = (ssize_t)sctp_sendmsgx(
|
|
1509
|
+
fileno,
|
|
1510
|
+
StringValueCStr(v_msg),
|
|
1511
|
+
RSTRING_LEN(v_msg),
|
|
1512
|
+
(struct sockaddr*)addrs,
|
|
1513
|
+
num_ip,
|
|
1514
|
+
ppid,
|
|
1515
|
+
flags,
|
|
1516
|
+
stream,
|
|
1517
|
+
ttl,
|
|
1518
|
+
context
|
|
1519
|
+
);
|
|
1520
|
+
#else
|
|
1521
|
+
num_bytes = (ssize_t)sctp_sendmsg(
|
|
1522
|
+
fileno,
|
|
1523
|
+
StringValueCStr(v_msg),
|
|
1524
|
+
RSTRING_LEN(v_msg),
|
|
1525
|
+
(struct sockaddr*)addrs,
|
|
1526
|
+
num_ip * sizeof(struct sockaddr_in),
|
|
1527
|
+
ppid,
|
|
1528
|
+
flags,
|
|
1529
|
+
stream,
|
|
1530
|
+
ttl,
|
|
1531
|
+
context
|
|
1532
|
+
);
|
|
1533
|
+
#endif
|
|
1534
|
+
}
|
|
1221
1535
|
}
|
|
1222
1536
|
else{
|
|
1537
|
+
// No addresses - use empty addrs
|
|
1538
|
+
num_ip = 0;
|
|
1223
1539
|
num_bytes = (ssize_t)sctp_sendmsg(
|
|
1224
1540
|
fileno,
|
|
1225
1541
|
StringValueCStr(v_msg),
|
|
1226
1542
|
RSTRING_LEN(v_msg),
|
|
1227
|
-
|
|
1228
|
-
|
|
1543
|
+
NULL,
|
|
1544
|
+
0,
|
|
1229
1545
|
ppid,
|
|
1230
1546
|
flags,
|
|
1231
1547
|
stream,
|
|
@@ -1233,20 +1549,6 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
|
1233
1549
|
context
|
|
1234
1550
|
);
|
|
1235
1551
|
}
|
|
1236
|
-
#else
|
|
1237
|
-
num_bytes = (ssize_t)sctp_sendmsg(
|
|
1238
|
-
fileno,
|
|
1239
|
-
StringValueCStr(v_msg),
|
|
1240
|
-
RSTRING_LEN(v_msg),
|
|
1241
|
-
(struct sockaddr*)addrs,
|
|
1242
|
-
size,
|
|
1243
|
-
ppid,
|
|
1244
|
-
flags,
|
|
1245
|
-
stream,
|
|
1246
|
-
ttl,
|
|
1247
|
-
context
|
|
1248
|
-
);
|
|
1249
|
-
#endif
|
|
1250
1552
|
|
|
1251
1553
|
if(num_bytes < 0){
|
|
1252
1554
|
#ifdef BSD
|
|
@@ -1264,10 +1566,13 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
|
1264
1566
|
|
|
1265
1567
|
/*
|
|
1266
1568
|
* call-seq:
|
|
1267
|
-
* SCTP::Socket#recvmsg(flags=0)
|
|
1569
|
+
* SCTP::Socket#recvmsg(flags=0, buffer_size=1024)
|
|
1268
1570
|
*
|
|
1269
1571
|
* Receive a message from another SCTP endpoint.
|
|
1270
1572
|
*
|
|
1573
|
+
* The optional buffer_size parameter specifies the size of the receive buffer
|
|
1574
|
+
* in bytes. Defaults to 1024 bytes if not specified.
|
|
1575
|
+
*
|
|
1271
1576
|
* Example:
|
|
1272
1577
|
*
|
|
1273
1578
|
* begin
|
|
@@ -1279,46 +1584,66 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
|
1279
1584
|
* while true
|
|
1280
1585
|
* info = socket.recvmsg
|
|
1281
1586
|
* puts "Received message: #{info.message}"
|
|
1587
|
+
*
|
|
1588
|
+
* # Or with custom buffer size
|
|
1589
|
+
* info = socket.recvmsg(0, 4096)
|
|
1590
|
+
* puts "Received message: #{info.message}"
|
|
1282
1591
|
* end
|
|
1283
1592
|
* ensure
|
|
1284
1593
|
* socket.close
|
|
1285
1594
|
* end
|
|
1286
1595
|
*/
|
|
1287
1596
|
static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
1288
|
-
VALUE v_flags, v_notification, v_message;
|
|
1597
|
+
VALUE v_flags, v_buffer_size, v_notification, v_message;
|
|
1289
1598
|
struct sctp_sndrcvinfo sndrcvinfo;
|
|
1290
1599
|
struct sockaddr_in clientaddr;
|
|
1291
|
-
int flags, fileno;
|
|
1600
|
+
int flags, fileno, buffer_size;
|
|
1292
1601
|
ssize_t bytes;
|
|
1293
|
-
char buffer
|
|
1602
|
+
char *buffer;
|
|
1294
1603
|
socklen_t length;
|
|
1295
1604
|
|
|
1296
|
-
rb_scan_args(argc, argv, "
|
|
1605
|
+
rb_scan_args(argc, argv, "02", &v_flags, &v_buffer_size);
|
|
1297
1606
|
|
|
1298
1607
|
if(NIL_P(v_flags))
|
|
1299
1608
|
flags = 0;
|
|
1300
1609
|
else
|
|
1301
1610
|
flags = NUM2INT(v_flags);
|
|
1302
1611
|
|
|
1612
|
+
if(NIL_P(v_buffer_size))
|
|
1613
|
+
buffer_size = 1024;
|
|
1614
|
+
else
|
|
1615
|
+
buffer_size = NUM2INT(v_buffer_size);
|
|
1616
|
+
|
|
1617
|
+
if(buffer_size <= 0)
|
|
1618
|
+
rb_raise(rb_eArgError, "buffer size must be positive");
|
|
1619
|
+
|
|
1620
|
+
buffer = (char*)malloc(buffer_size);
|
|
1621
|
+
if(buffer == NULL)
|
|
1622
|
+
rb_raise(rb_eNoMemError, "failed to allocate buffer");
|
|
1623
|
+
|
|
1624
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1625
|
+
|
|
1303
1626
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1304
1627
|
length = sizeof(struct sockaddr_in);
|
|
1305
1628
|
|
|
1306
|
-
bzero(buffer,
|
|
1629
|
+
bzero(buffer, buffer_size);
|
|
1307
1630
|
bzero(&clientaddr, sizeof(clientaddr));
|
|
1308
1631
|
bzero(&sndrcvinfo, sizeof(sndrcvinfo));
|
|
1309
1632
|
|
|
1310
1633
|
bytes = (ssize_t)sctp_recvmsg(
|
|
1311
1634
|
fileno,
|
|
1312
1635
|
buffer,
|
|
1313
|
-
|
|
1636
|
+
buffer_size,
|
|
1314
1637
|
(struct sockaddr*)&clientaddr,
|
|
1315
1638
|
&length,
|
|
1316
1639
|
&sndrcvinfo,
|
|
1317
1640
|
&flags
|
|
1318
1641
|
);
|
|
1319
1642
|
|
|
1320
|
-
if(bytes < 0)
|
|
1643
|
+
if(bytes < 0){
|
|
1644
|
+
free(buffer);
|
|
1321
1645
|
rb_raise(rb_eSystemCallError, "sctp_recvmsg: %s", strerror(errno));
|
|
1646
|
+
}
|
|
1322
1647
|
|
|
1323
1648
|
v_notification = Qnil;
|
|
1324
1649
|
|
|
@@ -1330,6 +1655,8 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
|
1330
1655
|
else
|
|
1331
1656
|
v_message = Qnil;
|
|
1332
1657
|
|
|
1658
|
+
free(buffer);
|
|
1659
|
+
|
|
1333
1660
|
return rb_struct_new(v_sndrcv_struct,
|
|
1334
1661
|
v_message,
|
|
1335
1662
|
UINT2NUM(sndrcvinfo.sinfo_stream),
|
|
@@ -1370,6 +1697,8 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
|
|
|
1370
1697
|
|
|
1371
1698
|
bzero(&initmsg, sizeof(initmsg));
|
|
1372
1699
|
|
|
1700
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1701
|
+
|
|
1373
1702
|
v_output = rb_hash_aref2(v_options, "output_streams");
|
|
1374
1703
|
v_input = rb_hash_aref2(v_options, "input_streams");
|
|
1375
1704
|
v_attempts = rb_hash_aref2(v_options, "max_attempts");
|
|
@@ -1440,6 +1769,8 @@ static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
|
|
|
1440
1769
|
bzero(&events, sizeof(events));
|
|
1441
1770
|
Check_Type(v_options, T_HASH);
|
|
1442
1771
|
|
|
1772
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1773
|
+
|
|
1443
1774
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1444
1775
|
|
|
1445
1776
|
if(RTEST(rb_hash_aref2(v_options, "data_io")))
|
|
@@ -1520,6 +1851,8 @@ static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
|
|
|
1520
1851
|
if(backlog > SOMAXCONN)
|
|
1521
1852
|
rb_raise(rb_eArgError, "backlog value exceeds maximum value of: %i", SOMAXCONN);
|
|
1522
1853
|
|
|
1854
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1855
|
+
|
|
1523
1856
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1524
1857
|
|
|
1525
1858
|
if(listen(fileno, backlog) < 0)
|
|
@@ -1550,6 +1883,8 @@ static VALUE rsctp_peeloff(VALUE self, VALUE v_assoc_id){
|
|
|
1550
1883
|
int fileno, assoc_fileno;
|
|
1551
1884
|
sctp_assoc_t assoc_id;
|
|
1552
1885
|
|
|
1886
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1887
|
+
|
|
1553
1888
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1554
1889
|
assoc_id = NUM2INT(v_assoc_id);
|
|
1555
1890
|
|
|
@@ -1587,6 +1922,8 @@ static VALUE rsctp_get_default_send_params(VALUE self){
|
|
|
1587
1922
|
|
|
1588
1923
|
bzero(&sndrcv, sizeof(sndrcv));
|
|
1589
1924
|
|
|
1925
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1926
|
+
|
|
1590
1927
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1591
1928
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
1592
1929
|
size = sizeof(struct sctp_sndrcvinfo);
|
|
@@ -1632,6 +1969,8 @@ static VALUE rsctp_get_association_info(VALUE self){
|
|
|
1632
1969
|
|
|
1633
1970
|
bzero(&assoc, sizeof(assoc));
|
|
1634
1971
|
|
|
1972
|
+
CHECK_SOCKET_CLOSED(self);
|
|
1973
|
+
|
|
1635
1974
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1636
1975
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
1637
1976
|
size = sizeof(struct sctp_assocparams);
|
|
@@ -1674,6 +2013,8 @@ static VALUE rsctp_set_association_info(VALUE self, VALUE v_options){
|
|
|
1674
2013
|
|
|
1675
2014
|
bzero(&assoc, sizeof(assoc));
|
|
1676
2015
|
|
|
2016
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2017
|
+
|
|
1677
2018
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1678
2019
|
|
|
1679
2020
|
v_assoc_id = rb_hash_aref2(v_options, "association_id");
|
|
@@ -1738,6 +2079,8 @@ static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
|
|
|
1738
2079
|
int how, fileno;
|
|
1739
2080
|
VALUE v_how;
|
|
1740
2081
|
|
|
2082
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2083
|
+
|
|
1741
2084
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1742
2085
|
|
|
1743
2086
|
rb_scan_args(argc, argv, "01", &v_how);
|
|
@@ -1777,6 +2120,8 @@ static VALUE rsctp_get_retransmission_info(VALUE self){
|
|
|
1777
2120
|
|
|
1778
2121
|
bzero(&rto, sizeof(rto));
|
|
1779
2122
|
|
|
2123
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2124
|
+
|
|
1780
2125
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1781
2126
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
1782
2127
|
size = sizeof(struct sctp_rtoinfo);
|
|
@@ -1816,6 +2161,8 @@ static VALUE rsctp_set_retransmission_info(VALUE self, VALUE v_options){
|
|
|
1816
2161
|
|
|
1817
2162
|
bzero(&rto, sizeof(rto));
|
|
1818
2163
|
|
|
2164
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2165
|
+
|
|
1819
2166
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1820
2167
|
|
|
1821
2168
|
v_assoc_id = rb_hash_aref2(v_options, "association_id");
|
|
@@ -1881,10 +2228,12 @@ static VALUE rsctp_get_status(VALUE self){
|
|
|
1881
2228
|
sctp_assoc_t assoc_id;
|
|
1882
2229
|
struct sctp_status status;
|
|
1883
2230
|
struct sctp_paddrinfo* spinfo;
|
|
1884
|
-
char tmpname[
|
|
2231
|
+
char tmpname[INET6_ADDRSTRLEN];
|
|
1885
2232
|
|
|
1886
2233
|
bzero(&status, sizeof(status));
|
|
1887
2234
|
|
|
2235
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2236
|
+
|
|
1888
2237
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1889
2238
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
1890
2239
|
size = sizeof(struct sctp_status);
|
|
@@ -1949,6 +2298,8 @@ static VALUE rsctp_get_subscriptions(VALUE self){
|
|
|
1949
2298
|
|
|
1950
2299
|
bzero(&events, sizeof(events));
|
|
1951
2300
|
|
|
2301
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2302
|
+
|
|
1952
2303
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
1953
2304
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
1954
2305
|
size = sizeof(struct sctp_event_subscribe);
|
|
@@ -2014,6 +2365,8 @@ static VALUE rsctp_get_peer_address_params(VALUE self){
|
|
|
2014
2365
|
bzero(&paddr, sizeof(paddr));
|
|
2015
2366
|
bzero(&str, sizeof(str));
|
|
2016
2367
|
|
|
2368
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2369
|
+
|
|
2017
2370
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2018
2371
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
2019
2372
|
size = sizeof(struct sctp_paddrparams);
|
|
@@ -2021,7 +2374,18 @@ static VALUE rsctp_get_peer_address_params(VALUE self){
|
|
|
2021
2374
|
if(sctp_opt_info(fileno, assoc_id, SCTP_PEER_ADDR_PARAMS, (void*)&paddr, &size) < 0)
|
|
2022
2375
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
|
2023
2376
|
|
|
2024
|
-
|
|
2377
|
+
{
|
|
2378
|
+
struct sockaddr* sa = (struct sockaddr*)&paddr.spp_address;
|
|
2379
|
+
|
|
2380
|
+
if(sa->sa_family == AF_INET6){
|
|
2381
|
+
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
|
|
2382
|
+
inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str));
|
|
2383
|
+
}
|
|
2384
|
+
else{
|
|
2385
|
+
struct sockaddr_in* sin = (struct sockaddr_in*)sa;
|
|
2386
|
+
inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str));
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2025
2389
|
|
|
2026
2390
|
return rb_struct_new(
|
|
2027
2391
|
v_sctp_peer_addr_params_struct,
|
|
@@ -2061,6 +2425,8 @@ static VALUE rsctp_get_init_msg(VALUE self){
|
|
|
2061
2425
|
|
|
2062
2426
|
bzero(&initmsg, sizeof(initmsg));
|
|
2063
2427
|
|
|
2428
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2429
|
+
|
|
2064
2430
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2065
2431
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
2066
2432
|
size = sizeof(struct sctp_initmsg);
|
|
@@ -2089,6 +2455,8 @@ static VALUE rsctp_get_nodelay(VALUE self){
|
|
|
2089
2455
|
sctp_assoc_t assoc_id;
|
|
2090
2456
|
int value;
|
|
2091
2457
|
|
|
2458
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2459
|
+
|
|
2092
2460
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2093
2461
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
2094
2462
|
size = sizeof(int);
|
|
@@ -2115,6 +2483,8 @@ static VALUE rsctp_set_nodelay(VALUE self, VALUE v_bool){
|
|
|
2115
2483
|
socklen_t size;
|
|
2116
2484
|
int value;
|
|
2117
2485
|
|
|
2486
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2487
|
+
|
|
2118
2488
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2119
2489
|
size = sizeof(int);
|
|
2120
2490
|
|
|
@@ -2148,6 +2518,8 @@ static VALUE rsctp_disable_fragments(VALUE self, VALUE v_bool){
|
|
|
2148
2518
|
sctp_assoc_t assoc_id;
|
|
2149
2519
|
int value;
|
|
2150
2520
|
|
|
2521
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2522
|
+
|
|
2151
2523
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2152
2524
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
2153
2525
|
size = sizeof(int);
|
|
@@ -2179,6 +2551,8 @@ static VALUE rsctp_get_autoclose(VALUE self){
|
|
|
2179
2551
|
sctp_assoc_t assoc_id;
|
|
2180
2552
|
int value;
|
|
2181
2553
|
|
|
2554
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2555
|
+
|
|
2182
2556
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2183
2557
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
2184
2558
|
size = sizeof(int);
|
|
@@ -2215,6 +2589,8 @@ static VALUE rsctp_set_autoclose(VALUE self, VALUE v_seconds){
|
|
|
2215
2589
|
int fileno;
|
|
2216
2590
|
int value;
|
|
2217
2591
|
|
|
2592
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2593
|
+
|
|
2218
2594
|
value = NUM2INT(v_seconds);
|
|
2219
2595
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2220
2596
|
|
|
@@ -2239,6 +2615,8 @@ static VALUE rsctp_enable_auth_support(int argc, VALUE* argv, VALUE self){
|
|
|
2239
2615
|
|
|
2240
2616
|
rb_scan_args(argc, argv, "01", &v_assoc_id);
|
|
2241
2617
|
|
|
2618
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2619
|
+
|
|
2242
2620
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2243
2621
|
size = sizeof(struct sctp_assoc_value);
|
|
2244
2622
|
|
|
@@ -2250,8 +2628,8 @@ static VALUE rsctp_enable_auth_support(int argc, VALUE* argv, VALUE self){
|
|
|
2250
2628
|
assoc_value.assoc_id = assoc_id;
|
|
2251
2629
|
assoc_value.assoc_value = 1;
|
|
2252
2630
|
|
|
2253
|
-
if(
|
|
2254
|
-
rb_raise(rb_eSystemCallError, "
|
|
2631
|
+
if(setsockopt(fileno, IPPROTO_SCTP, SCTP_AUTH_SUPPORTED, (void*)&assoc_value, size) < 0)
|
|
2632
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
2255
2633
|
|
|
2256
2634
|
return self;
|
|
2257
2635
|
}
|
|
@@ -2295,7 +2673,7 @@ static VALUE rsctp_get_auth_support(int argc, VALUE* argv, VALUE self){
|
|
|
2295
2673
|
|
|
2296
2674
|
/*
|
|
2297
2675
|
* call-seq:
|
|
2298
|
-
* SCTP::Socket#set_shared_key(key, keynum, association_id=nil)
|
|
2676
|
+
* SCTP::Socket#set_shared_key(key, keynum=1, association_id=nil)
|
|
2299
2677
|
*
|
|
2300
2678
|
* This option will set a shared secret key which is used to build an
|
|
2301
2679
|
* association shared key.
|
|
@@ -2324,25 +2702,18 @@ static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2324
2702
|
size_t len;
|
|
2325
2703
|
char* key;
|
|
2326
2704
|
uint keynum;
|
|
2327
|
-
|
|
2705
|
+
size_t size;
|
|
2328
2706
|
sctp_assoc_t assoc_id;
|
|
2329
2707
|
struct sctp_authkey* auth_key;
|
|
2330
2708
|
VALUE v_key, v_keynumber, v_assoc_id;
|
|
2331
2709
|
|
|
2332
2710
|
rb_scan_args(argc, argv, "12", &v_key, &v_keynumber, &v_assoc_id);
|
|
2333
2711
|
|
|
2712
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2713
|
+
|
|
2334
2714
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2335
2715
|
key = StringValuePtr(v_key);
|
|
2336
|
-
len =
|
|
2337
|
-
unsigned char byte_array[len+1];
|
|
2338
|
-
|
|
2339
|
-
for(size_t i = 0; i < len; i++)
|
|
2340
|
-
byte_array[i] = key[i];
|
|
2341
|
-
|
|
2342
|
-
byte_array[len] = '\0';
|
|
2343
|
-
|
|
2344
|
-
auth_key = malloc(sizeof(auth_key) + sizeof(char[strlen(key)+1]));
|
|
2345
|
-
size = sizeof(auth_key);
|
|
2716
|
+
len = RSTRING_LEN(v_key); // Use Ruby's string length, not strlen
|
|
2346
2717
|
|
|
2347
2718
|
if(NIL_P(v_assoc_id))
|
|
2348
2719
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
@@ -2354,14 +2725,25 @@ static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2354
2725
|
else
|
|
2355
2726
|
keynum = NUM2INT(v_keynumber);
|
|
2356
2727
|
|
|
2728
|
+
// Allocate the structure with space for the key
|
|
2729
|
+
size = sizeof(struct sctp_authkey) + len;
|
|
2730
|
+
auth_key = malloc(size);
|
|
2731
|
+
|
|
2732
|
+
if (auth_key == NULL)
|
|
2733
|
+
rb_raise(rb_eNoMemError, "Failed to allocate memory for auth key");
|
|
2734
|
+
|
|
2357
2735
|
auth_key->sca_assoc_id = assoc_id;
|
|
2358
2736
|
auth_key->sca_keynumber = keynum;
|
|
2359
|
-
auth_key->sca_keylength =
|
|
2360
|
-
memcpy(auth_key->sca_key,
|
|
2737
|
+
auth_key->sca_keylength = len;
|
|
2738
|
+
memcpy(auth_key->sca_key, key, len);
|
|
2361
2739
|
|
|
2362
|
-
if(
|
|
2363
|
-
|
|
2740
|
+
if(setsockopt(fileno, IPPROTO_SCTP, SCTP_AUTH_KEY, (void*)auth_key, size) < 0) {
|
|
2741
|
+
int err = errno;
|
|
2742
|
+
free(auth_key);
|
|
2743
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(err));
|
|
2744
|
+
}
|
|
2364
2745
|
|
|
2746
|
+
free(auth_key);
|
|
2365
2747
|
return self;
|
|
2366
2748
|
}
|
|
2367
2749
|
|
|
@@ -2377,14 +2759,21 @@ static VALUE rsctp_get_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2377
2759
|
struct sctp_authkeyid authkey;
|
|
2378
2760
|
sctp_assoc_t assoc_id;
|
|
2379
2761
|
VALUE v_assoc_id, v_keynum;
|
|
2380
|
-
|
|
2762
|
+
int keynum;
|
|
2381
2763
|
|
|
2382
2764
|
rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
|
|
2383
2765
|
|
|
2766
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2767
|
+
|
|
2384
2768
|
bzero(&authkey, sizeof(authkey));
|
|
2385
2769
|
|
|
2770
|
+
// Cast it later, we want to force a validity check.
|
|
2771
|
+
keynum = FIX2INT(v_keynum);
|
|
2772
|
+
|
|
2773
|
+
if(keynum < 0)
|
|
2774
|
+
rb_raise(rb_eArgError, "invalid keynum value");
|
|
2775
|
+
|
|
2386
2776
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2387
|
-
keynum = NUM2UINT(v_keynum);
|
|
2388
2777
|
|
|
2389
2778
|
if(NIL_P(v_assoc_id))
|
|
2390
2779
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
|
@@ -2392,7 +2781,7 @@ static VALUE rsctp_get_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2392
2781
|
assoc_id = NUM2INT(v_assoc_id);
|
|
2393
2782
|
|
|
2394
2783
|
authkey.scact_assoc_id = assoc_id;
|
|
2395
|
-
authkey.scact_keynumber = keynum;
|
|
2784
|
+
authkey.scact_keynumber = (uint)keynum;
|
|
2396
2785
|
|
|
2397
2786
|
size = sizeof(struct sctp_authkeyid);
|
|
2398
2787
|
|
|
@@ -2413,7 +2802,7 @@ static VALUE rsctp_get_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2413
2802
|
* authenticated chunks. The key identifier MUST correspond to an existing
|
|
2414
2803
|
* shared key. Note that shared key identifier '0' defaults to a null key.
|
|
2415
2804
|
*
|
|
2416
|
-
* The
|
|
2805
|
+
* The association_id parameter, if non-zero, indicates what association that
|
|
2417
2806
|
* the shared key identifier is being set active upon. If this element contains
|
|
2418
2807
|
* zero, then the activation applies to the endpoint and all future
|
|
2419
2808
|
* associations will use the specified shared key identifier.
|
|
@@ -2430,11 +2819,17 @@ static VALUE rsctp_set_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2430
2819
|
struct sctp_authkeyid authkey;
|
|
2431
2820
|
sctp_assoc_t assoc_id;
|
|
2432
2821
|
VALUE v_assoc_id, v_keynum;
|
|
2433
|
-
|
|
2822
|
+
int keynum;
|
|
2434
2823
|
|
|
2435
2824
|
rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
|
|
2436
2825
|
|
|
2437
|
-
|
|
2826
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2827
|
+
|
|
2828
|
+
keynum = FIX2INT(v_keynum);
|
|
2829
|
+
|
|
2830
|
+
if(keynum < 0)
|
|
2831
|
+
rb_raise(rb_eArgError, "invalid keynum value");
|
|
2832
|
+
|
|
2438
2833
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2439
2834
|
|
|
2440
2835
|
if(NIL_P(v_assoc_id))
|
|
@@ -2443,11 +2838,11 @@ static VALUE rsctp_set_active_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2443
2838
|
assoc_id = NUM2INT(v_assoc_id);
|
|
2444
2839
|
|
|
2445
2840
|
authkey.scact_assoc_id = assoc_id;
|
|
2446
|
-
authkey.scact_keynumber = keynum;
|
|
2841
|
+
authkey.scact_keynumber = (uint)keynum;
|
|
2447
2842
|
size = sizeof(struct sctp_authkeyid);
|
|
2448
2843
|
|
|
2449
|
-
if(
|
|
2450
|
-
rb_raise(rb_eSystemCallError, "
|
|
2844
|
+
if(setsockopt(fileno, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, (void*)&authkey, size) < 0)
|
|
2845
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
2451
2846
|
|
|
2452
2847
|
return self;
|
|
2453
2848
|
}
|
|
@@ -2487,6 +2882,8 @@ static VALUE rsctp_delete_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2487
2882
|
|
|
2488
2883
|
rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
|
|
2489
2884
|
|
|
2885
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2886
|
+
|
|
2490
2887
|
bzero(&authkey, sizeof(authkey));
|
|
2491
2888
|
|
|
2492
2889
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
@@ -2502,8 +2899,8 @@ static VALUE rsctp_delete_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2502
2899
|
|
|
2503
2900
|
size = sizeof(struct sctp_authkeyid);
|
|
2504
2901
|
|
|
2505
|
-
if(
|
|
2506
|
-
rb_raise(rb_eSystemCallError, "
|
|
2902
|
+
if(setsockopt(fileno, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY, (void*)&authkey, size) < 0)
|
|
2903
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
|
2507
2904
|
|
|
2508
2905
|
return INT2NUM(authkey.scact_keynumber);
|
|
2509
2906
|
}
|
|
@@ -2512,14 +2909,20 @@ static VALUE rsctp_delete_shared_key(int argc, VALUE* argv, VALUE self){
|
|
|
2512
2909
|
* call-seq:
|
|
2513
2910
|
* SCTP::Socket#map_ipv4=(bool)
|
|
2514
2911
|
*
|
|
2515
|
-
* If set to true and the socket is type
|
|
2912
|
+
* If set to true and the socket is type xF_INET6, then IPv4 addresses will be
|
|
2516
2913
|
* mapped to V6 representation. If set to false (the default), then no mapping
|
|
2517
|
-
* will be done of V4 addresses and a user will receive both
|
|
2518
|
-
*
|
|
2914
|
+
* will be done of V4 addresses and a user will receive both xF_INET6 and
|
|
2915
|
+
* xF_INET type addresses on the socket.
|
|
2916
|
+
*
|
|
2917
|
+
* Note that setting this to true on a socket that is not type xF_INET6 is
|
|
2918
|
+
* undefined behavior, and may raise an error on your platform. Otherwise it's
|
|
2919
|
+
* a no-op.
|
|
2519
2920
|
*/
|
|
2520
2921
|
static VALUE rsctp_map_ipv4(VALUE self, VALUE v_bool){
|
|
2521
2922
|
int fileno, boolean;
|
|
2522
2923
|
|
|
2924
|
+
CHECK_SOCKET_CLOSED(self);
|
|
2925
|
+
|
|
2523
2926
|
boolean = 0;
|
|
2524
2927
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2525
2928
|
|
|
@@ -2594,6 +2997,8 @@ static VALUE rsctp_set_default_send_params(VALUE self, VALUE v_options){
|
|
|
2594
2997
|
|
|
2595
2998
|
bzero(&sndrcv, sizeof(sndrcv));
|
|
2596
2999
|
|
|
3000
|
+
CHECK_SOCKET_CLOSED(self);
|
|
3001
|
+
|
|
2597
3002
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
2598
3003
|
|
|
2599
3004
|
v_stream = rb_hash_aref2(v_options, "stream");
|
|
@@ -2677,17 +3082,19 @@ static VALUE rsctp_set_default_send_params(VALUE self, VALUE v_options){
|
|
|
2677
3082
|
*/
|
|
2678
3083
|
static VALUE rsctp_set_peer_address_params(VALUE self, VALUE v_options){
|
|
2679
3084
|
VALUE v_assoc_id, v_address, v_hbinterval, v_pathmaxrxt, v_pathmtu, v_flags, v_ipv6_flowlabel;
|
|
2680
|
-
int fileno;
|
|
3085
|
+
int fileno, domain;
|
|
2681
3086
|
sctp_assoc_t assoc_id;
|
|
2682
3087
|
struct sctp_paddrparams paddr;
|
|
2683
|
-
struct sockaddr_in* sin;
|
|
2684
3088
|
|
|
2685
3089
|
if(!RB_TYPE_P(v_options, T_HASH))
|
|
2686
3090
|
rb_raise(rb_eTypeError, "options must be a hash");
|
|
2687
3091
|
|
|
2688
3092
|
bzero(&paddr, sizeof(paddr));
|
|
2689
3093
|
|
|
3094
|
+
CHECK_SOCKET_CLOSED(self);
|
|
3095
|
+
|
|
2690
3096
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
|
3097
|
+
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
|
2691
3098
|
|
|
2692
3099
|
v_assoc_id = rb_hash_aref2(v_options, "association_id");
|
|
2693
3100
|
v_address = rb_hash_aref2(v_options, "address");
|
|
@@ -2703,12 +3110,28 @@ static VALUE rsctp_set_peer_address_params(VALUE self, VALUE v_options){
|
|
|
2703
3110
|
assoc_id = NUM2INT(v_assoc_id);
|
|
2704
3111
|
paddr.spp_assoc_id = assoc_id;
|
|
2705
3112
|
|
|
2706
|
-
// If address is provided, set up the sockaddr structure
|
|
3113
|
+
// If address is provided, set up the sockaddr structure based on domain
|
|
2707
3114
|
if(!NIL_P(v_address)){
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
if(
|
|
2711
|
-
|
|
3115
|
+
const char* addr_str = StringValueCStr(v_address);
|
|
3116
|
+
|
|
3117
|
+
if(domain == AF_INET6){
|
|
3118
|
+
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&paddr.spp_address;
|
|
3119
|
+
sin6->sin6_family = AF_INET6;
|
|
3120
|
+
if(inet_pton(AF_INET6, addr_str, &sin6->sin6_addr) <= 0)
|
|
3121
|
+
rb_raise(rb_eArgError, "invalid IPv6 address: %s", addr_str);
|
|
3122
|
+
#ifdef BSD
|
|
3123
|
+
sin6->sin6_len = sizeof(struct sockaddr_in6);
|
|
3124
|
+
#endif
|
|
3125
|
+
}
|
|
3126
|
+
else{
|
|
3127
|
+
struct sockaddr_in* sin = (struct sockaddr_in*)&paddr.spp_address;
|
|
3128
|
+
sin->sin_family = AF_INET;
|
|
3129
|
+
if(inet_pton(AF_INET, addr_str, &sin->sin_addr) <= 0)
|
|
3130
|
+
rb_raise(rb_eArgError, "invalid IPv4 address: %s", addr_str);
|
|
3131
|
+
#ifdef BSD
|
|
3132
|
+
sin->sin_len = sizeof(struct sockaddr_in);
|
|
3133
|
+
#endif
|
|
3134
|
+
}
|
|
2712
3135
|
}
|
|
2713
3136
|
|
|
2714
3137
|
if(!NIL_P(v_hbinterval))
|
|
@@ -2826,7 +3249,7 @@ void Init_socket(void){
|
|
|
2826
3249
|
|
|
2827
3250
|
v_sctp_receive_info_struct = rb_struct_define(
|
|
2828
3251
|
"ReceiveInfo", "message", "sid", "ssn", "flags", "ppid", "tsn",
|
|
2829
|
-
"cumtsn", "context", "
|
|
3252
|
+
"cumtsn", "context", "association_id", NULL
|
|
2830
3253
|
);
|
|
2831
3254
|
|
|
2832
3255
|
v_sctp_peer_addr_params_struct = rb_struct_define(
|
|
@@ -2899,8 +3322,8 @@ void Init_socket(void){
|
|
|
2899
3322
|
rb_define_attr(cSocket, "association_id", 1, 1);
|
|
2900
3323
|
rb_define_attr(cSocket, "port", 1, 1);
|
|
2901
3324
|
|
|
2902
|
-
/* 0.
|
|
2903
|
-
rb_define_const(cSocket, "VERSION", rb_str_new2("0.2.
|
|
3325
|
+
/* 0.2.2: The version of this library */
|
|
3326
|
+
rb_define_const(cSocket, "VERSION", rb_str_new2("0.2.2"));
|
|
2904
3327
|
|
|
2905
3328
|
/* send flags */
|
|
2906
3329
|
|