Beginning of client/server example
This commit is contained in:
parent
aa547badfd
commit
472c1923ca
|
@ -0,0 +1,11 @@
|
||||||
|
import chronos, stew/byteutils
|
||||||
|
import ../webrtc/sctp
|
||||||
|
|
||||||
|
proc main() {.async.} =
|
||||||
|
let
|
||||||
|
sctp = Sctp.new(port = 4242)
|
||||||
|
address = TransportAddress(initTAddress("127.0.0.1:9899"))
|
||||||
|
conn = await sctp.connect(address)
|
||||||
|
await conn.write("toto".toBytes)
|
||||||
|
|
||||||
|
waitFor(main())
|
|
@ -0,0 +1,12 @@
|
||||||
|
import chronos, stew/byteutils
|
||||||
|
import ../webrtc/sctp
|
||||||
|
|
||||||
|
proc main() {.async.} =
|
||||||
|
let
|
||||||
|
sctp = Sctp.new(isServer = true)
|
||||||
|
address = initTAddress("127.0.0.1:9899")
|
||||||
|
conn = await sctp.listen(address)
|
||||||
|
let msg = await conn.read()
|
||||||
|
echo string.fromBytes(msg)
|
||||||
|
|
||||||
|
waitFor(main())
|
|
@ -1,77 +0,0 @@
|
||||||
import bitops
|
|
||||||
import chronos, posix
|
|
||||||
import ../webrtc/usrsctp
|
|
||||||
import stew/ranges/ptr_arith
|
|
||||||
|
|
||||||
const IPPROTO_SCTP = 132
|
|
||||||
let ta = initTAddress("127.0.0.1:4244")
|
|
||||||
let tar = initTAddress("127.0.0.1:4242")
|
|
||||||
|
|
||||||
proc connOutput(address: pointer,
|
|
||||||
buffer: pointer,
|
|
||||||
length: uint,
|
|
||||||
tos: uint8,
|
|
||||||
set_df: uint8): cint {.cdecl.} =
|
|
||||||
echo "====> connOutput: ", usrsctp_dumppacket(buffer, length, SCTP_DUMP_OUTBOUND)
|
|
||||||
let dg: ptr DatagramTransport = cast[ptr DatagramTransport](address)
|
|
||||||
proc testSend() {.async.} =
|
|
||||||
try:
|
|
||||||
let buf = @(buffer.makeOpenArray(byte, int(length)))
|
|
||||||
echo "START await sendTo START"
|
|
||||||
await sendTo(dg[], tar, buf, int(length))
|
|
||||||
echo "STOP await sendTo STOP"
|
|
||||||
except CatchableError as exc:
|
|
||||||
echo "Failure: ", exc.msg
|
|
||||||
|
|
||||||
asyncSpawn testSend()
|
|
||||||
echo "connOutput <===="
|
|
||||||
|
|
||||||
var connected = false
|
|
||||||
proc handleUpcall(sock: ptr socket, arg: pointer, length: cint) {.cdecl.} =
|
|
||||||
let e = usrsctp_get_events(sock)
|
|
||||||
echo "handleUpcall: event = ", e
|
|
||||||
if bitor(e, SCTP_EVENT_WRITE) != 0 and not connected:
|
|
||||||
echo "connect"
|
|
||||||
connected = true
|
|
||||||
elif bitor(e, SCTP_EVENT_READ) != 0:
|
|
||||||
echo "recv"
|
|
||||||
else:
|
|
||||||
echo "/!\\ ERROR /!\\"
|
|
||||||
|
|
||||||
proc printf(format: cstring) {.cdecl, varargs.} = echo "printf"
|
|
||||||
|
|
||||||
proc handleEvents(dg: DatagramTransport, sock: ptr socket, sconn_addr: pointer) {.async.} =
|
|
||||||
await sleepAsync(3.seconds)
|
|
||||||
|
|
||||||
proc main {.async, gcsafe.} =
|
|
||||||
let fut = newFuture[void]()
|
|
||||||
var p: pointer
|
|
||||||
proc clientMark(transp: DatagramTransport, raddr: TransportAddress): Future[void] {.async.} =
|
|
||||||
var msg = transp.getMessage()
|
|
||||||
echo "Client Mark: ", usrsctp_dumppacket(addr msg[0], uint(msg.len), SCTP_DUMP_INBOUND)
|
|
||||||
usrsctp_conninput(p, addr msg[0], uint(msg.len), 0)
|
|
||||||
|
|
||||||
var dg = newDatagramTransport(clientMark, remote=tar, local=ta)
|
|
||||||
p = cast[pointer](addr dg)
|
|
||||||
usrsctp_init_nothreads(0, connOutput, printf)
|
|
||||||
discard usrsctp_sysctl_set_sctp_ecn_enable(1)
|
|
||||||
usrsctp_register_address(p)
|
|
||||||
let sock = usrsctp_socket(AF_CONN, posix.SOCK_STREAM, IPPROTO_SCTP, nil, nil, 0, nil)
|
|
||||||
var on: int = 1
|
|
||||||
doAssert 0 == usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_RECVRCVINFO, addr on, sizeof(on).SockLen)
|
|
||||||
doAssert 0 == usrsctp_set_non_blocking(sock, 1)
|
|
||||||
doAssert 0 == usrsctp_set_upcall(sock, handleUpcall, nil)
|
|
||||||
var sconn: Sockaddr_conn
|
|
||||||
sconn.sconn_family = AF_CONN
|
|
||||||
sconn.sconn_port = htons(0)
|
|
||||||
sconn.sconn_addr = nil
|
|
||||||
doAssert 0 == usrsctp_bind(sock, cast[ptr SockAddr](addr sconn), sizeof(sconn).SockLen)
|
|
||||||
sconn.sconn_family = AF_CONN
|
|
||||||
sconn.sconn_port = htons(13)
|
|
||||||
sconn.sconn_addr = p
|
|
||||||
let connErr = usrsctp_connect(sock, cast[ptr SockAddr](addr sconn), sizeof(sconn).SockLen)
|
|
||||||
doAssert 0 == connErr or errno == EINPROGRESS, ($errno)
|
|
||||||
|
|
||||||
await handleEvents(dg, sock, sconn.sconn_addr)
|
|
||||||
|
|
||||||
waitFor(main())
|
|
|
@ -37,6 +37,8 @@ type
|
||||||
const
|
const
|
||||||
IPPROTO_SCTP = 132
|
IPPROTO_SCTP = 132
|
||||||
|
|
||||||
|
proc perror(error: cstring) {.importc, cdecl, header: "<errno.h>".}
|
||||||
|
|
||||||
proc new(T: typedesc[SctpConnection],
|
proc new(T: typedesc[SctpConnection],
|
||||||
sctp: Sctp,
|
sctp: Sctp,
|
||||||
udp: DatagramTransport,
|
udp: DatagramTransport,
|
||||||
|
@ -44,14 +46,14 @@ proc new(T: typedesc[SctpConnection],
|
||||||
sctpSocket: ptr socket): T =
|
sctpSocket: ptr socket): T =
|
||||||
T(sctp: sctp, udp: udp, address: address, sctpSocket: sctpSocket)
|
T(sctp: sctp, udp: udp, address: address, sctpSocket: sctpSocket)
|
||||||
|
|
||||||
proc read(self: SctpConnection): Future[seq[byte]] = discard
|
proc read*(self: SctpConnection): Future[seq[byte]] = discard
|
||||||
|
|
||||||
proc write(self: SctpConnection, buf: seq[byte]) {.async.} =
|
proc write*(self: SctpConnection, buf: seq[byte]) {.async.} =
|
||||||
self.sctp.sentConnection = self
|
self.sctp.sentConnection = self
|
||||||
discard self.sctpSocket.usrsctp_sendv(addr buf, buf.len.uint, nil, 0, nil, 0, SCTP_SENDV_NOINFO, 0)
|
discard self.sctpSocket.usrsctp_sendv(addr buf, buf.len.uint, nil, 0, nil, 0, SCTP_SENDV_NOINFO, 0)
|
||||||
await self.sctp.sentFuture
|
await self.sctp.sentFuture
|
||||||
|
|
||||||
proc close(self: SctpConnection) {.async.} = discard
|
proc close*(self: SctpConnection) {.async.} = discard
|
||||||
|
|
||||||
proc handleUpcall(sock: ptr socket, data: pointer, flags: cint) {.cdecl.} =
|
proc handleUpcall(sock: ptr socket, data: pointer, flags: cint) {.cdecl.} =
|
||||||
let e = usrsctp_get_events(sock)
|
let e = usrsctp_get_events(sock)
|
||||||
|
@ -78,6 +80,7 @@ proc handleAccept(sock: ptr socket, data: pointer, flags: cint) {.cdecl.} =
|
||||||
sin.fromSockAddr(sizeof(sin).SockLen, ipaddress, port)
|
sin.fromSockAddr(sizeof(sin).SockLen, ipaddress, port)
|
||||||
let address = initTAddress(ipaddress, port)
|
let address = initTAddress(ipaddress, port)
|
||||||
sctp.connections[address] = SctpConnection.new(sctp, sctp.udp, address, sctpSocket)
|
sctp.connections[address] = SctpConnection.new(sctp, sctp.udp, address, sctpSocket)
|
||||||
|
sctp.gotConnection.fire()
|
||||||
|
|
||||||
proc getOrCreateConnection(self: Sctp,
|
proc getOrCreateConnection(self: Sctp,
|
||||||
udp: DatagramTransport,
|
udp: DatagramTransport,
|
||||||
|
@ -95,8 +98,12 @@ proc getOrCreateConnection(self: Sctp,
|
||||||
sizeof(on).SockLen)
|
sizeof(on).SockLen)
|
||||||
doAssert 0 == usrsctp_set_non_blocking(conn.sctpSocket, 1)
|
doAssert 0 == usrsctp_set_non_blocking(conn.sctpSocket, 1)
|
||||||
doAssert 0 == usrsctp_set_upcall(conn.sctpSocket, handleUpcall, nil)
|
doAssert 0 == usrsctp_set_upcall(conn.sctpSocket, handleUpcall, nil)
|
||||||
|
var sconn: Sockaddr_conn
|
||||||
|
sconn.sconn_family = AF_CONN
|
||||||
|
sconn.sconn_port = htons(5000)
|
||||||
|
sconn.sconn_addr = nil
|
||||||
|
doAssert 0 == conn.sctpSocket.usrsctp_connect(cast[ptr SockAddr](addr sconn), SockLen(sizeof(sconn)))
|
||||||
self.connections[address] = conn
|
self.connections[address] = conn
|
||||||
self.gotConnection.fire()
|
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
proc sendCallback(address: pointer,
|
proc sendCallback(address: pointer,
|
||||||
|
@ -114,7 +121,7 @@ proc sendCallback(address: pointer,
|
||||||
echo "Failure: ", exc.msg
|
echo "Failure: ", exc.msg
|
||||||
sctp.sentFuture = testSend()
|
sctp.sentFuture = testSend()
|
||||||
|
|
||||||
proc new(T: typedesc[Sctp], port: uint16 = 9899, isServer: bool = true): T =
|
proc new*(T: typedesc[Sctp], port: uint16 = 9899, isServer: bool = false): T =
|
||||||
let
|
let
|
||||||
sctp = T(gotConnection: newAsyncEvent())
|
sctp = T(gotConnection: newAsyncEvent())
|
||||||
sctpPtr = cast[pointer](addr sctp)
|
sctpPtr = cast[pointer](addr sctp)
|
||||||
|
@ -128,25 +135,35 @@ proc new(T: typedesc[Sctp], port: uint16 = 9899, isServer: bool = true): T =
|
||||||
localAddr = TransportAddress(family: AddressFamily.IPv4, port: Port(port))
|
localAddr = TransportAddress(family: AddressFamily.IPv4, port: Port(port))
|
||||||
udp = newDatagramTransport(onReceive, local = localAddr)
|
udp = newDatagramTransport(onReceive, local = localAddr)
|
||||||
usrsctp_init_nothreads(port, sendCallback, nil) # TODO maybe put a debugger instead of nil
|
usrsctp_init_nothreads(port, sendCallback, nil) # TODO maybe put a debugger instead of nil
|
||||||
|
discard usrsctp_sysctl_set_sctp_ecn_enable(1)
|
||||||
usrsctp_register_address(sctpPtr)
|
usrsctp_register_address(sctpPtr)
|
||||||
sctp.udp = udp
|
sctp.udp = udp
|
||||||
if isServer:
|
if isServer:
|
||||||
|
echo errno, " <="
|
||||||
let sock = usrsctp_socket(AF_INET, posix.SOCK_STREAM, IPPROTO_SCTP, nil, nil, 0, nil)
|
let sock = usrsctp_socket(AF_INET, posix.SOCK_STREAM, IPPROTO_SCTP, nil, nil, 0, nil)
|
||||||
sock.usrsctp_set_upcall(handleAccept, sctpPtr)
|
perror("usrsctp_socket")
|
||||||
|
var on: int = 1
|
||||||
|
echo "=> ", errno
|
||||||
|
doAssert 0 == usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_RECVRCVINFO, addr on, SockLen(sizeof(on)))
|
||||||
|
doAssert 0 == usrsctp_set_non_blocking(sock, 1)
|
||||||
|
echo sock.usrsctp_set_upcall(handleAccept, sctpPtr)
|
||||||
|
echo errno
|
||||||
var sconn: Sockaddr_conn
|
var sconn: Sockaddr_conn
|
||||||
sconn.sconn_family = AF_CONN
|
sconn.sconn_family = AF_CONN
|
||||||
sconn.sconn_port = htons(0)
|
sconn.sconn_port = htons(5000)
|
||||||
sconn.sconn_addr = nil
|
sconn.sconn_addr = nil
|
||||||
doAssert 0 == usrsctp_bind(sock, cast[ptr SockAddr](addr sconn), sizeof(sconn).SockLen)
|
echo usrsctp_bind(sock, cast[ptr SockAddr](addr sconn), SockLen(sizeof(sconn)))
|
||||||
doAssert 0 < usrsctp_listen(sock, 1)
|
doAssert 0 < usrsctp_listen(sock, 1)
|
||||||
|
sctp.sock = sock
|
||||||
return sctp
|
return sctp
|
||||||
|
|
||||||
proc listen(self: Sctp, address: TransportAddress): Future[SctpConnection] {.async.} =
|
proc listen*(self: Sctp, address: TransportAddress): Future[SctpConnection] {.async.} =
|
||||||
while true:
|
while true:
|
||||||
if self.connections.hasKey(address):
|
if self.connections.hasKey(address):
|
||||||
return self.connections[address]
|
return self.connections[address]
|
||||||
self.gotConnection.clear()
|
self.gotConnection.clear()
|
||||||
await self.gotConnection.wait()
|
await self.gotConnection.wait()
|
||||||
|
|
||||||
proc connect(self: Sctp): Future[SctpConnection] = discard
|
proc connect*(self: Sctp, address: TransportAddress): Future[SctpConnection] {.async.} =
|
||||||
proc dial(self: Sctp, address: TransportAddress): Future[SctpConnection] = discard
|
let conn = self.getOrCreateConnection(self.udp, address)
|
||||||
|
return conn
|
||||||
|
|
Loading…
Reference in New Issue