Added Xor-Mapped-Address attribute
This commit is contained in:
parent
5bc19f3e03
commit
472306f5ce
|
@ -49,6 +49,7 @@ type
|
||||||
|
|
||||||
RawStunMessage = object
|
RawStunMessage = object
|
||||||
msgType: uint16
|
msgType: uint16
|
||||||
|
# it.conten.len() + 8 Because the Fingerprint is added after the encoding
|
||||||
length* {.bin_value: it.content.len() + 8.}: uint16
|
length* {.bin_value: it.content.len() + 8.}: uint16
|
||||||
magicCookie: uint32
|
magicCookie: uint32
|
||||||
transactionId: array[12, byte]
|
transactionId: array[12, byte]
|
||||||
|
@ -89,7 +90,9 @@ proc encode*(msg: StunMessage): seq[byte] =
|
||||||
result.add(Binary.encode(Fingerprint.encode(result)))
|
result.add(Binary.encode(Fingerprint.encode(result)))
|
||||||
|
|
||||||
proc getResponse*(T: typedesc[Stun], msg: seq[byte],
|
proc getResponse*(T: typedesc[Stun], msg: seq[byte],
|
||||||
address: TransportAddress): Option[StunMessage] =
|
ta: TransportAddress): Option[StunMessage] =
|
||||||
|
if ta.family != AddressFamily.IPv4 and ta.family != AddressFamily.IPv6:
|
||||||
|
return none(StunMessage)
|
||||||
let sm =
|
let sm =
|
||||||
try:
|
try:
|
||||||
StunMessage.decode(msg)
|
StunMessage.decode(msg)
|
||||||
|
@ -112,7 +115,8 @@ proc getResponse*(T: typedesc[Stun], msg: seq[byte],
|
||||||
res.attributes.add(UnknownAttribute.encode(unknownAttr))
|
res.attributes.add(UnknownAttribute.encode(unknownAttr))
|
||||||
return some(res)
|
return some(res)
|
||||||
|
|
||||||
#if sm.attributes.getAttribute())
|
res.attributes.add(XorMappedAddress.encode(ta, sm.transactionId))
|
||||||
|
return some(res)
|
||||||
|
|
||||||
proc new*(T: typedesc[Stun]): T =
|
proc new*(T: typedesc[Stun]): T =
|
||||||
result = T()
|
result = T()
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
import sequtils, typetraits
|
||||||
import binary_serialization,
|
import binary_serialization,
|
||||||
stew/byteutils
|
stew/byteutils,
|
||||||
|
chronos
|
||||||
import utils
|
import utils
|
||||||
|
|
||||||
type
|
type
|
||||||
|
StunAttributeEncodingError* = object of CatchableError
|
||||||
# Stun Attribute
|
# Stun Attribute
|
||||||
# 0 1 2 3
|
# 0 1 2 3
|
||||||
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
@ -100,12 +103,50 @@ proc encode*(T: typedesc[UnknownAttribute], unknownAttr: seq[uint16]): RawStunAt
|
||||||
length: value.len().uint16,
|
length: value.len().uint16,
|
||||||
value: value)
|
value: value)
|
||||||
|
|
||||||
|
# Fingerprint
|
||||||
|
|
||||||
type
|
type
|
||||||
Fingerprint* = object
|
Fingerprint* = object
|
||||||
crc32: uint32
|
crc32: uint32
|
||||||
|
|
||||||
proc encode*(T: typedesc[Fingerprint], msg: seq[byte]): RawStunAttribute =
|
proc encode*(T: typedesc[Fingerprint], msg: seq[byte]): RawStunAttribute =
|
||||||
let value = Binary.encode(Fingerprint(crc32: crc32(msg) xor 0x5354554e'u32))
|
let value = Binary.encode(T(crc32: crc32(msg) xor 0x5354554e'u32))
|
||||||
result = RawStunAttribute(attributeType: AttrFingerprint.uint16,
|
result = RawStunAttribute(attributeType: AttrFingerprint.uint16,
|
||||||
length: value.len().uint16,
|
length: value.len().uint16,
|
||||||
value: value)
|
value: value)
|
||||||
|
|
||||||
|
# Xor Mapped Address
|
||||||
|
|
||||||
|
type
|
||||||
|
MappedAddressFamily {.size: 1.} = enum
|
||||||
|
MAFIPv4 = 0x01
|
||||||
|
MAFIPv6 = 0x02
|
||||||
|
|
||||||
|
XorMappedAddress* = object
|
||||||
|
reserved: uint8 # should be 0
|
||||||
|
family: MappedAddressFamily
|
||||||
|
port: uint16
|
||||||
|
address: seq[byte]
|
||||||
|
|
||||||
|
proc encode*(T: typedesc[XorMappedAddress], ta: TransportAddress,
|
||||||
|
tid: array[12, byte]): RawStunAttribute =
|
||||||
|
const magicCookie = @[ 0x21'u8, 0x12, 0xa4, 0x42 ]
|
||||||
|
let
|
||||||
|
address =
|
||||||
|
if ta.family == AddressFamily.IPv4:
|
||||||
|
var s = newSeq[uint8](4)
|
||||||
|
for i in 0..3:
|
||||||
|
s[i] = ta.address_v4[i] xor magicCookie[i]
|
||||||
|
s
|
||||||
|
else:
|
||||||
|
let magicCookieTid = magicCookie.concat(@tid)
|
||||||
|
var s = newSeq[uint8](16)
|
||||||
|
for i in 0..15:
|
||||||
|
s[i] = ta.address_v6[i] xor magicCookieTid[i]
|
||||||
|
s
|
||||||
|
xma = T(family: if ta.family == AddressFamily.IPv4: MAFIPv4 else: MAFIPv6,
|
||||||
|
port: ta.port.distinctBase xor 0x2112'u16, address: address)
|
||||||
|
value = Binary.encode(xma)
|
||||||
|
result = RawStunAttribute(attributeType: AttrXORMappedAddress.uint16,
|
||||||
|
length: value.len().uint16,
|
||||||
|
value: value)
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
import chronos, chronicles
|
||||||
|
import stun
|
||||||
|
|
||||||
|
logScope:
|
||||||
|
topics = "webrtc"
|
||||||
|
|
||||||
|
let fut = newFuture[void]()
|
||||||
|
type
|
||||||
|
WebRTC* = object
|
||||||
|
udp: DatagramTransport
|
||||||
|
|
||||||
|
proc new*(T: typedesc[WebRTC], port: uint16 = 42657): T =
|
||||||
|
logScope: topics = "webrtc"
|
||||||
|
var webrtc = T()
|
||||||
|
proc onReceive(udp: DatagramTransport, address: TransportAddress) {.async, gcsafe.} =
|
||||||
|
let
|
||||||
|
msg = udp.getMessage()
|
||||||
|
if Stun.isMessage(msg):
|
||||||
|
let res = Stun.getResponse(msg, address)
|
||||||
|
echo res
|
||||||
|
if res.isSome():
|
||||||
|
await udp.sendTo(address, res.get().encode())
|
||||||
|
|
||||||
|
trace "onReceive", isStun = Stun.isMessage(msg)
|
||||||
|
if not fut.completed(): fut.complete()
|
||||||
|
|
||||||
|
let
|
||||||
|
laddr = initTAddress("127.0.0.1:" & $port)
|
||||||
|
udp = newDatagramTransport(onReceive, local = laddr)
|
||||||
|
trace "local address", laddr
|
||||||
|
webrtc.udp = udp
|
||||||
|
return webrtc
|
||||||
|
#
|
||||||
|
#proc main {.async.} =
|
||||||
|
# echo "/ip4/127.0.0.1/udp/42657/webrtc/certhash/uEiDKBGpmOW3zQhiCHagHZ8igwfKNIp8rQCJWd5E5mIhGHw/p2p/12D3KooWFjMiMZLaCKEZRvMqKp5qUGduS6iBZ9RWQgYZXYtAAaPC"
|
||||||
|
# discard WebRTC.new()
|
||||||
|
# await fut
|
||||||
|
# await sleepAsync(10.seconds)
|
||||||
|
#
|
||||||
|
#waitFor(main())
|
Loading…
Reference in New Issue