mirror of https://github.com/vacp2p/nim-libp2p.git
prevent interleaved channel data
This commit is contained in:
parent
8c76799d9e
commit
65ce1a93fc
|
@ -7,7 +7,7 @@
|
||||||
## This file may not be copied, modified, or distributed except according to
|
## This file may not be copied, modified, or distributed except according to
|
||||||
## those terms.
|
## those terms.
|
||||||
|
|
||||||
import chronos
|
import chronos, options, sequtils
|
||||||
import types,
|
import types,
|
||||||
../../connection,
|
../../connection,
|
||||||
../../varint,
|
../../varint,
|
||||||
|
@ -16,41 +16,57 @@ import types,
|
||||||
nimcrypto/utils
|
nimcrypto/utils
|
||||||
|
|
||||||
type
|
type
|
||||||
Phase = enum Header, Size
|
Msg* = tuple
|
||||||
|
id: uint
|
||||||
|
msgType: MessageType
|
||||||
|
data: seq[byte]
|
||||||
|
|
||||||
proc readMplexVarint(conn: Connection): Future[uint] {.async, gcsafe.} =
|
proc readMplexVarint(conn: Connection): Future[Option[uint]] {.async, gcsafe.} =
|
||||||
var
|
var
|
||||||
varint: uint
|
varint: uint
|
||||||
length: int
|
length: int
|
||||||
res: VarintStatus
|
res: VarintStatus
|
||||||
var buffer = newSeq[byte](10)
|
var buffer = newSeq[byte](10)
|
||||||
|
result = none(uint)
|
||||||
try:
|
try:
|
||||||
for i in 0..<len(buffer):
|
for i in 0..<len(buffer):
|
||||||
await conn.readExactly(addr buffer[i], 1)
|
await conn.readExactly(addr buffer[i], 1)
|
||||||
res = LP.getUVarint(buffer.toOpenArray(0, i), length, varint)
|
res = LP.getUVarint(buffer.toOpenArray(0, i), length, varint)
|
||||||
if res == VarintStatus.Success:
|
if res == VarintStatus.Success:
|
||||||
return varint
|
return some(varint)
|
||||||
if res != VarintStatus.Success:
|
if res != VarintStatus.Success:
|
||||||
buffer.setLen(0)
|
buffer.setLen(0)
|
||||||
return
|
return
|
||||||
except TransportIncompleteError, AsyncStreamIncompleteError:
|
except TransportIncompleteError, AsyncStreamIncompleteError:
|
||||||
buffer.setLen(0)
|
buffer.setLen(0)
|
||||||
|
|
||||||
proc readMsg*(conn: Connection): Future[(uint, MessageType, seq[byte])] {.async, gcsafe.} =
|
proc readMsg*(conn: Connection): Future[Option[Msg]] {.async, gcsafe.} =
|
||||||
let header = await conn.readMplexVarint()
|
let headerVarint = await conn.readMplexVarint()
|
||||||
let dataLen = await conn.readMplexVarint()
|
if headerVarint.isNone:
|
||||||
|
return
|
||||||
|
|
||||||
|
let dataLenVarint = await conn.readMplexVarint()
|
||||||
var data: seq[byte]
|
var data: seq[byte]
|
||||||
if dataLen > 0.uint:
|
if dataLenVarint.isSome and dataLenVarint.get() > 0.uint:
|
||||||
data = await conn.read(dataLen.int)
|
data = await conn.read(dataLenVarint.get().int)
|
||||||
result = (header shr 3, MessageType(header and 0x7), data)
|
|
||||||
|
let header = headerVarint.get()
|
||||||
|
result = some((header shr 3, MessageType(header and 0x7), data))
|
||||||
|
|
||||||
proc writeMsg*(conn: Connection,
|
proc writeMsg*(conn: Connection,
|
||||||
id: uint,
|
id: uint,
|
||||||
msgType: MessageType,
|
msgType: MessageType,
|
||||||
data: seq[byte] = @[]) {.async, gcsafe.} =
|
data: seq[byte] = @[]) {.async, gcsafe.} =
|
||||||
## write lenght prefixed
|
## write lenght prefixed
|
||||||
var buf = initVBuffer()
|
var buf = initVBuffer()
|
||||||
buf.writeVarint((id shl 3) or ord(msgType).uint)
|
let header = (id shl 3 or ord(msgType).uint)
|
||||||
|
buf.writeVarint(id shl 3 or ord(msgType).uint)
|
||||||
buf.writeVarint(data.len().uint) # size should be always sent
|
buf.writeVarint(data.len().uint) # size should be always sent
|
||||||
buf.finish()
|
buf.finish()
|
||||||
await conn.write(buf.buffer & data)
|
await conn.write(buf.buffer & data)
|
||||||
|
|
||||||
|
proc writeMsg*(conn: Connection,
|
||||||
|
id: uint,
|
||||||
|
msgType: MessageType,
|
||||||
|
data: string) {.async, gcsafe.} =
|
||||||
|
result = conn.writeMsg(id, msgType, cast[seq[byte]](toSeq(data.items)))
|
Loading…
Reference in New Issue