sctp-socket 0.2.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d41294806b8cc4ed6b74131f494a4a4309cac02ba490e3bbe20ef0f2cb89a09e
4
- data.tar.gz: 3a8d7207263715d37f7a42986ee734dd225af23e3e071daefcb35f0c53786cfe
3
+ metadata.gz: 8f9f0ecd09038bfc074d38f36b387c26a5f203c3d57ae5d6ad7f5b2c085e945f
4
+ data.tar.gz: 563a9e79224c46e71872de30a59a17ece441113dcab2cc8d4e153a7a89313b97
5
5
  SHA512:
6
- metadata.gz: 60fa99a73f494affaf1b6f68ce35178e64642e4c26feff61f349db97bec4f0240c268ef406150e0bc78fb78a6634ec7d5876490b722d84aef858f9e030085a0f
7
- data.tar.gz: '0925c76359dd0f1168c08556673a4f4d5db03bc891699042458e69f10509baf242ed95084ba97722f6a4ba24e5f88e43be39c1f9bb21a22fd6fbf8801f3446b9'
6
+ metadata.gz: 714abd0b5f6ecb95778ddf81d03dbfc6d23f1bfcfdebe62d4bed25cf3aaecc869e1235f6e5c04a5de123b0022ed9b6bdcb39d13a340d0aae3f3e50340c10ad26
7
+ data.tar.gz: c88bcdc5f0f456e4ef3a75f9c06f52ba60600959bfe7d654d398dfe0a3c8f9a19d76ee4d577c119a0b367c525b6395172a86ff6e6259fff8e697b345e122f616
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGES.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.2.2 - 7-Jan-2026
2
+ * Added IPv6 support.
3
+ * Some internal refactoring and updates, potential memory leak fixes, etc.
4
+ * Some specs skipped unless root.
5
+
1
6
  ## 0.2.1 - 17-Aug-2025
2
7
  * Several auth related methods were fixed.
3
8
  * The recvv and recvmsg methods now allow for an optional buffer size argument.
data/README.md CHANGED
@@ -167,7 +167,7 @@ Apache-2.0
167
167
 
168
168
  ## Copyright
169
169
 
170
- (C) 2020-2025, Daniel J. Berger
170
+ (C) 2020-2026, Daniel J. Berger
171
171
  Al Rights Reserved
172
172
 
173
173
  ## Author
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
- inet_ntop(
201
- ((struct sockaddr_in *)&snp->sn_paddr_change.spc_aaddr)->sin_family,
202
- &(((struct sockaddr_in *)&snp->sn_paddr_change.spc_aaddr)->sin_addr),
203
- str,
204
- sizeof(str)
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
- v_temp = ALLOCA_N(VALUE, snp->sn_remote_error.sre_length);
219
-
220
- for(i = 0; i < snp->sn_remote_error.sre_length; i++){
221
- v_temp[i] = UINT2NUM(snp->sn_remote_error.sre_data[i]);
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
- #ifdef HAVE_STRUCT_SCTP_SEND_FAILED_EVENT_SSFE_LENGTH
236
- v_temp = ALLOCA_N(VALUE, snp->sn_send_failed_event.ssfe_length);
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
- v_notification = rb_struct_new(v_send_failed_event_struct,
243
- UINT2NUM(snp->sn_send_failed_event.ssfe_type),
244
- UINT2NUM(snp->sn_send_failed_event.ssfe_length),
245
- UINT2NUM(snp->sn_send_failed_event.ssfe_error),
246
- rb_struct_new(v_sndinfo_struct,
247
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
248
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
249
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
250
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
251
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
252
- ),
253
- UINT2NUM(snp->sn_send_failed_event.ssfe_assoc_id),
254
- rb_ary_new4(snp->sn_send_failed_event.ssfe_length, v_temp)
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
- v_temp = ALLOCA_N(VALUE, snp->sn_send_failed_event.ssf_length);
258
-
259
- for(i = 0; i < snp->sn_send_failed_event.ssf_length; i++){
260
- v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssf_data[i]);
261
- }
262
-
263
- v_notification = rb_struct_new(v_send_failed_event_struct,
264
- UINT2NUM(snp->sn_send_failed_event.ssf_type),
265
- UINT2NUM(snp->sn_send_failed_event.ssf_length),
266
- UINT2NUM(snp->sn_send_failed_event.ssf_error),
267
- rb_struct_new(v_sndinfo_struct,
268
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
269
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
270
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
271
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
272
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
273
- ),
274
- UINT2NUM(snp->sn_send_failed_event.ssf_assoc_id),
275
- rb_ary_new4(snp->sn_send_failed_event.ssf_length, v_temp)
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
- v_temp = ALLOCA_N(VALUE, snp->sn_send_failed.ssf_length);
282
-
283
- for(i = 0; i < snp->sn_send_failed.ssf_length; i++){
284
- v_temp[i] = UINT2NUM(snp->sn_send_failed.ssf_data[i]);
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(sctp_bindx(fileno, (struct sockaddr *) addrs, num_ip, flags) != 0)
518
- rb_raise(rb_eSystemCallError, "sctp_bindx: %s", strerror(errno));
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
- struct sockaddr_in addrs[MAX_IP_ADDRESSES];
554
- int i, num_ip, fileno;
696
+ int i, num_ip, fileno, domain, port;
555
697
  sctp_assoc_t assoc;
556
- VALUE v_address, v_domain, v_options, v_addresses, v_port;
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
- v_domain = rb_iv_get(self, "@domain");
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
- for(i = 0; i < num_ip; i++){
580
- v_address = RARRAY_PTR(v_addresses)[i];
581
- addrs[i].sin_family = NUM2INT(v_domain);
582
- addrs[i].sin_port = htons(NUM2INT(v_port));
583
- addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
584
- #ifdef BSD
585
- addrs[i].sin_len = sizeof(struct sockaddr_in);
586
- #endif
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
- fileno = NUM2INT(rb_iv_get(self, "@fileno"));
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
- if(sctp_connectx(fileno, (struct sockaddr *) addrs, num_ip, &assoc) < 0)
592
- rb_raise(rb_eSystemCallError, "sctp_connectx: %s", strerror(errno));
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
- inet_ntop(AF_INET, &(((struct sockaddr_in *)&addrs[i])->sin_addr), str, sizeof(str));
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
- inet_ntop(AF_INET, &(((struct sockaddr_in *)&addrs[i])->sin_addr), str, sizeof(str));
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);
@@ -856,10 +1033,11 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
856
1033
  if(!NIL_P(v_addresses)){
857
1034
  Check_Type(v_addresses, T_ARRAY);
858
1035
  num_ip = (int)RARRAY_LEN(v_addresses);
859
- addrs = (struct sockaddr_in*)alloca(num_ip * sizeof(*addrs));
1036
+
1037
+ if(num_ip > MAX_IP_ADDRESSES)
1038
+ rb_raise(rb_eArgError, "too many IP addresses, maximum is eight");
860
1039
  }
861
1040
  else{
862
- addrs = NULL;
863
1041
  num_ip = 0;
864
1042
  }
865
1043
 
@@ -877,8 +1055,15 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
877
1055
  spa.sendv_sndinfo.snd_flags = SCTP_UNORDERED;
878
1056
  spa.sendv_sndinfo.snd_assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
879
1057
 
880
- if(!NIL_P(v_addresses)){
881
- int i, port, domain;
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){
882
1067
  VALUE v_address, v_port;
883
1068
 
884
1069
  v_port = rb_iv_get(self, "@port");
@@ -888,36 +1073,62 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
888
1073
  else
889
1074
  port = NUM2INT(v_port);
890
1075
 
891
- domain = NUM2INT(rb_iv_get(self, "@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));
892
1079
 
893
- for(i = 0; i < num_ip; i++){
894
- v_address = RARRAY_PTR(v_addresses)[i];
895
- addrs[i].sin_family = domain;
896
- addrs[i].sin_port = htons(port);
897
- addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
898
- #ifdef BSD
899
- addrs[i].sin_len = sizeof(struct sockaddr_in);
900
- #endif
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
+ );
901
1096
  }
902
- }
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));
903
1100
 
904
- for(i = 0; i < size; i++){
905
- v_msg = RARRAY_PTR(v_message)[i];
906
- iov[i].iov_base = StringValueCStr(v_msg);
907
- iov[i].iov_len = RSTRING_LEN(v_msg);
908
- }
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
+ }
909
1105
 
910
- num_bytes = (ssize_t)sctp_sendv(
911
- fileno,
912
- iov,
913
- size,
914
- (struct sockaddr*)addrs,
915
- num_ip,
916
- &spa,
917
- sizeof(spa),
918
- SCTP_SENDV_SPA,
919
- 0
920
- );
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
+ }
921
1132
 
922
1133
  if(num_bytes < 0)
923
1134
  rb_raise(rb_eSystemCallError, "sctp_sendv: %s", strerror(errno));
@@ -970,6 +1181,8 @@ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
970
1181
 
971
1182
  rb_scan_args(argc, argv, "02", &v_flags, &v_buffer_size);
972
1183
 
1184
+ CHECK_SOCKET_CLOSED(self);
1185
+
973
1186
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
974
1187
 
975
1188
  if(NIL_P(v_flags))
@@ -1116,6 +1329,8 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
1116
1329
  else
1117
1330
  assoc_id = NUM2INT(v_assoc_id);
1118
1331
 
1332
+ CHECK_SOCKET_CLOSED(self);
1333
+
1119
1334
  info.sinfo_stream = stream;
1120
1335
  info.sinfo_flags = send_flags;
1121
1336
  info.sinfo_ppid = ppid;
@@ -1176,13 +1391,10 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
1176
1391
  uint16_t stream;
1177
1392
  uint32_t ppid, flags, ttl, context;
1178
1393
  ssize_t num_bytes;
1179
- struct sockaddr_in addrs[MAX_IP_ADDRESSES];
1180
- int fileno, size, num_ip;
1394
+ int fileno, num_ip, domain;
1181
1395
 
1182
1396
  Check_Type(v_options, T_HASH);
1183
1397
 
1184
- bzero(&addrs, sizeof(addrs));
1185
-
1186
1398
  v_msg = rb_hash_aref2(v_options, "message");
1187
1399
  v_stream = rb_hash_aref2(v_options, "stream");
1188
1400
  v_ppid = rb_hash_aref2(v_options, "ppid");
@@ -1222,12 +1434,21 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
1222
1434
  else
1223
1435
  context = NUM2INT(v_context);
1224
1436
 
1437
+ CHECK_SOCKET_CLOSED(self);
1438
+
1439
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1440
+ domain = NUM2INT(rb_iv_get(self, "@domain"));
1441
+
1225
1442
  if(!NIL_P(v_addresses)){
1226
1443
  int i, port;
1227
1444
  VALUE v_address, v_port;
1228
1445
 
1229
1446
  Check_Type(v_addresses, T_ARRAY);
1230
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
+
1231
1452
  v_port = rb_hash_aref2(v_options, "port");
1232
1453
 
1233
1454
  if(NIL_P(v_port))
@@ -1235,47 +1456,92 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
1235
1456
  else
1236
1457
  port = NUM2INT(v_port);
1237
1458
 
1238
- for(i = 0; i < num_ip; i++){
1239
- v_address = RARRAY_PTR(v_addresses)[i];
1240
- addrs[i].sin_family = NUM2INT(rb_iv_get(self, "@domain"));
1241
- addrs[i].sin_port = htons(port);
1242
- addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
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
+
1243
1469
  #ifdef BSD
1244
- addrs[i].sin_len = sizeof(struct sockaddr_in);
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
+ );
1245
1495
  #endif
1246
1496
  }
1497
+ else{
1498
+ struct sockaddr_in addrs[MAX_IP_ADDRESSES];
1247
1499
 
1248
- size = sizeof(addrs);
1249
- }
1250
- else{
1251
- num_ip = 0;
1252
- size = 0;
1253
- }
1500
+ bzero(&addrs, sizeof(addrs));
1254
1501
 
1255
- fileno = NUM2INT(rb_iv_get(self, "@fileno"));
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
+ }
1256
1506
 
1257
1507
  #ifdef BSD
1258
- if(num_ip){
1259
- num_bytes = (ssize_t)sctp_sendmsgx(
1260
- fileno,
1261
- StringValueCStr(v_msg),
1262
- RSTRING_LEN(v_msg),
1263
- (struct sockaddr*)addrs,
1264
- num_ip,
1265
- ppid,
1266
- flags,
1267
- stream,
1268
- ttl,
1269
- context
1270
- );
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
+ }
1271
1535
  }
1272
1536
  else{
1537
+ // No addresses - use empty addrs
1538
+ num_ip = 0;
1273
1539
  num_bytes = (ssize_t)sctp_sendmsg(
1274
1540
  fileno,
1275
1541
  StringValueCStr(v_msg),
1276
1542
  RSTRING_LEN(v_msg),
1277
- (struct sockaddr*)addrs,
1278
- size,
1543
+ NULL,
1544
+ 0,
1279
1545
  ppid,
1280
1546
  flags,
1281
1547
  stream,
@@ -1283,20 +1549,6 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
1283
1549
  context
1284
1550
  );
1285
1551
  }
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
1552
 
1301
1553
  if(num_bytes < 0){
1302
1554
  #ifdef BSD
@@ -1369,6 +1621,8 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
1369
1621
  if(buffer == NULL)
1370
1622
  rb_raise(rb_eNoMemError, "failed to allocate buffer");
1371
1623
 
1624
+ CHECK_SOCKET_CLOSED(self);
1625
+
1372
1626
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1373
1627
  length = sizeof(struct sockaddr_in);
1374
1628
 
@@ -1443,6 +1697,8 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
1443
1697
 
1444
1698
  bzero(&initmsg, sizeof(initmsg));
1445
1699
 
1700
+ CHECK_SOCKET_CLOSED(self);
1701
+
1446
1702
  v_output = rb_hash_aref2(v_options, "output_streams");
1447
1703
  v_input = rb_hash_aref2(v_options, "input_streams");
1448
1704
  v_attempts = rb_hash_aref2(v_options, "max_attempts");
@@ -1513,6 +1769,8 @@ static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
1513
1769
  bzero(&events, sizeof(events));
1514
1770
  Check_Type(v_options, T_HASH);
1515
1771
 
1772
+ CHECK_SOCKET_CLOSED(self);
1773
+
1516
1774
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1517
1775
 
1518
1776
  if(RTEST(rb_hash_aref2(v_options, "data_io")))
@@ -1593,6 +1851,8 @@ static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
1593
1851
  if(backlog > SOMAXCONN)
1594
1852
  rb_raise(rb_eArgError, "backlog value exceeds maximum value of: %i", SOMAXCONN);
1595
1853
 
1854
+ CHECK_SOCKET_CLOSED(self);
1855
+
1596
1856
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1597
1857
 
1598
1858
  if(listen(fileno, backlog) < 0)
@@ -1623,6 +1883,8 @@ static VALUE rsctp_peeloff(VALUE self, VALUE v_assoc_id){
1623
1883
  int fileno, assoc_fileno;
1624
1884
  sctp_assoc_t assoc_id;
1625
1885
 
1886
+ CHECK_SOCKET_CLOSED(self);
1887
+
1626
1888
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1627
1889
  assoc_id = NUM2INT(v_assoc_id);
1628
1890
 
@@ -1660,6 +1922,8 @@ static VALUE rsctp_get_default_send_params(VALUE self){
1660
1922
 
1661
1923
  bzero(&sndrcv, sizeof(sndrcv));
1662
1924
 
1925
+ CHECK_SOCKET_CLOSED(self);
1926
+
1663
1927
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1664
1928
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1665
1929
  size = sizeof(struct sctp_sndrcvinfo);
@@ -1705,6 +1969,8 @@ static VALUE rsctp_get_association_info(VALUE self){
1705
1969
 
1706
1970
  bzero(&assoc, sizeof(assoc));
1707
1971
 
1972
+ CHECK_SOCKET_CLOSED(self);
1973
+
1708
1974
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1709
1975
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1710
1976
  size = sizeof(struct sctp_assocparams);
@@ -1747,6 +2013,8 @@ static VALUE rsctp_set_association_info(VALUE self, VALUE v_options){
1747
2013
 
1748
2014
  bzero(&assoc, sizeof(assoc));
1749
2015
 
2016
+ CHECK_SOCKET_CLOSED(self);
2017
+
1750
2018
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1751
2019
 
1752
2020
  v_assoc_id = rb_hash_aref2(v_options, "association_id");
@@ -1811,6 +2079,8 @@ static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
1811
2079
  int how, fileno;
1812
2080
  VALUE v_how;
1813
2081
 
2082
+ CHECK_SOCKET_CLOSED(self);
2083
+
1814
2084
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1815
2085
 
1816
2086
  rb_scan_args(argc, argv, "01", &v_how);
@@ -1850,6 +2120,8 @@ static VALUE rsctp_get_retransmission_info(VALUE self){
1850
2120
 
1851
2121
  bzero(&rto, sizeof(rto));
1852
2122
 
2123
+ CHECK_SOCKET_CLOSED(self);
2124
+
1853
2125
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1854
2126
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1855
2127
  size = sizeof(struct sctp_rtoinfo);
@@ -1889,6 +2161,8 @@ static VALUE rsctp_set_retransmission_info(VALUE self, VALUE v_options){
1889
2161
 
1890
2162
  bzero(&rto, sizeof(rto));
1891
2163
 
2164
+ CHECK_SOCKET_CLOSED(self);
2165
+
1892
2166
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1893
2167
 
1894
2168
  v_assoc_id = rb_hash_aref2(v_options, "association_id");
@@ -1954,10 +2228,12 @@ static VALUE rsctp_get_status(VALUE self){
1954
2228
  sctp_assoc_t assoc_id;
1955
2229
  struct sctp_status status;
1956
2230
  struct sctp_paddrinfo* spinfo;
1957
- char tmpname[INET_ADDRSTRLEN];
2231
+ char tmpname[INET6_ADDRSTRLEN];
1958
2232
 
1959
2233
  bzero(&status, sizeof(status));
1960
2234
 
2235
+ CHECK_SOCKET_CLOSED(self);
2236
+
1961
2237
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1962
2238
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1963
2239
  size = sizeof(struct sctp_status);
@@ -2022,6 +2298,8 @@ static VALUE rsctp_get_subscriptions(VALUE self){
2022
2298
 
2023
2299
  bzero(&events, sizeof(events));
2024
2300
 
2301
+ CHECK_SOCKET_CLOSED(self);
2302
+
2025
2303
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
2026
2304
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
2027
2305
  size = sizeof(struct sctp_event_subscribe);
@@ -2087,6 +2365,8 @@ static VALUE rsctp_get_peer_address_params(VALUE self){
2087
2365
  bzero(&paddr, sizeof(paddr));
2088
2366
  bzero(&str, sizeof(str));
2089
2367
 
2368
+ CHECK_SOCKET_CLOSED(self);
2369
+
2090
2370
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
2091
2371
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
2092
2372
  size = sizeof(struct sctp_paddrparams);
@@ -2094,7 +2374,18 @@ static VALUE rsctp_get_peer_address_params(VALUE self){
2094
2374
  if(sctp_opt_info(fileno, assoc_id, SCTP_PEER_ADDR_PARAMS, (void*)&paddr, &size) < 0)
2095
2375
  rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
2096
2376
 
2097
- inet_ntop(AF_INET, ((struct sockaddr_in*)&paddr.spp_address), str, sizeof(str));
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
+ }
2098
2389
 
2099
2390
  return rb_struct_new(
2100
2391
  v_sctp_peer_addr_params_struct,
@@ -2134,6 +2425,8 @@ static VALUE rsctp_get_init_msg(VALUE self){
2134
2425
 
2135
2426
  bzero(&initmsg, sizeof(initmsg));
2136
2427
 
2428
+ CHECK_SOCKET_CLOSED(self);
2429
+
2137
2430
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
2138
2431
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
2139
2432
  size = sizeof(struct sctp_initmsg);
@@ -2162,6 +2455,8 @@ static VALUE rsctp_get_nodelay(VALUE self){
2162
2455
  sctp_assoc_t assoc_id;
2163
2456
  int value;
2164
2457
 
2458
+ CHECK_SOCKET_CLOSED(self);
2459
+
2165
2460
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
2166
2461
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
2167
2462
  size = sizeof(int);
@@ -2188,6 +2483,8 @@ static VALUE rsctp_set_nodelay(VALUE self, VALUE v_bool){
2188
2483
  socklen_t size;
2189
2484
  int value;
2190
2485
 
2486
+ CHECK_SOCKET_CLOSED(self);
2487
+
2191
2488
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
2192
2489
  size = sizeof(int);
2193
2490
 
@@ -2221,6 +2518,8 @@ static VALUE rsctp_disable_fragments(VALUE self, VALUE v_bool){
2221
2518
  sctp_assoc_t assoc_id;
2222
2519
  int value;
2223
2520
 
2521
+ CHECK_SOCKET_CLOSED(self);
2522
+
2224
2523
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
2225
2524
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
2226
2525
  size = sizeof(int);
@@ -2252,6 +2551,8 @@ static VALUE rsctp_get_autoclose(VALUE self){
2252
2551
  sctp_assoc_t assoc_id;
2253
2552
  int value;
2254
2553
 
2554
+ CHECK_SOCKET_CLOSED(self);
2555
+
2255
2556
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
2256
2557
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
2257
2558
  size = sizeof(int);
@@ -2288,6 +2589,8 @@ static VALUE rsctp_set_autoclose(VALUE self, VALUE v_seconds){
2288
2589
  int fileno;
2289
2590
  int value;
2290
2591
 
2592
+ CHECK_SOCKET_CLOSED(self);
2593
+
2291
2594
  value = NUM2INT(v_seconds);
2292
2595
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
2293
2596
 
@@ -2399,7 +2702,7 @@ static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
2399
2702
  size_t len;
2400
2703
  char* key;
2401
2704
  uint keynum;
2402
- socklen_t size;
2705
+ size_t size;
2403
2706
  sctp_assoc_t assoc_id;
2404
2707
  struct sctp_authkey* auth_key;
2405
2708
  VALUE v_key, v_keynumber, v_assoc_id;
@@ -2460,6 +2763,8 @@ static VALUE rsctp_get_active_shared_key(int argc, VALUE* argv, VALUE self){
2460
2763
 
2461
2764
  rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
2462
2765
 
2766
+ CHECK_SOCKET_CLOSED(self);
2767
+
2463
2768
  bzero(&authkey, sizeof(authkey));
2464
2769
 
2465
2770
  // Cast it later, we want to force a validity check.
@@ -2518,6 +2823,8 @@ static VALUE rsctp_set_active_shared_key(int argc, VALUE* argv, VALUE self){
2518
2823
 
2519
2824
  rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
2520
2825
 
2826
+ CHECK_SOCKET_CLOSED(self);
2827
+
2521
2828
  keynum = FIX2INT(v_keynum);
2522
2829
 
2523
2830
  if(keynum < 0)
@@ -2614,6 +2921,8 @@ static VALUE rsctp_delete_shared_key(int argc, VALUE* argv, VALUE self){
2614
2921
  static VALUE rsctp_map_ipv4(VALUE self, VALUE v_bool){
2615
2922
  int fileno, boolean;
2616
2923
 
2924
+ CHECK_SOCKET_CLOSED(self);
2925
+
2617
2926
  boolean = 0;
2618
2927
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
2619
2928
 
@@ -2688,6 +2997,8 @@ static VALUE rsctp_set_default_send_params(VALUE self, VALUE v_options){
2688
2997
 
2689
2998
  bzero(&sndrcv, sizeof(sndrcv));
2690
2999
 
3000
+ CHECK_SOCKET_CLOSED(self);
3001
+
2691
3002
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
2692
3003
 
2693
3004
  v_stream = rb_hash_aref2(v_options, "stream");
@@ -2771,17 +3082,19 @@ static VALUE rsctp_set_default_send_params(VALUE self, VALUE v_options){
2771
3082
  */
2772
3083
  static VALUE rsctp_set_peer_address_params(VALUE self, VALUE v_options){
2773
3084
  VALUE v_assoc_id, v_address, v_hbinterval, v_pathmaxrxt, v_pathmtu, v_flags, v_ipv6_flowlabel;
2774
- int fileno;
3085
+ int fileno, domain;
2775
3086
  sctp_assoc_t assoc_id;
2776
3087
  struct sctp_paddrparams paddr;
2777
- struct sockaddr_in* sin;
2778
3088
 
2779
3089
  if(!RB_TYPE_P(v_options, T_HASH))
2780
3090
  rb_raise(rb_eTypeError, "options must be a hash");
2781
3091
 
2782
3092
  bzero(&paddr, sizeof(paddr));
2783
3093
 
3094
+ CHECK_SOCKET_CLOSED(self);
3095
+
2784
3096
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
3097
+ domain = NUM2INT(rb_iv_get(self, "@domain"));
2785
3098
 
2786
3099
  v_assoc_id = rb_hash_aref2(v_options, "association_id");
2787
3100
  v_address = rb_hash_aref2(v_options, "address");
@@ -2797,12 +3110,28 @@ static VALUE rsctp_set_peer_address_params(VALUE self, VALUE v_options){
2797
3110
  assoc_id = NUM2INT(v_assoc_id);
2798
3111
  paddr.spp_assoc_id = assoc_id;
2799
3112
 
2800
- // If address is provided, set up the sockaddr structure
3113
+ // If address is provided, set up the sockaddr structure based on domain
2801
3114
  if(!NIL_P(v_address)){
2802
- sin = (struct sockaddr_in*)&paddr.spp_address;
2803
- sin->sin_family = AF_INET;
2804
- if(inet_pton(AF_INET, StringValueCStr(v_address), &sin->sin_addr) <= 0)
2805
- rb_raise(rb_eArgError, "invalid IP address");
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
+ }
2806
3135
  }
2807
3136
 
2808
3137
  if(!NIL_P(v_hbinterval))
@@ -2920,7 +3249,7 @@ void Init_socket(void){
2920
3249
 
2921
3250
  v_sctp_receive_info_struct = rb_struct_define(
2922
3251
  "ReceiveInfo", "message", "sid", "ssn", "flags", "ppid", "tsn",
2923
- "cumtsn", "context", "assocation_id", NULL
3252
+ "cumtsn", "context", "association_id", NULL
2924
3253
  );
2925
3254
 
2926
3255
  v_sctp_peer_addr_params_struct = rb_struct_define(
@@ -2993,8 +3322,8 @@ void Init_socket(void){
2993
3322
  rb_define_attr(cSocket, "association_id", 1, 1);
2994
3323
  rb_define_attr(cSocket, "port", 1, 1);
2995
3324
 
2996
- /* 0.2.0: The version of this library */
2997
- rb_define_const(cSocket, "VERSION", rb_str_new2("0.2.1"));
3325
+ /* 0.2.2: The version of this library */
3326
+ rb_define_const(cSocket, "VERSION", rb_str_new2("0.2.2"));
2998
3327
 
2999
3328
  /* send flags */
3000
3329
 
data/sctp-socket.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = 'sctp-socket'
3
- spec.version = '0.2.1'
3
+ spec.version = '0.2.2'
4
4
  spec.author = 'Daniel Berger'
5
5
  spec.email = 'djberg96@gmail.com'
6
6
  spec.summary = 'Ruby bindings for SCTP sockets'
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,11 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sctp-socket
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Berger
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain:
11
10
  - |
@@ -35,7 +34,7 @@ cert_chain:
35
34
  ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
36
35
  WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
37
36
  -----END CERTIFICATE-----
38
- date: 2025-08-17 00:00:00.000000000 Z
37
+ date: 1980-01-02 00:00:00.000000000 Z
39
38
  dependencies:
40
39
  - !ruby/object:Gem::Dependency
41
40
  name: bundler
@@ -132,7 +131,6 @@ metadata:
132
131
  wiki_uri: https://github.com/djberg96/sctp-socket/wiki
133
132
  rubygems_mfa_required: 'true'
134
133
  funding_uri: https://github.com/sponsors/djberg96
135
- post_install_message:
136
134
  rdoc_options: []
137
135
  require_paths:
138
136
  - lib
@@ -147,8 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
145
  - !ruby/object:Gem::Version
148
146
  version: '0'
149
147
  requirements: []
150
- rubygems_version: 3.5.22
151
- signing_key:
148
+ rubygems_version: 3.6.9
152
149
  specification_version: 4
153
150
  summary: Ruby bindings for SCTP sockets
154
151
  test_files: []
metadata.gz.sig CHANGED
Binary file