-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: sctp connection using usrsctp #11
base: master
Are you sure you want to change the base?
Changes from 64 commits
3d746b2
654a69a
4b9c506
9b51d57
c8a9fd3
9b5c58d
3aa14e9
d09aa30
ccf671c
3f11895
a53f87f
d6f73ce
8910d1e
73e4731
bd5841c
a9df70a
b77410b
ac65c6f
df5eddd
62cc2c7
2d2f012
201a163
4a59265
96a363e
197c0c3
722db0f
54612e9
ecc4fbb
d6b00e5
6e96abe
785d2bb
c8ebe7e
2b1228f
108841d
5fcc26d
57cd0f0
e914f69
183d8d5
f317070
2a80d57
3305615
41a091f
b97ffaf
f0ff34c
a59bb76
4a80ffd
5f50e55
374c83d
0d7f15e
ab707d4
13e4560
1d66aac
f231a9d
3647e11
baf91b9
413f323
857e5da
21e0cfe
185642b
9c6b197
38d40f8
8d26ed6
a37f9df
f41f255
ae7d377
4f8f901
7d612aa
5adb9ae
fa54c20
48e7d44
c1fc6dc
b63044b
2e6055a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import chronos, stew/byteutils | ||
import ../webrtc/udp_transport | ||
import ../webrtc/stun/stun_transport | ||
import ../webrtc/dtls/dtls_transport | ||
import ../webrtc/sctp/[sctp_transport, sctp_connection] | ||
|
||
proc main() {.async.} = | ||
let laddr = initTAddress("127.0.0.1:4244") | ||
let udp = UdpTransport.new(laddr) | ||
let stun = Stun.new(udp) | ||
let dtls = Dtls.new(stun) | ||
let sctp = Sctp.new(dtls) | ||
Comment on lines
+9
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the final instance that matter is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There will be something similar in the |
||
|
||
let conn = await sctp.connect(initTAddress("127.0.0.1:4242"), sctpPort = 13) | ||
while true: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could do this only a few times, maybe 10? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's an example, not a test, having an infinite loop is not really bad practice imo. |
||
await conn.write("ping".toBytes) | ||
let msg = await conn.read() | ||
echo "Received: ", string.fromBytes(msg.data) | ||
await sleepAsync(1.seconds) | ||
|
||
waitFor(main()) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import chronos, stew/byteutils | ||
import ../webrtc/udp_transport | ||
import ../webrtc/stun/stun_transport | ||
import ../webrtc/dtls/dtls_transport | ||
import ../webrtc/sctp/[sctp_transport, sctp_connection] | ||
|
||
proc sendPong(conn: SctpConn) {.async.} = | ||
var i = 0 | ||
while true: | ||
let msg = await conn.read() | ||
echo "Received: ", string.fromBytes(msg.data) | ||
await conn.write(("pong " & $i).toBytes) | ||
i.inc() | ||
|
||
proc main() {.async.} = | ||
let laddr = initTAddress("127.0.0.1:4242") | ||
let udp = UdpTransport.new(laddr) | ||
let stun = Stun.new(udp) | ||
let dtls = Dtls.new(stun) | ||
let sctp = Sctp.new(dtls) | ||
|
||
sctp.listen(13) | ||
while true: | ||
let conn = await sctp.accept() | ||
asyncSpawn conn.sendPong() | ||
|
||
waitFor(main()) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,5 +9,8 @@ | |
|
||
{.used.} | ||
|
||
{.passc: "-DSCTP_DEBUG".} | ||
|
||
import teststun | ||
import testdtls | ||
import testsctp |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
# Nim-WebRTC | ||
# Copyright (c) 2024 Status Research & Development GmbH | ||
# Licensed under either of | ||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) | ||
# * MIT license ([LICENSE-MIT](LICENSE-MIT)) | ||
# at your option. | ||
# This file may not be copied, modified, or distributed except according to | ||
# those terms. | ||
|
||
{.used.} | ||
|
||
import chronos | ||
import ../webrtc/udp_transport | ||
import ../webrtc/stun/stun_transport | ||
import ../webrtc/dtls/dtls_transport | ||
import ../webrtc/sctp/sctp_transport | ||
import ../webrtc/sctp/sctp_connection | ||
import ./asyncunit | ||
|
||
suite "SCTP": | ||
teardown: | ||
checkLeaks() | ||
|
||
type | ||
SctpStackForTest = object | ||
localAddress: TransportAddress | ||
udp: UdpTransport | ||
stun: Stun | ||
dtls: Dtls | ||
sctp: Sctp | ||
|
||
proc initSctpStack(localAddress: TransportAddress): SctpStackForTest = | ||
result.localAddress = localAddress | ||
result.udp = UdpTransport.new(result.localAddress) | ||
result.stun = Stun.new(result.udp) | ||
result.dtls = Dtls.new(result.stun) | ||
result.sctp = Sctp.new(result.dtls) | ||
result.sctp.listen() | ||
|
||
proc closeSctpStack(self: SctpStackForTest) {.async: (raises: [CancelledError]).} = | ||
await self.sctp.stop() | ||
await self.dtls.stop() | ||
await self.stun.stop() | ||
await self.udp.close() | ||
|
||
asyncTest "Two SCTP nodes connecting to each other, then sending/receiving data": | ||
var | ||
sctpServer = initSctpStack(initTAddress("127.0.0.1:4444")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's better to use 0 port to avoid errors with port reuse. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed those. It makes me change some things in |
||
sctpClient = initSctpStack(initTAddress("127.0.0.1:5555")) | ||
let | ||
serverConnFut = sctpServer.sctp.accept() | ||
clientConn = await sctpClient.sctp.connect(sctpServer.localAddress) | ||
serverConn = await serverConnFut | ||
|
||
await clientConn.write(@[1'u8, 2, 3, 4]) | ||
check (await serverConn.read()).data == @[1'u8, 2, 3, 4] | ||
|
||
await serverConn.write(@[5'u8, 6, 7, 8]) | ||
check (await clientConn.read()).data == @[5'u8, 6, 7, 8] | ||
|
||
await clientConn.write(@[10'u8, 11, 12, 13]) | ||
await serverConn.write(@[14'u8, 15, 16, 17]) | ||
check (await clientConn.read()).data == @[14'u8, 15, 16, 17] | ||
check (await serverConn.read()).data == @[10'u8, 11, 12, 13] | ||
|
||
await allFutures(clientConn.close(), serverConn.close()) | ||
await allFutures(sctpClient.closeSctpStack(), sctpServer.closeSctpStack()) | ||
|
||
asyncTest "Two DTLS nodes connecting to the same DTLS server, sending/receiving data": | ||
var | ||
sctpServer = initSctpStack(initTAddress("127.0.0.1:4444")) | ||
sctpClient1 = initSctpStack(initTAddress("127.0.0.1:5555")) | ||
sctpClient2 = initSctpStack(initTAddress("127.0.0.1:6666")) | ||
let | ||
serverConn1Fut = sctpServer.sctp.accept() | ||
serverConn2Fut = sctpServer.sctp.accept() | ||
clientConn1 = await sctpClient1.sctp.connect(sctpServer.localAddress) | ||
clientConn2 = await sctpClient2.sctp.connect(sctpServer.localAddress) | ||
serverConn1 = await serverConn1Fut | ||
serverConn2 = await serverConn2Fut | ||
|
||
await serverConn1.write(@[1'u8, 2, 3, 4]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any particular meaning to these arrays? We can avoid the repetition by defining a const for the same values. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No particular meaning, no. I just wanted different message sent every time I read/write. |
||
await serverConn2.write(@[5'u8, 6, 7, 8]) | ||
await clientConn1.write(@[9'u8, 10, 11, 12]) | ||
await clientConn2.write(@[13'u8, 14, 15, 16]) | ||
check: | ||
(await clientConn1.read()).data == @[1'u8, 2, 3, 4] | ||
(await clientConn2.read()).data == @[5'u8, 6, 7, 8] | ||
(await serverConn1.read()).data == @[9'u8, 10, 11, 12] | ||
(await serverConn2.read()).data == @[13'u8, 14, 15, 16] | ||
await allFutures(clientConn1.close(), serverConn1.close()) | ||
|
||
await serverConn2.write(@[5'u8, 6, 7, 8]) | ||
await clientConn2.write(@[13'u8, 14, 15, 16]) | ||
check: | ||
(await clientConn2.read()).data == @[5'u8, 6, 7, 8] | ||
(await serverConn2.read()).data == @[13'u8, 14, 15, 16] | ||
await allFutures(clientConn2.close(), serverConn2.close()) | ||
|
||
await allFutures(sctpClient1.closeSctpStack(), | ||
sctpClient2.closeSctpStack(), | ||
sctpServer.closeSctpStack()) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,10 +24,18 @@ var cfg = | |
" --threads:on --opt:speed" | ||
|
||
when defined(windows): | ||
cfg = cfg & " --clib:ws2_32" | ||
cfg = cfg & " --clib:ws2_32 --clib:iphlpapi" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be good to add a comment explaining why this is necessary. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
|
||
import hashes | ||
|
||
proc buildExample(filename: string, run = false, extraFlags = "") = | ||
var excstr = nimc & " " & lang & " " & flags & " -p:. " & extraFlags | ||
excstr.add(" examples/" & filename) | ||
exec excstr | ||
if run: | ||
exec "./examples/" & filename.toExe | ||
rmFile "examples/" & filename.toExe | ||
|
||
proc runTest(filename: string) = | ||
var excstr = nimc & " " & lang & " -d:debug " & cfg & " " & flags | ||
excstr.add(" -d:nimOldCaseObjects") # TODO: fix this in binary-serialization | ||
|
@@ -36,5 +44,10 @@ proc runTest(filename: string) = | |
exec excstr & " -r " & " tests/" & filename | ||
rmFile "tests/" & filename.toExe | ||
|
||
task test, "Run test": | ||
task test, "Run the test suite": | ||
runTest("runalltests") | ||
exec "nimble build_example" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure this should be part of the test task There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, I created a "Build examples" task. |
||
|
||
task build_example, "Build the examples": | ||
buildExample("ping") | ||
buildExample("pong") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we fix a local address?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because it's an example and
ping.nim
works withpong.nim
. I could improve those with some arguments or with an interactive prompt, but, again, it's not meant to be run in the CI, just to be shown as an example of how you can create an SCTP ping.