Less exceptions more results (#188)
* Less exceptions more results * Fix daemonapi and interop tests * Add multibase * wip multiaddress * fix the build, consuming new result types * fix standard setup * Simplify match, rename into MaError, add more exaustive err text * Fix the CI issues * Fix directchat build * daemon api fixes * better err messages formatting Co-authored-by: Zahary Karadjov <zahary@gmail.com>
This commit is contained in:
parent
7c9e5c2f7a
commit
6affcda937
|
@ -41,11 +41,11 @@ type ChatProto = ref object of LPProtocol
|
||||||
|
|
||||||
|
|
||||||
proc initAddress(T: type MultiAddress, str: string): T =
|
proc initAddress(T: type MultiAddress, str: string): T =
|
||||||
let address = MultiAddress.init(str)
|
let address = MultiAddress.init(str).tryGet()
|
||||||
if IPFS.match(address) and matchPartial(multiaddress.TCP, address):
|
if IPFS.match(address) and matchPartial(multiaddress.TCP, address):
|
||||||
result = address
|
result = address
|
||||||
else:
|
else:
|
||||||
raise newException(MultiAddressError,
|
raise newException(ValueError,
|
||||||
"Invalid bootstrap node multi-address")
|
"Invalid bootstrap node multi-address")
|
||||||
|
|
||||||
proc dialPeer(p: ChatProto, address: string) {.async.} =
|
proc dialPeer(p: ChatProto, address: string) {.async.} =
|
||||||
|
@ -160,10 +160,10 @@ proc processInput(rfd: AsyncFD) {.async.} =
|
||||||
let a = await transp.readLine()
|
let a = await transp.readLine()
|
||||||
try:
|
try:
|
||||||
if a.len > 0:
|
if a.len > 0:
|
||||||
peerInfo.addrs.add(Multiaddress.init(a))
|
peerInfo.addrs.add(Multiaddress.init(a).tryGet())
|
||||||
break
|
break
|
||||||
|
|
||||||
peerInfo.addrs.add(Multiaddress.init(localAddress))
|
peerInfo.addrs.add(Multiaddress.init(localAddress).tryGet())
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
echo "invalid address"
|
echo "invalid address"
|
||||||
|
|
|
@ -130,7 +130,7 @@ proc decode(data: openarray[char], cid: var Cid): CidStatus =
|
||||||
proc validate*(ctype: typedesc[Cid], data: openarray[byte]): bool =
|
proc validate*(ctype: typedesc[Cid], data: openarray[byte]): bool =
|
||||||
## Returns ``true`` is data has valid binary CID representation.
|
## Returns ``true`` is data has valid binary CID representation.
|
||||||
var version, codec: uint64
|
var version, codec: uint64
|
||||||
var res: VarintStatus
|
var res: VarintResult[void]
|
||||||
if len(data) < 2:
|
if len(data) < 2:
|
||||||
return false
|
return false
|
||||||
let last = data.high
|
let last = data.high
|
||||||
|
@ -140,7 +140,7 @@ proc validate*(ctype: typedesc[Cid], data: openarray[byte]): bool =
|
||||||
var offset = 0
|
var offset = 0
|
||||||
var length = 0
|
var length = 0
|
||||||
res = LP.getUVarint(data.toOpenArray(offset, last), length, version)
|
res = LP.getUVarint(data.toOpenArray(offset, last), length, version)
|
||||||
if res != VarintStatus.Success:
|
if res.isErr():
|
||||||
return false
|
return false
|
||||||
if version != 1'u64:
|
if version != 1'u64:
|
||||||
return false
|
return false
|
||||||
|
@ -148,7 +148,7 @@ proc validate*(ctype: typedesc[Cid], data: openarray[byte]): bool =
|
||||||
if offset >= len(data):
|
if offset >= len(data):
|
||||||
return false
|
return false
|
||||||
res = LP.getUVarint(data.toOpenArray(offset, last), length, codec)
|
res = LP.getUVarint(data.toOpenArray(offset, last), length, codec)
|
||||||
if res != VarintStatus.Success:
|
if res.isErr():
|
||||||
return false
|
return false
|
||||||
var mcodec = CodeContentIds.getOrDefault(cast[int](codec), InvalidMultiCodec)
|
var mcodec = CodeContentIds.getOrDefault(cast[int](codec), InvalidMultiCodec)
|
||||||
if mcodec == InvalidMultiCodec:
|
if mcodec == InvalidMultiCodec:
|
||||||
|
@ -253,11 +253,11 @@ proc encode*(mbtype: typedesc[MultiBase], encoding: string,
|
||||||
cid: Cid): string {.inline.} =
|
cid: Cid): string {.inline.} =
|
||||||
## Get MultiBase encoded representation of ``cid`` using encoding
|
## Get MultiBase encoded representation of ``cid`` using encoding
|
||||||
## ``encoding``.
|
## ``encoding``.
|
||||||
result = MultiBase.encode(encoding, cid.data.buffer)
|
result = MultiBase.encode(encoding, cid.data.buffer).tryGet()
|
||||||
|
|
||||||
proc `$`*(cid: Cid): string =
|
proc `$`*(cid: Cid): string =
|
||||||
## Return official string representation of content identifier ``cid``.
|
## Return official string representation of content identifier ``cid``.
|
||||||
if cid.cidver == CIDv0:
|
if cid.cidver == CIDv0:
|
||||||
result = BTCBase58.encode(cid.data.buffer)
|
result = BTCBase58.encode(cid.data.buffer)
|
||||||
elif cid.cidver == CIDv1:
|
elif cid.cidver == CIDv1:
|
||||||
result = Multibase.encode("base58btc", cid.data.buffer)
|
result = Multibase.encode("base58btc", cid.data.buffer).tryGet()
|
||||||
|
|
|
@ -82,7 +82,7 @@ proc init*(sig: var SkSignature, data: string): SkResult[void] =
|
||||||
try:
|
try:
|
||||||
buffer = hexToSeqByte(data)
|
buffer = hexToSeqByte(data)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return err("Hex to bytes failed")
|
return err("secp: Hex to bytes failed")
|
||||||
init(sig, buffer)
|
init(sig, buffer)
|
||||||
|
|
||||||
proc init*(t: typedesc[SkPrivateKey], data: openarray[byte]): SkResult[SkPrivateKey] =
|
proc init*(t: typedesc[SkPrivateKey], data: openarray[byte]): SkResult[SkPrivateKey] =
|
||||||
|
@ -145,7 +145,7 @@ proc toBytes*(key: SkPrivateKey, data: var openarray[byte]): SkResult[int] =
|
||||||
data[0..<SkRawPrivateKeySize] = SkSecretKey(key).toRaw()
|
data[0..<SkRawPrivateKeySize] = SkSecretKey(key).toRaw()
|
||||||
ok(SkRawPrivateKeySize)
|
ok(SkRawPrivateKeySize)
|
||||||
else:
|
else:
|
||||||
err("Not enough bytes")
|
err("secp: Not enough bytes")
|
||||||
|
|
||||||
proc toBytes*(key: SkPublicKey, data: var openarray[byte]): SkResult[int] =
|
proc toBytes*(key: SkPublicKey, data: var openarray[byte]): SkResult[int] =
|
||||||
## Serialize Secp256k1 `public key` ``key`` to raw binary form and store it
|
## Serialize Secp256k1 `public key` ``key`` to raw binary form and store it
|
||||||
|
@ -157,7 +157,7 @@ proc toBytes*(key: SkPublicKey, data: var openarray[byte]): SkResult[int] =
|
||||||
data[0..<SkRawPublicKeySize] = secp256k1.SkPublicKey(key).toRawCompressed()
|
data[0..<SkRawPublicKeySize] = secp256k1.SkPublicKey(key).toRawCompressed()
|
||||||
ok(SkRawPublicKeySize)
|
ok(SkRawPublicKeySize)
|
||||||
else:
|
else:
|
||||||
err("Not enough bytes")
|
err("secp: Not enough bytes")
|
||||||
|
|
||||||
proc toBytes*(sig: SkSignature, data: var openarray[byte]): int =
|
proc toBytes*(sig: SkSignature, data: var openarray[byte]): int =
|
||||||
## Serialize Secp256k1 `signature` ``sig`` to raw binary form and store it
|
## Serialize Secp256k1 `signature` ``sig`` to raw binary form and store it
|
||||||
|
|
|
@ -474,15 +474,15 @@ proc recvMessage(conn: StreamTransport): Future[seq[byte]] {.async.} =
|
||||||
var
|
var
|
||||||
size: uint
|
size: uint
|
||||||
length: int
|
length: int
|
||||||
res: VarintStatus
|
res: VarintResult[void]
|
||||||
var buffer = newSeq[byte](10)
|
var buffer = newSeq[byte](10)
|
||||||
try:
|
try:
|
||||||
for i in 0..<len(buffer):
|
for i in 0..<len(buffer):
|
||||||
await conn.readExactly(addr buffer[i], 1)
|
await conn.readExactly(addr buffer[i], 1)
|
||||||
res = PB.getUVarint(buffer.toOpenArray(0, i), length, size)
|
res = PB.getUVarint(buffer.toOpenArray(0, i), length, size)
|
||||||
if res == VarintStatus.Success:
|
if res.isOk():
|
||||||
break
|
break
|
||||||
if res != VarintStatus.Success or size > MaxMessageSize:
|
if res.isErr() or size > MaxMessageSize:
|
||||||
buffer.setLen(0)
|
buffer.setLen(0)
|
||||||
result = buffer
|
result = buffer
|
||||||
return
|
return
|
||||||
|
@ -521,27 +521,27 @@ proc getSocket(pattern: string,
|
||||||
var sockname = ""
|
var sockname = ""
|
||||||
var pid = $getProcessId()
|
var pid = $getProcessId()
|
||||||
sockname = pattern % [pid, $(count[])]
|
sockname = pattern % [pid, $(count[])]
|
||||||
let tmpma = MultiAddress.init(sockname)
|
let tmpma = MultiAddress.init(sockname).tryGet()
|
||||||
|
|
||||||
if UNIX.match(tmpma):
|
if UNIX.match(tmpma):
|
||||||
while true:
|
while true:
|
||||||
count[] = count[] + 1
|
count[] = count[] + 1
|
||||||
sockname = pattern % [pid, $(count[])]
|
sockname = pattern % [pid, $(count[])]
|
||||||
var ma = MultiAddress.init(sockname)
|
var ma = MultiAddress.init(sockname).tryGet()
|
||||||
let res = await socketExists(ma)
|
let res = await socketExists(ma)
|
||||||
if not res:
|
if not res:
|
||||||
result = ma
|
result = ma
|
||||||
break
|
break
|
||||||
elif TCP.match(tmpma):
|
elif TCP.match(tmpma):
|
||||||
sockname = pattern % [pid, "0"]
|
sockname = pattern % [pid, "0"]
|
||||||
var ma = MultiAddress.init(sockname)
|
var ma = MultiAddress.init(sockname).tryGet()
|
||||||
var sock = createAsyncSocket(ma)
|
var sock = createAsyncSocket(ma)
|
||||||
if sock.bindAsyncSocket(ma):
|
if sock.bindAsyncSocket(ma):
|
||||||
# Socket was successfully bound, then its free to use
|
# Socket was successfully bound, then its free to use
|
||||||
count[] = count[] + 1
|
count[] = count[] + 1
|
||||||
var ta = sock.getLocalAddress()
|
var ta = sock.getLocalAddress()
|
||||||
sockname = pattern % [pid, $ta.port]
|
sockname = pattern % [pid, $ta.port]
|
||||||
result = MultiAddress.init(sockname)
|
result = MultiAddress.init(sockname).tryGet()
|
||||||
closeSocket(sock)
|
closeSocket(sock)
|
||||||
|
|
||||||
# This is forward declaration needed for newDaemonApi()
|
# This is forward declaration needed for newDaemonApi()
|
||||||
|
@ -649,7 +649,7 @@ proc newDaemonApi*(flags: set[P2PDaemonFlags] = {},
|
||||||
api.flags.excl(NoProcessCtrl)
|
api.flags.excl(NoProcessCtrl)
|
||||||
api.address = await getSocket(patternForSocket, addr daemonsCount)
|
api.address = await getSocket(patternForSocket, addr daemonsCount)
|
||||||
else:
|
else:
|
||||||
api.address = MultiAddress.init(sockpath)
|
api.address = MultiAddress.init(sockpath).tryGet()
|
||||||
api.flags.incl(NoProcessCtrl)
|
api.flags.incl(NoProcessCtrl)
|
||||||
let res = await socketExists(api.address)
|
let res = await socketExists(api.address)
|
||||||
if not res:
|
if not res:
|
||||||
|
@ -830,7 +830,7 @@ proc getPeerInfo(pb: var ProtoBuffer): PeerInfo =
|
||||||
while pb.getBytes(2, address) != -1:
|
while pb.getBytes(2, address) != -1:
|
||||||
if len(address) != 0:
|
if len(address) != 0:
|
||||||
var copyaddr = address
|
var copyaddr = address
|
||||||
result.addresses.add(MultiAddress.init(copyaddr))
|
result.addresses.add(MultiAddress.init(copyaddr).tryGet())
|
||||||
address.setLen(0)
|
address.setLen(0)
|
||||||
|
|
||||||
proc identity*(api: DaemonAPI): Future[PeerInfo] {.async.} =
|
proc identity*(api: DaemonAPI): Future[PeerInfo] {.async.} =
|
||||||
|
@ -888,7 +888,7 @@ proc openStream*(api: DaemonAPI, peer: PeerID,
|
||||||
raise newException(DaemonLocalError, "Missing `peer` field!")
|
raise newException(DaemonLocalError, "Missing `peer` field!")
|
||||||
if pb.getLengthValue(2, raddress) == -1:
|
if pb.getLengthValue(2, raddress) == -1:
|
||||||
raise newException(DaemonLocalError, "Missing `address` field!")
|
raise newException(DaemonLocalError, "Missing `address` field!")
|
||||||
stream.raddress = MultiAddress.init(raddress)
|
stream.raddress = MultiAddress.init(raddress).tryGet()
|
||||||
if pb.getLengthValue(3, stream.protocol) == -1:
|
if pb.getLengthValue(3, stream.protocol) == -1:
|
||||||
raise newException(DaemonLocalError, "Missing `proto` field!")
|
raise newException(DaemonLocalError, "Missing `proto` field!")
|
||||||
stream.flags.incl(Outbound)
|
stream.flags.incl(Outbound)
|
||||||
|
@ -909,7 +909,7 @@ proc streamHandler(server: StreamServer, transp: StreamTransport) {.async.} =
|
||||||
raise newException(DaemonLocalError, "Missing `peer` field!")
|
raise newException(DaemonLocalError, "Missing `peer` field!")
|
||||||
if pb.getLengthValue(2, raddress) == -1:
|
if pb.getLengthValue(2, raddress) == -1:
|
||||||
raise newException(DaemonLocalError, "Missing `address` field!")
|
raise newException(DaemonLocalError, "Missing `address` field!")
|
||||||
stream.raddress = MultiAddress.init(raddress)
|
stream.raddress = MultiAddress.init(raddress).tryGet()
|
||||||
if pb.getLengthValue(3, stream.protocol) == -1:
|
if pb.getLengthValue(3, stream.protocol) == -1:
|
||||||
raise newException(DaemonLocalError, "Missing `proto` field!")
|
raise newException(DaemonLocalError, "Missing `proto` field!")
|
||||||
stream.flags.incl(Inbound)
|
stream.flags.incl(Inbound)
|
||||||
|
|
|
@ -8,14 +8,16 @@
|
||||||
## those terms.
|
## those terms.
|
||||||
|
|
||||||
## This module implements MultiAddress.
|
## This module implements MultiAddress.
|
||||||
|
|
||||||
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import nativesockets
|
import nativesockets
|
||||||
import tables, strutils, net
|
import tables, strutils, net
|
||||||
import chronos
|
import chronos
|
||||||
import multicodec, multihash, multibase, transcoder, vbuffer
|
import multicodec, multihash, multibase, transcoder, vbuffer
|
||||||
import stew/[base58, base32, endians2]
|
import stew/[base58, base32, endians2, results]
|
||||||
from peer import PeerID
|
from peer import PeerID
|
||||||
|
export results
|
||||||
{.deadCodeElim:on.}
|
|
||||||
|
|
||||||
type
|
type
|
||||||
MAKind* = enum
|
MAKind* = enum
|
||||||
|
@ -42,7 +44,13 @@ type
|
||||||
flag*: bool
|
flag*: bool
|
||||||
rem*: seq[MultiCodec]
|
rem*: seq[MultiCodec]
|
||||||
|
|
||||||
MultiAddressError* = object of CatchableError
|
MaResult*[T] = Result[T, string]
|
||||||
|
|
||||||
|
const
|
||||||
|
# These are needed in order to avoid an ambiguity error stemming from
|
||||||
|
# some cint constants with the same name defined in the posix modules
|
||||||
|
IPPROTO_TCP = Protocol.IPPROTO_TCP
|
||||||
|
IPPROTO_UDP = Protocol.IPPROTO_UDP
|
||||||
|
|
||||||
proc ip4StB(s: string, vb: var VBuffer): bool =
|
proc ip4StB(s: string, vb: var VBuffer): bool =
|
||||||
## IPv4 stringToBuffer() implementation.
|
## IPv4 stringToBuffer() implementation.
|
||||||
|
@ -438,33 +446,35 @@ proc shcopy*(m1: var MultiAddress, m2: MultiAddress) =
|
||||||
m1.data.offset = m2.data.offset
|
m1.data.offset = m2.data.offset
|
||||||
m1.data.length = m2.data.length
|
m1.data.length = m2.data.length
|
||||||
|
|
||||||
proc protoCode*(ma: MultiAddress): MultiCodec =
|
proc protoCode*(ma: MultiAddress): MaResult[MultiCodec] =
|
||||||
## Returns MultiAddress ``ma`` protocol code.
|
## Returns MultiAddress ``ma`` protocol code.
|
||||||
var header: uint64
|
var header: uint64
|
||||||
var vb: MultiAddress
|
var vb: MultiAddress
|
||||||
shcopy(vb, ma)
|
shcopy(vb, ma)
|
||||||
if vb.data.readVarint(header) == -1:
|
if vb.data.readVarint(header) == -1:
|
||||||
raise newException(MultiAddressError, "Malformed binary address!")
|
err("multiaddress: Malformed binary address!")
|
||||||
let proto = CodeAddresses.getOrDefault(MultiCodec(header))
|
else:
|
||||||
if proto.kind == None:
|
let proto = CodeAddresses.getOrDefault(MultiCodec(header))
|
||||||
raise newException(MultiAddressError,
|
if proto.kind == None:
|
||||||
"Unsupported protocol '" & $header & "'")
|
err("multiaddress: Unsupported protocol '" & $header & "'")
|
||||||
result = proto.mcodec
|
else:
|
||||||
|
ok(proto.mcodec)
|
||||||
|
|
||||||
proc protoName*(ma: MultiAddress): string =
|
proc protoName*(ma: MultiAddress): MaResult[string] =
|
||||||
## Returns MultiAddress ``ma`` protocol name.
|
## Returns MultiAddress ``ma`` protocol name.
|
||||||
var header: uint64
|
var header: uint64
|
||||||
var vb: MultiAddress
|
var vb: MultiAddress
|
||||||
shcopy(vb, ma)
|
shcopy(vb, ma)
|
||||||
if vb.data.readVarint(header) == -1:
|
if vb.data.readVarint(header) == -1:
|
||||||
raise newException(MultiAddressError, "Malformed binary address!")
|
err("multiaddress: Malformed binary address!")
|
||||||
let proto = CodeAddresses.getOrDefault(MultiCodec(header))
|
else:
|
||||||
if proto.kind == None:
|
let proto = CodeAddresses.getOrDefault(MultiCodec(header))
|
||||||
raise newException(MultiAddressError,
|
if proto.kind == None:
|
||||||
"Unsupported protocol '" & $header & "'")
|
err("multiaddress: Unsupported protocol '" & $header & "'")
|
||||||
result = $(proto.mcodec)
|
else:
|
||||||
|
ok($(proto.mcodec))
|
||||||
|
|
||||||
proc protoArgument*(ma: MultiAddress, value: var openarray[byte]): int =
|
proc protoArgument*(ma: MultiAddress, value: var openarray[byte]): MaResult[int] =
|
||||||
## Returns MultiAddress ``ma`` protocol argument value.
|
## Returns MultiAddress ``ma`` protocol argument value.
|
||||||
##
|
##
|
||||||
## If current MultiAddress do not have argument value, then result will be
|
## If current MultiAddress do not have argument value, then result will be
|
||||||
|
@ -474,71 +484,85 @@ proc protoArgument*(ma: MultiAddress, value: var openarray[byte]): int =
|
||||||
var buffer: seq[byte]
|
var buffer: seq[byte]
|
||||||
shcopy(vb, ma)
|
shcopy(vb, ma)
|
||||||
if vb.data.readVarint(header) == -1:
|
if vb.data.readVarint(header) == -1:
|
||||||
raise newException(MultiAddressError, "Malformed binary address!")
|
err("multiaddress: Malformed binary address!")
|
||||||
let proto = CodeAddresses.getOrDefault(MultiCodec(header))
|
else:
|
||||||
if proto.kind == None:
|
let proto = CodeAddresses.getOrDefault(MultiCodec(header))
|
||||||
raise newException(MultiAddressError,
|
if proto.kind == None:
|
||||||
"Unsupported protocol '" & $header & "'")
|
err("multiaddress: Unsupported protocol '" & $header & "'")
|
||||||
if proto.kind == Fixed:
|
else:
|
||||||
result = proto.size
|
var res: int
|
||||||
if len(value) >= result:
|
if proto.kind == Fixed:
|
||||||
if vb.data.readArray(value.toOpenArray(0, proto.size - 1)) != proto.size:
|
res = proto.size
|
||||||
raise newException(MultiAddressError, "Decoding protocol error")
|
if len(value) >= res and
|
||||||
elif proto.kind in {Length, Path}:
|
vb.data.readArray(value.toOpenArray(0, proto.size - 1)) != proto.size:
|
||||||
if vb.data.readSeq(buffer) == -1:
|
err("multiaddress: Decoding protocol error")
|
||||||
raise newException(MultiAddressError, "Decoding protocol error")
|
else:
|
||||||
result = len(buffer)
|
ok(res)
|
||||||
if len(value) >= result:
|
elif proto.kind in {Length, Path}:
|
||||||
copyMem(addr value[0], addr buffer[0], result)
|
if vb.data.readSeq(buffer) == -1:
|
||||||
|
err("multiaddress: Decoding protocol error")
|
||||||
|
else:
|
||||||
|
res = len(buffer)
|
||||||
|
if len(value) >= res:
|
||||||
|
copyMem(addr value[0], addr buffer[0], res)
|
||||||
|
ok(res)
|
||||||
|
else:
|
||||||
|
ok(res)
|
||||||
|
|
||||||
proc protoAddress*(ma: MultiAddress): seq[byte] =
|
proc protoAddress*(ma: MultiAddress): MaResult[seq[byte]] =
|
||||||
## Returns MultiAddress ``ma`` protocol address binary blob.
|
## Returns MultiAddress ``ma`` protocol address binary blob.
|
||||||
##
|
##
|
||||||
## If current MultiAddress do not have argument value, then result array will
|
## If current MultiAddress do not have argument value, then result array will
|
||||||
## be empty.
|
## be empty.
|
||||||
result = newSeq[byte](len(ma.data.buffer))
|
var buffer = newSeq[byte](len(ma.data.buffer))
|
||||||
let res = protoArgument(ma, result)
|
let res = ? protoArgument(ma, buffer)
|
||||||
result.setLen(res)
|
buffer.setLen(res)
|
||||||
|
ok(buffer)
|
||||||
|
|
||||||
proc getPart(ma: MultiAddress, index: int): MultiAddress =
|
proc getPart(ma: MultiAddress, index: int): MaResult[MultiAddress] =
|
||||||
var header: uint64
|
var header: uint64
|
||||||
var data = newSeq[byte]()
|
var data = newSeq[byte]()
|
||||||
var offset = 0
|
var offset = 0
|
||||||
var vb = ma
|
var vb = ma
|
||||||
result.data = initVBuffer()
|
var res: MultiAddress
|
||||||
|
res.data = initVBuffer()
|
||||||
while offset <= index:
|
while offset <= index:
|
||||||
if vb.data.readVarint(header) == -1:
|
if vb.data.readVarint(header) == -1:
|
||||||
raise newException(MultiAddressError, "Malformed binary address!")
|
return err("multiaddress: Malformed binary address!")
|
||||||
|
|
||||||
let proto = CodeAddresses.getOrDefault(MultiCodec(header))
|
let proto = CodeAddresses.getOrDefault(MultiCodec(header))
|
||||||
if proto.kind == None:
|
if proto.kind == None:
|
||||||
raise newException(MultiAddressError,
|
return err("multiaddress: Unsupported protocol '" & $header & "'")
|
||||||
"Unsupported protocol '" & $header & "'")
|
|
||||||
elif proto.kind == Fixed:
|
elif proto.kind == Fixed:
|
||||||
data.setLen(proto.size)
|
data.setLen(proto.size)
|
||||||
if vb.data.readArray(data) != proto.size:
|
if vb.data.readArray(data) != proto.size:
|
||||||
raise newException(MultiAddressError, "Decoding protocol error")
|
return err("multiaddress: Decoding protocol error")
|
||||||
|
|
||||||
if offset == index:
|
if offset == index:
|
||||||
result.data.writeVarint(header)
|
res.data.writeVarint(header)
|
||||||
result.data.writeArray(data)
|
res.data.writeArray(data)
|
||||||
result.data.finish()
|
res.data.finish()
|
||||||
elif proto.kind in {Length, Path}:
|
elif proto.kind in {Length, Path}:
|
||||||
if vb.data.readSeq(data) == -1:
|
if vb.data.readSeq(data) == -1:
|
||||||
raise newException(MultiAddressError, "Decoding protocol error")
|
return err("multiaddress: Decoding protocol error")
|
||||||
|
|
||||||
if offset == index:
|
if offset == index:
|
||||||
result.data.writeVarint(header)
|
res.data.writeVarint(header)
|
||||||
result.data.writeSeq(data)
|
res.data.writeSeq(data)
|
||||||
result.data.finish()
|
res.data.finish()
|
||||||
elif proto.kind == Marker:
|
elif proto.kind == Marker:
|
||||||
if offset == index:
|
if offset == index:
|
||||||
result.data.writeVarint(header)
|
res.data.writeVarint(header)
|
||||||
result.data.finish()
|
res.data.finish()
|
||||||
inc(offset)
|
inc(offset)
|
||||||
|
ok(res)
|
||||||
|
|
||||||
proc `[]`*(ma: MultiAddress, i: int): MultiAddress {.inline.} =
|
proc `[]`*(ma: MultiAddress, i: int): MaResult[MultiAddress] {.inline.} =
|
||||||
## Returns part with index ``i`` of MultiAddress ``ma``.
|
## Returns part with index ``i`` of MultiAddress ``ma``.
|
||||||
result = ma.getPart(i)
|
ma.getPart(i)
|
||||||
|
|
||||||
iterator items*(ma: MultiAddress): MultiAddress =
|
iterator items*(ma: MultiAddress): MaResult[MultiAddress] =
|
||||||
## Iterates over all addresses inside of MultiAddress ``ma``.
|
## Iterates over all addresses inside of MultiAddress ``ma``.
|
||||||
var header: uint64
|
var header: uint64
|
||||||
var data = newSeq[byte]()
|
var data = newSeq[byte]()
|
||||||
|
@ -546,75 +570,70 @@ iterator items*(ma: MultiAddress): MultiAddress =
|
||||||
while true:
|
while true:
|
||||||
if vb.data.isEmpty():
|
if vb.data.isEmpty():
|
||||||
break
|
break
|
||||||
|
|
||||||
var res = MultiAddress(data: initVBuffer())
|
var res = MultiAddress(data: initVBuffer())
|
||||||
if vb.data.readVarint(header) == -1:
|
if vb.data.readVarint(header) == -1:
|
||||||
raise newException(MultiAddressError, "Malformed binary address!")
|
yield err(MaResult[MultiAddress], "Malformed binary address!")
|
||||||
|
|
||||||
let proto = CodeAddresses.getOrDefault(MultiCodec(header))
|
let proto = CodeAddresses.getOrDefault(MultiCodec(header))
|
||||||
if proto.kind == None:
|
if proto.kind == None:
|
||||||
raise newException(MultiAddressError,
|
yield err(MaResult[MultiAddress], "Unsupported protocol '" & $header & "'")
|
||||||
"Unsupported protocol '" & $header & "'")
|
|
||||||
elif proto.kind == Fixed:
|
elif proto.kind == Fixed:
|
||||||
data.setLen(proto.size)
|
data.setLen(proto.size)
|
||||||
if vb.data.readArray(data) != proto.size:
|
if vb.data.readArray(data) != proto.size:
|
||||||
raise newException(MultiAddressError, "Decoding protocol error")
|
yield err(MaResult[MultiAddress], "Decoding protocol error")
|
||||||
|
|
||||||
res.data.writeVarint(header)
|
res.data.writeVarint(header)
|
||||||
res.data.writeArray(data)
|
res.data.writeArray(data)
|
||||||
elif proto.kind in {Length, Path}:
|
elif proto.kind in {Length, Path}:
|
||||||
if vb.data.readSeq(data) == -1:
|
if vb.data.readSeq(data) == -1:
|
||||||
raise newException(MultiAddressError, "Decoding protocol error")
|
yield err(MaResult[MultiAddress], "Decoding protocol error")
|
||||||
|
|
||||||
res.data.writeVarint(header)
|
res.data.writeVarint(header)
|
||||||
res.data.writeSeq(data)
|
res.data.writeSeq(data)
|
||||||
elif proto.kind == Marker:
|
elif proto.kind == Marker:
|
||||||
res.data.writeVarint(header)
|
res.data.writeVarint(header)
|
||||||
res.data.finish()
|
res.data.finish()
|
||||||
yield res
|
yield ok(MaResult[MultiAddress], res)
|
||||||
|
|
||||||
proc contains*(ma: MultiAddress, codec: MultiCodec): bool {.inline.} =
|
proc contains*(ma: MultiAddress, codec: MultiCodec): MaResult[bool] {.inline.} =
|
||||||
## Returns ``true``, if address with MultiCodec ``codec`` present in
|
## Returns ``true``, if address with MultiCodec ``codec`` present in
|
||||||
## MultiAddress ``ma``.
|
## MultiAddress ``ma``.
|
||||||
var res = false
|
|
||||||
for item in ma.items:
|
for item in ma.items:
|
||||||
if item.protoCode() == codec:
|
let code = ?(?item).protoCode()
|
||||||
res = true
|
if code == codec:
|
||||||
break
|
return ok(true)
|
||||||
result = res
|
ok(false)
|
||||||
|
|
||||||
proc `[]`*(ma: MultiAddress, codec: MultiCodec): MultiAddress {.inline.} =
|
proc `[]`*(ma: MultiAddress, codec: MultiCodec): MaResult[MultiAddress] {.inline.} =
|
||||||
## Returns partial MultiAddress with MultiCodec ``codec`` and present in
|
## Returns partial MultiAddress with MultiCodec ``codec`` and present in
|
||||||
## MultiAddress ``ma``.
|
## MultiAddress ``ma``.
|
||||||
##
|
|
||||||
## Procedure will raise ``MultiAddressError`` if ``codec`` could not be
|
|
||||||
## found inside of ``ma``.
|
|
||||||
var res = MultiAddress(data: initVBuffer())
|
|
||||||
for item in ma.items:
|
for item in ma.items:
|
||||||
if item.protoCode == codec:
|
if ?(?item).protoCode == codec:
|
||||||
res = item
|
return item
|
||||||
break
|
err("multiaddress: Codec is not present in address")
|
||||||
if res.data.isEmpty():
|
|
||||||
raise newException(MultiAddressError, "Codec is not present in address")
|
|
||||||
result = res
|
|
||||||
|
|
||||||
proc `$`*(value: MultiAddress): string =
|
proc toString*(value: MultiAddress): MaResult[string] =
|
||||||
## Return string representation of MultiAddress ``value``.
|
## Return string representation of MultiAddress ``value``.
|
||||||
var header: uint64
|
var header: uint64
|
||||||
var vb = value
|
var vb = value
|
||||||
var parts = newSeq[string]()
|
var parts = newSeq[string]()
|
||||||
var part: string
|
var part: string
|
||||||
|
var res: string
|
||||||
while true:
|
while true:
|
||||||
if vb.data.isEmpty():
|
if vb.data.isEmpty():
|
||||||
break
|
break
|
||||||
if vb.data.readVarint(header) == -1:
|
if vb.data.readVarint(header) == -1:
|
||||||
raise newException(MultiAddressError, "Malformed binary address!")
|
return err("multiaddress: Malformed binary address!")
|
||||||
let proto = CodeAddresses.getOrDefault(MultiCodec(header))
|
let proto = CodeAddresses.getOrDefault(MultiCodec(header))
|
||||||
if proto.kind == None:
|
if proto.kind == None:
|
||||||
raise newException(MultiAddressError,
|
return err("multiaddress: Unsupported protocol '" & $header & "'")
|
||||||
"Unsupported protocol '" & $header & "'")
|
|
||||||
if proto.kind in {Fixed, Length, Path}:
|
if proto.kind in {Fixed, Length, Path}:
|
||||||
if isNil(proto.coder.bufferToString):
|
if isNil(proto.coder.bufferToString):
|
||||||
raise newException(MultiAddressError,
|
return err("multiaddress: Missing protocol '" & $(proto.mcodec) & "' coder")
|
||||||
"Missing protocol '" & $(proto.mcodec) & "' coder")
|
|
||||||
if not proto.coder.bufferToString(vb.data, part):
|
if not proto.coder.bufferToString(vb.data, part):
|
||||||
raise newException(MultiAddressError, "Decoding protocol error")
|
return err("multiaddress: Decoding protocol error")
|
||||||
parts.add($(proto.mcodec))
|
parts.add($(proto.mcodec))
|
||||||
if proto.kind == Path and part[0] == '/':
|
if proto.kind == Path and part[0] == '/':
|
||||||
parts.add(part[1..^1])
|
parts.add(part[1..^1])
|
||||||
|
@ -623,17 +642,23 @@ proc `$`*(value: MultiAddress): string =
|
||||||
elif proto.kind == Marker:
|
elif proto.kind == Marker:
|
||||||
parts.add($(proto.mcodec))
|
parts.add($(proto.mcodec))
|
||||||
if len(parts) > 0:
|
if len(parts) > 0:
|
||||||
result = "/" & parts.join("/")
|
res = "/" & parts.join("/")
|
||||||
|
ok(res)
|
||||||
|
|
||||||
proc protocols*(value: MultiAddress): seq[MultiCodec] =
|
proc `$`*(value: MultiAddress): string {.raises: [Defect, ResultError[string]].} =
|
||||||
|
## Return string representation of MultiAddress ``value``.
|
||||||
|
value.toString().tryGet()
|
||||||
|
|
||||||
|
proc protocols*(value: MultiAddress): MaResult[seq[MultiCodec]] =
|
||||||
## Returns list of protocol codecs inside of MultiAddress ``value``.
|
## Returns list of protocol codecs inside of MultiAddress ``value``.
|
||||||
result = newSeq[MultiCodec]()
|
var res = newSeq[MultiCodec]()
|
||||||
for item in value.items():
|
for item in value.items():
|
||||||
result.add(item.protoCode())
|
res.add(?(?item).protoCode())
|
||||||
|
ok(res)
|
||||||
|
|
||||||
proc hex*(value: MultiAddress): string =
|
proc hex*(value: MultiAddress): string =
|
||||||
## Return hexadecimal string representation of MultiAddress ``value``.
|
## Return hexadecimal string representation of MultiAddress ``value``.
|
||||||
result = $(value.data)
|
$(value.data)
|
||||||
|
|
||||||
proc write*(vb: var VBuffer, ma: MultiAddress) {.inline.} =
|
proc write*(vb: var VBuffer, ma: MultiAddress) {.inline.} =
|
||||||
## Write MultiAddress value ``ma`` to buffer ``vb``.
|
## Write MultiAddress value ``ma`` to buffer ``vb``.
|
||||||
|
@ -667,200 +692,239 @@ proc validate*(ma: MultiAddress): bool =
|
||||||
discard
|
discard
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc init*(mtype: typedesc[MultiAddress], protocol: MultiCodec,
|
proc init*(mtype: typedesc[MultiAddress], protocol: MultiCodec, value: openarray[byte]): MaResult[MultiAddress] =
|
||||||
value: openarray[byte]): MultiAddress =
|
|
||||||
## Initialize MultiAddress object from protocol id ``protocol`` and array
|
## Initialize MultiAddress object from protocol id ``protocol`` and array
|
||||||
## of bytes ``value``.
|
## of bytes ``value``.
|
||||||
let proto = CodeAddresses.getOrDefault(protocol)
|
let proto = CodeAddresses.getOrDefault(protocol)
|
||||||
if proto.kind == None:
|
if proto.kind == None:
|
||||||
raise newException(MultiAddressError, "Protocol not found")
|
err("multiaddress: Protocol not found")
|
||||||
result.data = initVBuffer()
|
else:
|
||||||
result.data.writeVarint(cast[uint64](proto.mcodec))
|
var res: MultiAddress
|
||||||
if proto.kind in {Fixed, Length, Path}:
|
res.data = initVBuffer()
|
||||||
if len(value) == 0:
|
res.data.writeVarint(cast[uint64](proto.mcodec))
|
||||||
raise newException(MultiAddressError, "Value must not be empty array")
|
if proto.kind in {Fixed, Length, Path}:
|
||||||
if proto.kind == Fixed:
|
if len(value) == 0:
|
||||||
result.data.writeArray(value)
|
err("multiaddress: Value must not be empty array")
|
||||||
else:
|
else:
|
||||||
var data = newSeq[byte](len(value))
|
if proto.kind == Fixed:
|
||||||
copyMem(addr data[0], unsafeAddr value[0], len(value))
|
res.data.writeArray(value)
|
||||||
result.data.writeSeq(data)
|
else:
|
||||||
result.data.finish()
|
var data = newSeq[byte](len(value))
|
||||||
|
copyMem(addr data[0], unsafeAddr value[0], len(value))
|
||||||
|
res.data.writeSeq(data)
|
||||||
|
res.data.finish()
|
||||||
|
ok(res)
|
||||||
|
|
||||||
proc init*(mtype: typedesc[MultiAddress], protocol: MultiCodec,
|
proc init*(mtype: typedesc[MultiAddress], protocol: MultiCodec, value: PeerID): MaResult[MultiAddress] {.inline.} =
|
||||||
value: PeerID): MultiAddress {.inline.} =
|
|
||||||
## Initialize MultiAddress object from protocol id ``protocol`` and peer id
|
## Initialize MultiAddress object from protocol id ``protocol`` and peer id
|
||||||
## ``value``.
|
## ``value``.
|
||||||
init(mtype, protocol, value.data)
|
init(mtype, protocol, value.data)
|
||||||
|
|
||||||
proc init*(mtype: typedesc[MultiAddress], protocol: MultiCodec): MultiAddress =
|
proc init*(mtype: typedesc[MultiAddress], protocol: MultiCodec): MaResult[MultiAddress] =
|
||||||
## Initialize MultiAddress object from protocol id ``protocol``.
|
## Initialize MultiAddress object from protocol id ``protocol``.
|
||||||
let proto = CodeAddresses.getOrDefault(protocol)
|
let proto = CodeAddresses.getOrDefault(protocol)
|
||||||
if proto.kind == None:
|
if proto.kind == None:
|
||||||
raise newException(MultiAddressError, "Protocol not found")
|
err("multiaddress: Protocol not found")
|
||||||
result.data = initVBuffer()
|
else:
|
||||||
if proto.kind != Marker:
|
var res: MultiAddress
|
||||||
raise newException(MultiAddressError, "Protocol missing value")
|
res.data = initVBuffer()
|
||||||
result.data.writeVarint(cast[uint64](proto.mcodec))
|
if proto.kind != Marker:
|
||||||
result.data.finish()
|
raise newException(MultiAddressError, "Protocol missing value")
|
||||||
|
res.data.writeVarint(cast[uint64](proto.mcodec))
|
||||||
|
res.data.finish()
|
||||||
|
ok(res)
|
||||||
|
|
||||||
proc init*(mtype: typedesc[MultiAddress], protocol: MultiCodec,
|
proc init*(mtype: typedesc[MultiAddress], protocol: MultiCodec, value: int): MaResult[MultiAddress] =
|
||||||
value: int): MultiAddress =
|
|
||||||
## Initialize MultiAddress object from protocol id ``protocol`` and integer
|
## Initialize MultiAddress object from protocol id ``protocol`` and integer
|
||||||
## ``value``. This procedure can be used to instantiate ``tcp``, ``udp``,
|
## ``value``. This procedure can be used to instantiate ``tcp``, ``udp``,
|
||||||
## ``dccp`` and ``sctp`` MultiAddresses.
|
## ``dccp`` and ``sctp`` MultiAddresses.
|
||||||
var allowed = [multiCodec("tcp"), multiCodec("udp"), multiCodec("dccp"),
|
var allowed = [multiCodec("tcp"), multiCodec("udp"), multiCodec("dccp"),
|
||||||
multiCodec("sctp")]
|
multiCodec("sctp")]
|
||||||
if protocol notin allowed:
|
if protocol notin allowed:
|
||||||
raise newException(MultiAddressError,
|
err("multiaddress: Incorrect protocol for integer value")
|
||||||
"Incorrect protocol for integer value")
|
else:
|
||||||
let proto = CodeAddresses.getOrDefault(protocol)
|
let proto = CodeAddresses.getOrDefault(protocol)
|
||||||
result.data = initVBuffer()
|
var res: MultiAddress
|
||||||
result.data.writeVarint(cast[uint64](proto.mcodec))
|
res.data = initVBuffer()
|
||||||
if value < 0 or value > 65535:
|
res.data.writeVarint(cast[uint64](proto.mcodec))
|
||||||
raise newException(MultiAddressError, "Incorrect integer value")
|
if value < 0 or value > 65535:
|
||||||
result.data.writeArray(toBytesBE(cast[uint16](value)))
|
err("multiaddress: Incorrect integer value")
|
||||||
result.data.finish()
|
else:
|
||||||
|
res.data.writeArray(toBytesBE(cast[uint16](value)))
|
||||||
|
res.data.finish()
|
||||||
|
ok(res)
|
||||||
|
|
||||||
proc getProtocol(name: string): MAProtocol {.inline.} =
|
proc getProtocol(name: string): MAProtocol {.inline.} =
|
||||||
let mc = MultiCodec.codec(name)
|
let mc = MultiCodec.codec(name)
|
||||||
if mc != InvalidMultiCodec:
|
if mc != InvalidMultiCodec:
|
||||||
result = CodeAddresses.getOrDefault(mc)
|
result = CodeAddresses.getOrDefault(mc)
|
||||||
|
|
||||||
proc init*(mtype: typedesc[MultiAddress], value: string): MultiAddress =
|
proc init*(mtype: typedesc[MultiAddress], value: string): MaResult[MultiAddress] =
|
||||||
## Initialize MultiAddress object from string representation ``value``.
|
## Initialize MultiAddress object from string representation ``value``.
|
||||||
var parts = value.trimRight('/').split('/')
|
var parts = value.trimRight('/').split('/')
|
||||||
if len(parts[0]) != 0:
|
if len(parts[0]) != 0:
|
||||||
raise newException(MultiAddressError,
|
err("multiaddress: Invalid MultiAddress, must start with `/`")
|
||||||
"Invalid MultiAddress, must start with `/`")
|
else:
|
||||||
var offset = 1
|
var offset = 1
|
||||||
result.data = initVBuffer()
|
var res: MultiAddress
|
||||||
while offset < len(parts):
|
res.data = initVBuffer()
|
||||||
let part = parts[offset]
|
while offset < len(parts):
|
||||||
let proto = getProtocol(part)
|
let part = parts[offset]
|
||||||
if proto.kind == None:
|
let proto = getProtocol(part)
|
||||||
raise newException(MultiAddressError,
|
if proto.kind == None:
|
||||||
"Unsupported protocol '" & part & "'")
|
return err("multiaddress: Unsupported protocol '" & part & "'")
|
||||||
if proto.kind in {Fixed, Length, Path}:
|
else:
|
||||||
if isNil(proto.coder.stringToBuffer):
|
if proto.kind in {Fixed, Length, Path}:
|
||||||
raise newException(MultiAddressError,
|
if isNil(proto.coder.stringToBuffer):
|
||||||
"Missing protocol '" & part & "' transcoder")
|
return err("multiaddress: Missing protocol '" & part & "' transcoder")
|
||||||
if offset + 1 >= len(parts):
|
|
||||||
raise newException(MultiAddressError,
|
|
||||||
"Missing protocol '" & part & "' argument")
|
|
||||||
|
|
||||||
if proto.kind in {Fixed, Length}:
|
if offset + 1 >= len(parts):
|
||||||
result.data.write(proto.mcodec)
|
return err("multiaddress: Missing protocol '" & part & "' argument")
|
||||||
let res = proto.coder.stringToBuffer(parts[offset + 1], result.data)
|
|
||||||
if not res:
|
|
||||||
raise newException(MultiAddressError,
|
|
||||||
"Error encoding `$1/$2`" % [part, parts[offset + 1]])
|
|
||||||
offset += 2
|
|
||||||
elif proto.kind == Path:
|
|
||||||
var path = "/" & (parts[(offset + 1)..^1].join("/"))
|
|
||||||
result.data.write(proto.mcodec)
|
|
||||||
if not proto.coder.stringToBuffer(path, result.data):
|
|
||||||
raise newException(MultiAddressError,
|
|
||||||
"Error encoding `$1/$2`" % [part, path])
|
|
||||||
break
|
|
||||||
elif proto.kind == Marker:
|
|
||||||
result.data.write(proto.mcodec)
|
|
||||||
offset += 1
|
|
||||||
result.data.finish()
|
|
||||||
|
|
||||||
proc init*(mtype: typedesc[MultiAddress], data: openarray[byte]): MultiAddress =
|
if proto.kind in {Fixed, Length}:
|
||||||
|
res.data.write(proto.mcodec)
|
||||||
|
let res = proto.coder.stringToBuffer(parts[offset + 1], res.data)
|
||||||
|
if not res:
|
||||||
|
return err("multiaddress: Error encoding `" & part & "/" & parts[offset + 1] & "`")
|
||||||
|
offset += 2
|
||||||
|
|
||||||
|
elif proto.kind == Path:
|
||||||
|
var path = "/" & (parts[(offset + 1)..^1].join("/"))
|
||||||
|
res.data.write(proto.mcodec)
|
||||||
|
if not proto.coder.stringToBuffer(path, res.data):
|
||||||
|
return err("multiaddress: Error encoding `" & part & "/" & path & "`")
|
||||||
|
|
||||||
|
break
|
||||||
|
elif proto.kind == Marker:
|
||||||
|
res.data.write(proto.mcodec)
|
||||||
|
offset += 1
|
||||||
|
res.data.finish()
|
||||||
|
ok(res)
|
||||||
|
|
||||||
|
|
||||||
|
proc init*(mtype: typedesc[MultiAddress], data: openarray[byte]): MaResult[MultiAddress] =
|
||||||
## Initialize MultiAddress with array of bytes ``data``.
|
## Initialize MultiAddress with array of bytes ``data``.
|
||||||
if len(data) == 0:
|
if len(data) == 0:
|
||||||
raise newException(MultiAddressError, "Address could not be empty!")
|
err("multiaddress: Address could not be empty!")
|
||||||
result.data = initVBuffer()
|
else:
|
||||||
result.data.buffer.setLen(len(data))
|
var res: MultiAddress
|
||||||
copyMem(addr result.data.buffer[0], unsafeAddr data[0], len(data))
|
res.data = initVBuffer()
|
||||||
if not result.validate():
|
res.data.buffer.setLen(len(data))
|
||||||
raise newException(MultiAddressError, "Incorrect MultiAddress!")
|
copyMem(addr res.data.buffer[0], unsafeAddr data[0], len(data))
|
||||||
|
if not res.validate():
|
||||||
|
err("multiaddress: Incorrect MultiAddress!")
|
||||||
|
else:
|
||||||
|
ok(res)
|
||||||
|
|
||||||
proc init*(mtype: typedesc[MultiAddress]): MultiAddress =
|
proc init*(mtype: typedesc[MultiAddress]): MultiAddress =
|
||||||
## Initialize empty MultiAddress.
|
## Initialize empty MultiAddress.
|
||||||
result.data = initVBuffer()
|
result.data = initVBuffer()
|
||||||
|
|
||||||
proc init*(mtype: typedesc[MultiAddress],
|
proc init*(mtype: typedesc[MultiAddress],
|
||||||
address: IpAddress, protocol: Protocol, port: Port): MultiAddress =
|
address: IpAddress, protocol: Protocol, port: Port): MaResult[MultiAddress] =
|
||||||
## Initialize MultiAddress using stdlib's net.IpAddress (IPv4/IPv6) and
|
## Initialize MultiAddress using stdlib's net.IpAddress (IPv4/IPv6) and
|
||||||
## net.Protocol (UDP/TCP) information.
|
## net.Protocol (UDP/TCP) information.
|
||||||
result.data = initVBuffer()
|
var res: MultiAddress
|
||||||
|
res.data = initVBuffer()
|
||||||
let familyProto = case address.family
|
let familyProto = case address.family
|
||||||
of IpAddressFamily.IPv4: getProtocol("ip4")
|
of IpAddressFamily.IPv4: getProtocol("ip4")
|
||||||
of IpAddressFamily.IPv6: getProtocol("ip6")
|
of IpAddressFamily.IPv6: getProtocol("ip6")
|
||||||
let protoProto = case protocol
|
let protoProto = case protocol
|
||||||
of IPPROTO_TCP: getProtocol("tcp")
|
of IPPROTO_TCP: getProtocol("tcp")
|
||||||
of IPPROTO_UDP: getProtocol("udp")
|
of IPPROTO_UDP: getProtocol("udp")
|
||||||
else: raise newException(AssertionError,
|
else: return err("multiaddress: protocol should be either TCP or UDP")
|
||||||
"protocol should be either TCP or UDP")
|
|
||||||
result.data.write(familyProto.mcodec)
|
res.data.write(familyProto.mcodec)
|
||||||
if not familyProto.coder.stringToBuffer($address, result.data):
|
if not familyProto.coder.stringToBuffer($address, res.data):
|
||||||
raise newException(MultiAddressError, "Error encoding IPv4/IPv6 address")
|
err("multiaddress: Error encoding IPv4/IPv6 address")
|
||||||
result.data.write(protoProto.mcodec)
|
else:
|
||||||
if not protoProto.coder.stringToBuffer($port, result.data):
|
res.data.write(protoProto.mcodec)
|
||||||
raise newException(MultiAddressError, "Error encoding port number")
|
if not protoProto.coder.stringToBuffer($port, res.data):
|
||||||
result.data.finish()
|
err("multiaddress: Error encoding port number")
|
||||||
|
else:
|
||||||
|
res.data.finish()
|
||||||
|
ok(res)
|
||||||
|
|
||||||
proc init*(mtype: typedesc[MultiAddress], address: TransportAddress,
|
proc init*(mtype: typedesc[MultiAddress], address: TransportAddress,
|
||||||
protocol: Protocol = IPPROTO_TCP): MultiAddress =
|
protocol = IPPROTO_TCP): MaResult[MultiAddress] =
|
||||||
## Initialize MultiAddress using chronos.TransportAddress (IPv4/IPv6/Unix)
|
## Initialize MultiAddress using chronos.TransportAddress (IPv4/IPv6/Unix)
|
||||||
## and protocol information (UDP/TCP).
|
## and protocol information (UDP/TCP).
|
||||||
result.data = initVBuffer()
|
var res: MultiAddress
|
||||||
|
res.data = initVBuffer()
|
||||||
let protoProto = case protocol
|
let protoProto = case protocol
|
||||||
of IPPROTO_TCP: getProtocol("tcp")
|
of IPPROTO_TCP: getProtocol("tcp")
|
||||||
of IPPROTO_UDP: getProtocol("udp")
|
of IPPROTO_UDP: getProtocol("udp")
|
||||||
else: raise newException(AssertionError,
|
else: return err("multiaddress: protocol should be either TCP or UDP")
|
||||||
"protocol should be either TCP or UDP")
|
|
||||||
if address.family == AddressFamily.IPv4:
|
if address.family == AddressFamily.IPv4:
|
||||||
result.data.write(getProtocol("ip4").mcodec)
|
res.data.write(getProtocol("ip4").mcodec)
|
||||||
result.data.writeArray(address.address_v4)
|
res.data.writeArray(address.address_v4)
|
||||||
result.data.write(protoProto.mcodec)
|
res.data.write(protoProto.mcodec)
|
||||||
discard protoProto.coder.stringToBuffer($address.port, result.data)
|
discard protoProto.coder.stringToBuffer($address.port, res.data)
|
||||||
elif address.family == AddressFamily.IPv6:
|
elif address.family == AddressFamily.IPv6:
|
||||||
result.data.write(getProtocol("ip6").mcodec)
|
res.data.write(getProtocol("ip6").mcodec)
|
||||||
result.data.writeArray(address.address_v6)
|
res.data.writeArray(address.address_v6)
|
||||||
result.data.write(protoProto.mcodec)
|
res.data.write(protoProto.mcodec)
|
||||||
discard protoProto.coder.stringToBuffer($address.port, result.data)
|
discard protoProto.coder.stringToBuffer($address.port, res.data)
|
||||||
elif address.family == AddressFamily.Unix:
|
elif address.family == AddressFamily.Unix:
|
||||||
result.data.write(getProtocol("unix").mcodec)
|
res.data.write(getProtocol("unix").mcodec)
|
||||||
result.data.writeSeq(address.address_un)
|
res.data.writeSeq(address.address_un)
|
||||||
result.data.finish()
|
res.data.finish()
|
||||||
|
ok(res)
|
||||||
|
|
||||||
proc isEmpty*(ma: MultiAddress): bool =
|
proc isEmpty*(ma: MultiAddress): bool =
|
||||||
## Returns ``true``, if MultiAddress ``ma`` is empty or non initialized.
|
## Returns ``true``, if MultiAddress ``ma`` is empty or non initialized.
|
||||||
result = len(ma.data) == 0
|
result = len(ma.data) == 0
|
||||||
|
|
||||||
proc `&`*(m1, m2: MultiAddress): MultiAddress =
|
proc concat*(m1, m2: MultiAddress): MaResult[MultiAddress] =
|
||||||
|
var res: MultiAddress
|
||||||
|
res.data = initVBuffer()
|
||||||
|
res.data.buffer = m1.data.buffer & m2.data.buffer
|
||||||
|
if not res.validate():
|
||||||
|
err("multiaddress: Incorrect MultiAddress!")
|
||||||
|
else:
|
||||||
|
ok(res)
|
||||||
|
|
||||||
|
proc append*(m1: var MultiAddress, m2: MultiAddress): MaResult[void] =
|
||||||
|
m1.data.buffer &= m2.data.buffer
|
||||||
|
if not m1.validate():
|
||||||
|
err("multiaddress: Incorrect MultiAddress!")
|
||||||
|
else:
|
||||||
|
ok()
|
||||||
|
|
||||||
|
proc `&`*(m1, m2: MultiAddress): MultiAddress {.raises: [Defect, ResultError[string]].} =
|
||||||
## Concatenates two addresses ``m1`` and ``m2``, and returns result.
|
## Concatenates two addresses ``m1`` and ``m2``, and returns result.
|
||||||
##
|
##
|
||||||
## This procedure performs validation of concatenated result and can raise
|
## This procedure performs validation of concatenated result and can raise
|
||||||
## exception on error.
|
## exception on error.
|
||||||
result.data = initVBuffer()
|
concat(m1, m2).tryGet()
|
||||||
result.data.buffer = m1.data.buffer & m2.data.buffer
|
|
||||||
if not result.validate():
|
|
||||||
raise newException(MultiAddressError, "Incorrect MultiAddress!")
|
|
||||||
|
|
||||||
proc `&=`*(m1: var MultiAddress, m2: MultiAddress) =
|
proc `&=`*(m1: var MultiAddress, m2: MultiAddress) {.raises: [Defect, ResultError[string]].} =
|
||||||
## Concatenates two addresses ``m1`` and ``m2``.
|
## Concatenates two addresses ``m1`` and ``m2``.
|
||||||
##
|
##
|
||||||
## This procedure performs validation of concatenated result and can raise
|
## This procedure performs validation of concatenated result and can raise
|
||||||
## exception on error.
|
## exception on error.
|
||||||
m1.data.buffer &= m2.data.buffer
|
##
|
||||||
if not m1.validate():
|
m1.append(m2).tryGet()
|
||||||
raise newException(MultiAddressError, "Incorrect MultiAddress!")
|
|
||||||
|
|
||||||
proc isWire*(ma: MultiAddress): bool =
|
proc isWire*(ma: MultiAddress): bool =
|
||||||
## Returns ``true`` if MultiAddress ``ma`` is one of:
|
## Returns ``true`` if MultiAddress ``ma`` is one of:
|
||||||
## - {IP4}/{TCP, UDP}
|
## - {IP4}/{TCP, UDP}
|
||||||
## - {IP6}/{TCP, UDP}
|
## - {IP6}/{TCP, UDP}
|
||||||
## - {UNIX}/{PATH}
|
## - {UNIX}/{PATH}
|
||||||
var state = 0
|
var
|
||||||
|
state = 0
|
||||||
try:
|
try:
|
||||||
for part in ma.items():
|
for rpart in ma.items():
|
||||||
|
if rpart.isErr():
|
||||||
|
return false
|
||||||
|
let part = rpart.get()
|
||||||
|
|
||||||
if state == 0:
|
if state == 0:
|
||||||
let code = part.protoCode()
|
let rcode = part.protoCode()
|
||||||
|
if rcode.isErr():
|
||||||
|
return false
|
||||||
|
let code = rcode.get()
|
||||||
|
|
||||||
if code == multiCodec("ip4") or code == multiCodec("ip6"):
|
if code == multiCodec("ip4") or code == multiCodec("ip6"):
|
||||||
inc(state)
|
inc(state)
|
||||||
continue
|
continue
|
||||||
|
@ -871,8 +935,12 @@ proc isWire*(ma: MultiAddress): bool =
|
||||||
result = false
|
result = false
|
||||||
break
|
break
|
||||||
elif state == 1:
|
elif state == 1:
|
||||||
if part.protoCode == multiCodec("tcp") or
|
let rcode = part.protoCode()
|
||||||
part.protoCode == multiCodec("udp"):
|
if rcode.isErr():
|
||||||
|
return false
|
||||||
|
let code = rcode.get()
|
||||||
|
|
||||||
|
if code == multiCodec("tcp") or code == multiCodec("udp"):
|
||||||
inc(state)
|
inc(state)
|
||||||
result = true
|
result = true
|
||||||
else:
|
else:
|
||||||
|
@ -912,16 +980,20 @@ proc matchPart(pat: MaPattern, protos: seq[MultiCodec]): MaPatResult =
|
||||||
proc match*(pat: MaPattern, address: MultiAddress): bool =
|
proc match*(pat: MaPattern, address: MultiAddress): bool =
|
||||||
## Match full ``address`` using pattern ``pat`` and return ``true`` if
|
## Match full ``address`` using pattern ``pat`` and return ``true`` if
|
||||||
## ``address`` satisfies pattern.
|
## ``address`` satisfies pattern.
|
||||||
var protos = address.protocols()
|
let protos = address.protocols()
|
||||||
let res = matchPart(pat, protos)
|
if protos.isErr():
|
||||||
result = res.flag and (len(res.rem) == 0)
|
return false
|
||||||
|
let res = matchPart(pat, protos.get())
|
||||||
|
res.flag and (len(res.rem) == 0)
|
||||||
|
|
||||||
proc matchPartial*(pat: MaPattern, address: MultiAddress): bool =
|
proc matchPartial*(pat: MaPattern, address: MultiAddress): bool =
|
||||||
## Match prefix part of ``address`` using pattern ``pat`` and return
|
## Match prefix part of ``address`` using pattern ``pat`` and return
|
||||||
## ``true`` if ``address`` starts with pattern.
|
## ``true`` if ``address`` starts with pattern.
|
||||||
var protos = address.protocols()
|
let protos = address.protocols()
|
||||||
let res = matchPart(pat, protos)
|
if protos.isErr():
|
||||||
result = res.flag
|
return false
|
||||||
|
let res = matchPart(pat, protos.get())
|
||||||
|
res.flag
|
||||||
|
|
||||||
proc `$`*(pat: MaPattern): string =
|
proc `$`*(pat: MaPattern): string =
|
||||||
## Return pattern ``pat`` as string.
|
## Return pattern ``pat`` as string.
|
||||||
|
|
|
@ -11,8 +11,12 @@
|
||||||
##
|
##
|
||||||
## TODO:
|
## TODO:
|
||||||
## 1. base32z
|
## 1. base32z
|
||||||
|
##
|
||||||
|
|
||||||
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import tables
|
import tables
|
||||||
import stew/[base32, base58, base64]
|
import stew/[base32, base58, base64, results]
|
||||||
|
|
||||||
type
|
type
|
||||||
MultibaseStatus* {.pure.} = enum
|
MultibaseStatus* {.pure.} = enum
|
||||||
|
@ -20,22 +24,20 @@ type
|
||||||
|
|
||||||
MultiBase* = object
|
MultiBase* = object
|
||||||
|
|
||||||
MBCodeSize = proc(length: int): int {.nimcall.}
|
MBCodeSize = proc(length: int): int {.nimcall, raises: [Defect].}
|
||||||
|
|
||||||
MBCodec = object
|
MBCodec = object
|
||||||
code: char
|
code: char
|
||||||
name: string
|
name: string
|
||||||
encr: proc(inbytes: openarray[byte],
|
encr: proc(inbytes: openarray[byte],
|
||||||
outbytes: var openarray[char],
|
outbytes: var openarray[char],
|
||||||
outlen: var int): MultibaseStatus {.nimcall.}
|
outlen: var int): MultibaseStatus {.nimcall, raises: [Defect].}
|
||||||
decr: proc(inbytes: openarray[char],
|
decr: proc(inbytes: openarray[char],
|
||||||
outbytes: var openarray[byte],
|
outbytes: var openarray[byte],
|
||||||
outlen: var int): MultibaseStatus {.nimcall.}
|
outlen: var int): MultibaseStatus {.nimcall, raises: [Defect].}
|
||||||
encl: MBCodeSize
|
encl: MBCodeSize
|
||||||
decl: MBCodeSize
|
decl: MBCodeSize
|
||||||
|
|
||||||
MultiBaseError* = object of CatchableError
|
|
||||||
|
|
||||||
proc idd(inbytes: openarray[char], outbytes: var openarray[byte],
|
proc idd(inbytes: openarray[char], outbytes: var openarray[byte],
|
||||||
outlen: var int): MultibaseStatus =
|
outlen: var int): MultibaseStatus =
|
||||||
let length = len(inbytes)
|
let length = len(inbytes)
|
||||||
|
@ -439,48 +441,50 @@ proc decode*(mbtype: typedesc[MultiBase], inbytes: openarray[char],
|
||||||
result = mb.decr(inbytes.toOpenArray(1, length - 1), outbytes, outlen)
|
result = mb.decr(inbytes.toOpenArray(1, length - 1), outbytes, outlen)
|
||||||
|
|
||||||
proc encode*(mbtype: typedesc[MultiBase], encoding: string,
|
proc encode*(mbtype: typedesc[MultiBase], encoding: string,
|
||||||
inbytes: openarray[byte]): string =
|
inbytes: openarray[byte]): Result[string, string] =
|
||||||
## Encode array ``inbytes`` using MultiBase encoding scheme ``encoding`` and
|
## Encode array ``inbytes`` using MultiBase encoding scheme ``encoding`` and
|
||||||
## return encoded string.
|
## return encoded string.
|
||||||
let length = len(inbytes)
|
let length = len(inbytes)
|
||||||
let mb = NameMultibases.getOrDefault(encoding)
|
let mb = NameMultibases.getOrDefault(encoding)
|
||||||
if len(mb.name) == 0:
|
if len(mb.name) == 0:
|
||||||
raise newException(MultiBaseError, "Encoding scheme is incorrect!")
|
return err("multibase: Encoding scheme is incorrect!")
|
||||||
if isNil(mb.encr) or isNil(mb.encl):
|
if isNil(mb.encr) or isNil(mb.encl):
|
||||||
raise newException(MultiBaseError, "Encoding scheme is not supported!")
|
return err("multibase: Encoding scheme is not supported!")
|
||||||
var buffer: string
|
var buffer: string
|
||||||
if length > 0:
|
if length > 0:
|
||||||
buffer = newString(mb.encl(length) + 1)
|
buffer = newString(mb.encl(length) + 1)
|
||||||
var outlen = 0
|
var outlen = 0
|
||||||
let res = mb.encr(inbytes, buffer.toOpenArray(1, buffer.high), outlen)
|
let res = mb.encr(inbytes, buffer.toOpenArray(1, buffer.high), outlen)
|
||||||
if res != MultiBaseStatus.Success:
|
if res != MultiBaseStatus.Success:
|
||||||
raise newException(MultiBaseError, "Encoding error [" & $res & "]")
|
return err("multibase: Encoding error [" & $res & "]")
|
||||||
buffer.setLen(outlen + 1)
|
buffer.setLen(outlen + 1)
|
||||||
buffer[0] = mb.code
|
buffer[0] = mb.code
|
||||||
else:
|
else:
|
||||||
buffer = newString(1)
|
buffer = newString(1)
|
||||||
buffer[0] = mb.code
|
buffer[0] = mb.code
|
||||||
result = buffer
|
ok(buffer)
|
||||||
|
|
||||||
proc decode*(mbtype: typedesc[MultiBase], inbytes: openarray[char]): seq[byte] =
|
proc decode*(mbtype: typedesc[MultiBase], inbytes: openarray[char]): Result[seq[byte], string] =
|
||||||
## Decode MultiBase encoded array ``inbytes`` and return decoded sequence of
|
## Decode MultiBase encoded array ``inbytes`` and return decoded sequence of
|
||||||
## bytes.
|
## bytes.
|
||||||
let length = len(inbytes)
|
let length = len(inbytes)
|
||||||
if length == 0:
|
if length == 0:
|
||||||
raise newException(MultiBaseError, "Could not decode zero-length string")
|
return err("multibase: Could not decode zero-length string")
|
||||||
let mb = CodeMultibases.getOrDefault(inbytes[0])
|
let mb = CodeMultibases.getOrDefault(inbytes[0])
|
||||||
if len(mb.name) == 0:
|
if len(mb.name) == 0:
|
||||||
raise newException(MultiBaseError, "MultiBase scheme is incorrect!")
|
return err("multibase: MultiBase scheme is incorrect!")
|
||||||
if isNil(mb.decr) or isNil(mb.decl):
|
if isNil(mb.decr) or isNil(mb.decl):
|
||||||
raise newException(MultiBaseError, "MultiBase scheme is not supported!")
|
return err("multibase: MultiBase scheme is not supported!")
|
||||||
if length == 1:
|
if length == 1:
|
||||||
result = newSeq[byte]()
|
let empty: seq[byte] = @[]
|
||||||
|
ok(empty) # empty
|
||||||
else:
|
else:
|
||||||
var buffer = newSeq[byte](mb.decl(length - 1))
|
var buffer = newSeq[byte](mb.decl(length - 1))
|
||||||
var outlen = 0
|
var outlen = 0
|
||||||
let res = mb.decr(inbytes.toOpenArray(1, length - 1),
|
let res = mb.decr(inbytes.toOpenArray(1, length - 1),
|
||||||
buffer, outlen)
|
buffer, outlen)
|
||||||
if res != MultiBaseStatus.Success:
|
if res != MultiBaseStatus.Success:
|
||||||
raise newException(MultiBaseError, "Decoding error [" & $res & "]")
|
err("multibase: Decoding error [" & $res & "]")
|
||||||
result = buffer
|
else:
|
||||||
result.setLen(outlen)
|
buffer.setLen(outlen)
|
||||||
|
ok(buffer)
|
||||||
|
|
|
@ -482,20 +482,20 @@ proc decode*(mhtype: typedesc[MultiHash], data: openarray[byte],
|
||||||
proc validate*(mhtype: typedesc[MultiHash], data: openarray[byte]): bool =
|
proc validate*(mhtype: typedesc[MultiHash], data: openarray[byte]): bool =
|
||||||
## Returns ``true`` if array of bytes ``data`` has correct MultiHash inside.
|
## Returns ``true`` if array of bytes ``data`` has correct MultiHash inside.
|
||||||
var code, size: uint64
|
var code, size: uint64
|
||||||
var res: VarintStatus
|
var res: VarintResult[void]
|
||||||
if len(data) < 2:
|
if len(data) < 2:
|
||||||
return false
|
return false
|
||||||
let last = data.high
|
let last = data.high
|
||||||
var offset = 0
|
var offset = 0
|
||||||
var length = 0
|
var length = 0
|
||||||
res = LP.getUVarint(data.toOpenArray(offset, last), length, code)
|
res = LP.getUVarint(data.toOpenArray(offset, last), length, code)
|
||||||
if res != VarintStatus.Success:
|
if res.isErr():
|
||||||
return false
|
return false
|
||||||
offset += length
|
offset += length
|
||||||
if offset >= len(data):
|
if offset >= len(data):
|
||||||
return false
|
return false
|
||||||
res = LP.getUVarint(data.toOpenArray(offset, last), length, size)
|
res = LP.getUVarint(data.toOpenArray(offset, last), length, size)
|
||||||
if res != VarintStatus.Success:
|
if res.isErr():
|
||||||
return false
|
return false
|
||||||
offset += length
|
offset += length
|
||||||
if size > 0x7FFF_FFFF'u64:
|
if size > 0x7FFF_FFFF'u64:
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
## those terms.
|
## those terms.
|
||||||
|
|
||||||
## This module implements minimal Google's ProtoBuf primitives.
|
## This module implements minimal Google's ProtoBuf primitives.
|
||||||
|
|
||||||
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import ../varint
|
import ../varint
|
||||||
|
|
||||||
const
|
const
|
||||||
|
@ -142,15 +145,15 @@ proc initProtoBuffer*(options: set[ProtoFlags] = {}): ProtoBuffer =
|
||||||
proc write*(pb: var ProtoBuffer, field: ProtoField) =
|
proc write*(pb: var ProtoBuffer, field: ProtoField) =
|
||||||
## Encode protobuf's field ``field`` and store it to protobuf's buffer ``pb``.
|
## Encode protobuf's field ``field`` and store it to protobuf's buffer ``pb``.
|
||||||
var length = 0
|
var length = 0
|
||||||
var res: VarintStatus
|
var res: VarintResult[void]
|
||||||
pb.buffer.setLen(len(pb.buffer) + vsizeof(field))
|
pb.buffer.setLen(len(pb.buffer) + vsizeof(field))
|
||||||
res = PB.putUVarint(pb.toOpenArray(), length, protoHeader(field))
|
res = PB.putUVarint(pb.toOpenArray(), length, protoHeader(field))
|
||||||
doAssert(res == VarintStatus.Success)
|
doAssert(res.isOk())
|
||||||
pb.offset += length
|
pb.offset += length
|
||||||
case field.kind
|
case field.kind
|
||||||
of ProtoFieldKind.Varint:
|
of ProtoFieldKind.Varint:
|
||||||
res = PB.putUVarint(pb.toOpenArray(), length, field.vint)
|
res = PB.putUVarint(pb.toOpenArray(), length, field.vint)
|
||||||
doAssert(res == VarintStatus.Success)
|
doAssert(res.isOk())
|
||||||
pb.offset += length
|
pb.offset += length
|
||||||
of ProtoFieldKind.Fixed64:
|
of ProtoFieldKind.Fixed64:
|
||||||
doAssert(pb.isEnough(8))
|
doAssert(pb.isEnough(8))
|
||||||
|
@ -174,7 +177,7 @@ proc write*(pb: var ProtoBuffer, field: ProtoField) =
|
||||||
pb.offset += 4
|
pb.offset += 4
|
||||||
of ProtoFieldKind.Length:
|
of ProtoFieldKind.Length:
|
||||||
res = PB.putUVarint(pb.toOpenArray(), length, uint(len(field.vbuffer)))
|
res = PB.putUVarint(pb.toOpenArray(), length, uint(len(field.vbuffer)))
|
||||||
doAssert(res == VarintStatus.Success)
|
doAssert(res.isOk())
|
||||||
pb.offset += length
|
pb.offset += length
|
||||||
doAssert(pb.isEnough(len(field.vbuffer)))
|
doAssert(pb.isEnough(len(field.vbuffer)))
|
||||||
if len(field.vbuffer) > 0:
|
if len(field.vbuffer) > 0:
|
||||||
|
@ -192,7 +195,7 @@ proc finish*(pb: var ProtoBuffer) =
|
||||||
let pos = 10 - vsizeof(size)
|
let pos = 10 - vsizeof(size)
|
||||||
var usedBytes = 0
|
var usedBytes = 0
|
||||||
let res = PB.putUVarint(pb.buffer.toOpenArray(pos, 9), usedBytes, size)
|
let res = PB.putUVarint(pb.buffer.toOpenArray(pos, 9), usedBytes, size)
|
||||||
doAssert(res == VarintStatus.Success)
|
doAssert(res.isOk())
|
||||||
pb.offset = pos
|
pb.offset = pos
|
||||||
elif WithUint32BeLength in pb.options:
|
elif WithUint32BeLength in pb.options:
|
||||||
let size = uint(len(pb.buffer) - 4)
|
let size = uint(len(pb.buffer) - 4)
|
||||||
|
@ -218,8 +221,7 @@ proc getVarintValue*(data: var ProtoBuffer, field: int,
|
||||||
var header = 0'u64
|
var header = 0'u64
|
||||||
var soffset = data.offset
|
var soffset = data.offset
|
||||||
|
|
||||||
if not data.isEmpty() and
|
if not data.isEmpty() and PB.getUVarint(data.toOpenArray(), length, header).isOk():
|
||||||
PB.getUVarint(data.toOpenArray(), length, header) == VarintStatus.Success:
|
|
||||||
data.offset += length
|
data.offset += length
|
||||||
if header == protoHeader(field, Varint):
|
if header == protoHeader(field, Varint):
|
||||||
if not data.isEmpty():
|
if not data.isEmpty():
|
||||||
|
@ -227,7 +229,7 @@ proc getVarintValue*(data: var ProtoBuffer, field: int,
|
||||||
let res = getSVarint(data.toOpenArray(), length, value)
|
let res = getSVarint(data.toOpenArray(), length, value)
|
||||||
else:
|
else:
|
||||||
let res = PB.getUVarint(data.toOpenArray(), length, value)
|
let res = PB.getUVarint(data.toOpenArray(), length, value)
|
||||||
if res == VarintStatus.Success:
|
if res.isOk():
|
||||||
data.offset += length
|
data.offset += length
|
||||||
result = length
|
result = length
|
||||||
return
|
return
|
||||||
|
@ -243,12 +245,10 @@ proc getLengthValue*[T: string|seq[byte]](data: var ProtoBuffer, field: int,
|
||||||
var soffset = data.offset
|
var soffset = data.offset
|
||||||
result = -1
|
result = -1
|
||||||
buffer.setLen(0)
|
buffer.setLen(0)
|
||||||
if not data.isEmpty() and
|
if not data.isEmpty() and PB.getUVarint(data.toOpenArray(), length, header).isOk():
|
||||||
PB.getUVarint(data.toOpenArray(), length, header) == VarintStatus.Success:
|
|
||||||
data.offset += length
|
data.offset += length
|
||||||
if header == protoHeader(field, Length):
|
if header == protoHeader(field, Length):
|
||||||
if not data.isEmpty() and
|
if not data.isEmpty() and PB.getUVarint(data.toOpenArray(), length, ssize).isOk():
|
||||||
PB.getUVarint(data.toOpenArray(), length, ssize) == VarintStatus.Success:
|
|
||||||
data.offset += length
|
data.offset += length
|
||||||
if ssize <= MaxMessageSize and data.isEnough(int(ssize)):
|
if ssize <= MaxMessageSize and data.isEnough(int(ssize)):
|
||||||
buffer.setLen(ssize)
|
buffer.setLen(ssize)
|
||||||
|
@ -280,12 +280,10 @@ proc enterSubmessage*(pb: var ProtoBuffer): int =
|
||||||
var msize = 0'u64
|
var msize = 0'u64
|
||||||
var soffset = pb.offset
|
var soffset = pb.offset
|
||||||
|
|
||||||
if not pb.isEmpty() and
|
if not pb.isEmpty() and PB.getUVarint(pb.toOpenArray(), length, header).isOk():
|
||||||
PB.getUVarint(pb.toOpenArray(), length, header) == VarintStatus.Success:
|
|
||||||
pb.offset += length
|
pb.offset += length
|
||||||
if (header and 0x07'u64) == cast[uint64](ProtoFieldKind.Length):
|
if (header and 0x07'u64) == cast[uint64](ProtoFieldKind.Length):
|
||||||
if not pb.isEmpty() and
|
if not pb.isEmpty() and PB.getUVarint(pb.toOpenArray(), length, msize).isOk():
|
||||||
PB.getUVarint(pb.toOpenArray(), length, msize) == VarintStatus.Success:
|
|
||||||
pb.offset += length
|
pb.offset += length
|
||||||
if msize <= MaxMessageSize and pb.isEnough(int(msize)):
|
if msize <= MaxMessageSize and pb.isEnough(int(msize)):
|
||||||
pb.length = int(msize)
|
pb.length = int(msize)
|
||||||
|
|
|
@ -78,7 +78,7 @@ proc decodeMsg*(buf: seq[byte]): IdentifyInfo =
|
||||||
while pb.getBytes(2, address) > 0:
|
while pb.getBytes(2, address) > 0:
|
||||||
if len(address) != 0:
|
if len(address) != 0:
|
||||||
var copyaddr = address
|
var copyaddr = address
|
||||||
var ma = MultiAddress.init(copyaddr)
|
var ma = MultiAddress.init(copyaddr).tryGet()
|
||||||
result.addrs.add(ma)
|
result.addrs.add(ma)
|
||||||
trace "read address bytes from message", address = ma
|
trace "read address bytes from message", address = ma
|
||||||
address.setLen(0)
|
address.setLen(0)
|
||||||
|
@ -91,7 +91,7 @@ proc decodeMsg*(buf: seq[byte]): IdentifyInfo =
|
||||||
|
|
||||||
var observableAddr = newSeq[byte]()
|
var observableAddr = newSeq[byte]()
|
||||||
if pb.getBytes(4, observableAddr) > 0: # attempt to read the observed addr
|
if pb.getBytes(4, observableAddr) > 0: # attempt to read the observed addr
|
||||||
var ma = MultiAddress.init(observableAddr)
|
var ma = MultiAddress.init(observableAddr).tryGet()
|
||||||
trace "read observedAddr from message", address = ma
|
trace "read observedAddr from message", address = ma
|
||||||
result.observedAddr = some(ma)
|
result.observedAddr = some(ma)
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ export
|
||||||
switch, peer, peerinfo, connection, multiaddress, crypto
|
switch, peer, peerinfo, connection, multiaddress, crypto
|
||||||
|
|
||||||
proc newStandardSwitch*(privKey = none(PrivateKey),
|
proc newStandardSwitch*(privKey = none(PrivateKey),
|
||||||
address = MultiAddress.init("/ip4/127.0.0.1/tcp/0"),
|
address = MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet(),
|
||||||
triggerSelf = false,
|
triggerSelf = false,
|
||||||
gossip = false,
|
gossip = false,
|
||||||
verifySignature = libp2p_pubsub_verify,
|
verifySignature = libp2p_pubsub_verify,
|
||||||
|
|
|
@ -120,9 +120,9 @@ proc readVarint*(conn: LPStream): Future[uint64] {.async, gcsafe.} =
|
||||||
for i in 0..<len(buffer):
|
for i in 0..<len(buffer):
|
||||||
await conn.readExactly(addr buffer[i], 1)
|
await conn.readExactly(addr buffer[i], 1)
|
||||||
let res = PB.getUVarint(buffer.toOpenArray(0, i), length, varint)
|
let res = PB.getUVarint(buffer.toOpenArray(0, i), length, varint)
|
||||||
if res == VarintStatus.Success:
|
if res.isOk():
|
||||||
return varint
|
return varint
|
||||||
if res != VarintStatus.Incomplete:
|
if res.error() != VarintError.Incomplete:
|
||||||
break
|
break
|
||||||
if true: # can't end with a raise apparently
|
if true: # can't end with a raise apparently
|
||||||
raise (ref InvalidVarintError)(msg: "Cannot parse varint")
|
raise (ref InvalidVarintError)(msg: "Cannot parse varint")
|
||||||
|
|
|
@ -13,7 +13,7 @@ import vbuffer
|
||||||
type
|
type
|
||||||
Transcoder* = object
|
Transcoder* = object
|
||||||
stringToBuffer*: proc(s: string,
|
stringToBuffer*: proc(s: string,
|
||||||
vb: var VBuffer): bool {.nimcall, gcsafe.}
|
vb: var VBuffer): bool {.nimcall, gcsafe, raises: [Defect].}
|
||||||
bufferToString*: proc(vb: var VBuffer,
|
bufferToString*: proc(vb: var VBuffer,
|
||||||
s: var string): bool {.nimcall, gcsafe.}
|
s: var string): bool {.nimcall, gcsafe, raises: [Defect].}
|
||||||
validateBuffer*: proc(vb: var VBuffer): bool {.nimcall, gcsafe.}
|
validateBuffer*: proc(vb: var VBuffer): bool {.nimcall, gcsafe, raises: [Defect].}
|
||||||
|
|
|
@ -63,7 +63,7 @@ proc connHandler*(t: TcpTransport,
|
||||||
initiator: bool): Connection =
|
initiator: bool): Connection =
|
||||||
trace "handling connection", address = $client.remoteAddress
|
trace "handling connection", address = $client.remoteAddress
|
||||||
let conn: Connection = newConnection(newChronosStream(client))
|
let conn: Connection = newConnection(newChronosStream(client))
|
||||||
conn.observedAddrs = MultiAddress.init(client.remoteAddress)
|
conn.observedAddrs = MultiAddress.init(client.remoteAddress).tryGet()
|
||||||
if not initiator:
|
if not initiator:
|
||||||
if not isNil(t.handler):
|
if not isNil(t.handler):
|
||||||
t.handlers &= t.handler(conn)
|
t.handlers &= t.handler(conn)
|
||||||
|
@ -142,7 +142,7 @@ method listen*(t: TcpTransport,
|
||||||
t.server.start()
|
t.server.start()
|
||||||
|
|
||||||
# always get the resolved address in case we're bound to 0.0.0.0:0
|
# always get the resolved address in case we're bound to 0.0.0.0:0
|
||||||
t.ma = MultiAddress.init(t.server.sock.getLocalAddress())
|
t.ma = MultiAddress.init(t.server.sock.getLocalAddress()).tryGet()
|
||||||
result = t.server.join()
|
result = t.server.join()
|
||||||
trace "started node on", address = t.ma
|
trace "started node on", address = t.ma
|
||||||
|
|
||||||
|
@ -156,4 +156,4 @@ method dial*(t: TcpTransport,
|
||||||
|
|
||||||
method handles*(t: TcpTransport, address: MultiAddress): bool {.gcsafe.} =
|
method handles*(t: TcpTransport, address: MultiAddress): bool {.gcsafe.} =
|
||||||
if procCall Transport(t).handles(address):
|
if procCall Transport(t).handles(address):
|
||||||
result = address.protocols.filterIt( it == multiCodec("tcp") ).len > 0
|
result = address.protocols.tryGet().filterIt( it == multiCodec("tcp") ).len > 0
|
||||||
|
|
|
@ -56,7 +56,7 @@ method handles*(t: Transport, address: MultiAddress): bool {.base, gcsafe.} =
|
||||||
|
|
||||||
# by default we skip circuit addresses to avoid
|
# by default we skip circuit addresses to avoid
|
||||||
# having to repeat the check in every transport
|
# having to repeat the check in every transport
|
||||||
address.protocols.filterIt( it == multiCodec("p2p-circuit") ).len == 0
|
address.protocols.tryGet().filterIt( it == multiCodec("p2p-circuit") ).len == 0
|
||||||
|
|
||||||
method localAddress*(t: Transport): MultiAddress {.base, gcsafe.} =
|
method localAddress*(t: Transport): MultiAddress {.base, gcsafe.} =
|
||||||
## get the local address of the transport in case started with 0.0.0.0:0
|
## get the local address of the transport in case started with 0.0.0.0:0
|
||||||
|
|
|
@ -15,17 +15,23 @@
|
||||||
## - LibP2P varint, which is able to encode only 63bits of uint64 number and
|
## - LibP2P varint, which is able to encode only 63bits of uint64 number and
|
||||||
## maximum size of encoded value is 9 octets (bytes).
|
## maximum size of encoded value is 9 octets (bytes).
|
||||||
## https://github.com/multiformats/unsigned-varint
|
## https://github.com/multiformats/unsigned-varint
|
||||||
|
|
||||||
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import bitops, typetraits
|
import bitops, typetraits
|
||||||
|
import stew/results
|
||||||
|
export results
|
||||||
|
|
||||||
type
|
type
|
||||||
VarintStatus* {.pure.} = enum
|
VarintError* {.pure.} = enum
|
||||||
Error,
|
Error,
|
||||||
Success,
|
|
||||||
Overflow,
|
Overflow,
|
||||||
Incomplete,
|
Incomplete,
|
||||||
Overlong,
|
Overlong,
|
||||||
Overrun
|
Overrun
|
||||||
|
|
||||||
|
VarintResult*[T] = Result[T, VarintError]
|
||||||
|
|
||||||
PB* = object
|
PB* = object
|
||||||
## Use this type to specify Google ProtoBuf's varint encoding
|
## Use this type to specify Google ProtoBuf's varint encoding
|
||||||
LP* = object
|
LP* = object
|
||||||
|
@ -49,7 +55,6 @@ type
|
||||||
LPSomeVarint* = LPSomeUVarint
|
LPSomeVarint* = LPSomeUVarint
|
||||||
SomeVarint* = PBSomeVarint | LPSomeVarint
|
SomeVarint* = PBSomeVarint | LPSomeVarint
|
||||||
SomeUVarint* = PBSomeUVarint | LPSomeUVarint
|
SomeUVarint* = PBSomeUVarint | LPSomeUVarint
|
||||||
VarintError* = object of CatchableError
|
|
||||||
|
|
||||||
proc vsizeof*(x: SomeUVarint): int {.inline.} =
|
proc vsizeof*(x: SomeUVarint): int {.inline.} =
|
||||||
## Returns number of bytes required to encode integer ``x`` as varint.
|
## Returns number of bytes required to encode integer ``x`` as varint.
|
||||||
|
@ -99,7 +104,7 @@ proc vsizeof*(x: PBZigVarint): int {.inline.} =
|
||||||
proc getUVarint*[T: PB|LP](vtype: typedesc[T],
|
proc getUVarint*[T: PB|LP](vtype: typedesc[T],
|
||||||
pbytes: openarray[byte],
|
pbytes: openarray[byte],
|
||||||
outlen: var int,
|
outlen: var int,
|
||||||
outval: var SomeUVarint): VarintStatus =
|
outval: var SomeUVarint): VarintResult[void] =
|
||||||
## Decode `unsigned varint` from buffer ``pbytes`` and store it to ``outval``.
|
## Decode `unsigned varint` from buffer ``pbytes`` and store it to ``outval``.
|
||||||
## On success ``outlen`` will be set to number of bytes processed while
|
## On success ``outlen`` will be set to number of bytes processed while
|
||||||
## decoding `unsigned varint`.
|
## decoding `unsigned varint`.
|
||||||
|
@ -130,38 +135,35 @@ proc getUVarint*[T: PB|LP](vtype: typedesc[T],
|
||||||
const MaxBits = byte(sizeof(outval) * 8)
|
const MaxBits = byte(sizeof(outval) * 8)
|
||||||
|
|
||||||
var shift = 0'u8
|
var shift = 0'u8
|
||||||
result = VarintStatus.Incomplete
|
|
||||||
outlen = 0
|
outlen = 0
|
||||||
outval = type(outval)(0)
|
outval = type(outval)(0)
|
||||||
for i in 0..<len(pbytes):
|
for i in 0..<len(pbytes):
|
||||||
let b = pbytes[i]
|
let b = pbytes[i]
|
||||||
if shift >= MaxBits:
|
if shift >= MaxBits:
|
||||||
result = VarintStatus.Overflow
|
|
||||||
outlen = 0
|
outlen = 0
|
||||||
outval = type(outval)(0)
|
outval = type(outval)(0)
|
||||||
break
|
return err(VarintError.Overflow)
|
||||||
else:
|
else:
|
||||||
outval = outval or (type(outval)(b and 0x7F'u8) shl shift)
|
outval = outval or (type(outval)(b and 0x7F'u8) shl shift)
|
||||||
shift += 7
|
shift += 7
|
||||||
inc(outlen)
|
inc(outlen)
|
||||||
if (b and 0x80'u8) == 0'u8:
|
if (b and 0x80'u8) == 0'u8:
|
||||||
result = VarintStatus.Success
|
# done, success
|
||||||
break
|
|
||||||
if result == VarintStatus.Incomplete:
|
|
||||||
outlen = 0
|
|
||||||
outval = type(outval)(0)
|
|
||||||
|
|
||||||
when vtype is LP:
|
|
||||||
if result == VarintStatus.Success:
|
|
||||||
if outlen != vsizeof(outval):
|
if outlen != vsizeof(outval):
|
||||||
outval = type(outval)(0)
|
outval = type(outval)(0)
|
||||||
outlen = 0
|
outlen = 0
|
||||||
result = VarintStatus.Overlong
|
return err(VarintError.Overlong)
|
||||||
|
else:
|
||||||
|
return ok()
|
||||||
|
|
||||||
|
outlen = 0
|
||||||
|
outval = type(outval)(0)
|
||||||
|
err(VarintError.Incomplete)
|
||||||
|
|
||||||
proc putUVarint*[T: PB|LP](vtype: typedesc[T],
|
proc putUVarint*[T: PB|LP](vtype: typedesc[T],
|
||||||
pbytes: var openarray[byte],
|
pbytes: var openarray[byte],
|
||||||
outlen: var int,
|
outlen: var int,
|
||||||
outval: SomeUVarint): VarintStatus =
|
outval: SomeUVarint): VarintResult[void] =
|
||||||
## Encode `unsigned varint` ``outval`` and store it to array ``pbytes``.
|
## Encode `unsigned varint` ``outval`` and store it to array ``pbytes``.
|
||||||
##
|
##
|
||||||
## On success ``outlen`` will hold number of bytes (octets) used to encode
|
## On success ``outlen`` will hold number of bytes (octets) used to encode
|
||||||
|
@ -185,8 +187,7 @@ proc putUVarint*[T: PB|LP](vtype: typedesc[T],
|
||||||
when vtype is LP:
|
when vtype is LP:
|
||||||
if sizeof(outval) == 8:
|
if sizeof(outval) == 8:
|
||||||
if (uint64(outval) and 0x8000_0000_0000_0000'u64) != 0'u64:
|
if (uint64(outval) and 0x8000_0000_0000_0000'u64) != 0'u64:
|
||||||
result = Overflow
|
return err(VarintError.Overflow)
|
||||||
return
|
|
||||||
|
|
||||||
if value <= type(outval)(0x7F):
|
if value <= type(outval)(0x7F):
|
||||||
buffer[0] = byte(outval and 0xFF)
|
buffer[0] = byte(outval and 0xFF)
|
||||||
|
@ -201,12 +202,12 @@ proc putUVarint*[T: PB|LP](vtype: typedesc[T],
|
||||||
outlen = k
|
outlen = k
|
||||||
if len(pbytes) >= k:
|
if len(pbytes) >= k:
|
||||||
copyMem(addr pbytes[0], addr buffer[0], k)
|
copyMem(addr pbytes[0], addr buffer[0], k)
|
||||||
result = VarintStatus.Success
|
ok()
|
||||||
else:
|
else:
|
||||||
result = VarintStatus.Overrun
|
err(VarintError.Overrun)
|
||||||
|
|
||||||
proc getSVarint*(pbytes: openarray[byte], outsize: var int,
|
proc getSVarint*(pbytes: openarray[byte], outsize: var int,
|
||||||
outval: var PBSomeSVarint): VarintStatus {.inline.} =
|
outval: var PBSomeSVarint): VarintResult[void] {.inline.} =
|
||||||
## Decode signed integer (``int32`` or ``int64``) from buffer ``pbytes``
|
## Decode signed integer (``int32`` or ``int64``) from buffer ``pbytes``
|
||||||
## and store it to ``outval``.
|
## and store it to ``outval``.
|
||||||
##
|
##
|
||||||
|
@ -230,12 +231,13 @@ proc getSVarint*(pbytes: openarray[byte], outsize: var int,
|
||||||
else:
|
else:
|
||||||
var value: uint32
|
var value: uint32
|
||||||
|
|
||||||
result = PB.getUVarint(pbytes, outsize, value)
|
let res = PB.getUVarint(pbytes, outsize, value)
|
||||||
if result == VarintStatus.Success:
|
if res.isOk():
|
||||||
outval = cast[type(outval)](value)
|
outval = cast[type(outval)](value)
|
||||||
|
res
|
||||||
|
|
||||||
proc getSVarint*(pbytes: openarray[byte], outsize: var int,
|
proc getSVarint*(pbytes: openarray[byte], outsize: var int,
|
||||||
outval: var PBZigVarint): VarintStatus {.inline.} =
|
outval: var PBZigVarint): VarintResult[void] {.inline.} =
|
||||||
## Decode Google ProtoBuf's zigzag encoded signed integer (``sint32`` or
|
## Decode Google ProtoBuf's zigzag encoded signed integer (``sint32`` or
|
||||||
## ``sint64`` ) from buffer ``pbytes`` and store it to ``outval``.
|
## ``sint64`` ) from buffer ``pbytes`` and store it to ``outval``.
|
||||||
##
|
##
|
||||||
|
@ -259,15 +261,16 @@ proc getSVarint*(pbytes: openarray[byte], outsize: var int,
|
||||||
else:
|
else:
|
||||||
var value: uint32
|
var value: uint32
|
||||||
|
|
||||||
result = PB.getUVarint(pbytes, outsize, value)
|
let res = PB.getUVarint(pbytes, outsize, value)
|
||||||
if result == VarintStatus.Success:
|
if res.isOk():
|
||||||
if (value and type(value)(1)) != type(value)(0):
|
if (value and type(value)(1)) != type(value)(0):
|
||||||
outval = cast[type(outval)](not(value shr 1))
|
outval = cast[type(outval)](not(value shr 1))
|
||||||
else:
|
else:
|
||||||
outval = cast[type(outval)](value shr 1)
|
outval = cast[type(outval)](value shr 1)
|
||||||
|
res
|
||||||
|
|
||||||
proc putSVarint*(pbytes: var openarray[byte], outsize: var int,
|
proc putSVarint*(pbytes: var openarray[byte], outsize: var int,
|
||||||
outval: PBZigVarint): VarintStatus {.inline.} =
|
outval: PBZigVarint): VarintResult[void] {.inline.} =
|
||||||
## Encode signed integer ``outval`` using ProtoBuffer's zigzag encoding
|
## Encode signed integer ``outval`` using ProtoBuffer's zigzag encoding
|
||||||
## (``sint32`` or ``sint64``) and store it to array ``pbytes``.
|
## (``sint32`` or ``sint64``) and store it to array ``pbytes``.
|
||||||
##
|
##
|
||||||
|
@ -292,10 +295,10 @@ proc putSVarint*(pbytes: var openarray[byte], outsize: var int,
|
||||||
not(uint32(outval) shl 1)
|
not(uint32(outval) shl 1)
|
||||||
else:
|
else:
|
||||||
uint32(outval) shl 1
|
uint32(outval) shl 1
|
||||||
result = PB.putUVarint(pbytes, outsize, value)
|
PB.putUVarint(pbytes, outsize, value)
|
||||||
|
|
||||||
proc putSVarint*(pbytes: var openarray[byte], outsize: var int,
|
proc putSVarint*(pbytes: var openarray[byte], outsize: var int,
|
||||||
outval: PBSomeSVarint): VarintStatus {.inline.} =
|
outval: PBSomeSVarint): VarintResult[void] {.inline.} =
|
||||||
## Encode signed integer ``outval`` (``int32`` or ``int64``) and store it to
|
## Encode signed integer ``outval`` (``int32`` or ``int64``) and store it to
|
||||||
## array ``pbytes``.
|
## array ``pbytes``.
|
||||||
##
|
##
|
||||||
|
@ -309,84 +312,87 @@ proc putSVarint*(pbytes: var openarray[byte], outsize: var int,
|
||||||
## Maximum encoded length of 64bit integer is 10 octets.
|
## Maximum encoded length of 64bit integer is 10 octets.
|
||||||
## Maximum encoded length of 32bit integer is 5 octets.
|
## Maximum encoded length of 32bit integer is 5 octets.
|
||||||
when sizeof(outval) == 8:
|
when sizeof(outval) == 8:
|
||||||
result = PB.putUVarint(pbytes, outsize, uint64(outval))
|
PB.putUVarint(pbytes, outsize, uint64(outval))
|
||||||
else:
|
else:
|
||||||
result = PB.putUVarint(pbytes, outsize, uint32(outval))
|
PB.putUVarint(pbytes, outsize, uint32(outval))
|
||||||
|
|
||||||
template varintFatal(msg) =
|
template varintFatal(msg) =
|
||||||
const m = msg
|
const m = msg
|
||||||
{.fatal: m.}
|
{.fatal: m.}
|
||||||
|
|
||||||
proc putVarint*[T: PB|LP](vtype: typedesc[T], pbytes: var openarray[byte],
|
proc putVarint*[T: PB|LP](vtype: typedesc[T], pbytes: var openarray[byte],
|
||||||
nbytes: var int, value: SomeVarint): VarintStatus {.inline.} =
|
nbytes: var int, value: SomeVarint): VarintResult[void] {.inline.} =
|
||||||
when vtype is PB:
|
when vtype is PB:
|
||||||
when (type(value) is PBSomeSVarint) or (type(value) is PBZigVarint):
|
when (type(value) is PBSomeSVarint) or (type(value) is PBZigVarint):
|
||||||
result = putSVarint(pbytes, nbytes, value)
|
putSVarint(pbytes, nbytes, value)
|
||||||
elif (type(value) is PBSomeUVarint):
|
elif (type(value) is PBSomeUVarint):
|
||||||
result = PB.putUVarint(pbytes, nbytes, value)
|
PB.putUVarint(pbytes, nbytes, value)
|
||||||
else:
|
else:
|
||||||
varintFatal("Protobuf's varint do not support type [" &
|
varintFatal("Protobuf's varint do not support type [" &
|
||||||
typetraits.name(type(value)) & "]")
|
typetraits.name(type(value)) & "]")
|
||||||
elif vtype is LP:
|
elif vtype is LP:
|
||||||
when (type(value) is LPSomeVarint):
|
when (type(value) is LPSomeVarint):
|
||||||
result = LP.putUVarint(pbytes, nbytes, value)
|
LP.putUVarint(pbytes, nbytes, value)
|
||||||
else:
|
else:
|
||||||
varintFatal("LibP2P's varint do not support type [" &
|
varintFatal("LibP2P's varint do not support type [" &
|
||||||
typetraits.name(type(value)) & "]")
|
typetraits.name(type(value)) & "]")
|
||||||
|
|
||||||
proc getVarint*[T: PB|LP](vtype: typedesc[T], pbytes: openarray[byte],
|
proc getVarint*[T: PB|LP](vtype: typedesc[T], pbytes: openarray[byte],
|
||||||
nbytes: var int,
|
nbytes: var int,
|
||||||
value: var SomeVarint): VarintStatus {.inline.} =
|
value: var SomeVarint): VarintResult[void] {.inline.} =
|
||||||
when vtype is PB:
|
when vtype is PB:
|
||||||
when (type(value) is PBSomeSVarint) or (type(value) is PBZigVarint):
|
when (type(value) is PBSomeSVarint) or (type(value) is PBZigVarint):
|
||||||
result = getSVarint(pbytes, nbytes, value)
|
getSVarint(pbytes, nbytes, value)
|
||||||
elif (type(value) is PBSomeUVarint):
|
elif (type(value) is PBSomeUVarint):
|
||||||
result = PB.getUVarint(pbytes, nbytes, value)
|
PB.getUVarint(pbytes, nbytes, value)
|
||||||
else:
|
else:
|
||||||
varintFatal("Protobuf's varint do not support type [" &
|
varintFatal("Protobuf's varint do not support type [" &
|
||||||
typetraits.name(type(value)) & "]")
|
typetraits.name(type(value)) & "]")
|
||||||
elif vtype is LP:
|
elif vtype is LP:
|
||||||
when (type(value) is LPSomeVarint):
|
when (type(value) is LPSomeVarint):
|
||||||
result = LP.getUVarint(pbytes, nbytes, value)
|
LP.getUVarint(pbytes, nbytes, value)
|
||||||
else:
|
else:
|
||||||
varintFatal("LibP2P's varint do not support type [" &
|
varintFatal("LibP2P's varint do not support type [" &
|
||||||
typetraits.name(type(value)) & "]")
|
typetraits.name(type(value)) & "]")
|
||||||
|
|
||||||
proc encodeVarint*(vtype: typedesc[PB],
|
proc encodeVarint*(vtype: typedesc[PB],
|
||||||
value: PBSomeVarint): seq[byte] {.inline.} =
|
value: PBSomeVarint): VarintResult[seq[byte]] {.inline.} =
|
||||||
## Encode integer to Google ProtoBuf's `signed/unsigned varint` and returns
|
## Encode integer to Google ProtoBuf's `signed/unsigned varint` and returns
|
||||||
## sequence of bytes as result.
|
## sequence of bytes as buffer.
|
||||||
var outsize = 0
|
var outsize = 0
|
||||||
result = newSeqOfCap[byte](10)
|
var buffer = newSeqOfCap[byte](10)
|
||||||
when sizeof(value) == 4:
|
when sizeof(value) == 4:
|
||||||
result.setLen(5)
|
buffer.setLen(5)
|
||||||
else:
|
else:
|
||||||
result.setLen(10)
|
buffer.setLen(10)
|
||||||
when (type(value) is PBSomeSVarint) or (type(value) is PBZigVarint):
|
when (type(value) is PBSomeSVarint) or (type(value) is PBZigVarint):
|
||||||
let res = putSVarint(result, outsize, value)
|
let res = putSVarint(buffer, outsize, value)
|
||||||
else:
|
else:
|
||||||
let res = PB.putUVarint(result, outsize, value)
|
let res = PB.putUVarint(buffer, outsize, value)
|
||||||
if res == VarintStatus.Success:
|
if res.isOk():
|
||||||
result.setLen(outsize)
|
buffer.setLen(outsize)
|
||||||
|
ok(buffer)
|
||||||
else:
|
else:
|
||||||
raise newException(VarintError, "Error '" & $res & "'")
|
err(res.error())
|
||||||
|
|
||||||
|
|
||||||
proc encodeVarint*(vtype: typedesc[LP],
|
proc encodeVarint*(vtype: typedesc[LP],
|
||||||
value: LPSomeVarint): seq[byte] {.inline.} =
|
value: LPSomeVarint): VarintResult[seq[byte]] {.inline.} =
|
||||||
## Encode integer to LibP2P `unsigned varint` and returns sequence of bytes
|
## Encode integer to LibP2P `unsigned varint` and returns sequence of bytes
|
||||||
## as result.
|
## as buffer.
|
||||||
var outsize = 0
|
var outsize = 0
|
||||||
result = newSeqOfCap[byte](9)
|
var buffer = newSeqOfCap[byte](9)
|
||||||
when sizeof(value) == 1:
|
when sizeof(value) == 1:
|
||||||
result.setLen(2)
|
buffer.setLen(2)
|
||||||
elif sizeof(value) == 2:
|
elif sizeof(value) == 2:
|
||||||
result.setLen(3)
|
buffer.setLen(3)
|
||||||
elif sizeof(value) == 4:
|
elif sizeof(value) == 4:
|
||||||
result.setLen(5)
|
buffer.setLen(5)
|
||||||
else:
|
else:
|
||||||
result.setLen(9)
|
buffer.setLen(9)
|
||||||
let res = LP.putUVarint(result, outsize, value)
|
let res = LP.putUVarint(buffer, outsize, value)
|
||||||
if res == VarintStatus.Success:
|
if res.isOk():
|
||||||
result.setLen(outsize)
|
buffer.setLen(outsize)
|
||||||
|
ok(buffer)
|
||||||
else:
|
else:
|
||||||
raise newException(VarintError, "Error '" & $res & "'")
|
err(res.error)
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
## those terms.
|
## those terms.
|
||||||
|
|
||||||
## This module implements variable buffer.
|
## This module implements variable buffer.
|
||||||
|
|
||||||
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import varint, strutils
|
import varint, strutils
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -66,7 +69,7 @@ proc writePBVarint*(vb: var VBuffer, value: PBSomeUVarint) =
|
||||||
vb.buffer.setLen(len(vb.buffer) + vsizeof(v))
|
vb.buffer.setLen(len(vb.buffer) + vsizeof(v))
|
||||||
let res = PB.putUVarint(toOpenArray(vb.buffer, vb.offset, vb.buffer.high),
|
let res = PB.putUVarint(toOpenArray(vb.buffer, vb.offset, vb.buffer.high),
|
||||||
length, v)
|
length, v)
|
||||||
doAssert(res == VarintStatus.Success)
|
doAssert(res.isOk())
|
||||||
vb.offset += length
|
vb.offset += length
|
||||||
|
|
||||||
proc writeLPVarint*(vb: var VBuffer, value: LPSomeUVarint) =
|
proc writeLPVarint*(vb: var VBuffer, value: LPSomeUVarint) =
|
||||||
|
@ -77,7 +80,7 @@ proc writeLPVarint*(vb: var VBuffer, value: LPSomeUVarint) =
|
||||||
vb.buffer.setLen(len(vb.buffer) + vsizeof(v))
|
vb.buffer.setLen(len(vb.buffer) + vsizeof(v))
|
||||||
let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, vb.buffer.high),
|
let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, vb.buffer.high),
|
||||||
length, v)
|
length, v)
|
||||||
doAssert(res == VarintStatus.Success)
|
doAssert(res.isOk())
|
||||||
vb.offset += length
|
vb.offset += length
|
||||||
|
|
||||||
proc writeVarint*(vb: var VBuffer, value: LPSomeUVarint) =
|
proc writeVarint*(vb: var VBuffer, value: LPSomeUVarint) =
|
||||||
|
@ -90,7 +93,7 @@ proc writeSeq*[T: byte|char](vb: var VBuffer, value: openarray[T]) =
|
||||||
vb.buffer.setLen(len(vb.buffer) + vsizeof(uint(len(value))) + len(value))
|
vb.buffer.setLen(len(vb.buffer) + vsizeof(uint(len(value))) + len(value))
|
||||||
let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, vb.buffer.high),
|
let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, vb.buffer.high),
|
||||||
length, uint(len(value)))
|
length, uint(len(value)))
|
||||||
doAssert(res == VarintStatus.Success)
|
doAssert(res.isOk())
|
||||||
vb.offset += length
|
vb.offset += length
|
||||||
if len(value) > 0:
|
if len(value) > 0:
|
||||||
copyMem(addr vb.buffer[vb.offset], unsafeAddr value[0], len(value))
|
copyMem(addr vb.buffer[vb.offset], unsafeAddr value[0], len(value))
|
||||||
|
@ -120,7 +123,7 @@ proc peekVarint*(vb: var VBuffer, value: var LPSomeUVarint): int =
|
||||||
if not vb.isEmpty():
|
if not vb.isEmpty():
|
||||||
let res = LP.getUVarint(
|
let res = LP.getUVarint(
|
||||||
toOpenArray(vb.buffer, vb.offset, vb.buffer.high), length, value)
|
toOpenArray(vb.buffer, vb.offset, vb.buffer.high), length, value)
|
||||||
if res == VarintStatus.Success:
|
if res.isOk():
|
||||||
result = length
|
result = length
|
||||||
|
|
||||||
proc peekSeq*[T: string|seq[byte]](vb: var VBuffer, value: var T): int =
|
proc peekSeq*[T: string|seq[byte]](vb: var VBuffer, value: var T): int =
|
||||||
|
@ -135,8 +138,7 @@ proc peekSeq*[T: string|seq[byte]](vb: var VBuffer, value: var T): int =
|
||||||
var length = 0
|
var length = 0
|
||||||
var size = 0'u64
|
var size = 0'u64
|
||||||
if not vb.isEmpty() and
|
if not vb.isEmpty() and
|
||||||
LP.getUVarint(toOpenArray(vb.buffer, vb.offset, vb.buffer.high),
|
LP.getUVarint(toOpenArray(vb.buffer, vb.offset, vb.buffer.high), length, size).isOk():
|
||||||
length, size) == VarintStatus.Success:
|
|
||||||
vb.offset += length
|
vb.offset += length
|
||||||
result = length
|
result = length
|
||||||
if vb.isEnough(int(size)):
|
if vb.isEnough(int(size)):
|
||||||
|
|
|
@ -22,38 +22,40 @@ proc initTAddress*(ma: MultiAddress): TransportAddress =
|
||||||
## MultiAddress must be wire address, e.g. ``{IP4, IP6, UNIX}/{TCP, UDP}``.
|
## MultiAddress must be wire address, e.g. ``{IP4, IP6, UNIX}/{TCP, UDP}``.
|
||||||
var state = 0
|
var state = 0
|
||||||
var pbuf: array[2, byte]
|
var pbuf: array[2, byte]
|
||||||
for part in ma.items():
|
for rpart in ma.items():
|
||||||
let code = part.protoCode()
|
let
|
||||||
|
part = rpart.tryGet()
|
||||||
|
rcode = part.protoCode()
|
||||||
|
code = rcode.tryGet()
|
||||||
|
|
||||||
if state == 0:
|
if state == 0:
|
||||||
if code == multiCodec("ip4"):
|
if code == multiCodec("ip4"):
|
||||||
result = TransportAddress(family: AddressFamily.IPv4)
|
result = TransportAddress(family: AddressFamily.IPv4)
|
||||||
if part.protoArgument(result.address_v4) == 0:
|
if part.protoArgument(result.address_v4).tryGet() == 0:
|
||||||
raise newException(TransportAddressError, "Incorrect IPv4 address")
|
raise newException(TransportAddressError, "Incorrect IPv4 address")
|
||||||
inc(state)
|
inc(state)
|
||||||
elif code == multiCodec("ip6"):
|
elif code == multiCodec("ip6"):
|
||||||
result = TransportAddress(family: AddressFamily.IPv6)
|
result = TransportAddress(family: AddressFamily.IPv6)
|
||||||
if part.protoArgument(result.address_v6) == 0:
|
if part.protoArgument(result.address_v6).tryGet() == 0:
|
||||||
raise newException(TransportAddressError, "Incorrect IPv6 address")
|
raise newException(TransportAddressError, "Incorrect IPv6 address")
|
||||||
inc(state)
|
inc(state)
|
||||||
elif code == multiCodec("unix"):
|
elif code == multiCodec("unix"):
|
||||||
result = TransportAddress(family: AddressFamily.Unix)
|
result = TransportAddress(family: AddressFamily.Unix)
|
||||||
if part.protoArgument(result.address_un) == 0:
|
if part.protoArgument(result.address_un).tryGet() == 0:
|
||||||
raise newException(TransportAddressError, "Incorrect Unix address")
|
raise newException(TransportAddressError, "Incorrect Unix address")
|
||||||
result.port = Port(1)
|
result.port = Port(1)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise newException(TransportAddressError,
|
raise newException(TransportAddressError, "Could not initialize address!")
|
||||||
"Could not initialize address!")
|
|
||||||
elif state == 1:
|
elif state == 1:
|
||||||
if code == multiCodec("tcp") or code == multiCodec("udp"):
|
if code == multiCodec("tcp") or code == multiCodec("udp"):
|
||||||
if part.protoArgument(pbuf) == 0:
|
if part.protoArgument(pbuf).tryGet() == 0:
|
||||||
raise newException(TransportAddressError, "Incorrect port")
|
raise newException(TransportAddressError, "Incorrect port")
|
||||||
result.port = Port((cast[uint16](pbuf[0]) shl 8) or
|
result.port = Port((cast[uint16](pbuf[0]) shl 8) or
|
||||||
cast[uint16](pbuf[1]))
|
cast[uint16](pbuf[1]))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise newException(TransportAddressError,
|
raise newException(TransportAddressError, "Could not initialize address!")
|
||||||
"Could not initialize address!")
|
|
||||||
|
|
||||||
proc connect*(ma: MultiAddress, bufferSize = DefaultStreamBufferSize,
|
proc connect*(ma: MultiAddress, bufferSize = DefaultStreamBufferSize,
|
||||||
child: StreamTransport = nil): Future[StreamTransport] {.async.} =
|
child: StreamTransport = nil): Future[StreamTransport] {.async.} =
|
||||||
|
@ -63,7 +65,7 @@ proc connect*(ma: MultiAddress, bufferSize = DefaultStreamBufferSize,
|
||||||
|
|
||||||
let address = initTAddress(ma)
|
let address = initTAddress(ma)
|
||||||
if address.family in {AddressFamily.IPv4, AddressFamily.IPv6}:
|
if address.family in {AddressFamily.IPv4, AddressFamily.IPv6}:
|
||||||
if ma[1].protoCode() != multiCodec("tcp"):
|
if ma[1].tryGet().protoCode().tryGet() != multiCodec("tcp"):
|
||||||
raise newException(TransportAddressError, "Incorrect address type!")
|
raise newException(TransportAddressError, "Incorrect address type!")
|
||||||
result = await connect(address, bufferSize, child)
|
result = await connect(address, bufferSize, child)
|
||||||
|
|
||||||
|
@ -79,7 +81,7 @@ proc createStreamServer*[T](ma: MultiAddress,
|
||||||
## Create new TCP stream server which bounds to ``ma`` address.
|
## Create new TCP stream server which bounds to ``ma`` address.
|
||||||
var address = initTAddress(ma)
|
var address = initTAddress(ma)
|
||||||
if address.family in {AddressFamily.IPv4, AddressFamily.IPv6}:
|
if address.family in {AddressFamily.IPv4, AddressFamily.IPv6}:
|
||||||
if ma[1].protoCode() != multiCodec("tcp"):
|
if ma[1].tryGet().protoCode().tryGet() != multiCodec("tcp"):
|
||||||
raise newException(TransportAddressError, "Incorrect address type!")
|
raise newException(TransportAddressError, "Incorrect address type!")
|
||||||
result = createStreamServer(address, cbproc, flags, udata, sock, backlog,
|
result = createStreamServer(address, cbproc, flags, udata, sock, backlog,
|
||||||
bufferSize, child, init)
|
bufferSize, child, init)
|
||||||
|
@ -100,10 +102,10 @@ proc createAsyncSocket*(ma: MultiAddress): AsyncFD =
|
||||||
return asyncInvalidSocket
|
return asyncInvalidSocket
|
||||||
|
|
||||||
if address.family in {AddressFamily.IPv4, AddressFamily.IPv6}:
|
if address.family in {AddressFamily.IPv4, AddressFamily.IPv6}:
|
||||||
if ma[1].protoCode() == multiCodec("udp"):
|
if ma[1].tryGet().protoCode().tryGet() == multiCodec("udp"):
|
||||||
socktype = SockType.SOCK_DGRAM
|
socktype = SockType.SOCK_DGRAM
|
||||||
protocol = Protocol.IPPROTO_UDP
|
protocol = Protocol.IPPROTO_UDP
|
||||||
elif ma[1].protoCode() == multiCodec("tcp"):
|
elif ma[1].tryGet().protoCode().tryGet() == multiCodec("tcp"):
|
||||||
socktype = SockType.SOCK_STREAM
|
socktype = SockType.SOCK_STREAM
|
||||||
protocol = Protocol.IPPROTO_TCP
|
protocol = Protocol.IPPROTO_TCP
|
||||||
elif address.family in {AddressFamily.Unix}:
|
elif address.family in {AddressFamily.Unix}:
|
||||||
|
|
|
@ -20,7 +20,7 @@ suite "Identify":
|
||||||
|
|
||||||
test "handle identify message":
|
test "handle identify message":
|
||||||
proc testHandle(): Future[bool] {.async.} =
|
proc testHandle(): Future[bool] {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
let remoteSecKey = PrivateKey.random(ECDSA).get()
|
let remoteSecKey = PrivateKey.random(ECDSA).get()
|
||||||
let remotePeerInfo = PeerInfo.init(remoteSecKey,
|
let remotePeerInfo = PeerInfo.init(remoteSecKey,
|
||||||
[ma],
|
[ma],
|
||||||
|
@ -65,7 +65,7 @@ suite "Identify":
|
||||||
|
|
||||||
test "handle failed identify":
|
test "handle failed identify":
|
||||||
proc testHandleError() {.async.} =
|
proc testHandleError() {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
var remotePeerInfo = PeerInfo.init(PrivateKey.random(ECDSA).get(), [ma])
|
var remotePeerInfo = PeerInfo.init(PrivateKey.random(ECDSA).get(), [ma])
|
||||||
let identifyProto1 = newIdentify(remotePeerInfo)
|
let identifyProto1 = newIdentify(remotePeerInfo)
|
||||||
let msListen = newMultistream()
|
let msListen = newMultistream()
|
||||||
|
|
|
@ -46,16 +46,15 @@ proc readLp*(s: StreamTransport): Future[seq[byte]] {.async, gcsafe.} =
|
||||||
var
|
var
|
||||||
size: uint
|
size: uint
|
||||||
length: int
|
length: int
|
||||||
res: VarintStatus
|
res: VarintResult[void]
|
||||||
result = newSeq[byte](10)
|
result = newSeq[byte](10)
|
||||||
|
|
||||||
for i in 0..<len(result):
|
for i in 0..<len(result):
|
||||||
await s.readExactly(addr result[i], 1)
|
await s.readExactly(addr result[i], 1)
|
||||||
res = LP.getUVarint(result.toOpenArray(0, i), length, size)
|
res = LP.getUVarint(result.toOpenArray(0, i), length, size)
|
||||||
if res == VarintStatus.Success:
|
if res.isOk():
|
||||||
break
|
break
|
||||||
if res != VarintStatus.Success:
|
res.expect("Valid varint")
|
||||||
raise (ref InvalidVarintError)()
|
|
||||||
result.setLen(size)
|
result.setLen(size)
|
||||||
if size > 0.uint:
|
if size > 0.uint:
|
||||||
await s.readExactly(addr result[0], int(size))
|
await s.readExactly(addr result[0], int(size))
|
||||||
|
@ -68,7 +67,7 @@ proc createNode*(privKey: Option[PrivateKey] = none(PrivateKey),
|
||||||
if privKey.isNone:
|
if privKey.isNone:
|
||||||
seckey = some(PrivateKey.random(RSA).get())
|
seckey = some(PrivateKey.random(RSA).get())
|
||||||
|
|
||||||
var peerInfo = NativePeerInfo.init(seckey.get(), [Multiaddress.init(address)])
|
var peerInfo = NativePeerInfo.init(seckey.get(), [Multiaddress.init(address).tryGet()])
|
||||||
proc createMplex(conn: Connection): Muxer = newMplex(conn)
|
proc createMplex(conn: Connection): Muxer = newMplex(conn)
|
||||||
let mplexProvider = newMuxerProvider(createMplex, MplexCodec)
|
let mplexProvider = newMuxerProvider(createMplex, MplexCodec)
|
||||||
let transports = @[Transport(TcpTransport.init())]
|
let transports = @[Transport(TcpTransport.init())]
|
||||||
|
|
|
@ -214,7 +214,7 @@ suite "Mplex":
|
||||||
|
|
||||||
test "e2e - read/write receiver":
|
test "e2e - read/write receiver":
|
||||||
proc testNewStream() {.async.} =
|
proc testNewStream() {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
var done = newFuture[void]()
|
var done = newFuture[void]()
|
||||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||||
|
@ -252,7 +252,7 @@ suite "Mplex":
|
||||||
|
|
||||||
test "e2e - read/write receiver lazy":
|
test "e2e - read/write receiver lazy":
|
||||||
proc testNewStream() {.async.} =
|
proc testNewStream() {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
var done = newFuture[void]()
|
var done = newFuture[void]()
|
||||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||||
|
@ -292,7 +292,7 @@ suite "Mplex":
|
||||||
test "e2e - write fragmented":
|
test "e2e - write fragmented":
|
||||||
proc testNewStream() {.async.} =
|
proc testNewStream() {.async.} =
|
||||||
let
|
let
|
||||||
ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
listenJob = newFuture[void]()
|
listenJob = newFuture[void]()
|
||||||
|
|
||||||
var bigseq = newSeqOfCap[uint8](MaxMsgSize * 2)
|
var bigseq = newSeqOfCap[uint8](MaxMsgSize * 2)
|
||||||
|
@ -338,7 +338,7 @@ suite "Mplex":
|
||||||
|
|
||||||
test "e2e - read/write initiator":
|
test "e2e - read/write initiator":
|
||||||
proc testNewStream() {.async.} =
|
proc testNewStream() {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
let done = newFuture[void]()
|
let done = newFuture[void]()
|
||||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||||
|
@ -375,7 +375,7 @@ suite "Mplex":
|
||||||
|
|
||||||
test "e2e - multiple streams":
|
test "e2e - multiple streams":
|
||||||
proc testNewStream() {.async.} =
|
proc testNewStream() {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
let done = newFuture[void]()
|
let done = newFuture[void]()
|
||||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||||
|
@ -417,7 +417,7 @@ suite "Mplex":
|
||||||
|
|
||||||
test "e2e - multiple read/write streams":
|
test "e2e - multiple read/write streams":
|
||||||
proc testNewStream() {.async.} =
|
proc testNewStream() {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
let done = newFuture[void]()
|
let done = newFuture[void]()
|
||||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||||
|
@ -461,7 +461,7 @@ suite "Mplex":
|
||||||
|
|
||||||
test "jitter - channel should be able to handle erratic read/writes":
|
test "jitter - channel should be able to handle erratic read/writes":
|
||||||
proc test() {.async.} =
|
proc test() {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
var complete = newFuture[void]()
|
var complete = newFuture[void]()
|
||||||
const MsgSize = 1024
|
const MsgSize = 1024
|
||||||
|
@ -529,7 +529,7 @@ suite "Mplex":
|
||||||
|
|
||||||
test "jitter - channel should handle 1 byte read/write":
|
test "jitter - channel should handle 1 byte read/write":
|
||||||
proc test() {.async.} =
|
proc test() {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
var complete = newFuture[void]()
|
var complete = newFuture[void]()
|
||||||
const MsgSize = 512
|
const MsgSize = 512
|
||||||
|
|
|
@ -297,23 +297,18 @@ suite "MultiAddress test suite":
|
||||||
|
|
||||||
test "go-multiaddr success test vectors":
|
test "go-multiaddr success test vectors":
|
||||||
for item in SuccessVectors:
|
for item in SuccessVectors:
|
||||||
var a = MultiAddress.init(item)
|
var a = MultiAddress.init(item).get()
|
||||||
check a.isEmpty() == false
|
check a.isEmpty() == false
|
||||||
check a.validate() == true
|
check a.validate() == true
|
||||||
|
|
||||||
test "go-multiaddr failure test vectors":
|
test "go-multiaddr failure test vectors":
|
||||||
for item in FailureVectors:
|
for item in FailureVectors:
|
||||||
var r = false
|
check MultiAddress.init(item).isErr()
|
||||||
try:
|
|
||||||
discard MultiAddress.init(item)
|
|
||||||
except:
|
|
||||||
r = true
|
|
||||||
check r == true
|
|
||||||
|
|
||||||
test "rust-multiaddr success test vectors":
|
test "rust-multiaddr success test vectors":
|
||||||
## Rust test vectors are with changed UDP encoding and without WSS
|
## Rust test vectors are with changed UDP encoding and without WSS
|
||||||
for i in 0..<len(RustSuccessVectors):
|
for i in 0..<len(RustSuccessVectors):
|
||||||
var a = MultiAddress.init(RustSuccessVectors[i])
|
var a = MultiAddress.init(RustSuccessVectors[i]).get()
|
||||||
check:
|
check:
|
||||||
hex(a) == RustSuccessExpects[i]
|
hex(a) == RustSuccessExpects[i]
|
||||||
|
|
||||||
|
@ -321,7 +316,7 @@ suite "MultiAddress test suite":
|
||||||
for item in RustFailureVectors:
|
for item in RustFailureVectors:
|
||||||
var r = false
|
var r = false
|
||||||
try:
|
try:
|
||||||
discard MultiAddress.init(item)
|
discard MultiAddress.init(item).get()
|
||||||
except:
|
except:
|
||||||
r = true
|
r = true
|
||||||
check r == true
|
check r == true
|
||||||
|
@ -329,9 +324,9 @@ suite "MultiAddress test suite":
|
||||||
test "Concatenation test":
|
test "Concatenation test":
|
||||||
var ma1 = MultiAddress.init()
|
var ma1 = MultiAddress.init()
|
||||||
var ma2 = MultiAddress.init()
|
var ma2 = MultiAddress.init()
|
||||||
var ma3 = MultiAddress.init("/ip4/127.0.0.1")
|
var ma3 = MultiAddress.init("/ip4/127.0.0.1").get()
|
||||||
var ma4 = MultiAddress.init("/udp/30000")
|
var ma4 = MultiAddress.init("/udp/30000").get()
|
||||||
var ma5 = MultiAddress.init("/p2p-circuit")
|
var ma5 = MultiAddress.init("/p2p-circuit").get()
|
||||||
var cma = ma1 & ma3 & ma4 & ma5
|
var cma = ma1 & ma3 & ma4 & ma5
|
||||||
ma2 &= ma3
|
ma2 &= ma3
|
||||||
ma2 &= ma4
|
ma2 &= ma4
|
||||||
|
@ -342,15 +337,15 @@ suite "MultiAddress test suite":
|
||||||
|
|
||||||
test "isWire() test":
|
test "isWire() test":
|
||||||
for item in UtilitySuccessVectors:
|
for item in UtilitySuccessVectors:
|
||||||
var a = MultiAddress.init(item)
|
var a = MultiAddress.init(item).get()
|
||||||
check a.isWire() == true
|
check a.isWire() == true
|
||||||
for item in UtilityFailVectors:
|
for item in UtilityFailVectors:
|
||||||
var a = MultiAddress.init(item)
|
var a = MultiAddress.init(item).get()
|
||||||
check a.isWire() == false
|
check a.isWire() == false
|
||||||
|
|
||||||
test "Path addresses serialization/deserialization":
|
test "Path addresses serialization/deserialization":
|
||||||
for i in 0..<len(PathVectors):
|
for i in 0..<len(PathVectors):
|
||||||
var a = MultiAddress.init(PathVectors[i])
|
var a = MultiAddress.init(PathVectors[i]).get()
|
||||||
check:
|
check:
|
||||||
hex(a) == PathExpects[i]
|
hex(a) == PathExpects[i]
|
||||||
$a == PathVectors[i]
|
$a == PathVectors[i]
|
||||||
|
@ -358,44 +353,44 @@ suite "MultiAddress test suite":
|
||||||
test "MultiAddress pattern matching test vectors":
|
test "MultiAddress pattern matching test vectors":
|
||||||
for item in PatternVectors:
|
for item in PatternVectors:
|
||||||
for gitem in item.good:
|
for gitem in item.good:
|
||||||
var a = MultiAddress.init(gitem)
|
var a = MultiAddress.init(gitem).get()
|
||||||
check item.pattern.match(a) == true
|
check item.pattern.match(a) == true
|
||||||
for bitem in item.bad:
|
for bitem in item.bad:
|
||||||
var a = MultiAddress.init(bitem)
|
var a = MultiAddress.init(bitem).get()
|
||||||
check item.pattern.match(a) == false
|
check item.pattern.match(a) == false
|
||||||
|
|
||||||
test "MultiAddress init(\"tcp/udp/dccp/sctp\", int) test":
|
test "MultiAddress init(\"tcp/udp/dccp/sctp\", int) test":
|
||||||
check:
|
check:
|
||||||
$MultiAddress.init(multiCodec("tcp"), 0) == "/tcp/0"
|
$MultiAddress.init(multiCodec("tcp"), 0).get() == "/tcp/0"
|
||||||
$MultiAddress.init(multiCodec("tcp"), 65535) == "/tcp/65535"
|
$MultiAddress.init(multiCodec("tcp"), 65535).get() == "/tcp/65535"
|
||||||
$MultiAddress.init(multiCodec("tcp"), 34000) == "/tcp/34000"
|
$MultiAddress.init(multiCodec("tcp"), 34000).get() == "/tcp/34000"
|
||||||
$MultiAddress.init(multiCodec("udp"), 0) == "/udp/0"
|
$MultiAddress.init(multiCodec("udp"), 0).get() == "/udp/0"
|
||||||
$MultiAddress.init(multiCodec("udp"), 65535) == "/udp/65535"
|
$MultiAddress.init(multiCodec("udp"), 65535).get() == "/udp/65535"
|
||||||
$MultiAddress.init(multiCodec("udp"), 34000) == "/udp/34000"
|
$MultiAddress.init(multiCodec("udp"), 34000).get() == "/udp/34000"
|
||||||
$MultiAddress.init(multiCodec("dccp"), 0) == "/dccp/0"
|
$MultiAddress.init(multiCodec("dccp"), 0).get() == "/dccp/0"
|
||||||
$MultiAddress.init(multiCodec("dccp"), 65535) == "/dccp/65535"
|
$MultiAddress.init(multiCodec("dccp"), 65535).get() == "/dccp/65535"
|
||||||
$MultiAddress.init(multiCodec("dccp"), 34000) == "/dccp/34000"
|
$MultiAddress.init(multiCodec("dccp"), 34000).get() == "/dccp/34000"
|
||||||
$MultiAddress.init(multiCodec("sctp"), 0) == "/sctp/0"
|
$MultiAddress.init(multiCodec("sctp"), 0).get() == "/sctp/0"
|
||||||
$MultiAddress.init(multiCodec("sctp"), 65535) == "/sctp/65535"
|
$MultiAddress.init(multiCodec("sctp"), 65535).get() == "/sctp/65535"
|
||||||
$MultiAddress.init(multiCodec("sctp"), 34000) == "/sctp/34000"
|
$MultiAddress.init(multiCodec("sctp"), 34000).get() == "/sctp/34000"
|
||||||
|
|
||||||
expect(MultiAddressError):
|
check:
|
||||||
discard MultiAddress.init(multiCodec("ip4"), 0)
|
MultiAddress.init(multiCodec("ip4"), 0).isErr()
|
||||||
discard MultiAddress.init(multiCodec("ip6"), 0)
|
MultiAddress.init(multiCodec("ip6"), 0).isErr()
|
||||||
discard MultiAddress.init(multiCodec("p2p"), 0)
|
MultiAddress.init(multiCodec("p2p"), 0).isErr()
|
||||||
discard MultiAddress.init(multiCodec("tcp"), 65536)
|
MultiAddress.init(multiCodec("tcp"), 65536).isErr()
|
||||||
discard MultiAddress.init(multiCodec("udp"), 65536)
|
MultiAddress.init(multiCodec("udp"), 65536).isErr()
|
||||||
discard MultiAddress.init(multiCodec("dccp"), 65536)
|
MultiAddress.init(multiCodec("dccp"), 65536).isErr()
|
||||||
discard MultiAddress.init(multiCodec("sctp"), 65536)
|
MultiAddress.init(multiCodec("sctp"), 65536).isErr()
|
||||||
discard MultiAddress.init(multiCodec("tcp"), -1)
|
MultiAddress.init(multiCodec("tcp"), -1).isErr()
|
||||||
discard MultiAddress.init(multiCodec("udp"), -1)
|
MultiAddress.init(multiCodec("udp"), -1).isErr()
|
||||||
discard MultiAddress.init(multiCodec("dccp"), -1)
|
MultiAddress.init(multiCodec("dccp"), -1).isErr()
|
||||||
discard MultiAddress.init(multiCodec("sctp"), -1)
|
MultiAddress.init(multiCodec("sctp"), -1).isErr()
|
||||||
|
|
||||||
test "MultiAddress protoAddress(fixed) test":
|
test "MultiAddress protoAddress(fixed) test":
|
||||||
var
|
var
|
||||||
address_v4: array[4, byte]
|
address_v4: array[4, byte]
|
||||||
address_v6: array[16, byte]
|
address_v6: array[16, byte]
|
||||||
check:
|
check:
|
||||||
MultiAddress.init("/ip4/0.0.0.0").protoAddress() == address_v4
|
MultiAddress.init("/ip4/0.0.0.0").get().protoAddress().get() == address_v4
|
||||||
MultiAddress.init("/ip6/::0").protoAddress() == address_v6
|
MultiAddress.init("/ip6/::0").get().protoAddress().get() == address_v6
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import unittest
|
import unittest
|
||||||
import ../libp2p/multibase
|
import ../libp2p/multibase
|
||||||
|
import stew/results
|
||||||
|
|
||||||
when defined(nimHasUsed): {.used.}
|
when defined(nimHasUsed): {.used.}
|
||||||
|
|
||||||
|
@ -97,49 +98,49 @@ suite "MultiBase test suite":
|
||||||
MultiBase.decodedLength('\x00', 0) == -1
|
MultiBase.decodedLength('\x00', 0) == -1
|
||||||
MultiBase.decodedLength('\x00', 1) == 0
|
MultiBase.decodedLength('\x00', 1) == 0
|
||||||
check:
|
check:
|
||||||
MultiBase.encode("identity", plain) == "\x00"
|
MultiBase.encode("identity", plain).get() == "\x00"
|
||||||
# MultiBase.encode("base1", plain) == "1"
|
# MultiBase.encode("base1", plain) == "1"
|
||||||
# MultiBase.encode("base2", plain) == "0"
|
# MultiBase.encode("base2", plain) == "0"
|
||||||
# MultiBase.encode("base8", plain) == "7"
|
# MultiBase.encode("base8", plain) == "7"
|
||||||
# MultiBase.encode("base10", plain) == "9"
|
# MultiBase.encode("base10", plain) == "9"
|
||||||
# MultiBase.encode("base16", plain) == "f"
|
# MultiBase.encode("base16", plain) == "f"
|
||||||
# MultiBase.encode("base16upper", plain) == "F"
|
# MultiBase.encode("base16upper", plain) == "F"
|
||||||
MultiBase.encode("base32hex", plain) == "v"
|
MultiBase.encode("base32hex", plain).get() == "v"
|
||||||
MultiBase.encode("base32hexupper", plain) == "V"
|
MultiBase.encode("base32hexupper", plain).get() == "V"
|
||||||
MultiBase.encode("base32hexpad", plain) == "t"
|
MultiBase.encode("base32hexpad", plain).get() == "t"
|
||||||
MultiBase.encode("base32hexpadupper", plain) == "T"
|
MultiBase.encode("base32hexpadupper", plain).get() == "T"
|
||||||
MultiBase.encode("base32", plain) == "b"
|
MultiBase.encode("base32", plain).get() == "b"
|
||||||
MultiBase.encode("base32upper", plain) == "B"
|
MultiBase.encode("base32upper", plain).get() == "B"
|
||||||
MultiBase.encode("base32pad", plain) == "c"
|
MultiBase.encode("base32pad", plain).get() == "c"
|
||||||
MultiBase.encode("base32padupper", plain) == "C"
|
MultiBase.encode("base32padupper", plain).get() == "C"
|
||||||
MultiBase.encode("base58btc", plain) == "z"
|
MultiBase.encode("base58btc", plain).get() == "z"
|
||||||
MultiBase.encode("base58flickr", plain) == "Z"
|
MultiBase.encode("base58flickr", plain).get() == "Z"
|
||||||
MultiBase.encode("base64", plain) == "m"
|
MultiBase.encode("base64", plain).get() == "m"
|
||||||
MultiBase.encode("base64pad", plain) == "M"
|
MultiBase.encode("base64pad", plain).get() == "M"
|
||||||
MultiBase.encode("base64url", plain) == "u"
|
MultiBase.encode("base64url", plain).get() == "u"
|
||||||
MultiBase.encode("base64urlpad", plain) == "U"
|
MultiBase.encode("base64urlpad", plain).get() == "U"
|
||||||
check:
|
check:
|
||||||
len(MultiBase.decode("\x00")) == 0
|
len(MultiBase.decode("\x00").get()) == 0
|
||||||
# len(MultiBase.decode("1")) == 0
|
# len(MultiBase.decode("1")) == 0
|
||||||
# len(MultiBase.decode("0")) == 0
|
# len(MultiBase.decode("0")) == 0
|
||||||
# len(MultiBase.decode("7")) == 0
|
# len(MultiBase.decode("7")) == 0
|
||||||
# len(MultiBase.decode("9")) == 0
|
# len(MultiBase.decode("9")) == 0
|
||||||
# len(MultiBase.decode("f")) == 0
|
# len(MultiBase.decode("f")) == 0
|
||||||
# len(MultiBase.decode("F")) == 0
|
# len(MultiBase.decode("F")) == 0
|
||||||
len(MultiBase.decode("v")) == 0
|
len(MultiBase.decode("v").get()) == 0
|
||||||
len(MultiBase.decode("V")) == 0
|
len(MultiBase.decode("V").get()) == 0
|
||||||
len(MultiBase.decode("t")) == 0
|
len(MultiBase.decode("t").get()) == 0
|
||||||
len(MultiBase.decode("T")) == 0
|
len(MultiBase.decode("T").get()) == 0
|
||||||
len(MultiBase.decode("b")) == 0
|
len(MultiBase.decode("b").get()) == 0
|
||||||
len(MultiBase.decode("B")) == 0
|
len(MultiBase.decode("B").get()) == 0
|
||||||
len(MultiBase.decode("c")) == 0
|
len(MultiBase.decode("c").get()) == 0
|
||||||
len(MultiBase.decode("C")) == 0
|
len(MultiBase.decode("C").get()) == 0
|
||||||
len(MultiBase.decode("z")) == 0
|
len(MultiBase.decode("z").get()) == 0
|
||||||
len(MultiBase.decode("Z")) == 0
|
len(MultiBase.decode("Z").get()) == 0
|
||||||
len(MultiBase.decode("m")) == 0
|
len(MultiBase.decode("m").get()) == 0
|
||||||
len(MultiBase.decode("M")) == 0
|
len(MultiBase.decode("M").get()) == 0
|
||||||
len(MultiBase.decode("u")) == 0
|
len(MultiBase.decode("u").get()) == 0
|
||||||
len(MultiBase.decode("U")) == 0
|
len(MultiBase.decode("U").get()) == 0
|
||||||
check:
|
check:
|
||||||
MultiBase.encode("identity", plain, enc,
|
MultiBase.encode("identity", plain, enc,
|
||||||
olens[0]) == MultiBaseStatus.Success
|
olens[0]) == MultiBaseStatus.Success
|
||||||
|
@ -261,8 +262,8 @@ suite "MultiBase test suite":
|
||||||
var bexpect = cast[seq[byte]](expect)
|
var bexpect = cast[seq[byte]](expect)
|
||||||
var outlen = 0
|
var outlen = 0
|
||||||
check:
|
check:
|
||||||
MultiBase.encode(encoding, bexpect) == encoded
|
MultiBase.encode(encoding, bexpect).get() == encoded
|
||||||
MultiBase.decode(encoded) == bexpect
|
MultiBase.decode(encoded).get() == bexpect
|
||||||
|
|
||||||
let elength = MultiBase.encodedLength(encoding, len(expect))
|
let elength = MultiBase.encodedLength(encoding, len(expect))
|
||||||
var ebuffer = newString(elength)
|
var ebuffer = newString(elength)
|
||||||
|
@ -291,18 +292,5 @@ suite "MultiBase test suite":
|
||||||
MultiBase.encode("unknown", data, ebuffer,
|
MultiBase.encode("unknown", data, ebuffer,
|
||||||
outlen) == MultiBaseStatus.BadCodec
|
outlen) == MultiBaseStatus.BadCodec
|
||||||
MultiBase.decode("\x01\x00", dbuffer, outlen) == MultiBaseStatus.BadCodec
|
MultiBase.decode("\x01\x00", dbuffer, outlen) == MultiBaseStatus.BadCodec
|
||||||
var r1 = false
|
MultiBase.encode("unknwon", data).isErr()
|
||||||
var r2 = false
|
MultiBase.decode("\x01\x00").isErr()
|
||||||
try:
|
|
||||||
discard MultiBase.encode("unknwon", data)
|
|
||||||
except MultiBaseError:
|
|
||||||
r1 = true
|
|
||||||
|
|
||||||
try:
|
|
||||||
discard MultiBase.decode("\x01\x00")
|
|
||||||
except MultiBaseError:
|
|
||||||
r2 = true
|
|
||||||
|
|
||||||
check:
|
|
||||||
r1 == true
|
|
||||||
r2 == true
|
|
||||||
|
|
|
@ -236,7 +236,7 @@ suite "Multistream select":
|
||||||
|
|
||||||
test "e2e - handle":
|
test "e2e - handle":
|
||||||
proc endToEnd(): Future[bool] {.async.} =
|
proc endToEnd(): Future[bool] {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
let
|
let
|
||||||
handlerWait1 = newFuture[void]()
|
handlerWait1 = newFuture[void]()
|
||||||
|
@ -283,7 +283,7 @@ suite "Multistream select":
|
||||||
|
|
||||||
test "e2e - ls":
|
test "e2e - ls":
|
||||||
proc endToEnd(): Future[bool] {.async.} =
|
proc endToEnd(): Future[bool] {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
let
|
let
|
||||||
handlerWait = newFuture[void]()
|
handlerWait = newFuture[void]()
|
||||||
|
@ -331,7 +331,7 @@ suite "Multistream select":
|
||||||
|
|
||||||
test "e2e - select one from a list with unsupported protos":
|
test "e2e - select one from a list with unsupported protos":
|
||||||
proc endToEnd(): Future[bool] {.async.} =
|
proc endToEnd(): Future[bool] {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
var protocol: LPProtocol = new LPProtocol
|
var protocol: LPProtocol = new LPProtocol
|
||||||
proc testHandler(conn: Connection,
|
proc testHandler(conn: Connection,
|
||||||
|
@ -371,7 +371,7 @@ suite "Multistream select":
|
||||||
|
|
||||||
test "e2e - select one with both valid":
|
test "e2e - select one with both valid":
|
||||||
proc endToEnd(): Future[bool] {.async.} =
|
proc endToEnd(): Future[bool] {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
var protocol: LPProtocol = new LPProtocol
|
var protocol: LPProtocol = new LPProtocol
|
||||||
proc testHandler(conn: Connection,
|
proc testHandler(conn: Connection,
|
||||||
|
|
|
@ -77,7 +77,7 @@ suite "Noise":
|
||||||
test "e2e: handle write + noise":
|
test "e2e: handle write + noise":
|
||||||
proc testListenerDialer(): Future[bool] {.async.} =
|
proc testListenerDialer(): Future[bool] {.async.} =
|
||||||
let
|
let
|
||||||
server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA).get(), [server])
|
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA).get(), [server])
|
||||||
serverNoise = newNoise(serverInfo.privateKey, outgoing = false)
|
serverNoise = newNoise(serverInfo.privateKey, outgoing = false)
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ suite "Noise":
|
||||||
test "e2e: handle read + noise":
|
test "e2e: handle read + noise":
|
||||||
proc testListenerDialer(): Future[bool] {.async.} =
|
proc testListenerDialer(): Future[bool] {.async.} =
|
||||||
let
|
let
|
||||||
server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA).get(), [server])
|
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA).get(), [server])
|
||||||
serverNoise = newNoise(serverInfo.privateKey, outgoing = false)
|
serverNoise = newNoise(serverInfo.privateKey, outgoing = false)
|
||||||
readTask = newFuture[void]()
|
readTask = newFuture[void]()
|
||||||
|
@ -156,7 +156,7 @@ suite "Noise":
|
||||||
test "e2e: handle read + noise fragmented":
|
test "e2e: handle read + noise fragmented":
|
||||||
proc testListenerDialer(): Future[bool] {.async.} =
|
proc testListenerDialer(): Future[bool] {.async.} =
|
||||||
let
|
let
|
||||||
server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA).get(), [server])
|
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA).get(), [server])
|
||||||
serverNoise = newNoise(serverInfo.privateKey, outgoing = false)
|
serverNoise = newNoise(serverInfo.privateKey, outgoing = false)
|
||||||
readTask = newFuture[void]()
|
readTask = newFuture[void]()
|
||||||
|
@ -199,8 +199,8 @@ suite "Noise":
|
||||||
|
|
||||||
test "e2e use switch dial proto string":
|
test "e2e use switch dial proto string":
|
||||||
proc testSwitch(): Future[bool] {.async, gcsafe.} =
|
proc testSwitch(): Future[bool] {.async, gcsafe.} =
|
||||||
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
var peerInfo1, peerInfo2: PeerInfo
|
var peerInfo1, peerInfo2: PeerInfo
|
||||||
var switch1, switch2: Switch
|
var switch1, switch2: Switch
|
||||||
|
|
|
@ -57,8 +57,8 @@ suite "Switch":
|
||||||
|
|
||||||
test "e2e use switch dial proto string":
|
test "e2e use switch dial proto string":
|
||||||
proc testSwitch() {.async, gcsafe.} =
|
proc testSwitch() {.async, gcsafe.} =
|
||||||
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
var peerInfo1, peerInfo2: PeerInfo
|
var peerInfo1, peerInfo2: PeerInfo
|
||||||
var switch1, switch2: Switch
|
var switch1, switch2: Switch
|
||||||
|
@ -104,8 +104,8 @@ suite "Switch":
|
||||||
|
|
||||||
test "e2e use switch no proto string":
|
test "e2e use switch no proto string":
|
||||||
proc testSwitch(): Future[bool] {.async, gcsafe.} =
|
proc testSwitch(): Future[bool] {.async, gcsafe.} =
|
||||||
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
|
|
||||||
var peerInfo1, peerInfo2: PeerInfo
|
var peerInfo1, peerInfo2: PeerInfo
|
||||||
var switch1, switch2: Switch
|
var switch1, switch2: Switch
|
||||||
|
|
|
@ -16,7 +16,7 @@ suite "TCP transport":
|
||||||
|
|
||||||
test "test listener: handle write":
|
test "test listener: handle write":
|
||||||
proc testListener(): Future[bool] {.async, gcsafe.} =
|
proc testListener(): Future[bool] {.async, gcsafe.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
let handlerWait = newFuture[void]()
|
let handlerWait = newFuture[void]()
|
||||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||||
await conn.write(cstring("Hello!"), 6)
|
await conn.write(cstring("Hello!"), 6)
|
||||||
|
@ -42,7 +42,7 @@ suite "TCP transport":
|
||||||
|
|
||||||
test "test listener: handle read":
|
test "test listener: handle read":
|
||||||
proc testListener(): Future[bool] {.async.} =
|
proc testListener(): Future[bool] {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
let handlerWait = newFuture[void]()
|
let handlerWait = newFuture[void]()
|
||||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||||
var msg = newSeq[byte](6)
|
var msg = newSeq[byte](6)
|
||||||
|
@ -82,7 +82,7 @@ suite "TCP transport":
|
||||||
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
||||||
server.start()
|
server.start()
|
||||||
|
|
||||||
let ma: MultiAddress = MultiAddress.init(server.sock.getLocalAddress())
|
let ma: MultiAddress = MultiAddress.init(server.sock.getLocalAddress()).tryGet()
|
||||||
let transport: TcpTransport = TcpTransport.init()
|
let transport: TcpTransport = TcpTransport.init()
|
||||||
let conn = await transport.dial(ma)
|
let conn = await transport.dial(ma)
|
||||||
var msg = newSeq[byte](6)
|
var msg = newSeq[byte](6)
|
||||||
|
@ -119,7 +119,7 @@ suite "TCP transport":
|
||||||
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
||||||
server.start()
|
server.start()
|
||||||
|
|
||||||
let ma: MultiAddress = MultiAddress.init(server.sock.getLocalAddress())
|
let ma: MultiAddress = MultiAddress.init(server.sock.getLocalAddress()).tryGet()
|
||||||
let transport: TcpTransport = TcpTransport.init()
|
let transport: TcpTransport = TcpTransport.init()
|
||||||
let conn = await transport.dial(ma)
|
let conn = await transport.dial(ma)
|
||||||
await conn.write(cstring("Hello!"), 6)
|
await conn.write(cstring("Hello!"), 6)
|
||||||
|
@ -138,7 +138,7 @@ suite "TCP transport":
|
||||||
|
|
||||||
test "e2e: handle write":
|
test "e2e: handle write":
|
||||||
proc testListenerDialer(): Future[bool] {.async.} =
|
proc testListenerDialer(): Future[bool] {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
let handlerWait = newFuture[void]()
|
let handlerWait = newFuture[void]()
|
||||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||||
await conn.write(cstring("Hello!"), 6)
|
await conn.write(cstring("Hello!"), 6)
|
||||||
|
@ -166,7 +166,7 @@ suite "TCP transport":
|
||||||
|
|
||||||
test "e2e: handle read":
|
test "e2e: handle read":
|
||||||
proc testListenerDialer(): Future[bool] {.async.} =
|
proc testListenerDialer(): Future[bool] {.async.} =
|
||||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||||
let handlerWait = newFuture[void]()
|
let handlerWait = newFuture[void]()
|
||||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||||
var msg = newSeq[byte](6)
|
var msg = newSeq[byte](6)
|
||||||
|
|
|
@ -205,8 +205,8 @@ suite "Variable integer test suite":
|
||||||
for i in 0 ..< len(PBedgeValues):
|
for i in 0 ..< len(PBedgeValues):
|
||||||
buffer.setLen(PBedgeSizes[i])
|
buffer.setLen(PBedgeSizes[i])
|
||||||
check:
|
check:
|
||||||
PB.putUVarint(buffer, length, PBedgeValues[i]) == VarintStatus.Success
|
PB.putUVarint(buffer, length, PBedgeValues[i]).isOk()
|
||||||
PB.getUVarint(buffer, length, uvalue) == VarintStatus.Success
|
PB.getUVarint(buffer, length, uvalue).isOk()
|
||||||
uvalue == PBedgeValues[i]
|
uvalue == PBedgeValues[i]
|
||||||
toHex(buffer) == PBedgeExpects[i]
|
toHex(buffer) == PBedgeExpects[i]
|
||||||
|
|
||||||
|
@ -214,16 +214,16 @@ suite "Variable integer test suite":
|
||||||
buffer.setLen(PBEdgeSignedPositiveSizes[i])
|
buffer.setLen(PBEdgeSignedPositiveSizes[i])
|
||||||
check:
|
check:
|
||||||
putSVarint(buffer, length,
|
putSVarint(buffer, length,
|
||||||
hint64(PBPositiveSignedEdgeValues[i])) == VarintStatus.Success
|
hint64(PBPositiveSignedEdgeValues[i])).isOk()
|
||||||
getSVarint(buffer, length, ivalue) == VarintStatus.Success
|
getSVarint(buffer, length, ivalue).isOk()
|
||||||
int64(ivalue) == int64(PBPositiveSignedEdgeValues[i])
|
int64(ivalue) == int64(PBPositiveSignedEdgeValues[i])
|
||||||
toHex(buffer) == PBPositiveSignedEdgeExpects[i]
|
toHex(buffer) == PBPositiveSignedEdgeExpects[i]
|
||||||
|
|
||||||
buffer.setLen(PBEdgeSignedPositiveZigZagSizes[i])
|
buffer.setLen(PBEdgeSignedPositiveZigZagSizes[i])
|
||||||
check:
|
check:
|
||||||
putSVarint(buffer, length,
|
putSVarint(buffer, length,
|
||||||
zint64(PBPositiveSignedEdgeValues[i])) == VarintStatus.Success
|
zint64(PBPositiveSignedEdgeValues[i])).isOk()
|
||||||
getSVarint(buffer, length, svalue) == VarintStatus.Success
|
getSVarint(buffer, length, svalue).isOk()
|
||||||
int64(svalue) == int64(PBPositiveSignedEdgeValues[i])
|
int64(svalue) == int64(PBPositiveSignedEdgeValues[i])
|
||||||
toHex(buffer) == PBPositiveSignedZigZagEdgeExpects[i]
|
toHex(buffer) == PBPositiveSignedZigZagEdgeExpects[i]
|
||||||
|
|
||||||
|
@ -231,16 +231,16 @@ suite "Variable integer test suite":
|
||||||
buffer.setLen(PBEdgeSignedNegativeSizes[i])
|
buffer.setLen(PBEdgeSignedNegativeSizes[i])
|
||||||
check:
|
check:
|
||||||
putSVarint(buffer, length,
|
putSVarint(buffer, length,
|
||||||
hint64(PBNegativeSignedEdgeValues[i])) == VarintStatus.Success
|
hint64(PBNegativeSignedEdgeValues[i])).isOk()
|
||||||
getSVarint(buffer, length, ivalue) == VarintStatus.Success
|
getSVarint(buffer, length, ivalue).isOk()
|
||||||
int64(ivalue) == int64(PBNegativeSignedEdgeValues[i])
|
int64(ivalue) == int64(PBNegativeSignedEdgeValues[i])
|
||||||
toHex(buffer) == PBNegativeSignedEdgeExpects[i]
|
toHex(buffer) == PBNegativeSignedEdgeExpects[i]
|
||||||
|
|
||||||
buffer.setLen(PBEdgeSignedNegativeZigZagSizes[i])
|
buffer.setLen(PBEdgeSignedNegativeZigZagSizes[i])
|
||||||
check:
|
check:
|
||||||
putSVarint(buffer, length,
|
putSVarint(buffer, length,
|
||||||
zint64(PBNegativeSignedEdgeValues[i])) == VarintStatus.Success
|
zint64(PBNegativeSignedEdgeValues[i])).isOk()
|
||||||
getSVarint(buffer, length, svalue) == VarintStatus.Success
|
getSVarint(buffer, length, svalue).isOk()
|
||||||
|
|
||||||
int64(svalue) == int64(PBNegativeSignedEdgeValues[i])
|
int64(svalue) == int64(PBNegativeSignedEdgeValues[i])
|
||||||
toHex(buffer) == PBNegativeSignedZigZagEdgeExpects[i]
|
toHex(buffer) == PBNegativeSignedZigZagEdgeExpects[i]
|
||||||
|
@ -252,7 +252,7 @@ suite "Variable integer test suite":
|
||||||
buffer.setLen(PBedgeSizes[i] - 1)
|
buffer.setLen(PBedgeSizes[i] - 1)
|
||||||
let res = PB.putUVarint(buffer, length, PBedgeValues[i])
|
let res = PB.putUVarint(buffer, length, PBedgeValues[i])
|
||||||
check:
|
check:
|
||||||
res == VarintStatus.Overrun
|
res.error() == VarintError.Overrun
|
||||||
length == PBedgeSizes[i]
|
length == PBedgeSizes[i]
|
||||||
|
|
||||||
test "[ProtoBuf] Buffer Incomplete edge cases test":
|
test "[ProtoBuf] Buffer Incomplete edge cases test":
|
||||||
|
@ -262,10 +262,10 @@ suite "Variable integer test suite":
|
||||||
for i in 0..<len(PBedgeValues):
|
for i in 0..<len(PBedgeValues):
|
||||||
buffer.setLen(PBedgeSizes[i])
|
buffer.setLen(PBedgeSizes[i])
|
||||||
check:
|
check:
|
||||||
PB.putUVarint(buffer, length, PBedgeValues[i]) == VarintStatus.Success
|
PB.putUVarint(buffer, length, PBedgeValues[i]).isOk()
|
||||||
buffer.setlen(buffer.high)
|
buffer.setlen(buffer.high)
|
||||||
check:
|
check:
|
||||||
PB.getUVarint(buffer, length, value) == VarintStatus.Incomplete
|
PB.getUVarint(buffer, length, value).error() == VarintError.Incomplete
|
||||||
|
|
||||||
test "[ProtoBuf] Integer Overflow 32bit test":
|
test "[ProtoBuf] Integer Overflow 32bit test":
|
||||||
var buffer = newSeq[byte]()
|
var buffer = newSeq[byte]()
|
||||||
|
@ -275,8 +275,8 @@ suite "Variable integer test suite":
|
||||||
var value = 0'u32
|
var value = 0'u32
|
||||||
buffer.setLen(PBedgeSizes[i])
|
buffer.setLen(PBedgeSizes[i])
|
||||||
check:
|
check:
|
||||||
PB.putUVarint(buffer, length, PBedgeValues[i]) == VarintStatus.Success
|
PB.putUVarint(buffer, length, PBedgeValues[i]).isOk()
|
||||||
PB.getUVarint(buffer, length, value) == VarintStatus.Overflow
|
PB.getUVarint(buffer, length, value).error() == VarintError.Overflow
|
||||||
|
|
||||||
test "[ProtoBuf] Integer Overflow 64bit test":
|
test "[ProtoBuf] Integer Overflow 64bit test":
|
||||||
var buffer = newSeq[byte]()
|
var buffer = newSeq[byte]()
|
||||||
|
@ -286,28 +286,28 @@ suite "Variable integer test suite":
|
||||||
var value = 0'u64
|
var value = 0'u64
|
||||||
buffer.setLen(PBedgeSizes[i] + 1)
|
buffer.setLen(PBedgeSizes[i] + 1)
|
||||||
check:
|
check:
|
||||||
PB.putUVarint(buffer, length, PBedgeValues[i]) == VarintStatus.Success
|
PB.putUVarint(buffer, length, PBedgeValues[i]).isOk()
|
||||||
buffer[9] = buffer[9] or 0x80'u8
|
buffer[9] = buffer[9] or 0x80'u8
|
||||||
buffer[10] = 0x01'u8
|
buffer[10] = 0x01'u8
|
||||||
check:
|
check:
|
||||||
PB.getUVarint(buffer, length, value) == VarintStatus.Overflow
|
PB.getUVarint(buffer, length, value).error() == VarintError.Overflow
|
||||||
|
|
||||||
test "[ProtoBuf] Test vectors":
|
test "[ProtoBuf] Test vectors":
|
||||||
# The test vectors which was obtained at:
|
# The test vectors which was obtained at:
|
||||||
# https://github.com/dermesser/integer-encoding-rs/blob/master/src/varint_tests.rs
|
# https://github.com/dermesser/integer-encoding-rs/blob/master/src/varint_tests.rs
|
||||||
# https://github.com/That3Percent/zigzag/blob/master/src/lib.rs
|
# https://github.com/That3Percent/zigzag/blob/master/src/lib.rs
|
||||||
check:
|
check:
|
||||||
PB.encodeVarint(0'u64) == @[0x00'u8]
|
PB.encodeVarint(0'u64).get() == @[0x00'u8]
|
||||||
PB.encodeVarint(0'u32) == @[0x00'u8]
|
PB.encodeVarint(0'u32).get() == @[0x00'u8]
|
||||||
PB.encodeVarint(hint64(0)) == @[0x00'u8]
|
PB.encodeVarint(hint64(0)).get() == @[0x00'u8]
|
||||||
PB.encodeVarint(hint32(0)) == @[0x00'u8]
|
PB.encodeVarint(hint32(0)).get() == @[0x00'u8]
|
||||||
PB.encodeVarint(zint64(0)) == @[0x00'u8]
|
PB.encodeVarint(zint64(0)).get() == @[0x00'u8]
|
||||||
PB.encodeVarint(zint32(0)) == @[0x00'u8]
|
PB.encodeVarint(zint32(0)).get() == @[0x00'u8]
|
||||||
PB.encodeVarint(zint32(-1)) == PB.encodeVarint(1'u32)
|
PB.encodeVarint(zint32(-1)).get() == PB.encodeVarint(1'u32).get()
|
||||||
PB.encodeVarint(zint64(150)) == PB.encodeVarint(300'u32)
|
PB.encodeVarint(zint64(150)).get( ) == PB.encodeVarint(300'u32).get()
|
||||||
PB.encodeVarint(zint64(-150)) == PB.encodeVarint(299'u32)
|
PB.encodeVarint(zint64(-150)).get() == PB.encodeVarint(299'u32).get()
|
||||||
PB.encodeVarint(zint32(-2147483648)) == PB.encodeVarint(4294967295'u64)
|
PB.encodeVarint(zint32(-2147483648)).get() == PB.encodeVarint(4294967295'u64).get()
|
||||||
PB.encodeVarint(zint32(2147483647)) == PB.encodeVarint(4294967294'u64)
|
PB.encodeVarint(zint32(2147483647)).get() == PB.encodeVarint(4294967294'u64).get()
|
||||||
|
|
||||||
test "[LibP2P] Success edge cases test":
|
test "[LibP2P] Success edge cases test":
|
||||||
var buffer = newSeq[byte]()
|
var buffer = newSeq[byte]()
|
||||||
|
@ -316,8 +316,8 @@ suite "Variable integer test suite":
|
||||||
for i in 0..<len(LPedgeValues):
|
for i in 0..<len(LPedgeValues):
|
||||||
buffer.setLen(LPedgeSizes[i])
|
buffer.setLen(LPedgeSizes[i])
|
||||||
check:
|
check:
|
||||||
LP.putUVarint(buffer, length, LPedgeValues[i]) == VarintStatus.Success
|
LP.putUVarint(buffer, length, LPedgeValues[i]).isOk()
|
||||||
LP.getUVarint(buffer, length, value) == VarintStatus.Success
|
LP.getUVarint(buffer, length, value).isOk()
|
||||||
value == LPedgeValues[i]
|
value == LPedgeValues[i]
|
||||||
toHex(buffer) == LPedgeExpects[i]
|
toHex(buffer) == LPedgeExpects[i]
|
||||||
|
|
||||||
|
@ -328,7 +328,7 @@ suite "Variable integer test suite":
|
||||||
buffer.setLen(PBedgeSizes[i] - 1)
|
buffer.setLen(PBedgeSizes[i] - 1)
|
||||||
let res = LP.putUVarint(buffer, length, LPedgeValues[i])
|
let res = LP.putUVarint(buffer, length, LPedgeValues[i])
|
||||||
check:
|
check:
|
||||||
res == VarintStatus.Overrun
|
res.error() == VarintError.Overrun
|
||||||
length == LPedgeSizes[i]
|
length == LPedgeSizes[i]
|
||||||
|
|
||||||
test "[LibP2P] Buffer Incomplete edge cases test":
|
test "[LibP2P] Buffer Incomplete edge cases test":
|
||||||
|
@ -338,10 +338,10 @@ suite "Variable integer test suite":
|
||||||
for i in 0..<len(LPedgeValues):
|
for i in 0..<len(LPedgeValues):
|
||||||
buffer.setLen(LPedgeSizes[i])
|
buffer.setLen(LPedgeSizes[i])
|
||||||
check:
|
check:
|
||||||
LP.putUVarint(buffer, length, LPedgeValues[i]) == VarintStatus.Success
|
LP.putUVarint(buffer, length, LPedgeValues[i]).isOk()
|
||||||
buffer.setlen(buffer.high)
|
buffer.setlen(buffer.high)
|
||||||
check:
|
check:
|
||||||
LP.getUVarint(buffer, length, value) == VarintStatus.Incomplete
|
LP.getUVarint(buffer, length, value).error() == VarintError.Incomplete
|
||||||
|
|
||||||
test "[LibP2P] Integer Overflow 32bit test":
|
test "[LibP2P] Integer Overflow 32bit test":
|
||||||
var buffer = newSeq[byte]()
|
var buffer = newSeq[byte]()
|
||||||
|
@ -351,8 +351,8 @@ suite "Variable integer test suite":
|
||||||
var value = 0'u32
|
var value = 0'u32
|
||||||
buffer.setLen(LPedgeSizes[i])
|
buffer.setLen(LPedgeSizes[i])
|
||||||
check:
|
check:
|
||||||
LP.putUVarint(buffer, length, LPedgeValues[i]) == VarintStatus.Success
|
LP.putUVarint(buffer, length, LPedgeValues[i]).isOk()
|
||||||
LP.getUVarint(buffer, length, value) == VarintStatus.Overflow
|
LP.getUVarint(buffer, length, value).error() == VarintError.Overflow
|
||||||
|
|
||||||
test "[LibP2P] Integer Overflow 64bit test":
|
test "[LibP2P] Integer Overflow 64bit test":
|
||||||
var buffer = newSeq[byte]()
|
var buffer = newSeq[byte]()
|
||||||
|
@ -362,22 +362,22 @@ suite "Variable integer test suite":
|
||||||
var value = 0'u64
|
var value = 0'u64
|
||||||
buffer.setLen(LPedgeSizes[i] + 1)
|
buffer.setLen(LPedgeSizes[i] + 1)
|
||||||
check:
|
check:
|
||||||
LP.putUVarint(buffer, length, LPedgeValues[i]) == VarintStatus.Success
|
LP.putUVarint(buffer, length, LPedgeValues[i]).isOk()
|
||||||
buffer[8] = buffer[8] or 0x80'u8
|
buffer[8] = buffer[8] or 0x80'u8
|
||||||
buffer[9] = 0x01'u8
|
buffer[9] = 0x01'u8
|
||||||
check:
|
check:
|
||||||
LP.getUVarint(buffer, length, value) == VarintStatus.Overflow
|
LP.getUVarint(buffer, length, value).error() == VarintError.Overflow
|
||||||
|
|
||||||
test "[LibP2P] Over 63bit test":
|
test "[LibP2P] Over 63bit test":
|
||||||
var buffer = newSeq[byte](10)
|
var buffer = newSeq[byte](10)
|
||||||
var length = 0
|
var length = 0
|
||||||
check:
|
check:
|
||||||
LP.putUVarint(buffer, length,
|
LP.putUVarint(buffer, length,
|
||||||
0x7FFF_FFFF_FFFF_FFFF'u64) == VarintStatus.Success
|
0x7FFF_FFFF_FFFF_FFFF'u64).isOk()
|
||||||
LP.putUVarint(buffer, length,
|
LP.putUVarint(buffer, length,
|
||||||
0x8000_0000_0000_0000'u64) == VarintStatus.Overflow
|
0x8000_0000_0000_0000'u64).error() == VarintError.Overflow
|
||||||
LP.putUVarint(buffer, length,
|
LP.putUVarint(buffer, length,
|
||||||
0xFFFF_FFFF_FFFF_FFFF'u64) == VarintStatus.Overflow
|
0xFFFF_FFFF_FFFF_FFFF'u64).error() == VarintError.Overflow
|
||||||
|
|
||||||
test "[LibP2P] Overlong values test":
|
test "[LibP2P] Overlong values test":
|
||||||
const OverlongValues = [
|
const OverlongValues = [
|
||||||
|
@ -414,19 +414,19 @@ suite "Variable integer test suite":
|
||||||
|
|
||||||
for item in OverlongValues:
|
for item in OverlongValues:
|
||||||
check:
|
check:
|
||||||
LP.getUVarint(item, length, value) == VarintStatus.Overlong
|
LP.getUVarint(item, length, value).error() == VarintError.Overlong
|
||||||
length == 0
|
length == 0
|
||||||
value == 0
|
value == 0
|
||||||
|
|
||||||
# We still should be able to decode zero value
|
# We still should be able to decode zero value
|
||||||
check:
|
check:
|
||||||
LP.getUVarint(@[0x00'u8], length, value) == VarintStatus.Success
|
LP.getUVarint(@[0x00'u8], length, value).isOk()
|
||||||
length == 1
|
length == 1
|
||||||
value == 0
|
value == 0
|
||||||
|
|
||||||
# But not overlonged zero value
|
# But not overlonged zero value
|
||||||
check:
|
check:
|
||||||
LP.getUVarint(@[0x80'u8, 0x00'u8], length, value) == VarintStatus.Overlong
|
LP.getUVarint(@[0x80'u8, 0x00'u8], length, value).error() == VarintError.Overlong
|
||||||
length == 0
|
length == 0
|
||||||
value == 0
|
value == 0
|
||||||
|
|
||||||
|
@ -440,11 +440,11 @@ suite "Variable integer test suite":
|
||||||
var ovalue: vtype
|
var ovalue: vtype
|
||||||
var buffer = newSeq[byte](10)
|
var buffer = newSeq[byte](10)
|
||||||
var length = 0
|
var length = 0
|
||||||
check ttype.putVarint(buffer, length, value) == VarintStatus.Success
|
check ttype.putVarint(buffer, length, value).isOk()
|
||||||
buffer.setLen(length)
|
buffer.setLen(length)
|
||||||
check:
|
check:
|
||||||
toHex(buffer) == expect
|
toHex(buffer) == expect
|
||||||
ttype.getVarint(buffer, length, ovalue) == VarintStatus.Success
|
ttype.getVarint(buffer, length, ovalue).isOk()
|
||||||
ovalue == value
|
ovalue == value
|
||||||
|
|
||||||
varintTest(PB, uint64, high(uint64), "FFFFFFFFFFFFFFFFFF01")
|
varintTest(PB, uint64, high(uint64), "FFFFFFFFFFFFFFFFFF01")
|
||||||
|
|
Loading…
Reference in New Issue