From b52dab9fd769e996a9b734759d27c88985bc6e7b Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Tue, 15 Dec 2020 19:15:22 +0100 Subject: [PATCH] use stew/leb128 (#481) * avoids multiple reallocations in readLp * simplifies varint implementation * remove vbuffer.length (unused) --- libp2p/multiaddress.nim | 2 - libp2p/stream/lpstream.nim | 17 +-- libp2p/varint.nim | 246 ++++++++++++------------------------- libp2p/vbuffer.nim | 1 - 4 files changed, 89 insertions(+), 177 deletions(-) diff --git a/libp2p/multiaddress.nim b/libp2p/multiaddress.nim index f5a987371..456c86601 100644 --- a/libp2p/multiaddress.nim +++ b/libp2p/multiaddress.nim @@ -63,7 +63,6 @@ proc hash*(a: MultiAddress): Hash = var h: Hash = 0 h = h !& hash(a.data.buffer) h = h !& hash(a.data.offset) - h = h !& hash(a.data.length) !$h proc ip4StB(s: string, vb: var VBuffer): bool = @@ -458,7 +457,6 @@ proc trimRight(s: string, ch: char): string = proc shcopy*(m1: var MultiAddress, m2: MultiAddress) = shallowCopy(m1.data.buffer, m2.data.buffer) m1.data.offset = m2.data.offset - m1.data.length = m2.data.length proc protoCode*(ma: MultiAddress): MaResult[MultiCodec] = ## Returns MultiAddress ``ma`` protocol code. diff --git a/libp2p/stream/lpstream.nim b/libp2p/stream/lpstream.nim index 507efcaef..c433b3a38 100644 --- a/libp2p/stream/lpstream.nim +++ b/libp2p/stream/lpstream.nim @@ -11,7 +11,6 @@ import std/oids import stew/byteutils import chronicles, chronos, metrics import ../varint, - ../vbuffer, ../peerinfo, ../multiaddress @@ -236,12 +235,16 @@ proc readLp*(s: LPStream, maxSize: int): Future[seq[byte]] {.async, gcsafe.} = method write*(s: LPStream, msg: seq[byte]): Future[void] {.base.} = doAssert(false, "not implemented!") -proc writeLp*(s: LPStream, msg: string | seq[byte]): Future[void] {.gcsafe.} = - ## write length prefixed - var buf = initVBuffer() - buf.writeSeq(msg) - buf.finish() - s.write(buf.buffer) +proc writeLp*(s: LPStream, msg: openArray[byte]): Future[void] = + ## Write `msg` with a varint-encoded length prefix + let vbytes = PB.toBytes(msg.len().uint64) + var buf = newSeqUninitialized[byte](msg.len() + vbytes.len) + buf[0..= MaxBits: - outlen = 0 - outval = type(outval)(0) + let parsed = type(outval).fromBytes(pbytes, Leb128) + + if parsed.len == 0: + return err(VarintError.Incomplete) + if parsed.len < 0: + return err(VarintError.Overflow) + + when vtype is LP and sizeof(outval) == 8: + if parsed.val >= 0x8000_0000_0000_0000'u64: 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: - # done, success - if outlen != vsizeof(outval): - outval = type(outval)(0) - outlen = 0 - return err(VarintError.Overlong) - else: - return ok() - - outlen = 0 - outval = type(outval)(0) - err(VarintError.Incomplete) + + if vsizeof(parsed.val) != parsed.len: + return err(VarintError.Overlong) + + (outval, outlen) = parsed + + ok() proc putUVarint*[T: PB|LP](vtype: typedesc[T], pbytes: var openarray[byte], @@ -180,34 +168,20 @@ proc putUVarint*[T: PB|LP](vtype: typedesc[T], ## LibP2P ## Maximum encoded length of 63bit integer is 9 octets. ## Maximum encoded length of 32bit integer is 5 octets. - var buffer: array[10, byte] - var value = outval - var k = 0 + when vtype is LP and sizeof(outval) == 8: + if (uint64(outval) and 0x8000_0000_0000_0000'u64) != 0'u64: + return err(VarintError.Overflow) - when vtype is LP: - if sizeof(outval) == 8: - if (uint64(outval) and 0x8000_0000_0000_0000'u64) != 0'u64: - return err(VarintError.Overflow) - - if value <= type(outval)(0x7F): - buffer[0] = byte(outval and 0xFF) - inc(k) - else: - while value != type(outval)(0): - buffer[k] = byte((value and 0x7F) or 0x80) - value = value shr 7 - inc(k) - buffer[k - 1] = buffer[k - 1] and 0x7F'u8 - - outlen = k - if len(pbytes) >= k: - copyMem(addr pbytes[0], addr buffer[0], k) + let bytes = toBytes(outval, Leb128) + outlen = len(bytes) + if len(pbytes) >= outlen: + pbytes[0..