sctp-socket 0.0.6 → 0.0.7

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: 0475ccb484ff3e6e758c037edf11b16fdb833e49aee961a98532dfb67c84f799
4
+ data.tar.gz: 70f7add0defeeb84a1ab6bb38ed3aeabb5f643bb05dea06a00a11c1934f588ed
5
5
  SHA512:
6
- metadata.gz: d023d5c17b03912812d02c8cb58279b5c874c45c481bdc1cd685dd89e8f2d62565512675d2cdc89f5e6b8107dce42634a3a1b4a063df8a6b32fed6762029adb4
7
- data.tar.gz: 900e6fb83030d63453d99f9046942b2e6dfaee4340615d668669a922abc5628f58056aa464c9f36fe974ac0cccec4f3699fee7211778b6e49f49d856d7ea002d
6
+ metadata.gz: e5e40484afdf170570c38ab9331c99ae4a6f42ba217d97e91ecd5bfbf9296c2ef95f219498fba13b524ad08a1f00271de8be6f358f2982a4c5e45fdc190f0951
7
+ data.tar.gz: f9b9dac418aeae1c79916e732d7310049812c2456c0f4f1c578641f145c2c72b73fbceb655954ad99b03c3c69a890cab9a7455930199902a40aed9de239754a8
checksums.yaml.gz.sig CHANGED
@@ -1,4 +1,3 @@
1
- qV���/u��� T�H��U�r��- ���*��g�zv/���1l���p�]t��K\T���K�/',�O9��N������O�
2
- D���ij1]ι�6N��| �c����qL
3
- U��%#D�G�V�/B�K�t�!�:h�����CnNL��B|�@N ��v���|'!'���Xg
4
- f�WT)��p|,��7�'���G��!;�h{b�a��]ч�Dw�� �x��`�'�O��18�Fh�ɎP���-}�V4��Ey��,I:�"���0ڸ� ���P��DŽ��T
1
+
2
+ ���׾#��:���Ww� ��m�x����TM��}��G����9����SЮ���/�e$����ǎce��1˪5��*�eNN^�=b�igE���s���x��D% pi�`ʹ��l��3Ja�Ⱦ�x��4[�9F@�VIi����t���>v���&�\�`y�1)[�|}za˾��‰�����%�^v�9o�v�tA6��
3
+ 9�t�Ljꔰ�Ҁ�[1&�*��[L�fV��J�z�9|G�Ek�~�j'��OJ�:I�B2��m+�D�6/�}f �M�J��i =�m����7$���!*I'�}*�bb��`p����+�g�2����ؘP[K�J1Xuup��e��q?��Y6��Z����0���5�|v�s��\�X���_
data/CHANGES.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## 0.0.7 - 28-May-2024
2
+ * Added the recvv method.
3
+ * The getlocalnames and getpeernames methods now accept optional fileno and
4
+ association ID arguments.
5
+ * The peeloff method now returns the peeled off fileno and no longer modifies
6
+ the receiver, so I dropped the exclamation point from the method name.
7
+ * Added the get_subscriptions method.
8
+ * Changed bind method to bindx and connect method to connectx. I may try to
9
+ subclass Socket someday so I didn't want a conflict, and this more closely
10
+ matches the underlying function name anyway.
11
+ * Changed the sock_fd method to fileno.
12
+ * Changed the default backlog from 1024 to 128 for the listen method.
13
+ * Updated comments and documentation.
14
+ * Added more specs.
15
+
1
16
  ## 0.0.6 - 24-May-2024
2
17
  * Fixup the sendv method and add some documentation.
3
18
  * 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,8 @@ 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;
24
26
 
25
27
  #if !defined(IOV_MAX)
26
28
  #if defined(_SC_IOV_MAX)
@@ -77,7 +79,7 @@ VALUE rb_hash_aref2(VALUE v_hash, const char* key){
77
79
  * socket2 = SCTP::Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
78
80
  */
79
81
  static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
80
- int sock_fd;
82
+ int fileno;
81
83
  VALUE v_domain, v_type;
82
84
 
83
85
  rb_scan_args(argc, argv, "02", &v_domain, &v_type);
@@ -88,14 +90,14 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
88
90
  if(NIL_P(v_type))
89
91
  v_type = INT2NUM(SOCK_SEQPACKET);
90
92
 
91
- sock_fd = socket(NUM2INT(v_domain), NUM2INT(v_type), IPPROTO_SCTP);
93
+ fileno = socket(NUM2INT(v_domain), NUM2INT(v_type), IPPROTO_SCTP);
92
94
 
93
- if(sock_fd < 0)
95
+ if(fileno < 0)
94
96
  rb_raise(rb_eSystemCallError, "socket: %s", strerror(errno));
95
97
 
96
98
  rb_iv_set(self, "@domain", v_domain);
97
99
  rb_iv_set(self, "@type", v_type);
98
- rb_iv_set(self, "@sock_fd", INT2NUM(sock_fd));
100
+ rb_iv_set(self, "@fileno", INT2NUM(fileno));
99
101
  rb_iv_set(self, "@association_id", INT2NUM(0));
100
102
 
101
103
  return self;
@@ -114,19 +116,19 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
114
116
  * socket = SCTP::Socket.new
115
117
  *
116
118
  * # Bind 2 addresses
117
- * socket.bind(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
119
+ * socket.bindx(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
118
120
  *
119
121
  * # Remove 1 later
120
- * socket.bind(:addresses => ['10.0.4.5'], :flags => SCTP::Socket::BINDX_REM_ADDR)
122
+ * socket.bindx(:addresses => ['10.0.4.5'], :flags => SCTP::Socket::BINDX_REM_ADDR)
121
123
  *
122
124
  * If no addresses are specified, then it will bind to all available interfaces. If
123
125
  * no port is specified, then one will be assigned by the host.
124
126
  *
125
127
  * Returns the port that it was bound to.
126
128
  */
127
- static VALUE rsctp_bind(int argc, VALUE* argv, VALUE self){
129
+ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
128
130
  struct sockaddr_in addrs[8];
129
- int i, sock_fd, num_ip, flags, domain, port;
131
+ int i, fileno, num_ip, flags, domain, port;
130
132
  VALUE v_addresses, v_port, v_flags, v_address, v_options;
131
133
 
132
134
  rb_scan_args(argc, argv, "01", &v_options);
@@ -156,7 +158,7 @@ static VALUE rsctp_bind(int argc, VALUE* argv, VALUE self){
156
158
  num_ip = RARRAY_LEN(v_addresses);
157
159
 
158
160
  domain = NUM2INT(rb_iv_get(self, "@domain"));
159
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
161
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
160
162
 
161
163
  if(num_ip > 1){
162
164
  for(i = 0; i < num_ip; i++){
@@ -172,14 +174,14 @@ static VALUE rsctp_bind(int argc, VALUE* argv, VALUE self){
172
174
  addrs[0].sin_addr.s_addr = htonl(INADDR_ANY);
173
175
  }
174
176
 
175
- if(sctp_bindx(sock_fd, (struct sockaddr *) addrs, num_ip, flags) != 0)
177
+ if(sctp_bindx(fileno, (struct sockaddr *) addrs, num_ip, flags) != 0)
176
178
  rb_raise(rb_eSystemCallError, "sctp_bindx: %s", strerror(errno));
177
179
 
178
180
  if(port == 0){
179
181
  struct sockaddr_in sin;
180
182
  socklen_t len = sizeof(sin);
181
183
 
182
- if(getsockname(sock_fd, (struct sockaddr *)&sin, &len) == -1)
184
+ if(getsockname(fileno, (struct sockaddr *)&sin, &len) == -1)
183
185
  rb_raise(rb_eSystemCallError, "getsockname: %s", strerror(errno));
184
186
 
185
187
  port = sin.sin_port;
@@ -197,13 +199,13 @@ static VALUE rsctp_bind(int argc, VALUE* argv, VALUE self){
197
199
  * Example:
198
200
  *
199
201
  * socket = SCTP::Socket.new
200
- * socket.connect(:port => 62354, :addresses => ['10.0.4.5', '10.0.5.5'])
202
+ * socket.connectx(:port => 62354, :addresses => ['10.0.4.5', '10.0.5.5'])
201
203
  *
202
204
  * Note that this will also set/update the object's association_id.
203
205
  */
204
- static VALUE rsctp_connect(int argc, VALUE* argv, VALUE self){
206
+ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
205
207
  struct sockaddr_in addrs[8];
206
- int i, num_ip, sock_fd;
208
+ int i, num_ip, fileno;
207
209
  sctp_assoc_t assoc;
208
210
  VALUE v_address, v_domain, v_options, v_addresses, v_port;
209
211
 
@@ -235,9 +237,9 @@ static VALUE rsctp_connect(int argc, VALUE* argv, VALUE self){
235
237
  addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
236
238
  }
237
239
 
238
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
240
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
239
241
 
240
- if(sctp_connectx(sock_fd, (struct sockaddr *) addrs, num_ip, &assoc) < 0)
242
+ if(sctp_connectx(fileno, (struct sockaddr *) addrs, num_ip, &assoc) < 0)
241
243
  rb_raise(rb_eSystemCallError, "sctp_connectx: %s", strerror(errno));
242
244
 
243
245
  rb_iv_set(self, "@association_id", INT2NUM(assoc));
@@ -254,30 +256,55 @@ static VALUE rsctp_connect(int argc, VALUE* argv, VALUE self){
254
256
  * socket.close
255
257
  */
256
258
  static VALUE rsctp_close(VALUE self){
257
- VALUE v_sock_fd = rb_iv_get(self, "@sock_fd");
259
+ VALUE v_fileno = rb_iv_get(self, "@fileno");
258
260
 
259
- if(close(NUM2INT(v_sock_fd)))
261
+ if(close(NUM2INT(v_fileno)))
260
262
  rb_raise(rb_eSystemCallError, "close: %s", strerror(errno));
261
263
 
262
264
  return self;
263
265
  }
264
266
 
265
267
  /*
266
- * Return an array of all addresses of a peer.
268
+ * Return an array of all addresses of a peer of the current socket
269
+ * and association number.
270
+ *
271
+ * You may optionally pass a assocation fileno and association ID. Typically
272
+ * this information would come from the peeloff method.
273
+ *
274
+ * Example:
275
+ *
276
+ * socket = SCTP::Socket.new
277
+ * # ...
278
+ * p socket.getpeernames
279
+ *
280
+ * info = socket.recvmsg
281
+ * association_fileno = socket.peeloff(info.association_id)
282
+ *
283
+ * p socket.getpeernames(association_fileno, info.association_id)
267
284
  */
268
- static VALUE rsctp_getpeernames(VALUE self){
285
+ static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
269
286
  sctp_assoc_t assoc_id;
270
287
  struct sockaddr* addrs;
271
- int i, sock_fd, num_addrs;
288
+ int i, fileno, num_addrs;
272
289
  char str[16];
290
+ VALUE v_fileno, v_association_id;
273
291
  VALUE v_array = rb_ary_new();
274
292
 
275
293
  bzero(&addrs, sizeof(addrs));
276
294
 
277
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
278
- assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
295
+ rb_scan_args(argc, argv, "02", &v_fileno, &v_association_id);
296
+
297
+ if(NIL_P(v_fileno))
298
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
299
+ else
300
+ fileno = NUM2INT(v_fileno);
301
+
302
+ if(NIL_P(v_association_id))
303
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
304
+ else
305
+ assoc_id = NUM2INT(v_association_id);
279
306
 
280
- num_addrs = sctp_getpaddrs(sock_fd, assoc_id, &addrs);
307
+ num_addrs = sctp_getpaddrs(fileno, assoc_id, &addrs);
281
308
 
282
309
  if(num_addrs < 0){
283
310
  sctp_freepaddrs(addrs);
@@ -303,20 +330,35 @@ static VALUE rsctp_getpeernames(VALUE self){
303
330
  * socket = SCTP::Socket.new
304
331
  * socket.bind(:addresses => ['10.0.4.5', '10.0.5.5'])
305
332
  * socket.getlocalnames # => ['10.0.4.5', '10.0.5.5'])
333
+ *
334
+ * # or get info from a peeled off association...
335
+ *
336
+ * assoc_fileno = socket.peeloff(some_association_id)
337
+ * socket.getlocalnames(assoc_fileno, some_association_id)
306
338
  */
307
- static VALUE rsctp_getlocalnames(VALUE self){
339
+ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
308
340
  sctp_assoc_t assoc_id;
309
341
  struct sockaddr* addrs;
310
- int i, sock_fd, num_addrs;
342
+ int i, fileno, num_addrs;
311
343
  char str[16];
344
+ VALUE v_assoc_fileno, v_assoc_id;
312
345
  VALUE v_array = rb_ary_new();
313
346
 
314
347
  bzero(&addrs, sizeof(addrs));
315
348
 
316
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
317
- assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
349
+ rb_scan_args(argc, argv, "02", &v_assoc_fileno, &v_assoc_id);
318
350
 
319
- num_addrs = sctp_getladdrs(sock_fd, assoc_id, &addrs);
351
+ if(NIL_P(v_assoc_fileno))
352
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
353
+ else
354
+ fileno = NUM2INT(v_assoc_fileno);
355
+
356
+ if(NIL_P(v_assoc_id))
357
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
358
+ else
359
+ assoc_id = NUM2INT(v_assoc_id);
360
+
361
+ num_addrs = sctp_getladdrs(fileno, assoc_id, &addrs);
320
362
 
321
363
  if(num_addrs < 0){
322
364
  sctp_freeladdrs(addrs);
@@ -362,7 +404,7 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
362
404
  struct iovec iov[IOV_MAX];
363
405
  struct sockaddr_in* addrs;
364
406
  struct sctp_sndinfo info;
365
- int i, sock_fd, num_bytes, size, num_ip;
407
+ int i, fileno, num_bytes, size, num_ip;
366
408
 
367
409
  Check_Type(v_options, T_HASH);
368
410
 
@@ -385,7 +427,7 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
385
427
  num_ip = 0;
386
428
  }
387
429
 
388
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
430
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
389
431
  size = RARRAY_LEN(v_message);
390
432
 
391
433
  if(!size)
@@ -424,7 +466,7 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
424
466
  }
425
467
 
426
468
  num_bytes = sctp_sendv(
427
- sock_fd,
469
+ fileno,
428
470
  iov,
429
471
  size,
430
472
  (struct sockaddr*)addrs,
@@ -442,6 +484,74 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
442
484
  }
443
485
  #endif
444
486
 
487
+ #ifdef HAVE_SCTP_RECVV
488
+ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
489
+ VALUE v_flags;
490
+ int fileno, flags, bytes, on;
491
+ uint infotype;
492
+ socklen_t infolen;
493
+ struct iovec iov[1];
494
+ struct sctp_rcvinfo info;
495
+ char buffer[1024];
496
+
497
+ bzero(&iov, sizeof(iov));
498
+ bzero(&info, sizeof(info));
499
+ bzero(&buffer, sizeof(buffer));
500
+
501
+ iov->iov_base = buffer;
502
+ iov->iov_len = sizeof(buffer);
503
+
504
+ rb_scan_args(argc, argv, "01", &v_flags);
505
+
506
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
507
+
508
+ if(NIL_P(v_flags))
509
+ flags = 0;
510
+ else
511
+ flags = NUM2INT(v_flags);
512
+
513
+ on = 1;
514
+ if(setsockopt(fileno, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(on)) < 0)
515
+ rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
516
+
517
+ infolen = sizeof(struct sctp_rcvinfo);
518
+ infotype = 0;
519
+
520
+ bytes = sctp_recvv(
521
+ fileno,
522
+ iov,
523
+ 1,
524
+ NULL,
525
+ NULL,
526
+ &info,
527
+ &infolen,
528
+ &infotype,
529
+ &flags
530
+ );
531
+
532
+ if(bytes < 0)
533
+ rb_raise(rb_eSystemCallError, "sctp_recvv: %s", strerror(errno));
534
+
535
+ if(infotype != SCTP_RECVV_RCVINFO){
536
+ return Qnil;
537
+ }
538
+ else{
539
+ return rb_struct_new(
540
+ v_sctp_receive_info_struct,
541
+ rb_str_new2(iov->iov_base),
542
+ UINT2NUM(info.rcv_sid),
543
+ UINT2NUM(info.rcv_ssn),
544
+ UINT2NUM(info.rcv_flags),
545
+ UINT2NUM(info.rcv_ppid),
546
+ UINT2NUM(info.rcv_tsn),
547
+ UINT2NUM(info.rcv_cumtsn),
548
+ UINT2NUM(info.rcv_context),
549
+ UINT2NUM(info.rcv_assoc_id)
550
+ );
551
+ }
552
+ }
553
+ #endif
554
+
445
555
  /*
446
556
  * Send a message on an already-connected socket to a specific association.
447
557
  *
@@ -458,7 +568,7 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
458
568
  uint16_t stream;
459
569
  uint32_t ppid, send_flags, ctrl_flags, ttl, context;
460
570
  ssize_t num_bytes;
461
- int sock_fd;
571
+ int fileno;
462
572
  sctp_assoc_t assoc_id;
463
573
  struct sctp_sndrcvinfo info;
464
574
  VALUE v_msg, v_stream, v_ppid, v_context, v_send_flags, v_ctrl_flags, v_ttl, v_assoc_id;
@@ -519,10 +629,10 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
519
629
  info.sinfo_timetolive = ttl;
520
630
  info.sinfo_assoc_id = assoc_id;
521
631
 
522
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
632
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
523
633
 
524
634
  num_bytes = sctp_send(
525
- sock_fd,
635
+ fileno,
526
636
  StringValueCStr(v_msg),
527
637
  RSTRING_LEN(v_msg),
528
638
  &info,
@@ -570,7 +680,7 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
570
680
  uint32_t ppid, flags, ttl, context;
571
681
  ssize_t num_bytes;
572
682
  struct sockaddr_in addrs[8];
573
- int sock_fd, size;
683
+ int fileno, size;
574
684
 
575
685
  Check_Type(v_options, T_HASH);
576
686
 
@@ -637,10 +747,10 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
637
747
  size = 0;
638
748
  }
639
749
 
640
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
750
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
641
751
 
642
752
  num_bytes = sctp_sendmsg(
643
- sock_fd,
753
+ fileno,
644
754
  StringValueCStr(v_msg),
645
755
  RSTRING_LEN(v_msg),
646
756
  (struct sockaddr*)addrs,
@@ -681,7 +791,7 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
681
791
  VALUE v_flags, v_notification, v_message;
682
792
  struct sctp_sndrcvinfo sndrcvinfo;
683
793
  struct sockaddr_in clientaddr;
684
- int flags, bytes, sock_fd;
794
+ int flags, bytes, fileno;
685
795
  char buffer[1024]; // TODO: Let this be configurable?
686
796
  socklen_t length;
687
797
 
@@ -692,7 +802,7 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
692
802
  else
693
803
  flags = NUM2INT(v_flags);
694
804
 
695
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
805
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
696
806
  length = sizeof(struct sockaddr_in);
697
807
 
698
808
  bzero(buffer, sizeof(buffer));
@@ -700,7 +810,7 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
700
810
  bzero(&sndrcvinfo, sizeof(sndrcvinfo));
701
811
 
702
812
  bytes = sctp_recvmsg(
703
- sock_fd,
813
+ fileno,
704
814
  buffer,
705
815
  sizeof(buffer),
706
816
  (struct sockaddr*)&clientaddr,
@@ -923,7 +1033,7 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
923
1033
  * By default these values are set to zero (i.e. ignored).
924
1034
  */
925
1035
  static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
926
- int sock_fd;
1036
+ int fileno;
927
1037
  struct sctp_initmsg initmsg;
928
1038
  VALUE v_output, v_input, v_attempts, v_timeout;
929
1039
 
@@ -934,7 +1044,7 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
934
1044
  v_attempts = rb_hash_aref2(v_options, "max_attempts");
935
1045
  v_timeout = rb_hash_aref2(v_options, "timeout");
936
1046
 
937
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1047
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
938
1048
 
939
1049
  if(!NIL_P(v_output))
940
1050
  initmsg.sinit_num_ostreams = NUM2INT(v_output);
@@ -948,15 +1058,15 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
948
1058
  if(!NIL_P(v_timeout))
949
1059
  initmsg.sinit_max_init_timeo = NUM2INT(v_timeout);
950
1060
 
951
- if(setsockopt(sock_fd, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg)) < 0)
1061
+ if(setsockopt(fileno, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg)) < 0)
952
1062
  rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
953
1063
 
954
1064
  return self;
955
1065
  }
956
1066
 
957
1067
  /*
958
- * Subscribe to various notification types, which will generate additional
959
- * data that the socket may receive. The possible notification types are
1068
+ * Subscribe to various notification type events, which will generate additional
1069
+ * data that the socket may receive. The possible notification type events are
960
1070
  * as follows:
961
1071
  *
962
1072
  * :association
@@ -993,11 +1103,13 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
993
1103
  * socket.subscribe(:data_io => true, :shutdown => true, :send_failure => true)
994
1104
  */
995
1105
  static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
996
- int sock_fd;
1106
+ int fileno;
997
1107
  struct sctp_event_subscribe events;
998
1108
 
999
1109
  bzero(&events, sizeof(events));
1000
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1110
+ Check_Type(v_options, T_HASH);
1111
+
1112
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1001
1113
 
1002
1114
  if(RTEST(rb_hash_aref2(v_options, "data_io")))
1003
1115
  events.sctp_data_io_event = 1;
@@ -1033,7 +1145,7 @@ static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
1033
1145
  if(RTEST(rb_hash_aref2(v_options, "sender_dry")))
1034
1146
  events.sctp_sender_dry_event = 1;
1035
1147
 
1036
- if(setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)) < 0)
1148
+ if(setsockopt(fileno, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)) < 0)
1037
1149
  rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
1038
1150
 
1039
1151
  return self;
@@ -1044,29 +1156,39 @@ static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
1044
1156
  * will be used to accept incoming connection requests.
1045
1157
  *
1046
1158
  * The backlog argument defines the maximum length to which the queue of
1047
- * pending connections for sockfd may grow. The default is 1024.
1159
+ * pending connections for sockfd may grow. The default value is 128. The
1160
+ * maximum value is Socket::SOMAXCONN.
1161
+ *
1162
+ * Why a default of 128? The answer is a "best guess" compromise between
1163
+ * handling server load versus avoiding SYN flood attacks. I leave it as an
1164
+ * exercise to the programmer to adjust as desired.
1165
+ *
1166
+ * See https://tangentsoft.com/wskfaq/advanced.html#backlog if you want
1167
+ * more details on the advantages and drawbacks of various values.
1048
1168
  *
1049
1169
  * Example:
1050
1170
  *
1051
1171
  * socket = SCTP::Socket.new
1052
1172
  * socket.bind(:port => 62534, :addresses => ['127.0.0.1'])
1053
1173
  * socket.listen
1054
- *
1055
1174
  */
1056
1175
  static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
1057
1176
  VALUE v_backlog;
1058
- int backlog, sock_fd;
1177
+ int backlog, fileno;
1059
1178
 
1060
1179
  rb_scan_args(argc, argv, "01", &v_backlog);
1061
1180
 
1062
1181
  if(NIL_P(v_backlog))
1063
- backlog = 1024;
1182
+ backlog = 128;
1064
1183
  else
1065
1184
  backlog = NUM2INT(v_backlog);
1066
1185
 
1067
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1186
+ if(backlog > SOMAXCONN)
1187
+ rb_raise(rb_eArgError, "backlog value exceeds maximum value of: %i", SOMAXCONN);
1068
1188
 
1069
- if(listen(sock_fd, backlog) < 0)
1189
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1190
+
1191
+ if(listen(fileno, backlog) < 0)
1070
1192
  rb_raise(rb_eSystemCallError, "listen: %s", strerror(errno));
1071
1193
 
1072
1194
  return self;
@@ -1074,38 +1196,47 @@ static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
1074
1196
 
1075
1197
  /*
1076
1198
  * 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.
1199
+ * a one-to-one style socket. Returns the socket descriptor (fileno).
1200
+ *
1201
+ * Example:
1202
+ *
1203
+ * socket = SCTP::Socket.new
1204
+ * # etc...
1205
+ *
1206
+ * while true
1207
+ * info = socket.recvmsg
1208
+ * assoc_fileno = socket.peeloff(info.association_id)
1209
+ * # ... Do something with this new
1210
+ * end
1078
1211
  */
1079
1212
  static VALUE rsctp_peeloff(VALUE self, VALUE v_assoc_id){
1080
- int sock_fd, new_sock_fd;
1213
+ int fileno, assoc_fileno;
1081
1214
  sctp_assoc_t assoc_id;
1082
1215
 
1083
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1216
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1084
1217
  assoc_id = NUM2INT(v_assoc_id);
1085
1218
 
1086
- new_sock_fd = sctp_peeloff(sock_fd, assoc_id);
1219
+ assoc_fileno = sctp_peeloff(fileno, assoc_id);
1087
1220
 
1088
- if(new_sock_fd < 0)
1221
+ if(assoc_fileno < 0)
1089
1222
  rb_raise(rb_eSystemCallError, "sctp_peeloff: %s", strerror(errno));
1090
1223
 
1091
- rb_iv_set(self, "@sock_fd", INT2NUM(new_sock_fd));
1092
-
1093
- return self;
1224
+ return INT2NUM(assoc_fileno);
1094
1225
  }
1095
1226
 
1096
1227
  static VALUE rsctp_get_default_send_params(VALUE self){
1097
- int sock_fd;
1228
+ int fileno;
1098
1229
  socklen_t size;
1099
1230
  sctp_assoc_t assoc_id;
1100
1231
  struct sctp_sndrcvinfo sndrcv;
1101
1232
 
1102
1233
  bzero(&sndrcv, sizeof(sndrcv));
1103
1234
 
1104
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1235
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1105
1236
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1106
1237
  size = sizeof(struct sctp_sndrcvinfo);
1107
1238
 
1108
- if(sctp_opt_info(sock_fd, assoc_id, SCTP_DEFAULT_SEND_PARAM, (void*)&sndrcv, &size) < 0)
1239
+ if(sctp_opt_info(fileno, assoc_id, SCTP_DEFAULT_SEND_PARAM, (void*)&sndrcv, &size) < 0)
1109
1240
  rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1110
1241
 
1111
1242
  return rb_struct_new(
@@ -1123,18 +1254,18 @@ static VALUE rsctp_get_default_send_params(VALUE self){
1123
1254
  }
1124
1255
 
1125
1256
  static VALUE rsctp_get_association_info(VALUE self){
1126
- int sock_fd;
1257
+ int fileno;
1127
1258
  socklen_t size;
1128
1259
  sctp_assoc_t assoc_id;
1129
1260
  struct sctp_assocparams assoc;
1130
1261
 
1131
1262
  bzero(&assoc, sizeof(assoc));
1132
1263
 
1133
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1264
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1134
1265
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1135
1266
  size = sizeof(struct sctp_assocparams);
1136
1267
 
1137
- if(sctp_opt_info(sock_fd, assoc_id, SCTP_ASSOCINFO, (void*)&assoc, &size) < 0)
1268
+ if(sctp_opt_info(fileno, assoc_id, SCTP_ASSOCINFO, (void*)&assoc, &size) < 0)
1138
1269
  rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1139
1270
 
1140
1271
  return rb_struct_new(
@@ -1149,10 +1280,10 @@ static VALUE rsctp_get_association_info(VALUE self){
1149
1280
  }
1150
1281
 
1151
1282
  static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
1152
- int how, sock_fd;
1283
+ int how, fileno;
1153
1284
  VALUE v_how;
1154
1285
 
1155
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1286
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1156
1287
 
1157
1288
  rb_scan_args(argc, argv, "01", &v_how);
1158
1289
 
@@ -1164,25 +1295,25 @@ static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
1164
1295
  how = NUM2INT(v_how);
1165
1296
  }
1166
1297
 
1167
- if(shutdown(sock_fd, how) < 0)
1298
+ if(shutdown(fileno, how) < 0)
1168
1299
  rb_raise(rb_eSystemCallError, "shutdown: %s", strerror(errno));
1169
1300
 
1170
1301
  return self;
1171
1302
  }
1172
1303
 
1173
1304
  static VALUE rsctp_get_retransmission_info(VALUE self){
1174
- int sock_fd;
1305
+ int fileno;
1175
1306
  socklen_t size;
1176
1307
  sctp_assoc_t assoc_id;
1177
1308
  struct sctp_rtoinfo rto;
1178
1309
 
1179
1310
  bzero(&rto, sizeof(rto));
1180
1311
 
1181
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1312
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1182
1313
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1183
1314
  size = sizeof(struct sctp_rtoinfo);
1184
1315
 
1185
- if(sctp_opt_info(sock_fd, assoc_id, SCTP_RTOINFO, (void*)&rto, &size) < 0)
1316
+ if(sctp_opt_info(fileno, assoc_id, SCTP_RTOINFO, (void*)&rto, &size) < 0)
1186
1317
  rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1187
1318
 
1188
1319
  return rb_struct_new(
@@ -1216,7 +1347,7 @@ static VALUE rsctp_get_retransmission_info(VALUE self){
1216
1347
  * * primary (IP)
1217
1348
  */
1218
1349
  static VALUE rsctp_get_status(VALUE self){
1219
- int sock_fd;
1350
+ int fileno;
1220
1351
  socklen_t size;
1221
1352
  sctp_assoc_t assoc_id;
1222
1353
  struct sctp_status status;
@@ -1225,11 +1356,11 @@ static VALUE rsctp_get_status(VALUE self){
1225
1356
 
1226
1357
  bzero(&status, sizeof(status));
1227
1358
 
1228
- sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
1359
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1229
1360
  assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1230
1361
  size = sizeof(struct sctp_status);
1231
1362
 
1232
- if(sctp_opt_info(sock_fd, assoc_id, SCTP_STATUS, (void*)&status, &size) < 0)
1363
+ if(sctp_opt_info(fileno, assoc_id, SCTP_STATUS, (void*)&status, &size) < 0)
1233
1364
  rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1234
1365
 
1235
1366
  spinfo = &status.sstat_primary;
@@ -1258,6 +1389,39 @@ static VALUE rsctp_get_status(VALUE self){
1258
1389
  );
1259
1390
  }
1260
1391
 
1392
+ static VALUE rsctp_get_subscriptions(VALUE self){
1393
+ int fileno;
1394
+ socklen_t size;
1395
+ sctp_assoc_t assoc_id;
1396
+ struct sctp_event_subscribe events;
1397
+
1398
+ bzero(&events, sizeof(events));
1399
+
1400
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1401
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1402
+ size = sizeof(struct sctp_event_subscribe);
1403
+
1404
+ if(sctp_opt_info(fileno, assoc_id, SCTP_EVENTS, (void*)&events, &size) < 0)
1405
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1406
+
1407
+ return rb_struct_new(v_sctp_event_subscribe_struct,
1408
+ (events.sctp_data_io_event ? Qtrue : Qfalse),
1409
+ (events.sctp_association_event ? Qtrue : Qfalse),
1410
+ (events.sctp_address_event ? Qtrue : Qfalse),
1411
+ (events.sctp_send_failure_event ? Qtrue : Qfalse),
1412
+ (events.sctp_peer_error_event ? Qtrue : Qfalse),
1413
+ (events.sctp_shutdown_event ? Qtrue : Qfalse),
1414
+ (events.sctp_partial_delivery_event ? Qtrue : Qfalse),
1415
+ (events.sctp_adaptation_layer_event ? Qtrue : Qfalse),
1416
+ (events.sctp_authentication_event ? Qtrue : Qfalse),
1417
+ (events.sctp_sender_dry_event ? Qtrue : Qfalse),
1418
+ (events.sctp_stream_reset_event ? Qtrue : Qfalse),
1419
+ (events.sctp_assoc_reset_event ? Qtrue : Qfalse),
1420
+ (events.sctp_stream_change_event ? Qtrue : Qfalse),
1421
+ (events.sctp_send_failure_event_event ? Qtrue : Qfalse)
1422
+ );
1423
+ }
1424
+
1261
1425
  void Init_socket(void){
1262
1426
  mSCTP = rb_define_module("SCTP");
1263
1427
  cSocket = rb_define_class_under(mSCTP, "Socket", rb_cObject);
@@ -1330,19 +1494,32 @@ void Init_socket(void){
1330
1494
  "ttl", "tsn", "cumtsn", "association_id", NULL
1331
1495
  );
1332
1496
 
1497
+ v_sctp_event_subscribe_struct = rb_struct_define(
1498
+ "EventSubscriptions", "data_io", "association", "address", "send_failure",
1499
+ "peer_error", "shutdown", "partial_delivery", "adaptation_layer",
1500
+ "authentication", "sender_dry", "stream_reset", "assoc_reset",
1501
+ "stream_change", "send_failure_event", NULL
1502
+ );
1503
+
1504
+ v_sctp_receive_info_struct = rb_struct_define(
1505
+ "ReceiveInfo", "message", "sid", "ssn", "flags", "ppid", "tsn",
1506
+ "cumtsn", "context", "assocation_id", NULL
1507
+ );
1508
+
1333
1509
  rb_define_method(cSocket, "initialize", rsctp_init, -1);
1334
1510
 
1335
- rb_define_method(cSocket, "bind", rsctp_bind, -1);
1511
+ rb_define_method(cSocket, "bindx", rsctp_bindx, -1);
1336
1512
  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);
1513
+ rb_define_method(cSocket, "connectx", rsctp_connectx, -1);
1514
+ rb_define_method(cSocket, "getpeernames", rsctp_getpeernames, -1);
1515
+ rb_define_method(cSocket, "getlocalnames", rsctp_getlocalnames, -1);
1340
1516
  rb_define_method(cSocket, "get_status", rsctp_get_status, 0);
1341
1517
  rb_define_method(cSocket, "get_default_send_params", rsctp_get_default_send_params, 0);
1342
1518
  rb_define_method(cSocket, "get_retransmission_info", rsctp_get_retransmission_info, 0);
1343
1519
  rb_define_method(cSocket, "get_association_info", rsctp_get_association_info, 0);
1520
+ rb_define_method(cSocket, "get_subscriptions", rsctp_get_subscriptions, 0);
1344
1521
  rb_define_method(cSocket, "listen", rsctp_listen, -1);
1345
- rb_define_method(cSocket, "peeloff!", rsctp_peeloff, 1);
1522
+ rb_define_method(cSocket, "peeloff", rsctp_peeloff, 1);
1346
1523
  rb_define_method(cSocket, "recvmsg", rsctp_recvmsg, -1);
1347
1524
  rb_define_method(cSocket, "send", rsctp_send, 1);
1348
1525
 
@@ -1350,6 +1527,10 @@ void Init_socket(void){
1350
1527
  rb_define_method(cSocket, "sendv", rsctp_sendv, 1);
1351
1528
  #endif
1352
1529
 
1530
+ #ifdef HAVE_SCTP_RECVV
1531
+ rb_define_method(cSocket, "recvv", rsctp_recvv, -1);
1532
+ #endif
1533
+
1353
1534
  rb_define_method(cSocket, "sendmsg", rsctp_sendmsg, 1);
1354
1535
  rb_define_method(cSocket, "set_initmsg", rsctp_set_initmsg, 1);
1355
1536
  rb_define_method(cSocket, "shutdown", rsctp_shutdown, -1);
@@ -1357,12 +1538,12 @@ void Init_socket(void){
1357
1538
 
1358
1539
  rb_define_attr(cSocket, "domain", 1, 1);
1359
1540
  rb_define_attr(cSocket, "type", 1, 1);
1360
- rb_define_attr(cSocket, "sock_fd", 1, 1);
1541
+ rb_define_attr(cSocket, "fileno", 1, 1);
1361
1542
  rb_define_attr(cSocket, "association_id", 1, 1);
1362
1543
  rb_define_attr(cSocket, "port", 1, 1);
1363
1544
 
1364
- /* 0.0.6: The version of this library */
1365
- rb_define_const(cSocket, "VERSION", rb_str_new2("0.0.6"));
1545
+ /* 0.0.7: The version of this library */
1546
+ rb_define_const(cSocket, "VERSION", rb_str_new2("0.0.7"));
1366
1547
 
1367
1548
  /* send flags */
1368
1549
 
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.0.7'
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,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.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Berger
@@ -35,7 +35,7 @@ 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-05-28 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: bundler
metadata.gz.sig CHANGED
Binary file