sctp-socket 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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