sctp-socket 0.1.4 → 0.2.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/.github/workflows/ruby.yml +1 -1
- data/.gitignore +1 -0
- data/CHANGES.md +12 -0
- data/README.md +75 -0
- data/examples/client_for_server_test.rb +34 -0
- data/examples/sctp_server_example.rb +69 -0
- data/examples/server_using_sctp_server.rb +65 -0
- data/ext/sctp/socket.c +460 -65
- data/lib/sctp/server.rb +207 -0
- data/sctp-socket.gemspec +1 -1
- data.tar.gz.sig +0 -0
- metadata +6 -5
- metadata.gz.sig +0 -0
- data/ext/sctp/socket/client.c +0 -7
- data/ext/sctp/socket/server.c +0 -7
- data/ext/sctp/socket.h +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fd42fc7e43b41e85d64c8a82f258add07ead601ff3f12bac22bf818e9ecb0162
|
4
|
+
data.tar.gz: bb950e7a673d6aeee90fed9435e0162d02b09e29df5a8abe35451fcc6823dddd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dab10bca673f2330c376686c53b6b5de62089be1b127252cf8ba8c5b46af2c7e1a409995b5b054bbf53702d47dc6c7b7b57660a624edbefeec566b8dff9aaaad
|
7
|
+
data.tar.gz: 28e75fa2e02f5388736d8515ace3497bfc7e907ffa0bae5131d14f89374c2045d800603a5a126e84bc5a2b2e36145a9887e0838b6c82aa1f869cea7463aa511b
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.github/workflows/ruby.yml
CHANGED
data/.gitignore
CHANGED
data/CHANGES.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## 0.2.0 - 3-Aug-2025
|
2
|
+
* Added an SCTP::Server class, generally modelled on the TCPServer class.
|
3
|
+
* Added the map_ipv4? method to query IPv4 mapping status.
|
4
|
+
* Added the auth_support? method to query authentication support status.
|
5
|
+
* Fixed critical segmentation fault in sendmsg method with improved parameter validation.
|
6
|
+
* Fixed potential segmentation fault in sendv method with better error handling.
|
7
|
+
* Added comprehensive test coverage for many more methods.
|
8
|
+
* Enhanced parameter validation across multiple methods to prevent crashes.
|
9
|
+
* Improved documentation and fixed syntax errors in method examples.
|
10
|
+
* Internally several methods were switched from sctp_opt_info to setsockopt
|
11
|
+
because the former doesn't always seem to work.
|
12
|
+
|
1
13
|
## 0.1.4 - 1-Feb-2025
|
2
14
|
* Added the set_retransmission_info method.
|
3
15
|
* Added the get_rto_info and set_rto_info aliases.
|
data/README.md
CHANGED
@@ -55,6 +55,81 @@ ensure
|
|
55
55
|
end
|
56
56
|
```
|
57
57
|
|
58
|
+
## Using SCTP::Server
|
59
|
+
|
60
|
+
The `SCTP::Server` class provides a TCPServer-like interface for SCTP sockets,
|
61
|
+
making it easier to create SCTP server applications.
|
62
|
+
|
63
|
+
### One-to-Many Mode (Default)
|
64
|
+
|
65
|
+
In one-to-many mode, a single server socket handles multiple client associations:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
require 'sctp/socket'
|
69
|
+
|
70
|
+
# Create server listening on multiple addresses
|
71
|
+
server = SCTP::Server.new(['127.0.0.1', '192.168.1.100'], 9999)
|
72
|
+
|
73
|
+
puts "Server listening on #{server.addr.join(', ')}:#{server.local_port}"
|
74
|
+
|
75
|
+
loop do
|
76
|
+
# Receive data from any client association
|
77
|
+
data, info = server.recvmsg
|
78
|
+
puts "Received from association #{info.association_id}: #{data}"
|
79
|
+
|
80
|
+
# Echo back to the same association
|
81
|
+
server.sendmsg("Echo: #{data}", association_id: info.association_id)
|
82
|
+
end
|
83
|
+
```
|
84
|
+
|
85
|
+
### One-to-One Mode
|
86
|
+
|
87
|
+
In one-to-one mode, the server creates individual sockets for each association:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
require 'sctp/socket'
|
91
|
+
|
92
|
+
# Create server in one-to-one mode
|
93
|
+
server = SCTP::Server.new(['127.0.0.1'], 9999, one_to_one: true)
|
94
|
+
|
95
|
+
loop do
|
96
|
+
# Accept a new client connection
|
97
|
+
client = server.accept
|
98
|
+
|
99
|
+
# Handle client in a thread
|
100
|
+
Thread.new(client) do |c|
|
101
|
+
# Get the initial message that established the connection
|
102
|
+
data, info = c.initial_message
|
103
|
+
puts "New client: #{data}"
|
104
|
+
|
105
|
+
# Continue receiving from this specific client
|
106
|
+
loop do
|
107
|
+
data, info = c.recvmsg
|
108
|
+
c.sendmsg("Echo: #{data}")
|
109
|
+
end
|
110
|
+
rescue => e
|
111
|
+
puts "Client error: #{e.message}"
|
112
|
+
ensure
|
113
|
+
c.close
|
114
|
+
end
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
### Server Options
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
# Create server with additional options
|
122
|
+
server = SCTP::Server.new(
|
123
|
+
['127.0.0.1'],
|
124
|
+
9999,
|
125
|
+
one_to_one: false,
|
126
|
+
backlog: 256,
|
127
|
+
autoclose: 30,
|
128
|
+
init_msg: { output_streams: 10, input_streams: 10 },
|
129
|
+
subscriptions: { data_io: true, association: true }
|
130
|
+
)
|
131
|
+
```
|
132
|
+
|
58
133
|
## Future Plans
|
59
134
|
|
60
135
|
* Add more specs.
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'sctp/socket'
|
4
|
+
|
5
|
+
# Simple SCTP client to test with the server
|
6
|
+
|
7
|
+
puts "SCTP Client Example"
|
8
|
+
puts "==================="
|
9
|
+
|
10
|
+
begin
|
11
|
+
# Connect to the server
|
12
|
+
client = SCTP::Socket.new
|
13
|
+
client.connectx(addresses: ['127.0.0.1'], port: 9999)
|
14
|
+
|
15
|
+
puts "Connected to server at 127.0.0.1:9999"
|
16
|
+
|
17
|
+
# Send a few test messages
|
18
|
+
["Hello, SCTP!", "How are you?", "Goodbye!"].each_with_index do |message, i|
|
19
|
+
puts "Sending: #{message}"
|
20
|
+
client.sendmsg(message: message, stream: i % 3) # Use different streams
|
21
|
+
|
22
|
+
# Receive the echo
|
23
|
+
data, info = client.recvmsg
|
24
|
+
puts "Received: #{data.inspect} on stream #{info.stream}"
|
25
|
+
|
26
|
+
sleep 1
|
27
|
+
end
|
28
|
+
|
29
|
+
rescue => e
|
30
|
+
puts "Error: #{e.message}"
|
31
|
+
ensure
|
32
|
+
client.close if client
|
33
|
+
puts "Client closed"
|
34
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Example SCTP server using the SCTP::Server class
|
3
|
+
# Run with: ruby -I lib examples/sctp_server_example.rb
|
4
|
+
|
5
|
+
require 'sctp/socket'
|
6
|
+
|
7
|
+
puts "SCTP::Server Example"
|
8
|
+
puts "==================="
|
9
|
+
|
10
|
+
# Example 1: One-to-many server (default mode)
|
11
|
+
puts "\n1. One-to-many server example:"
|
12
|
+
puts " Multiple clients can connect to the same server socket"
|
13
|
+
puts " All communication happens through the main server socket"
|
14
|
+
|
15
|
+
server = SCTP::Server.new(['127.0.0.1'], 9999)
|
16
|
+
puts " Server listening on: #{server}"
|
17
|
+
|
18
|
+
# Simulate server operation (normally you'd have a loop here)
|
19
|
+
puts " Server ready to receive messages with server.recvmsg"
|
20
|
+
puts " Send messages back with server.sendmsg(data, association_id: id)"
|
21
|
+
|
22
|
+
server.close
|
23
|
+
puts " Server closed"
|
24
|
+
|
25
|
+
# Example 2: One-to-one server with peeloff
|
26
|
+
puts "\n2. One-to-one server example:"
|
27
|
+
puts " Each client connection gets its own dedicated socket"
|
28
|
+
puts " Uses peeloff() to create individual sockets per association"
|
29
|
+
|
30
|
+
server_1to1 = SCTP::Server.new(['127.0.0.1'], 9998, one_to_one: true)
|
31
|
+
puts " Server listening on: #{server_1to1}"
|
32
|
+
|
33
|
+
# Simulate server operation
|
34
|
+
puts " Server ready to accept connections with server.accept"
|
35
|
+
puts " Each accepted connection returns a new SCTP::Socket"
|
36
|
+
puts " Handle each client in a separate thread"
|
37
|
+
|
38
|
+
server_1to1.close
|
39
|
+
puts " Server closed"
|
40
|
+
|
41
|
+
# Example 3: Server with multiple addresses (multihoming)
|
42
|
+
puts "\n3. Multihomed server example:"
|
43
|
+
puts " SCTP supports binding to multiple IP addresses"
|
44
|
+
|
45
|
+
begin
|
46
|
+
# This will work if you have multiple addresses configured
|
47
|
+
multi_server = SCTP::Server.new(['127.0.0.1', '127.0.0.2'], 9997)
|
48
|
+
puts " Multihomed server: #{multi_server}"
|
49
|
+
multi_server.close
|
50
|
+
rescue => e
|
51
|
+
puts " Multihomed server failed (expected if addresses not configured): #{e.message}"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Example 4: Server with custom options
|
55
|
+
puts "\n4. Server with custom options:"
|
56
|
+
|
57
|
+
custom_server = SCTP::Server.new(['127.0.0.1'], 9996,
|
58
|
+
backlog: 64,
|
59
|
+
autoclose: 10,
|
60
|
+
init_msg: { output_streams: 10, input_streams: 10 }
|
61
|
+
)
|
62
|
+
puts " Custom server: #{custom_server}"
|
63
|
+
custom_server.close
|
64
|
+
|
65
|
+
puts "\nExample complete!"
|
66
|
+
puts "\nTo test with a real client:"
|
67
|
+
puts "1. Start the server in one terminal"
|
68
|
+
puts "2. Use examples/client_example.rb to connect"
|
69
|
+
puts "3. Or create a simple client with SCTP::Socket.new and connectx()"
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'sctp/socket'
|
4
|
+
|
5
|
+
# Simple SCTP echo server example using SCTP::Server
|
6
|
+
|
7
|
+
puts "SCTP Echo Server Example"
|
8
|
+
puts "========================"
|
9
|
+
|
10
|
+
# Create a server that binds to localhost on port 9999
|
11
|
+
server = SCTP::Server.new(['127.0.0.1'], 9999)
|
12
|
+
|
13
|
+
puts "Server listening on #{server.addr.join(', ')}:#{server.local_port}"
|
14
|
+
puts "Mode: #{server.one_to_one ? 'one-to-one' : 'one-to-many'}"
|
15
|
+
puts "Press Ctrl+C to stop"
|
16
|
+
|
17
|
+
begin
|
18
|
+
if server.one_to_one
|
19
|
+
# One-to-one mode: accept individual connections
|
20
|
+
puts "Waiting for connections..."
|
21
|
+
loop do
|
22
|
+
client = server.accept
|
23
|
+
puts "Accepted connection from association #{client.initial_message[1].association_id}"
|
24
|
+
|
25
|
+
# Handle the connection in a thread
|
26
|
+
Thread.new(client) do |c|
|
27
|
+
begin
|
28
|
+
# Get the initial message that triggered the connection
|
29
|
+
data, info = c.initial_message
|
30
|
+
puts "Initial message: #{data.inspect}"
|
31
|
+
|
32
|
+
# Echo it back
|
33
|
+
c.sendmsg("Echo: #{data}")
|
34
|
+
|
35
|
+
# Continue receiving messages
|
36
|
+
loop do
|
37
|
+
data, info = c.recvmsg
|
38
|
+
puts "Received: #{data.inspect}"
|
39
|
+
c.sendmsg("Echo: #{data}")
|
40
|
+
end
|
41
|
+
rescue => e
|
42
|
+
puts "Client connection error: #{e.message}"
|
43
|
+
ensure
|
44
|
+
c.close
|
45
|
+
puts "Client disconnected"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
else
|
50
|
+
# One-to-many mode: handle all connections on the same socket
|
51
|
+
puts "Waiting for messages..."
|
52
|
+
loop do
|
53
|
+
data, info = server.recvmsg
|
54
|
+
puts "Received from association #{info.association_id}: #{data.inspect}"
|
55
|
+
|
56
|
+
# Echo the message back to the sender
|
57
|
+
server.sendmsg("Echo: #{data}", association_id: info.association_id)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
rescue Interrupt
|
61
|
+
puts "\nShutting down server..."
|
62
|
+
ensure
|
63
|
+
server.close
|
64
|
+
puts "Server closed"
|
65
|
+
end
|