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