sctp-socket 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a4c2e587ffc98a2c81d1d2a267fa4936539dc2456a9106a0146f31275e6db21
4
- data.tar.gz: e5aa191fd3beb57240128ef58ef82df8f3b6beba3c25a5b357bc9b5effc7c238
3
+ metadata.gz: a483264dd5712655f641ade00e03177756f25340c2fd398bed3ad453bc6a9cdb
4
+ data.tar.gz: 719857e2ce3a5db341aa317f23ec0bf2fa674dd9b427b502f99e3515cb786dac
5
5
  SHA512:
6
- metadata.gz: d023d5c17b03912812d02c8cb58279b5c874c45c481bdc1cd685dd89e8f2d62565512675d2cdc89f5e6b8107dce42634a3a1b4a063df8a6b32fed6762029adb4
7
- data.tar.gz: 900e6fb83030d63453d99f9046942b2e6dfaee4340615d668669a922abc5628f58056aa464c9f36fe974ac0cccec4f3699fee7211778b6e49f49d856d7ea002d
6
+ metadata.gz: 3dd98e9076f37396a55339fa20f1097ab5c582a418d885d8599b320b5cf722acb3c296b8afb798faadbee67519ee9368e87596c60d8658ef35a23a01d76c0d82
7
+ data.tar.gz: 4c7adf403e6075eb53129e9f4b92a97e3887518afa15458bf8b74fa7765478c54001d5f5f6cd997c2a4e44e1cba8783ee329ff9c3125f62fb9ae87e53c7e06b7
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGES.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## 0.1.0 - 31-May-2024
2
+ * Added support for sender dry events.
3
+ * Added the get_peer_address_params method.
4
+ * Comments were added to methods that were missing them.
5
+ * Remove version locking for dev dependencies, doesn't matter to me.
6
+ * Bumped version to 0.1.0, I guess I'll declare it stable.
7
+
8
+ ## 0.0.7 - 28-May-2024
9
+ * Added the recvv method.
10
+ * The getlocalnames and getpeernames methods now accept optional fileno and
11
+ association ID arguments.
12
+ * The peeloff method now returns the peeled off fileno and no longer modifies
13
+ the receiver, so I dropped the exclamation point from the method name.
14
+ * Added the get_subscriptions method.
15
+ * Changed bind method to bindx and connect method to connectx. I may try to
16
+ subclass Socket someday so I didn't want a conflict, and this more closely
17
+ matches the underlying function name anyway.
18
+ * Changed the sock_fd method to fileno.
19
+ * Changed the default backlog from 1024 to 128 for the listen method.
20
+ * Updated comments and documentation.
21
+ * Added more specs.
22
+
1
23
  ## 0.0.6 - 24-May-2024
2
24
  * Fixup the sendv method and add some documentation.
3
25
  * Added documentation to the get_status method.
data/README.md CHANGED
@@ -39,7 +39,7 @@ require 'sctp/socket'
39
39
  begin
40
40
  port = 62324
41
41
  socket = SCTP::Socket.new
42
- socket.bind(:port => port, :addresses => ['10.0.5.4', '10.0.6.4'])
42
+ socket.bindx(:port => port, :addresses => ['10.0.5.4', '10.0.6.4'])
43
43
  socket.set_initmsg(:output_streams => 5, :input_streams => 5, :max_attempts => 4)
44
44
  socket.subscribe(:data_io => true)
45
45
  socket.listen
@@ -10,10 +10,11 @@ begin
10
10
  socket = SCTP::Socket.new
11
11
 
12
12
  # Optional, but could bind to a subset of available addresses
13
- p socket.bind(:addresses => addresses)
13
+ p socket.bindx(:addresses => addresses)
14
14
 
15
15
  # Initial connection
16
- p socket.connect(:addresses => addresses, :port => port)
16
+ p socket.connectx(:addresses => addresses, :port => port)
17
+ p socket.get_status
17
18
 
18
19
  # Try a sendv
19
20
  p socket.sendv(:message => ["Hello ", "World!"])
@@ -23,7 +23,7 @@ addresses = ['1.1.1.1', '1.1.1.2']
23
23
  begin
24
24
  port = 62324
25
25
  socket = SCTP::Socket.new
26
- socket.bind(:port => port, :addresses => addresses)
26
+ socket.bindx(:port => port, :addresses => addresses)
27
27
  socket.set_initmsg(:output_streams => 5, :input_streams => 5, :max_attempts => 4)
28
28
  socket.subscribe(:data_io => true, :shutdown => true, :send_failure => true, :partial_delivery => true)
29
29
  socket.listen
data/ext/sctp/extconf.rb CHANGED
@@ -26,5 +26,6 @@ end
26
26
 
27
27
  have_library('sctp')
28
28
  have_func('sctp_sendv', 'netinet/sctp.h')
29
+ have_func('sctp_recvv', 'netinet/sctp.h')
29
30
  have_struct_member('struct sctp_event_subscribe', 'sctp_send_failure_event', 'netinet/sctp.h')
30
31
  create_makefile('sctp/socket')
data/ext/sctp/socket.c CHANGED
@@ -21,6 +21,10 @@ VALUE v_sctp_status_struct;
21
21
  VALUE v_sctp_rtoinfo_struct;
22
22
  VALUE v_sctp_associnfo_struct;
23
23
  VALUE v_sctp_default_send_params_struct;
24
+ VALUE v_sctp_event_subscribe_struct;
25
+ VALUE v_sctp_receive_info_struct;
26
+ VALUE v_sctp_peer_addr_params_struct;
27
+ VALUE v_sender_dry_event_struct;
24
28
 
25
29
  #if !defined(IOV_MAX)
26
30
  #if defined(_SC_IOV_MAX)
@@ -77,7 +81,7 @@ VALUE rb_hash_aref2(VALUE v_hash, const char* key){
77
81
  * socket2 = SCTP::Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
78
82
  */
79
83
  static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
80
- int sock_fd;
84
+ int fileno;
81
85
  VALUE v_domain, v_type;
82
86
 
83
87
  rb_scan_args(argc, argv, "02", &v_domain, &v_type);
@@ -88,14 +92,14 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
88
92
  if(NIL_P(v_type))
89
93
  v_type = INT2NUM(SOCK_SEQPACKET);
90
94
 
91
- sock_fd = socket(NUM2INT(v_domain), NUM2INT(v_type), IPPROTO_SCTP);
95
+ fileno = socket(NUM2INT(v_domain), NUM2INT(v_type), IPPROTO_SCTP);
92
96
 
93
- if(sock_fd < 0)
97
+ if(fileno < 0)
94
98
  rb_raise(rb_eSystemCallError, "socket: %s", strerror(errno));
95
99
 
96
100
  rb_iv_set(self, "@domain", v_domain);
97
101
  rb_iv_set(self, "@type", v_type);
98
- rb_iv_set(self, "@sock_fd", INT2NUM(sock_fd));
102
+ rb_iv_set(self, "@fileno", INT2NUM(fileno));
99
103
  rb_iv_set(self, "@association_id", INT2NUM(0));
100
104
 
101
105
  return self;
@@ -114,19 +118,19 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
114
118
  * socket = SCTP::Socket.new
115
119
  *
116
120
  * # Bind 2 addresses
117
- * socket.bind(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
121
+ * socket.bindx(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
118
122
  *
119
123
  * # Remove 1 later
120
- * socket.bind(:addresses => ['10.0.4.5'], :flags => SCTP::Socket::BINDX_REM_ADDR)
124
+ * socket.bindx(:addresses => ['10.0.4.5'], :flags => SCTP::Socket::BINDX_REM_ADDR)
121
125
  *
122
126
  * If no addresses are specified, then it will bind to all available interfaces. If
123
127
  * no port is specified, then one will be assigned by the host.
124
128
  *
125
129
  * Returns the port that it was bound to.
126
130
  */
127
- static VALUE rsctp_bind(int argc, VALUE* argv, VALUE self){
131
+ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
128
132
  struct sockaddr_in addrs[8];
129
- int i, sock_fd, num_ip, flags, domain, port;
133
+ int i, fileno, num_ip, flags, domain, port;
130
134
  VALUE v_addresses, v_port, v_flags, v_address, v_options;
131
135
 
132
136
  rb_scan_args(argc, argv, "01", &v_options);
@@ -156,7 +160,7 @@ static VALUE rsctp_bind(int argc, VALUE* argv, VALUE self){
156
160
  num_ip = RARRAY_LEN(v_addresses);
157
161
 
158
162
  domain = NUM2INT(rb_iv_get(self, "@domain"));
159
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
163
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
160
164
 
161
165
  if(num_ip > 1){
162
166
  for(i = 0; i < num_ip; i++){
@@ -172,14 +176,15 @@ static VALUE rsctp_bind(int argc, VALUE* argv, VALUE self){
172
176
  addrs[0].sin_addr.s_addr = htonl(INADDR_ANY);
173
177
  }
174
178
 
175
- if(sctp_bindx(sock_fd, (struct sockaddr *) addrs, num_ip, flags) != 0)
179
+ if(sctp_bindx(fileno, (struct sockaddr *) addrs, num_ip, flags) != 0)
176
180
  rb_raise(rb_eSystemCallError, "sctp_bindx: %s", strerror(errno));
177
181
 
178
182
  if(port == 0){
179
183
  struct sockaddr_in sin;
180
184
  socklen_t len = sizeof(sin);
185
+ bzero(&sin, len);
181
186
 
182
- if(getsockname(sock_fd, (struct sockaddr *)&sin, &len) == -1)
187
+ if(getsockname(fileno, (struct sockaddr *)&sin, &len) == -1)
183
188
  rb_raise(rb_eSystemCallError, "getsockname: %s", strerror(errno));
184
189
 
185
190
  port = sin.sin_port;
@@ -197,13 +202,13 @@ static VALUE rsctp_bind(int argc, VALUE* argv, VALUE self){
197
202
  * Example:
198
203
  *
199
204
  * socket = SCTP::Socket.new
200
- * socket.connect(:port => 62354, :addresses => ['10.0.4.5', '10.0.5.5'])
205
+ * socket.connectx(:port => 62354, :addresses => ['10.0.4.5', '10.0.5.5'])
201
206
  *
202
207
  * Note that this will also set/update the object's association_id.
203
208
  */
204
- static VALUE rsctp_connect(int argc, VALUE* argv, VALUE self){
209
+ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
205
210
  struct sockaddr_in addrs[8];
206
- int i, num_ip, sock_fd;
211
+ int i, num_ip, fileno;
207
212
  sctp_assoc_t assoc;
208
213
  VALUE v_address, v_domain, v_options, v_addresses, v_port;
209
214
 
@@ -235,9 +240,9 @@ static VALUE rsctp_connect(int argc, VALUE* argv, VALUE self){
235
240
  addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
236
241
  }
237
242
 
238
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
243
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
239
244
 
240
- if(sctp_connectx(sock_fd, (struct sockaddr *) addrs, num_ip, &assoc) < 0)
245
+ if(sctp_connectx(fileno, (struct sockaddr *) addrs, num_ip, &assoc) < 0)
241
246
  rb_raise(rb_eSystemCallError, "sctp_connectx: %s", strerror(errno));
242
247
 
243
248
  rb_iv_set(self, "@association_id", INT2NUM(assoc));
@@ -254,30 +259,55 @@ static VALUE rsctp_connect(int argc, VALUE* argv, VALUE self){
254
259
  * socket.close
255
260
  */
256
261
  static VALUE rsctp_close(VALUE self){
257
- VALUE v_sock_fd = rb_iv_get(self, "@sock_fd");
262
+ VALUE v_fileno = rb_iv_get(self, "@fileno");
258
263
 
259
- if(close(NUM2INT(v_sock_fd)))
264
+ if(close(NUM2INT(v_fileno)))
260
265
  rb_raise(rb_eSystemCallError, "close: %s", strerror(errno));
261
266
 
262
267
  return self;
263
268
  }
264
269
 
265
270
  /*
266
- * Return an array of all addresses of a peer.
271
+ * Return an array of all addresses of a peer of the current socket
272
+ * and association number.
273
+ *
274
+ * You may optionally pass a assocation fileno and association ID. Typically
275
+ * this information would come from the peeloff method.
276
+ *
277
+ * Example:
278
+ *
279
+ * socket = SCTP::Socket.new
280
+ * # ...
281
+ * p socket.getpeernames
282
+ *
283
+ * info = socket.recvmsg
284
+ * association_fileno = socket.peeloff(info.association_id)
285
+ *
286
+ * p socket.getpeernames(association_fileno, info.association_id)
267
287
  */
268
- static VALUE rsctp_getpeernames(VALUE self){
288
+ static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
269
289
  sctp_assoc_t assoc_id;
270
290
  struct sockaddr* addrs;
271
- int i, sock_fd, num_addrs;
291
+ int i, fileno, num_addrs;
272
292
  char str[16];
293
+ VALUE v_fileno, v_association_id;
273
294
  VALUE v_array = rb_ary_new();
274
295
 
275
296
  bzero(&addrs, sizeof(addrs));
276
297
 
277
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
278
- assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
298
+ rb_scan_args(argc, argv, "02", &v_fileno, &v_association_id);
279
299
 
280
- num_addrs = sctp_getpaddrs(sock_fd, assoc_id, &addrs);
300
+ if(NIL_P(v_fileno))
301
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
302
+ else
303
+ fileno = NUM2INT(v_fileno);
304
+
305
+ if(NIL_P(v_association_id))
306
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
307
+ else
308
+ assoc_id = NUM2INT(v_association_id);
309
+
310
+ num_addrs = sctp_getpaddrs(fileno, assoc_id, &addrs);
281
311
 
282
312
  if(num_addrs < 0){
283
313
  sctp_freepaddrs(addrs);
@@ -303,20 +333,35 @@ static VALUE rsctp_getpeernames(VALUE self){
303
333
  * socket = SCTP::Socket.new
304
334
  * socket.bind(:addresses => ['10.0.4.5', '10.0.5.5'])
305
335
  * socket.getlocalnames # => ['10.0.4.5', '10.0.5.5'])
336
+ *
337
+ * # or get info from a peeled off association...
338
+ *
339
+ * assoc_fileno = socket.peeloff(some_association_id)
340
+ * socket.getlocalnames(assoc_fileno, some_association_id)
306
341
  */
307
- static VALUE rsctp_getlocalnames(VALUE self){
342
+ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
308
343
  sctp_assoc_t assoc_id;
309
344
  struct sockaddr* addrs;
310
- int i, sock_fd, num_addrs;
345
+ int i, fileno, num_addrs;
311
346
  char str[16];
347
+ VALUE v_assoc_fileno, v_assoc_id;
312
348
  VALUE v_array = rb_ary_new();
313
349
 
314
350
  bzero(&addrs, sizeof(addrs));
315
351
 
316
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
317
- assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
352
+ rb_scan_args(argc, argv, "02", &v_assoc_fileno, &v_assoc_id);
318
353
 
319
- num_addrs = sctp_getladdrs(sock_fd, assoc_id, &addrs);
354
+ if(NIL_P(v_assoc_fileno))
355
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
356
+ else
357
+ fileno = NUM2INT(v_assoc_fileno);
358
+
359
+ if(NIL_P(v_assoc_id))
360
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
361
+ else
362
+ assoc_id = NUM2INT(v_assoc_id);
363
+
364
+ num_addrs = sctp_getladdrs(fileno, assoc_id, &addrs);
320
365
 
321
366
  if(num_addrs < 0){
322
367
  sctp_freeladdrs(addrs);
@@ -362,7 +407,7 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
362
407
  struct iovec iov[IOV_MAX];
363
408
  struct sockaddr_in* addrs;
364
409
  struct sctp_sndinfo info;
365
- int i, sock_fd, num_bytes, size, num_ip;
410
+ int i, fileno, num_bytes, size, num_ip;
366
411
 
367
412
  Check_Type(v_options, T_HASH);
368
413
 
@@ -385,7 +430,7 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
385
430
  num_ip = 0;
386
431
  }
387
432
 
388
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
433
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
389
434
  size = RARRAY_LEN(v_message);
390
435
 
391
436
  if(!size)
@@ -424,7 +469,7 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
424
469
  }
425
470
 
426
471
  num_bytes = sctp_sendv(
427
- sock_fd,
472
+ fileno,
428
473
  iov,
429
474
  size,
430
475
  (struct sockaddr*)addrs,
@@ -442,6 +487,74 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
442
487
  }
443
488
  #endif
444
489
 
490
+ #ifdef HAVE_SCTP_RECVV
491
+ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
492
+ VALUE v_flags;
493
+ int fileno, flags, bytes, on;
494
+ uint infotype;
495
+ socklen_t infolen;
496
+ struct iovec iov[1];
497
+ struct sctp_rcvinfo info;
498
+ char buffer[1024];
499
+
500
+ bzero(&iov, sizeof(iov));
501
+ bzero(&info, sizeof(info));
502
+ bzero(&buffer, sizeof(buffer));
503
+
504
+ iov->iov_base = buffer;
505
+ iov->iov_len = sizeof(buffer);
506
+
507
+ rb_scan_args(argc, argv, "01", &v_flags);
508
+
509
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
510
+
511
+ if(NIL_P(v_flags))
512
+ flags = 0;
513
+ else
514
+ flags = NUM2INT(v_flags);
515
+
516
+ on = 1;
517
+ if(setsockopt(fileno, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(on)) < 0)
518
+ rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
519
+
520
+ infolen = sizeof(struct sctp_rcvinfo);
521
+ infotype = 0;
522
+
523
+ bytes = sctp_recvv(
524
+ fileno,
525
+ iov,
526
+ 1,
527
+ NULL,
528
+ NULL,
529
+ &info,
530
+ &infolen,
531
+ &infotype,
532
+ &flags
533
+ );
534
+
535
+ if(bytes < 0)
536
+ rb_raise(rb_eSystemCallError, "sctp_recvv: %s", strerror(errno));
537
+
538
+ if(infotype != SCTP_RECVV_RCVINFO){
539
+ return Qnil;
540
+ }
541
+ else{
542
+ return rb_struct_new(
543
+ v_sctp_receive_info_struct,
544
+ rb_str_new2(iov->iov_base),
545
+ UINT2NUM(info.rcv_sid),
546
+ UINT2NUM(info.rcv_ssn),
547
+ UINT2NUM(info.rcv_flags),
548
+ UINT2NUM(info.rcv_ppid),
549
+ UINT2NUM(info.rcv_tsn),
550
+ UINT2NUM(info.rcv_cumtsn),
551
+ UINT2NUM(info.rcv_context),
552
+ UINT2NUM(info.rcv_assoc_id)
553
+ );
554
+ }
555
+ }
556
+ #endif
557
+
445
558
  /*
446
559
  * Send a message on an already-connected socket to a specific association.
447
560
  *
@@ -458,7 +571,7 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
458
571
  uint16_t stream;
459
572
  uint32_t ppid, send_flags, ctrl_flags, ttl, context;
460
573
  ssize_t num_bytes;
461
- int sock_fd;
574
+ int fileno;
462
575
  sctp_assoc_t assoc_id;
463
576
  struct sctp_sndrcvinfo info;
464
577
  VALUE v_msg, v_stream, v_ppid, v_context, v_send_flags, v_ctrl_flags, v_ttl, v_assoc_id;
@@ -519,10 +632,10 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
519
632
  info.sinfo_timetolive = ttl;
520
633
  info.sinfo_assoc_id = assoc_id;
521
634
 
522
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
635
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
523
636
 
524
637
  num_bytes = sctp_send(
525
- sock_fd,
638
+ fileno,
526
639
  StringValueCStr(v_msg),
527
640
  RSTRING_LEN(v_msg),
528
641
  &info,
@@ -570,7 +683,7 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
570
683
  uint32_t ppid, flags, ttl, context;
571
684
  ssize_t num_bytes;
572
685
  struct sockaddr_in addrs[8];
573
- int sock_fd, size;
686
+ int fileno, size;
574
687
 
575
688
  Check_Type(v_options, T_HASH);
576
689
 
@@ -637,10 +750,10 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
637
750
  size = 0;
638
751
  }
639
752
 
640
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
753
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
641
754
 
642
755
  num_bytes = sctp_sendmsg(
643
- sock_fd,
756
+ fileno,
644
757
  StringValueCStr(v_msg),
645
758
  RSTRING_LEN(v_msg),
646
759
  (struct sockaddr*)addrs,
@@ -681,7 +794,7 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
681
794
  VALUE v_flags, v_notification, v_message;
682
795
  struct sctp_sndrcvinfo sndrcvinfo;
683
796
  struct sockaddr_in clientaddr;
684
- int flags, bytes, sock_fd;
797
+ int flags, bytes, fileno;
685
798
  char buffer[1024]; // TODO: Let this be configurable?
686
799
  socklen_t length;
687
800
 
@@ -692,7 +805,7 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
692
805
  else
693
806
  flags = NUM2INT(v_flags);
694
807
 
695
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
808
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
696
809
  length = sizeof(struct sockaddr_in);
697
810
 
698
811
  bzero(buffer, sizeof(buffer));
@@ -700,7 +813,7 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
700
813
  bzero(&sndrcvinfo, sizeof(sndrcvinfo));
701
814
 
702
815
  bytes = sctp_recvmsg(
703
- sock_fd,
816
+ fileno,
704
817
  buffer,
705
818
  sizeof(buffer),
706
819
  (struct sockaddr*)&clientaddr,
@@ -803,6 +916,7 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
803
916
 
804
917
  v_notification = rb_struct_new(v_remote_error_struct,
805
918
  UINT2NUM(snp->sn_remote_error.sre_type),
919
+ UINT2NUM(snp->sn_remote_error.sre_flags),
806
920
  UINT2NUM(snp->sn_remote_error.sre_length),
807
921
  UINT2NUM(snp->sn_remote_error.sre_error),
808
922
  UINT2NUM(snp->sn_remote_error.sre_assoc_id),
@@ -884,6 +998,14 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
884
998
  UINT2NUM(snp->sn_authkey_event.auth_assoc_id)
885
999
  );
886
1000
  break;
1001
+ case SCTP_SENDER_DRY_EVENT:
1002
+ v_notification = rb_struct_new(v_sender_dry_event_struct,
1003
+ UINT2NUM(snp->sn_sender_dry_event.sender_dry_type),
1004
+ UINT2NUM(snp->sn_sender_dry_event.sender_dry_flags),
1005
+ UINT2NUM(snp->sn_sender_dry_event.sender_dry_length),
1006
+ UINT2NUM(snp->sn_sender_dry_event.sender_dry_assoc_id)
1007
+ );
1008
+ break;
887
1009
  }
888
1010
  }
889
1011
 
@@ -915,15 +1037,15 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
915
1037
  *
916
1038
  * The following parameters can be configured:
917
1039
  *
918
- * :output_streams - The number of outbound SCTP streams an application would like to request.
919
- * :input_streams - The maximum number of inbound streams an application is prepared to allow.
920
- * :max_attempts - How many times the the SCTP stack should send the initial INIT message before it's considered unreachable.
921
- * :timeout - The maximum RTO value for the INIT timer.
1040
+ * :output_streams - The number of outbound SCTP streams an application would like to request.
1041
+ * :input_streams - The maximum number of inbound streams an application is prepared to allow.
1042
+ * :max_attempts - How many times the the SCTP stack should send the initial INIT message before it's considered unreachable.
1043
+ * :timeout - The maximum RTO value for the INIT timer.
922
1044
  *
923
1045
  * By default these values are set to zero (i.e. ignored).
924
1046
  */
925
1047
  static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
926
- int sock_fd;
1048
+ int fileno;
927
1049
  struct sctp_initmsg initmsg;
928
1050
  VALUE v_output, v_input, v_attempts, v_timeout;
929
1051
 
@@ -934,7 +1056,7 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
934
1056
  v_attempts = rb_hash_aref2(v_options, "max_attempts");
935
1057
  v_timeout = rb_hash_aref2(v_options, "timeout");
936
1058
 
937
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1059
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
938
1060
 
939
1061
  if(!NIL_P(v_output))
940
1062
  initmsg.sinit_num_ostreams = NUM2INT(v_output);
@@ -948,15 +1070,15 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
948
1070
  if(!NIL_P(v_timeout))
949
1071
  initmsg.sinit_max_init_timeo = NUM2INT(v_timeout);
950
1072
 
951
- if(setsockopt(sock_fd, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg)) < 0)
1073
+ if(setsockopt(fileno, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg)) < 0)
952
1074
  rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
953
1075
 
954
1076
  return self;
955
1077
  }
956
1078
 
957
1079
  /*
958
- * Subscribe to various notification types, which will generate additional
959
- * data that the socket may receive. The possible notification types are
1080
+ * Subscribe to various notification type events, which will generate additional
1081
+ * data that the socket may receive. The possible notification type events are
960
1082
  * as follows:
961
1083
  *
962
1084
  * :association
@@ -979,11 +1101,8 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
979
1101
  * :adaptation
980
1102
  * :authentication
981
1103
  * :partial_delivery
982
- *
983
- * Not yet supported:
984
- *
985
1104
  * :sender_dry
986
- * :peer_error
1105
+ * :peer_error (aka remote error)
987
1106
  *
988
1107
  * Example:
989
1108
  *
@@ -993,11 +1112,13 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
993
1112
  * socket.subscribe(:data_io => true, :shutdown => true, :send_failure => true)
994
1113
  */
995
1114
  static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
996
- int sock_fd;
1115
+ int fileno;
997
1116
  struct sctp_event_subscribe events;
998
1117
 
999
1118
  bzero(&events, sizeof(events));
1000
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1119
+ Check_Type(v_options, T_HASH);
1120
+
1121
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1001
1122
 
1002
1123
  if(RTEST(rb_hash_aref2(v_options, "data_io")))
1003
1124
  events.sctp_data_io_event = 1;
@@ -1033,7 +1154,7 @@ static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
1033
1154
  if(RTEST(rb_hash_aref2(v_options, "sender_dry")))
1034
1155
  events.sctp_sender_dry_event = 1;
1035
1156
 
1036
- if(setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)) < 0)
1157
+ if(setsockopt(fileno, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)) < 0)
1037
1158
  rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
1038
1159
 
1039
1160
  return self;
@@ -1044,29 +1165,39 @@ static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
1044
1165
  * will be used to accept incoming connection requests.
1045
1166
  *
1046
1167
  * The backlog argument defines the maximum length to which the queue of
1047
- * pending connections for sockfd may grow. The default is 1024.
1168
+ * pending connections for sockfd may grow. The default value is 128. The
1169
+ * maximum value is Socket::SOMAXCONN.
1170
+ *
1171
+ * Why a default of 128? The answer is a "best guess" compromise between
1172
+ * handling server load versus avoiding SYN flood attacks. I leave it as an
1173
+ * exercise to the programmer to adjust as desired.
1174
+ *
1175
+ * See https://tangentsoft.com/wskfaq/advanced.html#backlog if you want
1176
+ * more details on the advantages and drawbacks of various values.
1048
1177
  *
1049
1178
  * Example:
1050
1179
  *
1051
1180
  * socket = SCTP::Socket.new
1052
1181
  * socket.bind(:port => 62534, :addresses => ['127.0.0.1'])
1053
1182
  * socket.listen
1054
- *
1055
1183
  */
1056
1184
  static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
1057
1185
  VALUE v_backlog;
1058
- int backlog, sock_fd;
1186
+ int backlog, fileno;
1059
1187
 
1060
1188
  rb_scan_args(argc, argv, "01", &v_backlog);
1061
1189
 
1062
1190
  if(NIL_P(v_backlog))
1063
- backlog = 1024;
1191
+ backlog = 128;
1064
1192
  else
1065
1193
  backlog = NUM2INT(v_backlog);
1066
1194
 
1067
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1195
+ if(backlog > SOMAXCONN)
1196
+ rb_raise(rb_eArgError, "backlog value exceeds maximum value of: %i", SOMAXCONN);
1197
+
1198
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1068
1199
 
1069
- if(listen(sock_fd, backlog) < 0)
1200
+ if(listen(fileno, backlog) < 0)
1070
1201
  rb_raise(rb_eSystemCallError, "listen: %s", strerror(errno));
1071
1202
 
1072
1203
  return self;
@@ -1074,38 +1205,62 @@ static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
1074
1205
 
1075
1206
  /*
1076
1207
  * Extracts an association contained by a one-to-many socket connection into
1077
- * a one-to-one style socket. Note that this modifies the underlying sock_fd.
1208
+ * a one-to-one style socket. Returns the socket descriptor (fileno).
1209
+ *
1210
+ * Example:
1211
+ *
1212
+ * socket = SCTP::Socket.new
1213
+ * # etc...
1214
+ *
1215
+ * while true
1216
+ * info = socket.recvmsg
1217
+ * assoc_fileno = socket.peeloff(info.association_id)
1218
+ * # ... Do something with this new fileno
1219
+ * end
1078
1220
  */
1079
1221
  static VALUE rsctp_peeloff(VALUE self, VALUE v_assoc_id){
1080
- int sock_fd, new_sock_fd;
1222
+ int fileno, assoc_fileno;
1081
1223
  sctp_assoc_t assoc_id;
1082
1224
 
1083
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1225
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1084
1226
  assoc_id = NUM2INT(v_assoc_id);
1085
1227
 
1086
- new_sock_fd = sctp_peeloff(sock_fd, assoc_id);
1228
+ assoc_fileno = sctp_peeloff(fileno, assoc_id);
1087
1229
 
1088
- if(new_sock_fd < 0)
1230
+ if(assoc_fileno < 0)
1089
1231
  rb_raise(rb_eSystemCallError, "sctp_peeloff: %s", strerror(errno));
1090
1232
 
1091
- rb_iv_set(self, "@sock_fd", INT2NUM(new_sock_fd));
1092
-
1093
- return self;
1233
+ return INT2NUM(assoc_fileno);
1094
1234
  }
1095
1235
 
1236
+ /*
1237
+ * Returns the default set of parameters that a call to the sendto function
1238
+ * uses on this association. This is a struct that contains the following
1239
+ * members:
1240
+ *
1241
+ * * stream
1242
+ * * ssn
1243
+ * * flags
1244
+ * * ppid
1245
+ * * context
1246
+ * * ttl
1247
+ * * tsn
1248
+ * * cumtsn
1249
+ * * association_id
1250
+ */
1096
1251
  static VALUE rsctp_get_default_send_params(VALUE self){
1097
- int sock_fd;
1252
+ int fileno;
1098
1253
  socklen_t size;
1099
1254
  sctp_assoc_t assoc_id;
1100
1255
  struct sctp_sndrcvinfo sndrcv;
1101
1256
 
1102
1257
  bzero(&sndrcv, sizeof(sndrcv));
1103
1258
 
1104
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1259
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1105
1260
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1106
1261
  size = sizeof(struct sctp_sndrcvinfo);
1107
1262
 
1108
- if(sctp_opt_info(sock_fd, assoc_id, SCTP_DEFAULT_SEND_PARAM, (void*)&sndrcv, &size) < 0)
1263
+ if(sctp_opt_info(fileno, assoc_id, SCTP_DEFAULT_SEND_PARAM, (void*)&sndrcv, &size) < 0)
1109
1264
  rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1110
1265
 
1111
1266
  return rb_struct_new(
@@ -1122,19 +1277,32 @@ static VALUE rsctp_get_default_send_params(VALUE self){
1122
1277
  );
1123
1278
  }
1124
1279
 
1280
+ /*
1281
+ * Returns the association specific parameters. This is a struct
1282
+ * that contains the following members:
1283
+ *
1284
+ * * association_id
1285
+ * * max_retransmission_count
1286
+ * * number_peer_destinations
1287
+ * * peer_receive_window
1288
+ * * local_receive_window
1289
+ * * cookie_life
1290
+ *
1291
+ * All values that refer to time values are measured in milliseconds.
1292
+ */
1125
1293
  static VALUE rsctp_get_association_info(VALUE self){
1126
- int sock_fd;
1294
+ int fileno;
1127
1295
  socklen_t size;
1128
1296
  sctp_assoc_t assoc_id;
1129
1297
  struct sctp_assocparams assoc;
1130
1298
 
1131
1299
  bzero(&assoc, sizeof(assoc));
1132
1300
 
1133
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1301
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1134
1302
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1135
1303
  size = sizeof(struct sctp_assocparams);
1136
1304
 
1137
- if(sctp_opt_info(sock_fd, assoc_id, SCTP_ASSOCINFO, (void*)&assoc, &size) < 0)
1305
+ if(sctp_opt_info(fileno, assoc_id, SCTP_ASSOCINFO, (void*)&assoc, &size) < 0)
1138
1306
  rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1139
1307
 
1140
1308
  return rb_struct_new(
@@ -1148,11 +1316,23 @@ static VALUE rsctp_get_association_info(VALUE self){
1148
1316
  );
1149
1317
  }
1150
1318
 
1319
+ /*
1320
+ * Shuts down socket send and receive operations.
1321
+ *
1322
+ * Optionally accepts an argument that specifieds the type of shutdown.
1323
+ * This can be one of the following values:
1324
+ *
1325
+ * * SHUT_RD - Disables further receive operations.
1326
+ * * SHUT_WR - Disables further send operations.
1327
+ * * SHUT_RDWR - Disables further send and receive operations.
1328
+ *
1329
+ * The default is SHUT_RDWR.
1330
+ */
1151
1331
  static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
1152
- int how, sock_fd;
1332
+ int how, fileno;
1153
1333
  VALUE v_how;
1154
1334
 
1155
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1335
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1156
1336
 
1157
1337
  rb_scan_args(argc, argv, "01", &v_how);
1158
1338
 
@@ -1164,25 +1344,35 @@ static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
1164
1344
  how = NUM2INT(v_how);
1165
1345
  }
1166
1346
 
1167
- if(shutdown(sock_fd, how) < 0)
1347
+ if(shutdown(fileno, how) < 0)
1168
1348
  rb_raise(rb_eSystemCallError, "shutdown: %s", strerror(errno));
1169
1349
 
1170
1350
  return self;
1171
1351
  }
1172
1352
 
1353
+ /*
1354
+ * Returns the protocol parameters that are used to initialize and bind the
1355
+ * retransmission timeout (RTO) tunable. This is a struct with the following
1356
+ * members:
1357
+ *
1358
+ * * association_id
1359
+ * * initial
1360
+ * * max
1361
+ * * min
1362
+ */
1173
1363
  static VALUE rsctp_get_retransmission_info(VALUE self){
1174
- int sock_fd;
1364
+ int fileno;
1175
1365
  socklen_t size;
1176
1366
  sctp_assoc_t assoc_id;
1177
1367
  struct sctp_rtoinfo rto;
1178
1368
 
1179
1369
  bzero(&rto, sizeof(rto));
1180
1370
 
1181
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1371
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1182
1372
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1183
1373
  size = sizeof(struct sctp_rtoinfo);
1184
1374
 
1185
- if(sctp_opt_info(sock_fd, assoc_id, SCTP_RTOINFO, (void*)&rto, &size) < 0)
1375
+ if(sctp_opt_info(fileno, assoc_id, SCTP_RTOINFO, (void*)&rto, &size) < 0)
1186
1376
  rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1187
1377
 
1188
1378
  return rb_struct_new(
@@ -1216,7 +1406,7 @@ static VALUE rsctp_get_retransmission_info(VALUE self){
1216
1406
  * * primary (IP)
1217
1407
  */
1218
1408
  static VALUE rsctp_get_status(VALUE self){
1219
- int sock_fd;
1409
+ int fileno;
1220
1410
  socklen_t size;
1221
1411
  sctp_assoc_t assoc_id;
1222
1412
  struct sctp_status status;
@@ -1225,11 +1415,11 @@ static VALUE rsctp_get_status(VALUE self){
1225
1415
 
1226
1416
  bzero(&status, sizeof(status));
1227
1417
 
1228
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1418
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1229
1419
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1230
1420
  size = sizeof(struct sctp_status);
1231
1421
 
1232
- if(sctp_opt_info(sock_fd, assoc_id, SCTP_STATUS, (void*)&status, &size) < 0)
1422
+ if(sctp_opt_info(fileno, assoc_id, SCTP_STATUS, (void*)&status, &size) < 0)
1233
1423
  rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1234
1424
 
1235
1425
  spinfo = &status.sstat_primary;
@@ -1258,6 +1448,87 @@ static VALUE rsctp_get_status(VALUE self){
1258
1448
  );
1259
1449
  }
1260
1450
 
1451
+ /*
1452
+ * Returns a struct of events detailing which events have been
1453
+ * subscribed to by the socket. The struct contains the following
1454
+ * members:
1455
+ *
1456
+ * * data_io
1457
+ * * association
1458
+ * * address
1459
+ * * send_failure
1460
+ * * peer_error
1461
+ * * shutdown
1462
+ * * partial_delivery
1463
+ * * adaptation_layer
1464
+ * * authentication
1465
+ * * sender_dry
1466
+ * * stream_reset
1467
+ * * assoc_reset
1468
+ * * stream_change
1469
+ * * send_failure_event
1470
+ */
1471
+ static VALUE rsctp_get_subscriptions(VALUE self){
1472
+ int fileno;
1473
+ socklen_t size;
1474
+ sctp_assoc_t assoc_id;
1475
+ struct sctp_event_subscribe events;
1476
+
1477
+ bzero(&events, sizeof(events));
1478
+
1479
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1480
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1481
+ size = sizeof(struct sctp_event_subscribe);
1482
+
1483
+ if(sctp_opt_info(fileno, assoc_id, SCTP_EVENTS, (void*)&events, &size) < 0)
1484
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1485
+
1486
+ return rb_struct_new(v_sctp_event_subscribe_struct,
1487
+ (events.sctp_data_io_event ? Qtrue : Qfalse),
1488
+ (events.sctp_association_event ? Qtrue : Qfalse),
1489
+ (events.sctp_address_event ? Qtrue : Qfalse),
1490
+ (events.sctp_send_failure_event ? Qtrue : Qfalse),
1491
+ (events.sctp_peer_error_event ? Qtrue : Qfalse),
1492
+ (events.sctp_shutdown_event ? Qtrue : Qfalse),
1493
+ (events.sctp_partial_delivery_event ? Qtrue : Qfalse),
1494
+ (events.sctp_adaptation_layer_event ? Qtrue : Qfalse),
1495
+ (events.sctp_authentication_event ? Qtrue : Qfalse),
1496
+ (events.sctp_sender_dry_event ? Qtrue : Qfalse),
1497
+ (events.sctp_stream_reset_event ? Qtrue : Qfalse),
1498
+ (events.sctp_assoc_reset_event ? Qtrue : Qfalse),
1499
+ (events.sctp_stream_change_event ? Qtrue : Qfalse),
1500
+ (events.sctp_send_failure_event_event ? Qtrue : Qfalse)
1501
+ );
1502
+ }
1503
+
1504
+ static VALUE rsctp_get_peer_address_params(VALUE self){
1505
+ int fileno;
1506
+ char str[16];
1507
+ socklen_t size;
1508
+ sctp_assoc_t assoc_id;
1509
+ struct sctp_paddrparams paddr;
1510
+
1511
+ bzero(&paddr, sizeof(paddr));
1512
+ bzero(&str, sizeof(str));
1513
+
1514
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1515
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1516
+ size = sizeof(struct sctp_paddrparams);
1517
+
1518
+ if(sctp_opt_info(fileno, assoc_id, SCTP_PEER_ADDR_PARAMS, (void*)&paddr, &size) < 0)
1519
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1520
+
1521
+ inet_ntop(AF_INET, ((struct sockaddr_in*)&paddr.spp_address), str, sizeof(str));
1522
+
1523
+ return rb_struct_new(
1524
+ v_sctp_peer_addr_params_struct,
1525
+ INT2NUM(paddr.spp_assoc_id),
1526
+ rb_str_new2(str),
1527
+ INT2NUM(paddr.spp_hbinterval),
1528
+ INT2NUM(paddr.spp_pathmaxrxt)
1529
+ );
1530
+ }
1531
+
1261
1532
  void Init_socket(void){
1262
1533
  mSCTP = rb_define_module("SCTP");
1263
1534
  cSocket = rb_define_class_under(mSCTP, "Socket", rb_cObject);
@@ -1278,7 +1549,7 @@ void Init_socket(void){
1278
1549
  );
1279
1550
 
1280
1551
  v_remote_error_struct = rb_struct_define(
1281
- "RemoteError", "type", "length", "error", "association_id", "data", NULL
1552
+ "RemoteError", "type", "flags", "length", "error", "association_id", "data", NULL
1282
1553
  );
1283
1554
 
1284
1555
  v_send_failed_event_struct = rb_struct_define(
@@ -1306,6 +1577,10 @@ void Init_socket(void){
1306
1577
  "AuthEvent", "type", "length", "key_number", "indication", "association_id", NULL
1307
1578
  );
1308
1579
 
1580
+ v_sender_dry_event_struct = rb_struct_define(
1581
+ "SenderDryEvent", "type", "flags", "length", "association_id", NULL
1582
+ );
1583
+
1309
1584
  v_sockaddr_in_struct = rb_struct_define(
1310
1585
  "SockAddrIn", "family", "port", "address", NULL
1311
1586
  );
@@ -1330,19 +1605,38 @@ void Init_socket(void){
1330
1605
  "ttl", "tsn", "cumtsn", "association_id", NULL
1331
1606
  );
1332
1607
 
1608
+ v_sctp_event_subscribe_struct = rb_struct_define(
1609
+ "EventSubscriptions", "data_io", "association", "address", "send_failure",
1610
+ "peer_error", "shutdown", "partial_delivery", "adaptation_layer",
1611
+ "authentication", "sender_dry", "stream_reset", "assoc_reset",
1612
+ "stream_change", "send_failure_event", NULL
1613
+ );
1614
+
1615
+ v_sctp_receive_info_struct = rb_struct_define(
1616
+ "ReceiveInfo", "message", "sid", "ssn", "flags", "ppid", "tsn",
1617
+ "cumtsn", "context", "assocation_id", NULL
1618
+ );
1619
+
1620
+ v_sctp_peer_addr_params_struct = rb_struct_define(
1621
+ "PeerAddressParams", "association_id", "address", "heartbeat_interval",
1622
+ "max_retransmission_count", NULL
1623
+ );
1624
+
1333
1625
  rb_define_method(cSocket, "initialize", rsctp_init, -1);
1334
1626
 
1335
- rb_define_method(cSocket, "bind", rsctp_bind, -1);
1627
+ rb_define_method(cSocket, "bindx", rsctp_bindx, -1);
1336
1628
  rb_define_method(cSocket, "close", rsctp_close, 0);
1337
- rb_define_method(cSocket, "connect", rsctp_connect, -1);
1338
- rb_define_method(cSocket, "getpeernames", rsctp_getpeernames, 0);
1339
- rb_define_method(cSocket, "getlocalnames", rsctp_getlocalnames, 0);
1629
+ rb_define_method(cSocket, "connectx", rsctp_connectx, -1);
1630
+ rb_define_method(cSocket, "getpeernames", rsctp_getpeernames, -1);
1631
+ rb_define_method(cSocket, "getlocalnames", rsctp_getlocalnames, -1);
1340
1632
  rb_define_method(cSocket, "get_status", rsctp_get_status, 0);
1341
1633
  rb_define_method(cSocket, "get_default_send_params", rsctp_get_default_send_params, 0);
1342
1634
  rb_define_method(cSocket, "get_retransmission_info", rsctp_get_retransmission_info, 0);
1343
1635
  rb_define_method(cSocket, "get_association_info", rsctp_get_association_info, 0);
1636
+ rb_define_method(cSocket, "get_subscriptions", rsctp_get_subscriptions, 0);
1637
+ rb_define_method(cSocket, "get_peer_address_params", rsctp_get_peer_address_params, 0);
1344
1638
  rb_define_method(cSocket, "listen", rsctp_listen, -1);
1345
- rb_define_method(cSocket, "peeloff!", rsctp_peeloff, 1);
1639
+ rb_define_method(cSocket, "peeloff", rsctp_peeloff, 1);
1346
1640
  rb_define_method(cSocket, "recvmsg", rsctp_recvmsg, -1);
1347
1641
  rb_define_method(cSocket, "send", rsctp_send, 1);
1348
1642
 
@@ -1350,6 +1644,10 @@ void Init_socket(void){
1350
1644
  rb_define_method(cSocket, "sendv", rsctp_sendv, 1);
1351
1645
  #endif
1352
1646
 
1647
+ #ifdef HAVE_SCTP_RECVV
1648
+ rb_define_method(cSocket, "recvv", rsctp_recvv, -1);
1649
+ #endif
1650
+
1353
1651
  rb_define_method(cSocket, "sendmsg", rsctp_sendmsg, 1);
1354
1652
  rb_define_method(cSocket, "set_initmsg", rsctp_set_initmsg, 1);
1355
1653
  rb_define_method(cSocket, "shutdown", rsctp_shutdown, -1);
@@ -1357,12 +1655,12 @@ void Init_socket(void){
1357
1655
 
1358
1656
  rb_define_attr(cSocket, "domain", 1, 1);
1359
1657
  rb_define_attr(cSocket, "type", 1, 1);
1360
- rb_define_attr(cSocket, "sock_fd", 1, 1);
1658
+ rb_define_attr(cSocket, "fileno", 1, 1);
1361
1659
  rb_define_attr(cSocket, "association_id", 1, 1);
1362
1660
  rb_define_attr(cSocket, "port", 1, 1);
1363
1661
 
1364
- /* 0.0.6: The version of this library */
1365
- rb_define_const(cSocket, "VERSION", rb_str_new2("0.0.6"));
1662
+ /* 0.1.0: The version of this library */
1663
+ rb_define_const(cSocket, "VERSION", rb_str_new2("0.1.0"));
1366
1664
 
1367
1665
  /* send flags */
1368
1666
 
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.0.6'
3
+ spec.version = '0.1.0'
4
4
  spec.author = 'Daniel Berger'
5
5
  spec.email = 'djberg96@gmail.com'
6
6
  spec.summary = 'Ruby bindings for SCTP sockets'
@@ -14,10 +14,10 @@ Gem::Specification.new do |spec|
14
14
 
15
15
  spec.extensions = ['ext/sctp/extconf.rb']
16
16
 
17
- spec.add_development_dependency 'bundler', '~> 2.1'
18
- spec.add_development_dependency 'rake', '~> 13.0'
19
- spec.add_development_dependency 'rake-compiler', '~> 1.1'
20
- spec.add_development_dependency 'rspec', '~> 3.9'
17
+ spec.add_development_dependency 'bundler'
18
+ spec.add_development_dependency 'rake'
19
+ spec.add_development_dependency 'rake-compiler'
20
+ spec.add_development_dependency 'rspec'
21
21
 
22
22
  spec.metadata = {
23
23
  'homepage_uri' => 'https://github.com/djberg96/sctp-socket',
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sctp-socket
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Berger
@@ -35,64 +35,64 @@ cert_chain:
35
35
  ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
36
36
  WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
37
37
  -----END CERTIFICATE-----
38
- date: 2024-05-25 00:00:00.000000000 Z
38
+ date: 2024-06-01 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: bundler
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "~>"
44
+ - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: '2.1'
46
+ version: '0'
47
47
  type: :development
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - "~>"
51
+ - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: '2.1'
53
+ version: '0'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: rake
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - "~>"
58
+ - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: '13.0'
60
+ version: '0'
61
61
  type: :development
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - "~>"
65
+ - - ">="
66
66
  - !ruby/object:Gem::Version
67
- version: '13.0'
67
+ version: '0'
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: rake-compiler
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - "~>"
72
+ - - ">="
73
73
  - !ruby/object:Gem::Version
74
- version: '1.1'
74
+ version: '0'
75
75
  type: :development
76
76
  prerelease: false
77
77
  version_requirements: !ruby/object:Gem::Requirement
78
78
  requirements:
79
- - - "~>"
79
+ - - ">="
80
80
  - !ruby/object:Gem::Version
81
- version: '1.1'
81
+ version: '0'
82
82
  - !ruby/object:Gem::Dependency
83
83
  name: rspec
84
84
  requirement: !ruby/object:Gem::Requirement
85
85
  requirements:
86
- - - "~>"
86
+ - - ">="
87
87
  - !ruby/object:Gem::Version
88
- version: '3.9'
88
+ version: '0'
89
89
  type: :development
90
90
  prerelease: false
91
91
  version_requirements: !ruby/object:Gem::Requirement
92
92
  requirements:
93
- - - "~>"
93
+ - - ">="
94
94
  - !ruby/object:Gem::Version
95
- version: '3.9'
95
+ version: '0'
96
96
  description: |2
97
97
  The sctp-socket library provides Ruby bindings for SCTP sockets. is a
98
98
  message oriented, reliable transport protocol with direct support for
metadata.gz.sig CHANGED
Binary file