Skip to content

Commit 84f74d5

Browse files
committed
Add version community mixin
1 parent 99e624f commit 84f74d5

File tree

3 files changed

+136
-1
lines changed

3 files changed

+136
-1
lines changed

src/tribler-core/tribler_core/modules/popularity/popularity_community.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99

1010
from tribler_core.modules.metadata_store.community.remote_query_community import RemoteQueryCommunity
1111
from tribler_core.modules.popularity.payload import TorrentsHealthPayload
12+
from tribler_core.modules.popularity.version_community_mixin import VersionCommunityMixin
1213
from tribler_core.utilities.unicode import hexlify
1314

1415

15-
class PopularityCommunity(RemoteQueryCommunity):
16+
class PopularityCommunity(RemoteQueryCommunity, VersionCommunityMixin):
1617
"""
1718
Community for disseminating the content across the network.
1819
@@ -44,6 +45,9 @@ def __init__(self, my_peer, endpoint, network, **kwargs):
4445
self.register_task("gossip_random_torrents", self.gossip_random_torrents_health,
4546
interval=PopularityCommunity.GOSSIP_INTERVAL_FOR_RANDOM_TORRENTS)
4647

48+
# Init version community message handlers
49+
self.init_version_community()
50+
4751
@staticmethod
4852
def select_torrents_to_gossip(torrents, include_popular=True, include_random=True) -> (set, set):
4953
""" Select torrents to gossip.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import os
2+
import sys
3+
from asyncio import Future
4+
5+
from ipv8.community import Community
6+
from ipv8.messaging.serialization import default_serializer
7+
from ipv8.test.base import TestBase
8+
from ipv8.test.mocking.ipv8 import MockIPv8
9+
from tribler_core.modules.popularity.version_community_mixin import VersionResponse, VersionCommunityMixin
10+
from tribler_core.version import version_id
11+
12+
13+
class VersionCommunity(VersionCommunityMixin, Community):
14+
community_id = os.urandom(20)
15+
16+
def __init__(self, *args, **kwargs):
17+
super().__init__(*args, **kwargs)
18+
self.init_version_community()
19+
20+
21+
class TestVersionCommunity(TestBase):
22+
NUM_NODES = 2
23+
24+
def setUp(self):
25+
super().setUp()
26+
self.initialize(VersionCommunity, self.NUM_NODES)
27+
28+
def create_node(self, *args, **kwargs):
29+
return MockIPv8("curve25519", VersionCommunity)
30+
31+
def test_version_response_payload(self):
32+
"""
33+
Check if the version response is correctly serialized.
34+
"""
35+
version = "v7.10.0"
36+
platform = "linux"
37+
38+
version_response = VersionResponse(version, platform)
39+
serialized = default_serializer.pack_serializable(version_response)
40+
deserialized, _ = default_serializer.unpack_serializable(VersionResponse, serialized)
41+
42+
self.assertEqual(version_response.version, version)
43+
self.assertEqual(version_response.platform, platform)
44+
self.assertEqual(deserialized.version, version)
45+
self.assertEqual(deserialized.platform, platform)
46+
47+
async def test_request_for_version(self):
48+
"""
49+
Test whether version request is responded well.
50+
"""
51+
await self.introduce_nodes()
52+
53+
on_process_version_response_called = Future()
54+
55+
def on_process_version_response(peer, version, platform):
56+
self.assertEqual(peer, self.peer(1))
57+
self.assertEqual(version, version_id)
58+
self.assertEqual(platform, sys.platform)
59+
on_process_version_response_called.set_result(True)
60+
61+
self.overlay(0).process_version_response = on_process_version_response
62+
self.overlay(0).send_version_request(self.peer(1))
63+
64+
return await on_process_version_response_called
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import sys
2+
3+
from ipv8.lazy_community import lazy_wrapper
4+
from ipv8.messaging.lazy_payload import VariablePayload, vp_compile
5+
from tribler_core.version import version_id
6+
7+
8+
@vp_compile
9+
class VersionRequest(VariablePayload):
10+
msg_id = 101
11+
12+
13+
@vp_compile
14+
class VersionResponse(VariablePayload):
15+
msg_id = 102
16+
format_list = ['varlenI', 'varlenI']
17+
names = ['version', 'platform']
18+
19+
def fix_pack_version(self, value):
20+
return value.encode('utf-8')
21+
22+
def fix_pack_platform(self, value):
23+
return value.encode('utf-8')
24+
25+
@classmethod
26+
def fix_unpack_version(cls, value):
27+
return value.decode('utf-8')
28+
29+
@classmethod
30+
def fix_unpack_platform(cls, value):
31+
return value.decode('utf-8')
32+
33+
34+
class VersionCommunityMixin:
35+
"""
36+
This mixin add the protocol messages to ask and receive version of Tribler and community the
37+
peer is currently running.
38+
39+
Knowing the version of Tribler or the individual community is not critical for normal operation
40+
of Tribler but is useful in doing network experiments and monitoring of the network behavior
41+
because of a new feature/algorithm deployment.
42+
"""
43+
44+
def init_version_community(self):
45+
self.add_message_handler(VersionRequest, self.on_version_request)
46+
self.add_message_handler(VersionResponse, self.on_version_response)
47+
48+
def send_version_request(self, peer):
49+
self.logger.info(f"Sending version request to {peer.address}")
50+
self.ez_send(peer, VersionRequest())
51+
52+
@lazy_wrapper(VersionRequest)
53+
async def on_version_request(self, peer, _):
54+
self.logger.info(f"Received version request from {peer.address}")
55+
version_response = VersionResponse(version_id, sys.platform)
56+
self.ez_send(peer, version_response)
57+
58+
@lazy_wrapper(VersionResponse)
59+
async def on_version_response(self, peer, payload):
60+
self.logger.info(f"Received version response from {peer.address}")
61+
self.process_version_response(peer, payload.version, payload.platform)
62+
63+
def process_version_response(self, peer, version, platform):
64+
"""
65+
This is the method the implementation community or the experiment will implement
66+
to process the version and platform information.
67+
"""

0 commit comments

Comments
 (0)