sctp-socket 0.1.1 → 0.1.3

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: 5ad81d72b62e06897cdc0704d1ea3213392697884787d698bab4985c0e7c822e
4
- data.tar.gz: 975927d8093ff35fe599a51b0d94fd0402cb15de8225dd0143e2598eb35c6ff1
3
+ metadata.gz: 81048dca4080fa86d9a50626a8fe69462af57e7d95231083e03272757949cddc
4
+ data.tar.gz: c4f7e5952deeefbb1b7a453179241bb79d6256f90c3b4ede166a3f99897f2def
5
5
  SHA512:
6
- metadata.gz: 8a46199d3d957907bbd3b95b321887018944c964ce12f1650125339445811693b6b9ac08ad894901d94842145ad699114f48c66b6f7dda95a0b859a46625006f
7
- data.tar.gz: 54f42c50b8d63dc1fbd30497064bf605f0fc8e83bd61e27badb10cad9319fe84fe8dbb14bd40455b5d86709537072f99be17dab57a7cb1aa6662238f54e10f08
6
+ metadata.gz: '001209834d222cab4fe021741e9cfa91448c7fae70ca9418de8e3b05084d2a30fe5897b57adb42394525efc7dfef58cf8d8ca08e6218d7a2b490e7172d1a2454'
7
+ data.tar.gz: 9a597dcd249ef7133a0bbd8fa145a018e41c5bcc76a3fcfaf8b658d90f40b39afbb585dbb3c05fc4a4173b42d495814f7a8ba1934a7c8fb7baf0a3c3d1b69ca9
checksums.yaml.gz.sig CHANGED
Binary file
@@ -35,3 +35,25 @@ jobs:
35
35
  bundler-cache: true
36
36
  - name: Run Specs
37
37
  run: bundle exec rake
38
+ freebsd:
39
+ runs-on: ubuntu-latest
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+ - name: Test in FreeBSD
43
+ id: test
44
+ uses: vmactions/freebsd-vm@v1
45
+ with:
46
+ usesh: true
47
+ prepare: |
48
+ pkg install -y llvm ruby devel/ruby-gems sctplib git-tiny
49
+
50
+ run: |
51
+ git config --global --add safe.directory /home/runner/work/sctp-socket/sctp-socket
52
+ kldload sctp
53
+ ifconfig lo1 create
54
+ ifconfig lo1 1.1.1.1/24 up
55
+ ifconfig lo2 create
56
+ ifconfig lo2 1.1.1.2/24 up
57
+ gem install bundler --no-document
58
+ bundle install --quiet
59
+ bundle exec rake
data/CHANGES.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.1.3 - 22-Jan-2025
2
+ * The close method now accepts an optional `linger` argument.
3
+ * The bindx method now accepts an optional `reuse_addr` argument.
4
+ * Fixed a bug in the bindx method for address arrays with a single element.
5
+
6
+ ## 0.1.2 - 10-Jan-2025
7
+ * Added support for BSD.
8
+
1
9
  ## 0.1.1 - 1-Jan-2025
2
10
  * Added the set_shared_key method.
3
11
  * Added the get_active_shared_key and set_active_shared_key methods.
data/README.md CHANGED
@@ -63,11 +63,11 @@ end
63
63
 
64
64
  ## Known Issues
65
65
 
66
- Currently this has only been developed and tested on Linux. Other platforms
67
- will probably only be supported via community contributions.
66
+ Currently this has only been developed and tested on Linux and BSD. Other
67
+ platforms will probably only be supported via community contributions.
68
68
 
69
69
  The sendv and recvv methods may not be available. Use the sendmsg and recvmsg
70
- methods instead.
70
+ methods instead if that's the case.
71
71
 
72
72
  I am currently unable to subclass the Socket class from Ruby's standard library.
73
73
  For whatever reason the call to rb_call_super works, but the fileno is always
@@ -92,7 +92,7 @@ Apache-2.0
92
92
 
93
93
  ## Copyright
94
94
 
95
- (C) 2020-2024, Daniel J. Berger
95
+ (C) 2020-2025, Daniel J. Berger
96
96
  Al Rights Reserved
97
97
 
98
98
  ## Author
data/Rakefile CHANGED
@@ -39,13 +39,21 @@ end
39
39
 
40
40
  desc "Create dummy IP addresses to use for testing"
41
41
  task :create_dummy_links do
42
- system('sudo ip link add dummy1 type dummy')
43
- system('sudo ip link add dummy2 type dummy')
44
- system('sudo ip addr add 1.1.1.1/24 dev dummy1')
45
- system('sudo ip addr add 1.1.1.2/24 dev dummy2')
46
- system('sudo ip link set dummy1 up')
47
- system('sudo ip link set dummy2 up')
48
- system('ip link show')
42
+ if RbConfig::CONFIG['host_os'] =~ /linux/i
43
+ system('sudo ip link add dummy1 type dummy')
44
+ system('sudo ip link add dummy2 type dummy')
45
+ system('sudo ip addr add 1.1.1.1/24 dev dummy1')
46
+ system('sudo ip addr add 1.1.1.2/24 dev dummy2')
47
+ system('sudo ip link set dummy1 up')
48
+ system('sudo ip link set dummy2 up')
49
+ system('ip link show')
50
+ else
51
+ system("sudo ifconfig lo1 create")
52
+ system("sudo ifconfig lo1 1.1.1.1/24 up")
53
+ system("sudo ifconfig lo2 create")
54
+ system("sudo ifconfig lo2 1.1.1.2/24 up")
55
+ system("sudo ifconfig -a")
56
+ end
49
57
  end
50
58
 
51
59
  RSpec::Core::RakeTask.new
@@ -10,7 +10,7 @@ begin
10
10
  socket = SCTP::Socket.new
11
11
 
12
12
  # Optional, but could bind to a subset of available addresses
13
- p socket.bindx(:addresses => addresses)
13
+ # p socket.bindx(:addresses => addresses)
14
14
 
15
15
  # Initial connection
16
16
  p socket.connectx(:addresses => addresses, :port => port)
@@ -30,6 +30,7 @@ begin
30
30
 
31
31
  while true
32
32
  info = socket.recvmsg
33
+ # info = socket.recvv # Or this
33
34
  p info
34
35
  end
35
36
  ensure
data/ext/sctp/extconf.rb CHANGED
@@ -24,8 +24,25 @@ unless have_header('netinet/sctp.h')
24
24
  exit
25
25
  end
26
26
 
27
+ header = 'netinet/sctp.h'
28
+
27
29
  have_library('sctp')
28
- have_func('sctp_sendv', 'netinet/sctp.h')
29
- have_func('sctp_recvv', 'netinet/sctp.h')
30
- have_struct_member('struct sctp_event_subscribe', 'sctp_send_failure_event', 'netinet/sctp.h')
30
+
31
+ have_header('sys/param.h')
32
+
33
+ have_func('sctp_sendv', header)
34
+ have_func('sctp_recvv', header)
35
+
36
+ have_struct_member('struct sctp_event_subscribe', 'sctp_send_failure_event', header)
37
+ have_struct_member('struct sctp_event_subscribe', 'sctp_stream_reset_event', header)
38
+ have_struct_member('struct sctp_event_subscribe', 'sctp_assoc_reset_event', header)
39
+ have_struct_member('struct sctp_event_subscribe', 'sctp_stream_change_event', header)
40
+ have_struct_member('struct sctp_event_subscribe', 'sctp_send_failure_event_event', header)
41
+
42
+ have_struct_member('struct sctp_send_failed_event', 'ssfe_length', header)
43
+
44
+ have_struct_member('union sctp_notification', 'sn_auth_event', header)
45
+
46
+ have_const('SCTP_EMPTY', header)
47
+
31
48
  create_makefile('sctp/socket')
data/ext/sctp/socket.c CHANGED
@@ -4,6 +4,10 @@
4
4
  #include <arpa/inet.h>
5
5
  #include <netinet/sctp.h>
6
6
 
7
+ #ifdef HAVE_SYS_PARAM_H
8
+ #include <sys/param.h>
9
+ #endif
10
+
7
11
  VALUE mSCTP;
8
12
  VALUE cSocket;
9
13
  VALUE v_sndrcv_struct;
@@ -163,6 +167,28 @@ VALUE get_notification_info(char* buffer){
163
167
  break;
164
168
  #ifdef SCTP_SEND_FAILED_EVENT
165
169
  case SCTP_SEND_FAILED_EVENT:
170
+ #ifdef HAVE_STRUCT_SCTP_SEND_FAILED_EVENT_SSFE_LENGTH
171
+ v_temp = ALLOCA_N(VALUE, snp->sn_send_failed_event.ssfe_length);
172
+
173
+ for(i = 0; i < snp->sn_send_failed_event.ssfe_length; i++){
174
+ v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssfe_data[i]);
175
+ }
176
+
177
+ v_notification = rb_struct_new(v_send_failed_event_struct,
178
+ UINT2NUM(snp->sn_send_failed_event.ssfe_type),
179
+ UINT2NUM(snp->sn_send_failed_event.ssfe_length),
180
+ UINT2NUM(snp->sn_send_failed_event.ssfe_error),
181
+ rb_struct_new(v_sndinfo_struct,
182
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
183
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
184
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
185
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
186
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
187
+ ),
188
+ UINT2NUM(snp->sn_send_failed_event.ssfe_assoc_id),
189
+ rb_ary_new4(snp->sn_send_failed_event.ssfe_length, v_temp)
190
+ );
191
+ #else
166
192
  v_temp = ALLOCA_N(VALUE, snp->sn_send_failed_event.ssf_length);
167
193
 
168
194
  for(i = 0; i < snp->sn_send_failed_event.ssf_length; i++){
@@ -183,6 +209,7 @@ VALUE get_notification_info(char* buffer){
183
209
  UINT2NUM(snp->sn_send_failed_event.ssf_assoc_id),
184
210
  rb_ary_new4(snp->sn_send_failed_event.ssf_length, v_temp)
185
211
  );
212
+ #endif
186
213
  break;
187
214
  #else
188
215
  case SCTP_SEND_FAILED:
@@ -229,11 +256,19 @@ VALUE get_notification_info(char* buffer){
229
256
  break;
230
257
  case SCTP_AUTHENTICATION_EVENT:
231
258
  v_notification = rb_struct_new(v_auth_event_struct,
259
+ #ifdef HAVE_UNION_SCTP_NOTIFICATION_SN_AUTH_EVENT
260
+ UINT2NUM(snp->sn_auth_event.auth_type),
261
+ UINT2NUM(snp->sn_auth_event.auth_length),
262
+ UINT2NUM(snp->sn_auth_event.auth_keynumber),
263
+ UINT2NUM(snp->sn_auth_event.auth_indication),
264
+ UINT2NUM(snp->sn_auth_event.auth_assoc_id)
265
+ #else
232
266
  UINT2NUM(snp->sn_authkey_event.auth_type),
233
267
  UINT2NUM(snp->sn_authkey_event.auth_length),
234
268
  UINT2NUM(snp->sn_authkey_event.auth_keynumber),
235
269
  UINT2NUM(snp->sn_authkey_event.auth_indication),
236
270
  UINT2NUM(snp->sn_authkey_event.auth_assoc_id)
271
+ #endif
237
272
  );
238
273
  break;
239
274
  case SCTP_SENDER_DRY_EVENT:
@@ -300,11 +335,28 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
300
335
  *
301
336
  * Bind a subset of IP addresses associated with the host system on the
302
337
  * given port, or a port assigned by the operating system if none is provided.
338
+ * You may bind a maximum of eight IP addresses.
303
339
  *
304
340
  * Note that you can both add or remove an address to or from the socket
305
341
  * using the SCTP_BINDX_ADD_ADDR (default) or SCTP_BINDX_REM_ADDR constants,
306
342
  * respectively.
307
343
  *
344
+ * Possible options:
345
+ *
346
+ * * addresses - Array of IP addresses to bind to. If none are specified then
347
+ * INADDR_ANY is used.
348
+ *
349
+ * * port - The port to bind to. If none is specified then 0 is used, i.e. the
350
+ * OS will select one for you.
351
+ *
352
+ * * flags - Flags to pass to the underlying sctp_bindx function. In practice
353
+ * there are only two options: BINDX_ADD_ADDR and BINDX_REM_ADDR. By
354
+ * default a flag of BINDX_ADD_ADDR is assumed.
355
+ *
356
+ * * reuse_addr - If set to true, then the SO_REUSEADDR flag will be applied to
357
+ * the socket before the bind call. This will allow other sockets to reuse
358
+ * the addresses that are currently bound to the socket.
359
+ *
308
360
  * Example:
309
361
  *
310
362
  * socket = SCTP::Socket.new
@@ -322,8 +374,8 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
322
374
  */
323
375
  static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
324
376
  struct sockaddr_in addrs[8];
325
- int i, fileno, num_ip, flags, domain, port;
326
- VALUE v_addresses, v_port, v_flags, v_address, v_options;
377
+ int i, fileno, num_ip, flags, domain, port, on;
378
+ VALUE v_addresses, v_port, v_flags, v_address, v_reuse_addr, v_options;
327
379
 
328
380
  rb_scan_args(argc, argv, "01", &v_options);
329
381
 
@@ -335,6 +387,7 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
335
387
  v_addresses = rb_hash_aref2(v_options, "addresses");
336
388
  v_flags = rb_hash_aref2(v_options, "flags");
337
389
  v_port = rb_hash_aref2(v_options, "port");
390
+ v_reuse_addr = rb_hash_aref2(v_options, "reuse_addr");
338
391
 
339
392
  if(NIL_P(v_port))
340
393
  port = 0;
@@ -349,23 +402,38 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
349
402
  if(NIL_P(v_addresses))
350
403
  num_ip = 1;
351
404
  else
352
- num_ip = RARRAY_LEN(v_addresses);
405
+ num_ip = (int)RARRAY_LEN(v_addresses);
406
+
407
+ if(num_ip > 8)
408
+ rb_raise(rb_eArgError, "too many IP addresses to bind, maximum is eight");
353
409
 
354
410
  domain = NUM2INT(rb_iv_get(self, "@domain"));
355
411
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
356
412
 
357
- if(num_ip > 1){
413
+ if(!NIL_P(v_addresses)){
358
414
  for(i = 0; i < num_ip; i++){
359
415
  v_address = RARRAY_PTR(v_addresses)[i];
360
416
  addrs[i].sin_family = domain;
361
417
  addrs[i].sin_port = htons(port);
362
418
  addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
419
+ #ifdef BSD
420
+ addrs[i].sin_len = sizeof(struct sockaddr_in);
421
+ #endif
363
422
  }
364
423
  }
365
424
  else{
366
425
  addrs[0].sin_family = domain;
367
426
  addrs[0].sin_port = htons(port);
368
427
  addrs[0].sin_addr.s_addr = htonl(INADDR_ANY);
428
+ #ifdef BSD
429
+ addrs[0].sin_len = sizeof(struct sockaddr_in);
430
+ #endif
431
+ }
432
+
433
+ if(v_reuse_addr == Qtrue){
434
+ on = 1;
435
+ if(setsockopt(fileno, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
436
+ rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
369
437
  }
370
438
 
371
439
  if(sctp_bindx(fileno, (struct sockaddr *) addrs, num_ip, flags) != 0)
@@ -427,7 +495,7 @@ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
427
495
 
428
496
  v_domain = rb_iv_get(self, "@domain");
429
497
 
430
- num_ip = RARRAY_LEN(v_addresses);
498
+ num_ip = (int)RARRAY_LEN(v_addresses);
431
499
  bzero(&addrs, sizeof(addrs));
432
500
 
433
501
  for(i = 0; i < num_ip; i++){
@@ -435,6 +503,9 @@ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
435
503
  addrs[i].sin_family = NUM2INT(v_domain);
436
504
  addrs[i].sin_port = htons(NUM2INT(v_port));
437
505
  addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
506
+ #ifdef BSD
507
+ addrs[i].sin_len = sizeof(struct sockaddr_in);
508
+ #endif
438
509
  }
439
510
 
440
511
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
@@ -453,15 +524,46 @@ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
453
524
  *
454
525
  * Close the socket. You should always do this.
455
526
  *
527
+ * By default the underlying close operation is non-blocking. This means that the
528
+ * bound IP addresses may not be available right away after closing. You may
529
+ * optionally control this behavior with the +linger+ option.
530
+ *
531
+ *
532
+ * * linger - If present, this should be set to a numeric value, in seconds.
533
+ * The value will cause the close operation to block for that number of
534
+ * seconds, after which it will return (i.e. return to non-blocking).
535
+ *
456
536
  * Example:
457
537
  *
458
538
  * socket = SCTP::Socket.new
459
- * socket.close
539
+ * socket.close # or
540
+ * socket.close(linger: 5)
460
541
  */
461
- static VALUE rsctp_close(VALUE self){
462
- VALUE v_fileno = rb_iv_get(self, "@fileno");
542
+ static VALUE rsctp_close(int argc, VALUE* argv, VALUE self){
543
+ VALUE v_options, v_linger;
544
+ int fileno;
545
+
546
+ rb_scan_args(argc, argv, "01", &v_options);
463
547
 
464
- if(close(NUM2INT(v_fileno)))
548
+ if(NIL_P(v_options))
549
+ v_options = rb_hash_new();
550
+
551
+ Check_Type(v_options, T_HASH);
552
+
553
+ v_linger = rb_hash_aref2(v_options, "linger");
554
+
555
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
556
+
557
+ if(!NIL_P(v_linger)){
558
+ struct linger lin;
559
+ lin.l_onoff = 1;
560
+ lin.l_linger = NUM2INT(v_linger);
561
+
562
+ if(setsockopt(fileno, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0)
563
+ rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
564
+ }
565
+
566
+ if(close(fileno))
465
567
  rb_raise(rb_eSystemCallError, "close: %s", strerror(errno));
466
568
 
467
569
  return self;
@@ -617,7 +719,8 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
617
719
  struct iovec iov[IOV_MAX];
618
720
  struct sockaddr_in* addrs;
619
721
  struct sctp_sendv_spa spa;
620
- int i, fileno, num_bytes, size, num_ip;
722
+ int i, fileno, size, num_ip;
723
+ ssize_t num_bytes;
621
724
 
622
725
  Check_Type(v_options, T_HASH);
623
726
 
@@ -632,7 +735,7 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
632
735
 
633
736
  if(!NIL_P(v_addresses)){
634
737
  Check_Type(v_addresses, T_ARRAY);
635
- num_ip = RARRAY_LEN(v_addresses);
738
+ num_ip = (int)RARRAY_LEN(v_addresses);
636
739
  addrs = (struct sockaddr_in*)alloca(num_ip * sizeof(*addrs));
637
740
  }
638
741
  else{
@@ -641,7 +744,7 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
641
744
  }
642
745
 
643
746
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
644
- size = RARRAY_LEN(v_message);
747
+ size = (int)RARRAY_LEN(v_message);
645
748
 
646
749
  if(!size)
647
750
  rb_raise(rb_eArgError, "Must contain at least one message");
@@ -650,6 +753,7 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
650
753
  rb_raise(rb_eArgError, "Array size is greater than IOV_MAX");
651
754
 
652
755
  // TODO: Make this configurable
756
+ spa.sendv_flags = SCTP_SEND_SNDINFO_VALID;
653
757
  spa.sendv_sndinfo.snd_flags = SCTP_UNORDERED;
654
758
  spa.sendv_sndinfo.snd_assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
655
759
 
@@ -671,6 +775,9 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
671
775
  addrs[i].sin_family = domain;
672
776
  addrs[i].sin_port = htons(port);
673
777
  addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
778
+ #ifdef BSD
779
+ addrs[i].sin_len = sizeof(struct sockaddr_in);
780
+ #endif
674
781
  }
675
782
  }
676
783
 
@@ -680,7 +787,7 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
680
787
  iov[i].iov_len = RSTRING_LEN(v_msg);
681
788
  }
682
789
 
683
- num_bytes = sctp_sendv(
790
+ num_bytes = (ssize_t)sctp_sendv(
684
791
  fileno,
685
792
  iov,
686
793
  size,
@@ -695,14 +802,15 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
695
802
  if(num_bytes < 0)
696
803
  rb_raise(rb_eSystemCallError, "sctp_sendv: %s", strerror(errno));
697
804
 
698
- return INT2NUM(num_bytes);
805
+ return LONG2NUM(num_bytes);
699
806
  }
700
807
  #endif
701
808
 
702
809
  #ifdef HAVE_SCTP_RECVV
703
810
  static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
704
811
  VALUE v_flags;
705
- int fileno, flags, bytes, on;
812
+ int fileno, flags, on;
813
+ ssize_t bytes;
706
814
  uint infotype;
707
815
  socklen_t infolen;
708
816
  struct iovec iov[1];
@@ -732,7 +840,7 @@ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
732
840
  infolen = sizeof(struct sctp_rcvinfo);
733
841
  infotype = 0;
734
842
 
735
- bytes = sctp_recvv(
843
+ bytes = (ssize_t)sctp_recvv(
736
844
  fileno,
737
845
  iov,
738
846
  1,
@@ -849,7 +957,7 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
849
957
 
850
958
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
851
959
 
852
- num_bytes = sctp_send(
960
+ num_bytes = (ssize_t)sctp_send(
853
961
  fileno,
854
962
  StringValueCStr(v_msg),
855
963
  RSTRING_LEN(v_msg),
@@ -860,7 +968,7 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
860
968
  if(num_bytes < 0)
861
969
  rb_raise(rb_eSystemCallError, "sctp_send: %s", strerror(errno));
862
970
 
863
- return INT2NUM(num_bytes);
971
+ return LONG2NUM(num_bytes);
864
972
  }
865
973
 
866
974
  /*
@@ -901,7 +1009,7 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
901
1009
  uint32_t ppid, flags, ttl, context;
902
1010
  ssize_t num_bytes;
903
1011
  struct sockaddr_in addrs[8];
904
- int fileno, size;
1012
+ int fileno, size, num_ip;
905
1013
 
906
1014
  Check_Type(v_options, T_HASH);
907
1015
 
@@ -944,10 +1052,10 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
944
1052
  context = NUM2INT(v_context);
945
1053
 
946
1054
  if(!NIL_P(v_addresses)){
947
- int i, num_ip, port;
1055
+ int i, port;
948
1056
  VALUE v_address, v_port;
949
1057
 
950
- num_ip = RARRAY_LEN(v_addresses);
1058
+ num_ip = (int)RARRAY_LEN(v_addresses);
951
1059
  v_port = rb_hash_aref2(v_options, "port");
952
1060
 
953
1061
  if(NIL_P(v_port))
@@ -960,17 +1068,51 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
960
1068
  addrs[i].sin_family = NUM2INT(rb_iv_get(self, "@domain"));
961
1069
  addrs[i].sin_port = htons(port);
962
1070
  addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
1071
+ #ifdef BSD
1072
+ addrs[i].sin_len = sizeof(struct sockaddr_in);
1073
+ #endif
963
1074
  }
964
1075
 
965
1076
  size = sizeof(addrs);
966
1077
  }
967
1078
  else{
1079
+ num_ip = 0;
968
1080
  size = 0;
969
1081
  }
970
1082
 
971
1083
  fileno = NUM2INT(rb_iv_get(self, "@fileno"));
972
1084
 
973
- num_bytes = sctp_sendmsg(
1085
+ #ifdef BSD
1086
+ if(num_ip){
1087
+ num_bytes = (ssize_t)sctp_sendmsgx(
1088
+ fileno,
1089
+ StringValueCStr(v_msg),
1090
+ RSTRING_LEN(v_msg),
1091
+ (struct sockaddr*)addrs,
1092
+ num_ip,
1093
+ ppid,
1094
+ flags,
1095
+ stream,
1096
+ ttl,
1097
+ context
1098
+ );
1099
+ }
1100
+ else{
1101
+ num_bytes = (ssize_t)sctp_sendmsg(
1102
+ fileno,
1103
+ StringValueCStr(v_msg),
1104
+ RSTRING_LEN(v_msg),
1105
+ (struct sockaddr*)addrs,
1106
+ size,
1107
+ ppid,
1108
+ flags,
1109
+ stream,
1110
+ ttl,
1111
+ context
1112
+ );
1113
+ }
1114
+ #else
1115
+ num_bytes = (ssize_t)sctp_sendmsg(
974
1116
  fileno,
975
1117
  StringValueCStr(v_msg),
976
1118
  RSTRING_LEN(v_msg),
@@ -982,11 +1124,20 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
982
1124
  ttl,
983
1125
  context
984
1126
  );
1127
+ #endif
985
1128
 
986
- if(num_bytes < 0)
1129
+ if(num_bytes < 0){
1130
+ #ifdef BSD
1131
+ if(num_ip > 0)
1132
+ rb_raise(rb_eSystemCallError, "sctp_sendmsgx: %s", strerror(errno));
1133
+ else
1134
+ rb_raise(rb_eSystemCallError, "sctp_sendmsg: %s", strerror(errno));
1135
+ #else
987
1136
  rb_raise(rb_eSystemCallError, "sctp_sendmsg: %s", strerror(errno));
1137
+ #endif
1138
+ }
988
1139
 
989
- return INT2NUM(num_bytes);
1140
+ return LONG2NUM(num_bytes);
990
1141
  }
991
1142
 
992
1143
  /*
@@ -1015,7 +1166,8 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
1015
1166
  VALUE v_flags, v_notification, v_message;
1016
1167
  struct sctp_sndrcvinfo sndrcvinfo;
1017
1168
  struct sockaddr_in clientaddr;
1018
- int flags, bytes, fileno;
1169
+ int flags, fileno;
1170
+ ssize_t bytes;
1019
1171
  char buffer[1024]; // TODO: Let this be configurable?
1020
1172
  socklen_t length;
1021
1173
 
@@ -1033,7 +1185,7 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
1033
1185
  bzero(&clientaddr, sizeof(clientaddr));
1034
1186
  bzero(&sndrcvinfo, sizeof(sndrcvinfo));
1035
1187
 
1036
- bytes = sctp_recvmsg(
1188
+ bytes = (ssize_t)sctp_recvmsg(
1037
1189
  fileno,
1038
1190
  buffer,
1039
1191
  sizeof(buffer),
@@ -1555,7 +1707,8 @@ static VALUE rsctp_get_subscriptions(VALUE self){
1555
1707
  if(sctp_opt_info(fileno, assoc_id, SCTP_EVENTS, (void*)&events, &size) < 0)
1556
1708
  rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1557
1709
 
1558
- return rb_struct_new(v_sctp_event_subscribe_struct,
1710
+ return rb_struct_new(
1711
+ v_sctp_event_subscribe_struct,
1559
1712
  (events.sctp_data_io_event ? Qtrue : Qfalse),
1560
1713
  (events.sctp_association_event ? Qtrue : Qfalse),
1561
1714
  (events.sctp_address_event ? Qtrue : Qfalse),
@@ -1565,11 +1718,19 @@ static VALUE rsctp_get_subscriptions(VALUE self){
1565
1718
  (events.sctp_partial_delivery_event ? Qtrue : Qfalse),
1566
1719
  (events.sctp_adaptation_layer_event ? Qtrue : Qfalse),
1567
1720
  (events.sctp_authentication_event ? Qtrue : Qfalse),
1568
- (events.sctp_sender_dry_event ? Qtrue : Qfalse),
1569
- (events.sctp_stream_reset_event ? Qtrue : Qfalse),
1570
- (events.sctp_assoc_reset_event ? Qtrue : Qfalse),
1571
- (events.sctp_stream_change_event ? Qtrue : Qfalse),
1572
- (events.sctp_send_failure_event_event ? Qtrue : Qfalse)
1721
+ (events.sctp_sender_dry_event ? Qtrue : Qfalse)
1722
+ #ifdef HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_STREAM_RESET_EVENT
1723
+ ,(events.sctp_stream_reset_event ? Qtrue : Qfalse)
1724
+ #endif
1725
+ #ifdef HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_ASSOC_RESET_EVENT
1726
+ ,(events.sctp_assoc_reset_event ? Qtrue : Qfalse)
1727
+ #endif
1728
+ #ifdef HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_STREAM_CHANGE_EVENT
1729
+ ,(events.sctp_stream_change_event ? Qtrue : Qfalse)
1730
+ #endif
1731
+ #ifdef HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_SEND_FAILURE_EVENT_EVENT
1732
+ ,(events.sctp_send_failure_event_event ? Qtrue : Qfalse)
1733
+ #endif
1573
1734
  );
1574
1735
  }
1575
1736
 
@@ -1724,6 +1885,40 @@ static VALUE rsctp_set_nodelay(VALUE self, VALUE v_bool){
1724
1885
  return Qfalse;
1725
1886
  }
1726
1887
 
1888
+ /*
1889
+ * call-seq:
1890
+ * SCTP::Socket#disable_fragments=(bool)
1891
+ *
1892
+ * This option is a on/off flag and is passed an integer where a non-
1893
+ * zero is on and a zero is off. If enabled no SCTP message
1894
+ * fragmentation will be performed. Instead if a message being sent
1895
+ * exceeds the current PMTU size, the message will NOT be sent and
1896
+ * instead a error will be indicated to the user.
1897
+ */
1898
+ static VALUE rsctp_disable_fragments(VALUE self, VALUE v_bool){
1899
+ int fileno;
1900
+ socklen_t size;
1901
+ sctp_assoc_t assoc_id;
1902
+ int value;
1903
+
1904
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1905
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1906
+ size = sizeof(int);
1907
+
1908
+ if(NIL_P(v_bool) || v_bool == Qfalse)
1909
+ value = 0;
1910
+ else
1911
+ value = 1;
1912
+
1913
+ if(sctp_opt_info(fileno, assoc_id, SCTP_DISABLE_FRAGMENTS, (void*)&value, &size) < 0)
1914
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1915
+
1916
+ if(value)
1917
+ return Qtrue;
1918
+ else
1919
+ return Qfalse;
1920
+ }
1921
+
1727
1922
  /*
1728
1923
  * call-seq:
1729
1924
  * SCTP::Socket#autoclose
@@ -1845,7 +2040,8 @@ static VALUE rsctp_enable_auth_support(int argc, VALUE* argv, VALUE self){
1845
2040
  * otherwise this will set a key on the endpoint.
1846
2041
  */
1847
2042
  static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
1848
- int fileno, len;
2043
+ int fileno;
2044
+ size_t len;
1849
2045
  char* key;
1850
2046
  uint keynum;
1851
2047
  socklen_t size;
@@ -1860,7 +2056,7 @@ static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
1860
2056
  len = strlen(key);
1861
2057
  unsigned char byte_array[len+1];
1862
2058
 
1863
- for(int i = 0; i < len; i++)
2059
+ for(size_t i = 0; i < len; i++)
1864
2060
  byte_array[i] = key[i];
1865
2061
 
1866
2062
  byte_array[len] = '\0';
@@ -2161,9 +2357,10 @@ void Init_socket(void){
2161
2357
 
2162
2358
  rb_define_method(cSocket, "autoclose=", rsctp_set_autoclose, 1);
2163
2359
  rb_define_method(cSocket, "bindx", rsctp_bindx, -1);
2164
- rb_define_method(cSocket, "close", rsctp_close, 0);
2360
+ rb_define_method(cSocket, "close", rsctp_close, -1);
2165
2361
  rb_define_method(cSocket, "connectx", rsctp_connectx, -1);
2166
2362
  rb_define_method(cSocket, "delete_shared_key", rsctp_delete_shared_key, -1);
2363
+ rb_define_method(cSocket, "disable_fragments=", rsctp_disable_fragments, 1);
2167
2364
  rb_define_method(cSocket, "enable_auth_support", rsctp_enable_auth_support, -1);
2168
2365
  rb_define_method(cSocket, "getpeernames", rsctp_getpeernames, -1);
2169
2366
  rb_define_method(cSocket, "getlocalnames", rsctp_getlocalnames, -1);
@@ -2206,8 +2403,8 @@ void Init_socket(void){
2206
2403
  rb_define_attr(cSocket, "association_id", 1, 1);
2207
2404
  rb_define_attr(cSocket, "port", 1, 1);
2208
2405
 
2209
- /* 0.1.1: The version of this library */
2210
- rb_define_const(cSocket, "VERSION", rb_str_new2("0.1.1"));
2406
+ /* 0.1.3: The version of this library */
2407
+ rb_define_const(cSocket, "VERSION", rb_str_new2("0.1.3"));
2211
2408
 
2212
2409
  /* send flags */
2213
2410
 
@@ -2230,7 +2427,9 @@ void Init_socket(void){
2230
2427
 
2231
2428
  // ASSOCIATION STATES //
2232
2429
 
2430
+ #ifdef HAVE_SCTP_EMPTY
2233
2431
  rb_define_const(cSocket, "SCTP_EMPTY", INT2NUM(SCTP_EMPTY));
2432
+ #endif
2234
2433
  rb_define_const(cSocket, "SCTP_CLOSED", INT2NUM(SCTP_CLOSED));
2235
2434
  rb_define_const(cSocket, "SCTP_COOKIE_WAIT", INT2NUM(SCTP_COOKIE_WAIT));
2236
2435
  rb_define_const(cSocket, "SCTP_COOKIE_ECHOED", INT2NUM(SCTP_COOKIE_ECHOED));
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.1.1'
3
+ spec.version = '0.1.3'
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,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sctp-socket
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Berger
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain:
11
11
  - |
@@ -35,7 +35,7 @@ cert_chain:
35
35
  ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
36
36
  WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
37
37
  -----END CERTIFICATE-----
38
- date: 2025-01-01 00:00:00.000000000 Z
38
+ date: 2025-01-22 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: bundler
@@ -133,7 +133,7 @@ metadata:
133
133
  wiki_uri: https://github.com/djberg96/sctp-socket/wiki
134
134
  rubygems_mfa_required: 'true'
135
135
  funding_uri: https://github.com/sponsors/djberg96
136
- post_install_message:
136
+ post_install_message:
137
137
  rdoc_options: []
138
138
  require_paths:
139
139
  - lib
@@ -149,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
149
  version: '0'
150
150
  requirements: []
151
151
  rubygems_version: 3.5.22
152
- signing_key:
152
+ signing_key:
153
153
  specification_version: 4
154
154
  summary: Ruby bindings for SCTP sockets
155
155
  test_files: []
metadata.gz.sig CHANGED
Binary file