feat: udp connection (#8)

This commit is contained in:
Ludovic Chenut 2024-04-02 14:04:14 +02:00 committed by GitHub
parent a0f6c777d8
commit 928fc59a62
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 110 additions and 1 deletions

View File

@ -48,11 +48,20 @@ jobs:
with:
submodules: true
- name: MSYS2 (Windows amd64)
if: ${{ matrix.target.os == 'windows' && matrix.target.cpu == 'amd64' }}
uses: msys2/setup-msys2@v2
with:
path-type: inherit
install: >-
base-devel
git
mingw-w64-x86_64-toolchain
- uses: iffy/install-nim@v3
with:
version: ${{ matrix.nim }}
- name: Install deps
run: |
nimble install -dy

12
webrtc/errors.nim Normal file
View File

@ -0,0 +1,12 @@
# 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.
type
# Base exception for nim-webrtc
WebRtcError* = object of CatchableError

88
webrtc/udp_connection.nim Normal file
View File

@ -0,0 +1,88 @@
# 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.
import errors
import chronos, chronicles
logScope:
topics = "webrtc udp"
# UdpConn is a small wrapper of the chronos DatagramTransport.
# It's the simplest solution we found to store the message and
# the remote address used by the underlying protocols (dtls/sctp etc...)
type
WebRtcUdpError = object of WebRtcError
UdpPacketInfo* = tuple
message: seq[byte]
raddr: TransportAddress
UdpConn* = ref object
laddr*: TransportAddress
udp: DatagramTransport
dataRecv: AsyncQueue[UdpPacketInfo]
closed: bool
proc init*(T: type UdpConn, laddr: TransportAddress): T =
## Initialize an Udp Connection
##
var self = T(laddr: laddr, closed: false)
proc onReceive(
udp: DatagramTransport,
raddr: TransportAddress
) {.async: (raises: []), gcsafe.} =
# On receive Udp message callback, store the
# message with the corresponding remote address
try:
trace "UDP onReceive"
let msg = udp.getMessage()
self.dataRecv.addLastNoWait((msg, raddr))
except CatchableError as exc:
raiseAssert(exc.msg)
self.dataRecv = newAsyncQueue[UdpPacketInfo]()
self.udp = newDatagramTransport(onReceive, local = laddr)
return self
proc close*(self: UdpConn) =
## Close an Udp Connection
##
if self.closed:
debug "Trying to close an already closed UdpConn"
return
self.closed = true
self.udp.close()
proc write*(
self: UdpConn,
raddr: TransportAddress,
msg: seq[byte]
) {.async: (raises: [CancelledError, WebRtcUdpError]).} =
## Write a message on Udp to a remote address `raddr`
##
if self.closed:
debug "Try to write on an already closed UdpConn"
return
trace "UDP write", msg
try:
await self.udp.sendTo(raddr, msg)
except TransportError as exc:
raise newException(WebRtcUdpError,
"Error when sending data on a DatagramTransport: " & exc.msg , exc)
proc read*(self: UdpConn): Future[UdpPacketInfo] {.async: (raises: [CancelledError]).} =
## Read the next received Udp message
##
if self.closed:
debug "Try to read on an already closed UdpConn"
return
trace "UDP read"
return await self.dataRecv.popFirst()