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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGES.md +22 -0
- data/README.md +1 -1
- data/examples/client_example.rb +3 -2
- data/examples/server_example.rb +1 -1
- data/ext/sctp/extconf.rb +1 -0
- data/ext/sctp/socket.c +393 -95
- data/sctp-socket.gemspec +5 -5
- data.tar.gz.sig +0 -0
- metadata +18 -18
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a483264dd5712655f641ade00e03177756f25340c2fd398bed3ad453bc6a9cdb
|
4
|
+
data.tar.gz: 719857e2ce3a5db341aa317f23ec0bf2fa674dd9b427b502f99e3515cb786dac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
data/examples/client_example.rb
CHANGED
@@ -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.
|
13
|
+
p socket.bindx(:addresses => addresses)
|
14
14
|
|
15
15
|
# Initial connection
|
16
|
-
p socket.
|
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!"])
|
data/examples/server_example.rb
CHANGED
@@ -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.
|
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
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
|
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
|
-
|
95
|
+
fileno = socket(NUM2INT(v_domain), NUM2INT(v_type), IPPROTO_SCTP);
|
92
96
|
|
93
|
-
if(
|
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, "@
|
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.
|
121
|
+
* socket.bindx(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
|
118
122
|
*
|
119
123
|
* # Remove 1 later
|
120
|
-
* socket.
|
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
|
131
|
+
static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
128
132
|
struct sockaddr_in addrs[8];
|
129
|
-
int i,
|
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
|
-
|
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(
|
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(
|
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.
|
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
|
209
|
+
static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
|
205
210
|
struct sockaddr_in addrs[8];
|
206
|
-
int i, num_ip,
|
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
|
-
|
243
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
239
244
|
|
240
|
-
if(sctp_connectx(
|
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
|
262
|
+
VALUE v_fileno = rb_iv_get(self, "@fileno");
|
258
263
|
|
259
|
-
if(close(NUM2INT(
|
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,
|
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
|
-
|
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
|
-
|
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,
|
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
|
-
|
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
|
-
|
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,
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
635
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
523
636
|
|
524
637
|
num_bytes = sctp_send(
|
525
|
-
|
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
|
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
|
-
|
753
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
641
754
|
|
642
755
|
num_bytes = sctp_sendmsg(
|
643
|
-
|
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,
|
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
|
-
|
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
|
-
|
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
|
-
*
|
919
|
-
*
|
920
|
-
*
|
921
|
-
*
|
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
|
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
|
-
|
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(
|
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
|
959
|
-
* data that the socket may receive. The possible notification
|
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
|
1115
|
+
int fileno;
|
997
1116
|
struct sctp_event_subscribe events;
|
998
1117
|
|
999
1118
|
bzero(&events, sizeof(events));
|
1000
|
-
|
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(
|
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
|
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,
|
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 =
|
1191
|
+
backlog = 128;
|
1064
1192
|
else
|
1065
1193
|
backlog = NUM2INT(v_backlog);
|
1066
1194
|
|
1067
|
-
|
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(
|
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.
|
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
|
1222
|
+
int fileno, assoc_fileno;
|
1081
1223
|
sctp_assoc_t assoc_id;
|
1082
1224
|
|
1083
|
-
|
1225
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
1084
1226
|
assoc_id = NUM2INT(v_assoc_id);
|
1085
1227
|
|
1086
|
-
|
1228
|
+
assoc_fileno = sctp_peeloff(fileno, assoc_id);
|
1087
1229
|
|
1088
|
-
if(
|
1230
|
+
if(assoc_fileno < 0)
|
1089
1231
|
rb_raise(rb_eSystemCallError, "sctp_peeloff: %s", strerror(errno));
|
1090
1232
|
|
1091
|
-
|
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
|
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
|
-
|
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(
|
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
|
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
|
-
|
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(
|
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,
|
1332
|
+
int how, fileno;
|
1153
1333
|
VALUE v_how;
|
1154
1334
|
|
1155
|
-
|
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(
|
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
|
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
|
-
|
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(
|
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
|
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
|
-
|
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(
|
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, "
|
1627
|
+
rb_define_method(cSocket, "bindx", rsctp_bindx, -1);
|
1336
1628
|
rb_define_method(cSocket, "close", rsctp_close, 0);
|
1337
|
-
rb_define_method(cSocket, "
|
1338
|
-
rb_define_method(cSocket, "getpeernames", rsctp_getpeernames,
|
1339
|
-
rb_define_method(cSocket, "getlocalnames", rsctp_getlocalnames,
|
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
|
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, "
|
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
|
1365
|
-
rb_define_const(cSocket, "VERSION", rb_str_new2("0.0
|
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
|
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'
|
18
|
-
spec.add_development_dependency 'rake'
|
19
|
-
spec.add_development_dependency 'rake-compiler'
|
20
|
-
spec.add_development_dependency 'rspec'
|
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
|
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-
|
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: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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
|