diff --git a/src/wormhole/_boss.py b/src/wormhole/_boss.py index 33c00e2..c99bb3d 100644 --- a/src/wormhole/_boss.py +++ b/src/wormhole/_boss.py @@ -32,6 +32,7 @@ class Boss(object): _url = attrib(validator=instance_of(type(u""))) _appid = attrib(validator=instance_of(type(u""))) _versions = attrib(validator=instance_of(dict)) + _client_version = attrib(validator=instance_of(tuple)) _reactor = attrib() _journal = attrib(validator=provides(_interfaces.IJournal)) _tor = attrib(validator=optional(provides(_interfaces.ITorManager))) @@ -52,7 +53,8 @@ class Boss(object): self._R = Receive(self._side, self._timing) self._RC = RendezvousConnector(self._url, self._appid, self._side, self._reactor, self._journal, - self._tor, self._timing) + self._tor, self._timing, + self._client_version) self._L = Lister(self._timing) self._A = Allocator(self._timing) self._I = Input(self._timing) diff --git a/src/wormhole/_rendezvous.py b/src/wormhole/_rendezvous.py index 28a64cd..963d12a 100644 --- a/src/wormhole/_rendezvous.py +++ b/src/wormhole/_rendezvous.py @@ -67,6 +67,7 @@ class RendezvousConnector(object): _journal = attrib(validator=provides(_interfaces.IJournal)) _tor = attrib(validator=optional(provides(_interfaces.ITorManager))) _timing = attrib(validator=provides(_interfaces.ITiming)) + _client_version = attrib(validator=instance_of(tuple)) def __attrs_post_init__(self): self._have_made_a_successful_connection = False @@ -165,7 +166,8 @@ class RendezvousConnector(object): self._have_made_a_successful_connection = True self._ws = proto try: - self._tx("bind", appid=self._appid, side=self._side) + self._tx("bind", appid=self._appid, side=self._side, + client_version=self._client_version) self._N.connected() self._M.connected() self._L.connected() diff --git a/src/wormhole/test/test_machines.py b/src/wormhole/test/test_machines.py index 52a2d0c..ec96fc0 100644 --- a/src/wormhole/test/test_machines.py +++ b/src/wormhole/test/test_machines.py @@ -5,7 +5,7 @@ from zope.interface import directlyProvides, implementer from twisted.trial import unittest from .. import (errors, timing, _order, _receive, _key, _code, _lister, _boss, _input, _allocator, _send, _terminator, _nameplate, _mailbox, - _rendezvous) + _rendezvous, __version__) from .._interfaces import (IKey, IReceive, IBoss, ISend, IMailbox, IOrder, IRendezvousConnector, ILister, IInput, IAllocator, INameplate, ICode, IWordlist, ITerminator) @@ -1219,8 +1219,9 @@ class Boss(unittest.TestCase): reactor = None journal = ImmediateJournal() tor_manager = None + client_version = ("python", __version__) b = MockBoss(wormhole, "side", "url", "appid", versions, - reactor, journal, tor_manager, + client_version, reactor, journal, tor_manager, timing.DebugTiming()) b._T = Dummy("t", events, ITerminator, "close") b._S = Dummy("s", events, ISend, "send") @@ -1449,10 +1450,12 @@ class Rendezvous(unittest.TestCase): reactor = object() journal = ImmediateJournal() tor_manager = None + client_version = ("python", __version__) rc = _rendezvous.RendezvousConnector("ws://host:4000/v1", "appid", "side", reactor, journal, tor_manager, - timing.DebugTiming()) + timing.DebugTiming(), + client_version) b = Dummy("b", events, IBoss, "error") n = Dummy("n", events, INameplate, "connected", "lost") m = Dummy("m", events, IMailbox, "connected", "lost") @@ -1501,8 +1504,9 @@ class Rendezvous(unittest.TestCase): self.assertEqual(c[1][1], False, ws.mock_calls) yield bytes_to_dict(c[1][0]) self.assertEqual(list(sent_messages(ws)), - [dict(appid="appid", side="side", id="0000", - type="bind"), + [dict(appid="appid", side="side", + client_version=["python", __version__], + id="0000", type="bind"), ]) rc.ws_close(True, None, None) diff --git a/src/wormhole/wormhole.py b/src/wormhole/wormhole.py index 72feb07..311e3fc 100644 --- a/src/wormhole/wormhole.py +++ b/src/wormhole/wormhole.py @@ -3,6 +3,7 @@ import os, sys from attr import attrs, attrib from zope.interface import implementer from twisted.python import failure +from . import __version__ from ._interfaces import IWormhole, IDeferredWormhole from .util import bytes_to_hexstr from .eventual import EventualQueue @@ -230,8 +231,12 @@ def create(appid, relay_url, reactor, # use keyword args for everything else w = _DeferredWormhole(eq) wormhole_versions = {} # will be used to indicate Wormhole capabilities wormhole_versions["app_versions"] = versions # app-specific capabilities - b = Boss(w, side, relay_url, appid, wormhole_versions, - reactor, journal, tor, timing) + v = __version__ + if isinstance(v, type(b"")): + v = v.decode("utf-8", errors="replace") + client_version = ("python", v) + b = Boss(w, side, relay_url, appid, wormhole_versions, client_version, + reactor, journal, tor, timing) w._set_boss(b) b.start() return w