sctp-socket 0.0.4 → 0.0.6
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/FUNDING.yml +4 -0
- data/.gitignore +1 -0
- data/CHANGES.md +14 -0
- data/Gemfile +2 -10
- data/README.md +16 -6
- data/Rakefile +10 -9
- data/examples/client_example.rb +31 -2
- data/examples/server_example.rb +21 -1
- data/ext/sctp/extconf.rb +26 -1
- data/ext/sctp/socket.c +364 -24
- data/sctp-socket.gemspec +11 -1
- data.tar.gz.sig +0 -0
- metadata +12 -4
- 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: 6a4c2e587ffc98a2c81d1d2a267fa4936539dc2456a9106a0146f31275e6db21
|
4
|
+
data.tar.gz: e5aa191fd3beb57240128ef58ef82df8f3b6beba3c25a5b357bc9b5effc7c238
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d023d5c17b03912812d02c8cb58279b5c874c45c481bdc1cd685dd89e8f2d62565512675d2cdc89f5e6b8107dce42634a3a1b4a063df8a6b32fed6762029adb4
|
7
|
+
data.tar.gz: 900e6fb83030d63453d99f9046942b2e6dfaee4340615d668669a922abc5628f58056aa464c9f36fe974ac0cccec4f3699fee7211778b6e49f49d856d7ea002d
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.github/FUNDING.yml
ADDED
data/.gitignore
CHANGED
data/CHANGES.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 0.0.6 - 24-May-2024
|
2
|
+
* Fixup the sendv method and add some documentation.
|
3
|
+
* Added documentation to the get_status method.
|
4
|
+
* Update the example server and client code, including comments for how to
|
5
|
+
setup multiple dummy IP addresses locally for testing.
|
6
|
+
* Some warning cleanup and build improvements.
|
7
|
+
* Added SCTP_BINDX constants.
|
8
|
+
* Started adding some real specs.
|
9
|
+
|
10
|
+
## 0.0.5 - 15-Dec-2021
|
11
|
+
* Add handling for Linux platforms that don't support the sctp_sendv function
|
12
|
+
and/or the SCTP_SEND_FAILED_EVENT notification.
|
13
|
+
* Some minor updates to Rakefile and Gemfile.
|
14
|
+
|
1
15
|
## 0.0.4 - 3-Dec-2020
|
2
16
|
* Added the send method. Use this when you already have a connection.
|
3
17
|
* Fixed a flags bug in the sendmsg method.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,17 +2,19 @@
|
|
2
2
|
|
3
3
|
A Ruby interface for SCTP sockets.
|
4
4
|
|
5
|
-
WARNING: THIS IS CURRENTLY AN ALPHA PRODUCT. NOT RECOMMENDED FOR PRODUCTION USE AT THIS TIME.
|
6
|
-
|
7
5
|
## Prerequisites
|
8
6
|
|
9
7
|
You will need the sctp development headers installed.
|
10
8
|
|
11
|
-
On some systems, such as RHEL8, you may need to enable the sctp module.
|
9
|
+
On some systems, such as RHEL8 or later, you may need to enable the sctp module.
|
12
10
|
|
13
11
|
## Installation
|
14
12
|
|
15
|
-
|
13
|
+
`gem install sctp-socket`
|
14
|
+
|
15
|
+
## Installing the Trusted Cert
|
16
|
+
|
17
|
+
`gem cert --add <(curl -Ls https://raw.githubusercontent.com/djberg96/sctp-socket/main/certs/djberg96_pub.pem)`
|
16
18
|
|
17
19
|
## About SCTP
|
18
20
|
|
@@ -30,7 +32,7 @@ is applied to correct loss or corruption of data.
|
|
30
32
|
|
31
33
|
## Synopsis
|
32
34
|
|
33
|
-
```
|
35
|
+
```ruby
|
34
36
|
# sample_server.rb
|
35
37
|
require 'sctp/socket'
|
36
38
|
|
@@ -62,17 +64,25 @@ end
|
|
62
64
|
Currently this has only been developed and tested on Linux. Other platforms
|
63
65
|
will probably only be supported via community contributions.
|
64
66
|
|
67
|
+
The sendv method is not available on some Linux variants. Use the sendmsg method instead.
|
68
|
+
|
65
69
|
Please report any issues on the github project page.
|
66
70
|
|
67
71
|
https://github.com/djberg96/sctp-socket
|
68
72
|
|
73
|
+
## More Information on SCTP
|
74
|
+
|
75
|
+
* https://www.linuxjournal.com/article/9748
|
76
|
+
* https://www.linuxjournal.com/article/9749
|
77
|
+
* https://www.linuxjournal.com/article/9784
|
78
|
+
|
69
79
|
## License
|
70
80
|
|
71
81
|
Apache-2.0
|
72
82
|
|
73
83
|
## Copyright
|
74
84
|
|
75
|
-
(C) 2020, Daniel J. Berger
|
85
|
+
(C) 2020-2024, Daniel J. Berger
|
76
86
|
Al Rights Reserved
|
77
87
|
|
78
88
|
## Author
|
data/Rakefile
CHANGED
@@ -6,20 +6,21 @@ require 'rake/extensiontask'
|
|
6
6
|
include RbConfig
|
7
7
|
|
8
8
|
CLEAN.include(
|
9
|
-
'**/*.gem',
|
10
|
-
'**/*.rbc',
|
11
|
-
'**/*.o',
|
12
|
-
'**/*.log',
|
13
|
-
'**/Makefile',
|
14
|
-
'**/conftest.dSYM',
|
15
|
-
"**/*.#{CONFIG['DLEXT']}" # C shared object
|
9
|
+
'**/*.gem', # Gem files
|
10
|
+
'**/*.rbc', # Rubinius
|
11
|
+
'**/*.o', # C object file
|
12
|
+
'**/*.log', # Ruby extension build log
|
13
|
+
'**/Makefile', # C Makefile
|
14
|
+
'**/conftest.dSYM', # OS X build directory
|
15
|
+
"**/*.#{CONFIG['DLEXT']}", # C shared object
|
16
|
+
'tmp' # Rake compiler
|
16
17
|
)
|
17
18
|
|
18
19
|
namespace :gem do
|
19
20
|
desc "Create the sys-uname gem"
|
20
21
|
task :create => [:clean] do
|
21
22
|
require 'rubygems/package'
|
22
|
-
spec =
|
23
|
+
spec = Gem::Specification.load('sctp-socket.gemspec')
|
23
24
|
spec.signing_key = File.join(Dir.home, '.ssh', 'gem-private_key.pem')
|
24
25
|
Gem::Package.build(spec)
|
25
26
|
end
|
@@ -39,4 +40,4 @@ end
|
|
39
40
|
RSpec::Core::RakeTask.new
|
40
41
|
|
41
42
|
task :spec => :compile
|
42
|
-
task :default => :spec
|
43
|
+
task :default => [:clean, :spec]
|
data/examples/client_example.rb
CHANGED
@@ -1,11 +1,40 @@
|
|
1
1
|
require 'socket'
|
2
2
|
require 'sctp/socket'
|
3
3
|
|
4
|
+
# Adjust as needed. Server server_example.rb for creating
|
5
|
+
# fake network interfaces for testing.
|
6
|
+
addresses = ['1.1.1.1', '1.1.1.2']
|
7
|
+
|
4
8
|
begin
|
5
9
|
port = 62324
|
6
10
|
socket = SCTP::Socket.new
|
7
|
-
|
8
|
-
|
11
|
+
|
12
|
+
# Optional, but could bind to a subset of available addresses
|
13
|
+
p socket.bind(:addresses => addresses)
|
14
|
+
|
15
|
+
# Initial connection
|
16
|
+
p socket.connect(:addresses => addresses, :port => port)
|
17
|
+
|
18
|
+
# Try a sendv
|
19
|
+
p socket.sendv(:message => ["Hello ", "World!"])
|
20
|
+
|
21
|
+
# Send messages on separate streams of the same connection
|
22
|
+
arr = []
|
23
|
+
|
24
|
+
0.upto(4) do |n|
|
25
|
+
arr << Thread.new do |t|
|
26
|
+
puts "Stream: #{n}"
|
27
|
+
bytes_sent = socket.sendmsg(
|
28
|
+
:message => "Hello World: #{n+1}",
|
29
|
+
:addresses => addresses.shuffle,
|
30
|
+
:stream => n,
|
31
|
+
:port => port
|
32
|
+
)
|
33
|
+
puts "Bytes Sent: #{bytes_sent}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
arr.map(&:join)
|
9
38
|
ensure
|
10
39
|
socket.close if socket
|
11
40
|
end
|
data/examples/server_example.rb
CHANGED
@@ -1,11 +1,31 @@
|
|
1
1
|
require 'sctp/socket'
|
2
2
|
|
3
|
+
# rake compile + ruby -Ilib to run local version
|
4
|
+
puts "VERSION: #{SCTP::Socket::VERSION}"
|
5
|
+
|
6
|
+
# To test multiple IP addresses locally:
|
7
|
+
#
|
8
|
+
# sudo apt install iproute2
|
9
|
+
# Add 'dummy' to /etc/modules
|
10
|
+
#
|
11
|
+
# sudo ip link add dummy1 type dummy
|
12
|
+
# sudo ip link add dummy2 type dummy
|
13
|
+
#
|
14
|
+
# sudo ip addr add 1.1.1.1/24 dev dummy1
|
15
|
+
# sudo ip addr add 1.1.1.2/24 dev dummy2
|
16
|
+
#
|
17
|
+
# sudo ip link set dummy1 up
|
18
|
+
# sudo ip link set dummy2 up
|
19
|
+
|
3
20
|
# Adjust IP addresses as needed
|
21
|
+
addresses = ['1.1.1.1', '1.1.1.2']
|
22
|
+
|
4
23
|
begin
|
5
24
|
port = 62324
|
6
25
|
socket = SCTP::Socket.new
|
7
|
-
socket.bind(:port => port, :addresses =>
|
26
|
+
socket.bind(:port => port, :addresses => addresses)
|
8
27
|
socket.set_initmsg(:output_streams => 5, :input_streams => 5, :max_attempts => 4)
|
28
|
+
socket.subscribe(:data_io => true, :shutdown => true, :send_failure => true, :partial_delivery => true)
|
9
29
|
socket.listen
|
10
30
|
|
11
31
|
while true
|
data/ext/sctp/extconf.rb
CHANGED
@@ -1,5 +1,30 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
|
3
|
-
|
3
|
+
dir_config('sctp')
|
4
|
+
|
5
|
+
unless have_header('netinet/sctp.h')
|
6
|
+
os = IO.readlines('/etc/os-release').first.split('=').last
|
7
|
+
msg = "\nSCTP HEADERS NOT FOUND. PLEASE INSTALL THEM FIRST LIKE SO:\n\n"
|
8
|
+
|
9
|
+
if os =~ /red|fedora|centos/i
|
10
|
+
msg << "#####################################################################################\n"
|
11
|
+
msg << "# dnf install lksctp-tools #\n"
|
12
|
+
msg << "# dnf install kernel-modules-extra #\n"
|
13
|
+
msg << "# #\n"
|
14
|
+
msg << "# sed -e '/blacklist sctp/s/^b/#b/g' -i /etc/modprobe.d/sctp-blacklist.conf #\n"
|
15
|
+
msg << "# sed -e '/blacklist sctp/s/^b/#b/g' -i /etc/modprobe.d/sctp_diag-blacklist.conf #\n"
|
16
|
+
msg << "# #\n"
|
17
|
+
msg << "# sudo systemctl restart systemd-modules-load.service #\n"
|
18
|
+
msg << "#####################################################################################\n"
|
19
|
+
else
|
20
|
+
msg << "sudo apt-get install libsctp-dev lksctp-tools\n\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
warn msg
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
|
4
27
|
have_library('sctp')
|
28
|
+
have_func('sctp_sendv', 'netinet/sctp.h')
|
29
|
+
have_struct_member('struct sctp_event_subscribe', 'sctp_send_failure_event', 'netinet/sctp.h')
|
5
30
|
create_makefile('sctp/socket')
|
data/ext/sctp/socket.c
CHANGED
@@ -17,11 +17,27 @@ VALUE v_adaptation_event_struct;
|
|
17
17
|
VALUE v_partial_delivery_event_struct;
|
18
18
|
VALUE v_auth_event_struct;
|
19
19
|
VALUE v_sockaddr_in_struct;
|
20
|
-
|
20
|
+
VALUE v_sctp_status_struct;
|
21
|
+
VALUE v_sctp_rtoinfo_struct;
|
22
|
+
VALUE v_sctp_associnfo_struct;
|
23
|
+
VALUE v_sctp_default_send_params_struct;
|
24
|
+
|
25
|
+
#if !defined(IOV_MAX)
|
26
|
+
#if defined(_SC_IOV_MAX)
|
27
|
+
#define IOV_MAX (sysconf(_SC_IOV_MAX))
|
28
|
+
#else
|
29
|
+
#define IOV_MAX INT_MAX
|
30
|
+
#endif
|
31
|
+
#endif
|
32
|
+
|
33
|
+
// TODO: Yes, I know I need to update the signature.
|
21
34
|
VALUE convert_sockaddr_in_to_struct(struct sockaddr_in* addr){
|
22
|
-
char ipbuf[
|
35
|
+
char ipbuf[INET6_ADDRSTRLEN];
|
23
36
|
|
24
|
-
|
37
|
+
if(addr->sin_family == AF_INET6)
|
38
|
+
inet_ntop(addr->sin_family, &(((struct sockaddr_in6 *)addr)->sin6_addr), ipbuf, sizeof(ipbuf));
|
39
|
+
else
|
40
|
+
inet_ntop(addr->sin_family, &(((struct sockaddr_in *)addr)->sin_addr), ipbuf, sizeof(ipbuf));
|
25
41
|
|
26
42
|
return rb_struct_new(v_sockaddr_in_struct,
|
27
43
|
INT2NUM(addr->sin_family),
|
@@ -169,6 +185,8 @@ static VALUE rsctp_bind(int argc, VALUE* argv, VALUE self){
|
|
169
185
|
port = sin.sin_port;
|
170
186
|
}
|
171
187
|
|
188
|
+
rb_iv_set(self, "@port", INT2NUM(port));
|
189
|
+
|
172
190
|
return INT2NUM(port);
|
173
191
|
}
|
174
192
|
|
@@ -316,6 +334,114 @@ static VALUE rsctp_getlocalnames(VALUE self){
|
|
316
334
|
return v_array;
|
317
335
|
}
|
318
336
|
|
337
|
+
#ifdef HAVE_SCTP_SENDV
|
338
|
+
/*
|
339
|
+
* Transmit a message to an SCTP endpoint using a gather-write. The following
|
340
|
+
* hash of options is permitted:
|
341
|
+
*
|
342
|
+
* * message - An array of strings that will be joined into a single message.
|
343
|
+
* * addresses - An array of IP addresses to setup an association to send the message.
|
344
|
+
* * info_type - The type of information provided. The default is SCTP_SENDV_SNDINFO.
|
345
|
+
*
|
346
|
+
* Example:
|
347
|
+
*
|
348
|
+
* socket = SCTP::Socket.new
|
349
|
+
*
|
350
|
+
* socket.sendv
|
351
|
+
* :message => ['Hello ', 'World.'],
|
352
|
+
* :addresses => ['10.0.5.4', '10.0.6.4'],
|
353
|
+
* :info_type => SCTP::Socket:::SCTP_SENDV_SNDINFO
|
354
|
+
* )
|
355
|
+
*
|
356
|
+
* CAVEAT: Currently addresses does not work, and info_type is not yet supported.
|
357
|
+
*
|
358
|
+
* Returns the number of bytes sent.
|
359
|
+
*/
|
360
|
+
static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
361
|
+
VALUE v_msg, v_message, v_addresses;
|
362
|
+
struct iovec iov[IOV_MAX];
|
363
|
+
struct sockaddr_in* addrs;
|
364
|
+
struct sctp_sndinfo info;
|
365
|
+
int i, sock_fd, num_bytes, size, num_ip;
|
366
|
+
|
367
|
+
Check_Type(v_options, T_HASH);
|
368
|
+
|
369
|
+
bzero(&iov, sizeof(iov));
|
370
|
+
bzero(&info, sizeof(info));
|
371
|
+
|
372
|
+
v_message = rb_hash_aref2(v_options, "message");
|
373
|
+
v_addresses = rb_hash_aref2(v_options, "addresses");
|
374
|
+
|
375
|
+
if(!NIL_P(v_message))
|
376
|
+
Check_Type(v_message, T_ARRAY);
|
377
|
+
|
378
|
+
if(!NIL_P(v_addresses)){
|
379
|
+
Check_Type(v_addresses, T_ARRAY);
|
380
|
+
num_ip = RARRAY_LEN(v_addresses);
|
381
|
+
addrs = (struct sockaddr_in*)alloca(sizeof(struct sockaddr_in) * num_ip);
|
382
|
+
}
|
383
|
+
else{
|
384
|
+
addrs = NULL;
|
385
|
+
num_ip = 0;
|
386
|
+
}
|
387
|
+
|
388
|
+
sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
|
389
|
+
size = RARRAY_LEN(v_message);
|
390
|
+
|
391
|
+
if(!size)
|
392
|
+
rb_raise(rb_eArgError, "Must contain at least one message");
|
393
|
+
|
394
|
+
if(size > IOV_MAX)
|
395
|
+
rb_raise(rb_eArgError, "Array size is greater than IOV_MAX");
|
396
|
+
|
397
|
+
info.snd_flags = SCTP_UNORDERED;
|
398
|
+
info.snd_assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
399
|
+
|
400
|
+
if(!NIL_P(v_addresses)){
|
401
|
+
int i, port;
|
402
|
+
VALUE v_address, v_port;
|
403
|
+
|
404
|
+
v_port = NUM2INT(rb_iv_get(self, "@port"));
|
405
|
+
|
406
|
+
if(NIL_P(v_port))
|
407
|
+
port = 0;
|
408
|
+
else
|
409
|
+
port = NUM2INT(v_port);
|
410
|
+
|
411
|
+
for(i = 0; i < num_ip; i++){
|
412
|
+
v_address = RARRAY_PTR(v_addresses)[i];
|
413
|
+
addrs->sin_family = NUM2INT(rb_iv_get(self, "@domain"));
|
414
|
+
addrs->sin_port = htons(port);
|
415
|
+
addrs->sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
|
416
|
+
addrs += sizeof(struct sockaddr_in);
|
417
|
+
}
|
418
|
+
}
|
419
|
+
|
420
|
+
for(i = 0; i < size; i++){
|
421
|
+
v_msg = RARRAY_PTR(v_message)[i];
|
422
|
+
iov[i].iov_base = StringValueCStr(v_msg);
|
423
|
+
iov[i].iov_len = RSTRING_LEN(v_msg);
|
424
|
+
}
|
425
|
+
|
426
|
+
num_bytes = sctp_sendv(
|
427
|
+
sock_fd,
|
428
|
+
iov,
|
429
|
+
size,
|
430
|
+
(struct sockaddr*)addrs,
|
431
|
+
num_ip,
|
432
|
+
&info,
|
433
|
+
sizeof(info),
|
434
|
+
SCTP_SENDV_SNDINFO,
|
435
|
+
0
|
436
|
+
);
|
437
|
+
|
438
|
+
if(num_bytes < 0)
|
439
|
+
rb_raise(rb_eSystemCallError, "sctp_sendv: %s", strerror(errno));
|
440
|
+
|
441
|
+
return INT2NUM(num_bytes);
|
442
|
+
}
|
443
|
+
#endif
|
444
|
+
|
319
445
|
/*
|
320
446
|
* Send a message on an already-connected socket to a specific association.
|
321
447
|
*
|
@@ -413,14 +539,14 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
|
|
413
539
|
* Transmit a message to an SCTP endpoint. The following hash of options
|
414
540
|
* is permitted:
|
415
541
|
*
|
416
|
-
* :message
|
417
|
-
* :stream
|
418
|
-
* :
|
419
|
-
* :context
|
420
|
-
* :ppid
|
421
|
-
* :flags
|
542
|
+
* :message -> The message to send to the endpoint. Mandatory.
|
543
|
+
* :stream -> The SCTP stream number you wish to send the message on.
|
544
|
+
* :addresses -> An array of addresses to send the message to.
|
545
|
+
* :context -> The default context used for the sendmsg call if the send fails.
|
546
|
+
* :ppid -> The payload protocol identifier that is passed to the peer endpoint.
|
547
|
+
* :flags -> A bitwise integer that contain one or more values that control behavior.
|
422
548
|
*
|
423
|
-
* Note that the :
|
549
|
+
* Note that the :addresses option is not mandatory in a one-to-one (SOCK_STREAM)
|
424
550
|
* socket connection. However, it must have been set previously via the
|
425
551
|
* connect method.
|
426
552
|
*
|
@@ -429,12 +555,14 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
|
|
429
555
|
* socket = SCTP::Socket.new
|
430
556
|
*
|
431
557
|
* socket.sendmsg(
|
432
|
-
* :message
|
433
|
-
* :stream
|
434
|
-
* :flags
|
435
|
-
* :ttl
|
436
|
-
* :
|
558
|
+
* :message => "Hello World!",
|
559
|
+
* :stream => 3,
|
560
|
+
* :flags => SCTP::Socket::SCTP_UNORDERED | SCTP::Socket::SCTP_SENDALL,
|
561
|
+
* :ttl => 100,
|
562
|
+
* :addresses => ['10.0.5.4', '10.0.6.4']
|
437
563
|
* )
|
564
|
+
*
|
565
|
+
* Returns the number of bytes sent.
|
438
566
|
*/
|
439
567
|
static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
440
568
|
VALUE v_msg, v_ppid, v_flags, v_stream, v_ttl, v_context, v_addresses;
|
@@ -566,7 +694,10 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
566
694
|
|
567
695
|
sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
|
568
696
|
length = sizeof(struct sockaddr_in);
|
697
|
+
|
569
698
|
bzero(buffer, sizeof(buffer));
|
699
|
+
bzero(&clientaddr, sizeof(clientaddr));
|
700
|
+
bzero(&sndrcvinfo, sizeof(sndrcvinfo));
|
570
701
|
|
571
702
|
bytes = sctp_recvmsg(
|
572
703
|
sock_fd,
|
@@ -678,6 +809,7 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
678
809
|
rb_ary_new4(snp->sn_remote_error.sre_length, v_temp)
|
679
810
|
);
|
680
811
|
break;
|
812
|
+
#ifdef SCTP_SEND_FAILED_EVENT
|
681
813
|
case SCTP_SEND_FAILED_EVENT:
|
682
814
|
v_temp = ALLOCA_N(VALUE, snp->sn_send_failed_event.ssf_length);
|
683
815
|
|
@@ -700,6 +832,24 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
700
832
|
rb_ary_new4(snp->sn_send_failed_event.ssf_length, v_temp)
|
701
833
|
);
|
702
834
|
break;
|
835
|
+
#else
|
836
|
+
case SCTP_SEND_FAILED:
|
837
|
+
v_temp = ALLOCA_N(VALUE, snp->sn_send_failed.ssf_length);
|
838
|
+
|
839
|
+
for(i = 0; i < snp->sn_send_failed.ssf_length; i++){
|
840
|
+
v_temp[i] = UINT2NUM(snp->sn_send_failed.ssf_data[i]);
|
841
|
+
}
|
842
|
+
|
843
|
+
v_notification = rb_struct_new(v_send_failed_event_struct,
|
844
|
+
UINT2NUM(snp->sn_send_failed.ssf_type),
|
845
|
+
UINT2NUM(snp->sn_send_failed.ssf_length),
|
846
|
+
UINT2NUM(snp->sn_send_failed.ssf_error),
|
847
|
+
Qnil,
|
848
|
+
UINT2NUM(snp->sn_send_failed.ssf_assoc_id),
|
849
|
+
rb_ary_new4(snp->sn_send_failed.ssf_length, v_temp)
|
850
|
+
);
|
851
|
+
break;
|
852
|
+
#endif
|
703
853
|
case SCTP_SHUTDOWN_EVENT:
|
704
854
|
v_notification = rb_struct_new(v_shutdown_event_struct,
|
705
855
|
UINT2NUM(snp->sn_shutdown_event.sse_type),
|
@@ -822,7 +972,7 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
|
|
822
972
|
* - The peer has sent a shutdown to the local endpoint.
|
823
973
|
*
|
824
974
|
* :data_io
|
825
|
-
* - Message data was received.
|
975
|
+
* - Message data was received. You will want to subscribe to this in most cases.
|
826
976
|
*
|
827
977
|
* Others:
|
828
978
|
*
|
@@ -835,14 +985,12 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
|
|
835
985
|
* :sender_dry
|
836
986
|
* :peer_error
|
837
987
|
*
|
838
|
-
* By default only data_io is subscribed to.
|
839
|
-
*
|
840
988
|
* Example:
|
841
989
|
*
|
842
990
|
* socket = SCTP::Socket.new
|
843
991
|
*
|
844
992
|
* socket.bind(:port => port, :addresses => ['127.0.0.1'])
|
845
|
-
* socket.subscribe(:shutdown => true, :send_failure => true)
|
993
|
+
* socket.subscribe(:data_io => true, :shutdown => true, :send_failure => true)
|
846
994
|
*/
|
847
995
|
static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
|
848
996
|
int sock_fd;
|
@@ -860,9 +1008,12 @@ static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
|
|
860
1008
|
if(RTEST(rb_hash_aref2(v_options, "address")))
|
861
1009
|
events.sctp_address_event = 1;
|
862
1010
|
|
863
|
-
// Use the new version
|
864
1011
|
if(RTEST(rb_hash_aref2(v_options, "send_failure")))
|
1012
|
+
#ifdef HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_SEND_FAILURE_EVENT
|
1013
|
+
events.sctp_send_failure_event = 1;
|
1014
|
+
#else
|
865
1015
|
events.sctp_send_failure_event_event = 1;
|
1016
|
+
#endif
|
866
1017
|
|
867
1018
|
if(RTEST(rb_hash_aref2(v_options, "peer_error")))
|
868
1019
|
events.sctp_peer_error_event = 1;
|
@@ -916,7 +1067,7 @@ static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
|
|
916
1067
|
sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
|
917
1068
|
|
918
1069
|
if(listen(sock_fd, backlog) < 0)
|
919
|
-
rb_raise(rb_eSystemCallError, "
|
1070
|
+
rb_raise(rb_eSystemCallError, "listen: %s", strerror(errno));
|
920
1071
|
|
921
1072
|
return self;
|
922
1073
|
}
|
@@ -942,6 +1093,61 @@ static VALUE rsctp_peeloff(VALUE self, VALUE v_assoc_id){
|
|
942
1093
|
return self;
|
943
1094
|
}
|
944
1095
|
|
1096
|
+
static VALUE rsctp_get_default_send_params(VALUE self){
|
1097
|
+
int sock_fd;
|
1098
|
+
socklen_t size;
|
1099
|
+
sctp_assoc_t assoc_id;
|
1100
|
+
struct sctp_sndrcvinfo sndrcv;
|
1101
|
+
|
1102
|
+
bzero(&sndrcv, sizeof(sndrcv));
|
1103
|
+
|
1104
|
+
sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
|
1105
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
1106
|
+
size = sizeof(struct sctp_sndrcvinfo);
|
1107
|
+
|
1108
|
+
if(sctp_opt_info(sock_fd, assoc_id, SCTP_DEFAULT_SEND_PARAM, (void*)&sndrcv, &size) < 0)
|
1109
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
1110
|
+
|
1111
|
+
return rb_struct_new(
|
1112
|
+
v_sctp_default_send_params_struct,
|
1113
|
+
INT2NUM(sndrcv.sinfo_stream),
|
1114
|
+
INT2NUM(sndrcv.sinfo_ssn),
|
1115
|
+
INT2NUM(sndrcv.sinfo_flags),
|
1116
|
+
INT2NUM(sndrcv.sinfo_ppid),
|
1117
|
+
INT2NUM(sndrcv.sinfo_context),
|
1118
|
+
INT2NUM(sndrcv.sinfo_timetolive),
|
1119
|
+
INT2NUM(sndrcv.sinfo_tsn),
|
1120
|
+
INT2NUM(sndrcv.sinfo_cumtsn),
|
1121
|
+
INT2NUM(sndrcv.sinfo_assoc_id)
|
1122
|
+
);
|
1123
|
+
}
|
1124
|
+
|
1125
|
+
static VALUE rsctp_get_association_info(VALUE self){
|
1126
|
+
int sock_fd;
|
1127
|
+
socklen_t size;
|
1128
|
+
sctp_assoc_t assoc_id;
|
1129
|
+
struct sctp_assocparams assoc;
|
1130
|
+
|
1131
|
+
bzero(&assoc, sizeof(assoc));
|
1132
|
+
|
1133
|
+
sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
|
1134
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
1135
|
+
size = sizeof(struct sctp_assocparams);
|
1136
|
+
|
1137
|
+
if(sctp_opt_info(sock_fd, assoc_id, SCTP_ASSOCINFO, (void*)&assoc, &size) < 0)
|
1138
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
1139
|
+
|
1140
|
+
return rb_struct_new(
|
1141
|
+
v_sctp_associnfo_struct,
|
1142
|
+
INT2NUM(assoc.sasoc_assoc_id),
|
1143
|
+
INT2NUM(assoc.sasoc_asocmaxrxt),
|
1144
|
+
INT2NUM(assoc.sasoc_number_peer_destinations),
|
1145
|
+
INT2NUM(assoc.sasoc_peer_rwnd),
|
1146
|
+
INT2NUM(assoc.sasoc_local_rwnd),
|
1147
|
+
INT2NUM(assoc.sasoc_cookie_life)
|
1148
|
+
);
|
1149
|
+
}
|
1150
|
+
|
945
1151
|
static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
|
946
1152
|
int how, sock_fd;
|
947
1153
|
VALUE v_how;
|
@@ -964,7 +1170,95 @@ static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
|
|
964
1170
|
return self;
|
965
1171
|
}
|
966
1172
|
|
967
|
-
|
1173
|
+
static VALUE rsctp_get_retransmission_info(VALUE self){
|
1174
|
+
int sock_fd;
|
1175
|
+
socklen_t size;
|
1176
|
+
sctp_assoc_t assoc_id;
|
1177
|
+
struct sctp_rtoinfo rto;
|
1178
|
+
|
1179
|
+
bzero(&rto, sizeof(rto));
|
1180
|
+
|
1181
|
+
sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
|
1182
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
1183
|
+
size = sizeof(struct sctp_rtoinfo);
|
1184
|
+
|
1185
|
+
if(sctp_opt_info(sock_fd, assoc_id, SCTP_RTOINFO, (void*)&rto, &size) < 0)
|
1186
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
1187
|
+
|
1188
|
+
return rb_struct_new(
|
1189
|
+
v_sctp_rtoinfo_struct,
|
1190
|
+
INT2NUM(rto.srto_assoc_id),
|
1191
|
+
INT2NUM(rto.srto_initial),
|
1192
|
+
INT2NUM(rto.srto_max),
|
1193
|
+
INT2NUM(rto.srto_min)
|
1194
|
+
);
|
1195
|
+
}
|
1196
|
+
|
1197
|
+
/*
|
1198
|
+
* Get the status of a connected socket.
|
1199
|
+
*
|
1200
|
+
* Example:
|
1201
|
+
*
|
1202
|
+
* socket = SCTP::Socket.new
|
1203
|
+
* socket.connect(...)
|
1204
|
+
* socket.get_status
|
1205
|
+
*
|
1206
|
+
* Returns a Struct::Status object, which contains the following fields:
|
1207
|
+
*
|
1208
|
+
* * association_id
|
1209
|
+
* * state
|
1210
|
+
* * receive_window
|
1211
|
+
* * unacknowledged_data
|
1212
|
+
* * pending_data
|
1213
|
+
* * inbound_streams
|
1214
|
+
* * outbound_streams
|
1215
|
+
* * fragmentation_point
|
1216
|
+
* * primary (IP)
|
1217
|
+
*/
|
1218
|
+
static VALUE rsctp_get_status(VALUE self){
|
1219
|
+
int sock_fd;
|
1220
|
+
socklen_t size;
|
1221
|
+
sctp_assoc_t assoc_id;
|
1222
|
+
struct sctp_status status;
|
1223
|
+
struct sctp_paddrinfo* spinfo;
|
1224
|
+
char tmpname[INET_ADDRSTRLEN];
|
1225
|
+
|
1226
|
+
bzero(&status, sizeof(status));
|
1227
|
+
|
1228
|
+
sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
|
1229
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
1230
|
+
size = sizeof(struct sctp_status);
|
1231
|
+
|
1232
|
+
if(sctp_opt_info(sock_fd, assoc_id, SCTP_STATUS, (void*)&status, &size) < 0)
|
1233
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
1234
|
+
|
1235
|
+
spinfo = &status.sstat_primary;
|
1236
|
+
|
1237
|
+
if (spinfo->spinfo_address.ss_family == AF_INET6) {
|
1238
|
+
struct sockaddr_in6 *sin6;
|
1239
|
+
sin6 = (struct sockaddr_in6 *)&spinfo->spinfo_address;
|
1240
|
+
inet_ntop(AF_INET6, &sin6->sin6_addr, tmpname, sizeof (tmpname));
|
1241
|
+
}
|
1242
|
+
else {
|
1243
|
+
struct sockaddr_in *sin;
|
1244
|
+
sin = (struct sockaddr_in *)&spinfo->spinfo_address;
|
1245
|
+
inet_ntop(AF_INET, &sin->sin_addr, tmpname, sizeof (tmpname));
|
1246
|
+
}
|
1247
|
+
|
1248
|
+
return rb_struct_new(v_sctp_status_struct,
|
1249
|
+
INT2NUM(status.sstat_assoc_id),
|
1250
|
+
INT2NUM(status.sstat_state),
|
1251
|
+
INT2NUM(status.sstat_rwnd),
|
1252
|
+
INT2NUM(status.sstat_unackdata),
|
1253
|
+
INT2NUM(status.sstat_penddata),
|
1254
|
+
INT2NUM(status.sstat_instrms),
|
1255
|
+
INT2NUM(status.sstat_outstrms),
|
1256
|
+
INT2NUM(status.sstat_fragmentation_point),
|
1257
|
+
rb_str_new2(tmpname)
|
1258
|
+
);
|
1259
|
+
}
|
1260
|
+
|
1261
|
+
void Init_socket(void){
|
968
1262
|
mSCTP = rb_define_module("SCTP");
|
969
1263
|
cSocket = rb_define_class_under(mSCTP, "Socket", rb_cObject);
|
970
1264
|
|
@@ -1016,6 +1310,26 @@ void Init_socket(){
|
|
1016
1310
|
"SockAddrIn", "family", "port", "address", NULL
|
1017
1311
|
);
|
1018
1312
|
|
1313
|
+
v_sctp_status_struct = rb_struct_define(
|
1314
|
+
"Status", "association_id", "state", "receive_window", "unacknowledged_data",
|
1315
|
+
"pending_data", "inbound_streams", "outbound_streams", "fragmentation_point", "primary", NULL
|
1316
|
+
);
|
1317
|
+
|
1318
|
+
v_sctp_rtoinfo_struct = rb_struct_define(
|
1319
|
+
"RetransmissionInfo", "association_id", "initial", "max", "min", NULL
|
1320
|
+
);
|
1321
|
+
|
1322
|
+
v_sctp_associnfo_struct = rb_struct_define(
|
1323
|
+
"AssociationInfo", "association_id", "max_retransmission_count",
|
1324
|
+
"number_peer_destinations", "peer_receive_window", "local_receive_window",
|
1325
|
+
"cookie_life", NULL
|
1326
|
+
);
|
1327
|
+
|
1328
|
+
v_sctp_default_send_params_struct = rb_struct_define(
|
1329
|
+
"DefaultSendParams", "stream", "ssn", "flags", "ppid", "context",
|
1330
|
+
"ttl", "tsn", "cumtsn", "association_id", NULL
|
1331
|
+
);
|
1332
|
+
|
1019
1333
|
rb_define_method(cSocket, "initialize", rsctp_init, -1);
|
1020
1334
|
|
1021
1335
|
rb_define_method(cSocket, "bind", rsctp_bind, -1);
|
@@ -1023,10 +1337,19 @@ void Init_socket(){
|
|
1023
1337
|
rb_define_method(cSocket, "connect", rsctp_connect, -1);
|
1024
1338
|
rb_define_method(cSocket, "getpeernames", rsctp_getpeernames, 0);
|
1025
1339
|
rb_define_method(cSocket, "getlocalnames", rsctp_getlocalnames, 0);
|
1340
|
+
rb_define_method(cSocket, "get_status", rsctp_get_status, 0);
|
1341
|
+
rb_define_method(cSocket, "get_default_send_params", rsctp_get_default_send_params, 0);
|
1342
|
+
rb_define_method(cSocket, "get_retransmission_info", rsctp_get_retransmission_info, 0);
|
1343
|
+
rb_define_method(cSocket, "get_association_info", rsctp_get_association_info, 0);
|
1026
1344
|
rb_define_method(cSocket, "listen", rsctp_listen, -1);
|
1027
1345
|
rb_define_method(cSocket, "peeloff!", rsctp_peeloff, 1);
|
1028
1346
|
rb_define_method(cSocket, "recvmsg", rsctp_recvmsg, -1);
|
1029
1347
|
rb_define_method(cSocket, "send", rsctp_send, 1);
|
1348
|
+
|
1349
|
+
#ifdef HAVE_SCTP_SENDV
|
1350
|
+
rb_define_method(cSocket, "sendv", rsctp_sendv, 1);
|
1351
|
+
#endif
|
1352
|
+
|
1030
1353
|
rb_define_method(cSocket, "sendmsg", rsctp_sendmsg, 1);
|
1031
1354
|
rb_define_method(cSocket, "set_initmsg", rsctp_set_initmsg, 1);
|
1032
1355
|
rb_define_method(cSocket, "shutdown", rsctp_shutdown, -1);
|
@@ -1038,8 +1361,8 @@ void Init_socket(){
|
|
1038
1361
|
rb_define_attr(cSocket, "association_id", 1, 1);
|
1039
1362
|
rb_define_attr(cSocket, "port", 1, 1);
|
1040
1363
|
|
1041
|
-
/* 0.0.
|
1042
|
-
rb_define_const(cSocket, "VERSION", rb_str_new2("0.0.
|
1364
|
+
/* 0.0.6: The version of this library */
|
1365
|
+
rb_define_const(cSocket, "VERSION", rb_str_new2("0.0.6"));
|
1043
1366
|
|
1044
1367
|
/* send flags */
|
1045
1368
|
|
@@ -1059,4 +1382,21 @@ void Init_socket(){
|
|
1059
1382
|
rb_define_const(cSocket, "SCTP_SENDALL", INT2NUM(SCTP_SENDALL));
|
1060
1383
|
|
1061
1384
|
rb_define_const(cSocket, "MSG_NOTIFICATION", INT2NUM(MSG_NOTIFICATION));
|
1385
|
+
|
1386
|
+
// ASSOCIATION STATES //
|
1387
|
+
|
1388
|
+
rb_define_const(cSocket, "SCTP_EMPTY", INT2NUM(SCTP_EMPTY));
|
1389
|
+
rb_define_const(cSocket, "SCTP_CLOSED", INT2NUM(SCTP_CLOSED));
|
1390
|
+
rb_define_const(cSocket, "SCTP_COOKIE_WAIT", INT2NUM(SCTP_COOKIE_WAIT));
|
1391
|
+
rb_define_const(cSocket, "SCTP_COOKIE_ECHOED", INT2NUM(SCTP_COOKIE_ECHOED));
|
1392
|
+
rb_define_const(cSocket, "SCTP_ESTABLISHED", INT2NUM(SCTP_ESTABLISHED));
|
1393
|
+
rb_define_const(cSocket, "SCTP_SHUTDOWN_PENDING", INT2NUM(SCTP_SHUTDOWN_PENDING));
|
1394
|
+
rb_define_const(cSocket, "SCTP_SHUTDOWN_SENT", INT2NUM(SCTP_SHUTDOWN_SENT));
|
1395
|
+
rb_define_const(cSocket, "SCTP_SHUTDOWN_RECEIVED", INT2NUM(SCTP_SHUTDOWN_RECEIVED));
|
1396
|
+
rb_define_const(cSocket, "SCTP_SHUTDOWN_ACK_SENT", INT2NUM(SCTP_SHUTDOWN_ACK_SENT));
|
1397
|
+
|
1398
|
+
// BINDING //
|
1399
|
+
|
1400
|
+
rb_define_const(cSocket, "SCTP_BINDX_ADD_ADDR", INT2NUM(SCTP_BINDX_ADD_ADDR));
|
1401
|
+
rb_define_const(cSocket, "SCTP_BINDX_REM_ADDR", INT2NUM(SCTP_BINDX_REM_ADDR));
|
1062
1402
|
}
|
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.0.6'
|
4
4
|
spec.author = 'Daniel Berger'
|
5
5
|
spec.email = 'djberg96@gmail.com'
|
6
6
|
spec.summary = 'Ruby bindings for SCTP sockets'
|
@@ -19,6 +19,16 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.add_development_dependency 'rake-compiler', '~> 1.1'
|
20
20
|
spec.add_development_dependency 'rspec', '~> 3.9'
|
21
21
|
|
22
|
+
spec.metadata = {
|
23
|
+
'homepage_uri' => 'https://github.com/djberg96/sctp-socket',
|
24
|
+
'bug_tracker_uri' => 'https://github.com/djberg96/sctp-socket/issues',
|
25
|
+
'changelog_uri' => 'https://github.com/djberg96/sctp-socket/blob/main/CHANGES.md',
|
26
|
+
'documentation_uri' => 'https://github.com/djberg96/sctp-socket/wiki',
|
27
|
+
'source_code_uri' => 'https://github.com/djberg96/sctp-socket',
|
28
|
+
'wiki_uri' => 'https://github.com/djberg96/sctp-socket/wiki',
|
29
|
+
'rubygems_mfa_required' => 'true'
|
30
|
+
}
|
31
|
+
|
22
32
|
spec.description = <<-EOF
|
23
33
|
The sctp-socket library provides Ruby bindings for SCTP sockets. is a
|
24
34
|
message oriented, reliable transport protocol with direct support for
|
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.0.6
|
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:
|
38
|
+
date: 2024-05-25 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: bundler
|
@@ -103,6 +103,7 @@ extensions:
|
|
103
103
|
- ext/sctp/extconf.rb
|
104
104
|
extra_rdoc_files: []
|
105
105
|
files:
|
106
|
+
- ".github/FUNDING.yml"
|
106
107
|
- ".gitignore"
|
107
108
|
- CHANGES.md
|
108
109
|
- Gemfile
|
@@ -122,7 +123,14 @@ files:
|
|
122
123
|
homepage: https://github.com/djberg96/sctp-socket
|
123
124
|
licenses:
|
124
125
|
- Apache-2.0
|
125
|
-
metadata:
|
126
|
+
metadata:
|
127
|
+
homepage_uri: https://github.com/djberg96/sctp-socket
|
128
|
+
bug_tracker_uri: https://github.com/djberg96/sctp-socket/issues
|
129
|
+
changelog_uri: https://github.com/djberg96/sctp-socket/blob/main/CHANGES.md
|
130
|
+
documentation_uri: https://github.com/djberg96/sctp-socket/wiki
|
131
|
+
source_code_uri: https://github.com/djberg96/sctp-socket
|
132
|
+
wiki_uri: https://github.com/djberg96/sctp-socket/wiki
|
133
|
+
rubygems_mfa_required: 'true'
|
126
134
|
post_install_message:
|
127
135
|
rdoc_options: []
|
128
136
|
require_paths:
|
@@ -138,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
146
|
- !ruby/object:Gem::Version
|
139
147
|
version: '0'
|
140
148
|
requirements: []
|
141
|
-
rubygems_version: 3.
|
149
|
+
rubygems_version: 3.4.19
|
142
150
|
signing_key:
|
143
151
|
specification_version: 4
|
144
152
|
summary: Ruby bindings for SCTP sockets
|
metadata.gz.sig
CHANGED
Binary file
|