From 7b1e652224c3d9aeb69923b557daba04f3742a14 Mon Sep 17 00:00:00 2001 From: Dmitriy Ryajov Date: Wed, 25 Nov 2020 07:42:02 -0600 Subject: [PATCH] Allow custom identify agent string (#451) * allow custom agent version string * rework tests and add test for custom agent version --- libp2p/protocols/identify.nim | 5 +- tests/helpers.nim | 6 +- tests/testidentify.nim | 157 +++++++++++++++++++--------------- 3 files changed, 97 insertions(+), 71 deletions(-) diff --git a/libp2p/protocols/identify.nim b/libp2p/protocols/identify.nim index 76d1f67a9..95ca1e3a5 100644 --- a/libp2p/protocols/identify.nim +++ b/libp2p/protocols/identify.nim @@ -55,7 +55,10 @@ proc encodeMsg*(peerInfo: PeerInfo, observedAddr: Multiaddress): ProtoBuffer = result.write(4, observedAddr.data.buffer) let protoVersion = ProtoVersion result.write(5, protoVersion) - let agentVersion = AgentVersion + let agentVersion = if peerInfo.agentVersion.len <= 0: + AgentVersion + else: + peerInfo.agentVersion result.write(6, agentVersion) result.finish() diff --git a/tests/helpers.nim b/tests/helpers.nim index 60d4aaf0e..b8ef25158 100644 --- a/tests/helpers.nim +++ b/tests/helpers.nim @@ -49,21 +49,21 @@ template checkTrackers*() = template asyncTeardown*(body: untyped): untyped = teardown: waitFor(( - proc() {.async.} = + proc() {.async, gcsafe.} = body )()) template asyncSetup*(body: untyped): untyped = setup: waitFor(( - proc() {.async.} = + proc() {.async, gcsafe.} = body )()) template asyncTest*(name: string, body: untyped): untyped = test name: waitFor(( - proc() {.async.} = + proc() {.async, gcsafe.} = body )()) diff --git a/tests/testidentify.nim b/tests/testidentify.nim index f57355c8f..5b87be552 100644 --- a/tests/testidentify.nim +++ b/tests/testidentify.nim @@ -17,80 +17,103 @@ suite "Identify": teardown: checkTrackers() - asyncTest "handle identify message": - let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet() - let remoteSecKey = PrivateKey.random(ECDSA, rng[]).get() - let remotePeerInfo = PeerInfo.init( - remoteSecKey, [ma], ["/test/proto1/1.0.0", "/test/proto2/1.0.0"]) - var serverFut: Future[void] - let identifyProto1 = newIdentify(remotePeerInfo) - let msListen = newMultistream() + suite "handle identify message": + var + ma {.threadvar.}: MultiAddress + remoteSecKey {.threadvar.}: PrivateKey + remotePeerInfo {.threadvar.}: PeerInfo + serverFut {.threadvar.}: Future[void] + acceptFut {.threadvar.}: Future[void] + identifyProto1 {.threadvar.}: Identify + identifyProto2 {.threadvar.}: Identify + transport1 {.threadvar.}: Transport + transport2 {.threadvar.}: Transport + msListen {.threadvar.}: MultistreamSelect + msDial {.threadvar.}: MultistreamSelect + conn {.threadvar.}: Connection - msListen.addHandler(IdentifyCodec, identifyProto1) + asyncSetup: + ma = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet() + remoteSecKey = PrivateKey.random(ECDSA, rng[]).get() + remotePeerInfo = PeerInfo.init( + remoteSecKey, [ma], ["/test/proto1/1.0.0", "/test/proto2/1.0.0"]) - var transport1 = TcpTransport.init() - serverFut = transport1.start(ma) + transport1 = TcpTransport.init() + transport2 = TcpTransport.init() - proc acceptHandler(): Future[void] {.async, gcsafe.} = - let conn = await transport1.accept() - await msListen.handle(conn) + identifyProto1 = newIdentify(remotePeerInfo) + identifyProto2 = newIdentify(remotePeerInfo) - let acceptFut = acceptHandler() - let msDial = newMultistream() - let transport2: TcpTransport = TcpTransport.init() - let conn = await transport2.dial(transport1.ma) + msListen = newMultistream() + msDial = newMultistream() - var peerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [ma]) - let identifyProto2 = newIdentify(peerInfo) - discard await msDial.select(conn, IdentifyCodec) - let id = await identifyProto2.identify(conn, remotePeerInfo) + asyncTeardown: + await conn.close() + await acceptFut + await transport1.stop() + await serverFut + await transport2.stop() - check id.pubKey.get() == remoteSecKey.getKey().get() - check id.addrs[0] == ma - check id.protoVersion.get() == ProtoVersion - # check id.agentVersion.get() == AgentVersion - check id.protos == @["/test/proto1/1.0.0", "/test/proto2/1.0.0"] + asyncTest "default agent version": + msListen.addHandler(IdentifyCodec, identifyProto1) + serverFut = transport1.start(ma) + proc acceptHandler(): Future[void] {.async, gcsafe.} = + let c = await transport1.accept() + await msListen.handle(c) - await conn.close() - await acceptFut - await transport1.stop() - await serverFut - await transport2.stop() + acceptFut = acceptHandler() + conn = await transport2.dial(transport1.ma) - asyncTest "handle failed identify": - let ma = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet() - var remotePeerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [ma]) - let identifyProto1 = newIdentify(remotePeerInfo) - let msListen = newMultistream() - - msListen.addHandler(IdentifyCodec, identifyProto1) - - let transport1: TcpTransport = TcpTransport.init() - asyncCheck transport1.start(ma) - - proc acceptHandler() {.async.} = - var conn: Connection - try: - conn = await transport1.accept() - await msListen.handle(conn) - except CatchableError: - discard - finally: - await conn.close() - - let acceptFut = acceptHandler() - let msDial = newMultistream() - let transport2: TcpTransport = TcpTransport.init() - let conn = await transport2.dial(transport1.ma) - var localPeerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [ma]) - let identifyProto2 = newIdentify(localPeerInfo) - - expect IdentityNoMatchError: - let pi2 = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get()) discard await msDial.select(conn, IdentifyCodec) - discard await identifyProto2.identify(conn, pi2) + let id = await identifyProto2.identify(conn, remotePeerInfo) - await conn.close() - await acceptFut.wait(5000.millis) # when no issues will not wait that long! - await transport2.stop() - await transport1.stop() + check id.pubKey.get() == remoteSecKey.getKey().get() + check id.addrs[0] == ma + check id.protoVersion.get() == ProtoVersion + check id.agentVersion.get() == AgentVersion + check id.protos == @["/test/proto1/1.0.0", "/test/proto2/1.0.0"] + + asyncTest "custom agent version": + const customAgentVersion = "MY CUSTOM AGENT STRING" + remotePeerInfo.agentVersion = customAgentVersion + msListen.addHandler(IdentifyCodec, identifyProto1) + + serverFut = transport1.start(ma) + + proc acceptHandler(): Future[void] {.async, gcsafe.} = + let c = await transport1.accept() + await msListen.handle(c) + + acceptFut = acceptHandler() + conn = await transport2.dial(transport1.ma) + + discard await msDial.select(conn, IdentifyCodec) + let id = await identifyProto2.identify(conn, remotePeerInfo) + + check id.pubKey.get() == remoteSecKey.getKey().get() + check id.addrs[0] == ma + check id.protoVersion.get() == ProtoVersion + check id.agentVersion.get() == customAgentVersion + check id.protos == @["/test/proto1/1.0.0", "/test/proto2/1.0.0"] + + asyncTest "handle failed identify": + msListen.addHandler(IdentifyCodec, identifyProto1) + asyncCheck transport1.start(ma) + + proc acceptHandler() {.async.} = + var conn: Connection + try: + conn = await transport1.accept() + await msListen.handle(conn) + except CatchableError: + discard + finally: + await conn.close() + + acceptFut = acceptHandler() + conn = await transport2.dial(transport1.ma) + + expect IdentityNoMatchError: + let pi2 = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get()) + discard await msDial.select(conn, IdentifyCodec) + discard await identifyProto2.identify(conn, pi2)