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