From f6cd2bc7dbc60ddc336c77132611447989fb10ae Mon Sep 17 00:00:00 2001 From: Jonathan Zernik Date: Sat, 30 Jan 2021 19:56:01 -0800 Subject: [PATCH] Return core types from peer client (#765) * Create message module with util functions for peer protocol * Use message util functions in rpc server servicer --- squeaknode/network/messages.py | 49 +++++++++++++++ squeaknode/network/peer_client.py | 35 ++++------- squeaknode/server/squeak_server_servicer.py | 69 +++++---------------- squeaknode/sync/peer_connection.py | 7 +-- squeaknode/sync/util.py | 17 ----- 5 files changed, 80 insertions(+), 97 deletions(-) create mode 100644 squeaknode/network/messages.py delete mode 100644 squeaknode/sync/util.py diff --git a/squeaknode/network/messages.py b/squeaknode/network/messages.py new file mode 100644 index 00000000..840ab122 --- /dev/null +++ b/squeaknode/network/messages.py @@ -0,0 +1,49 @@ +import logging + +from squeak.core import CheckSqueak +from squeak.core import CSqueak + +from proto import squeak_server_pb2 +from squeaknode.core.offer import Offer +from squeaknode.core.util import get_hash + + +logger = logging.getLogger(__name__) + + +def squeak_to_msg(squeak: CSqueak) -> squeak_server_pb2.Squeak: + return squeak_server_pb2.Squeak( + hash=get_hash(squeak), + serialized_squeak=squeak.serialize(), + ) + + +def squeak_from_msg(squeak_msg: squeak_server_pb2.Squeak) -> CSqueak: + squeak = CSqueak.deserialize(squeak_msg.serialized_squeak) + CheckSqueak(squeak, skipDecryptionCheck=True) + squeak_hash = get_hash(squeak) + if squeak_msg.hash != squeak_hash: + raise Exception("Invalid squeak hash: {}".format( + squeak_hash + )) + return squeak + + +def offer_from_msg(offer_msg: squeak_server_pb2.Offer) -> Offer: + return Offer( + squeak_hash=offer_msg.squeak_hash, + nonce=offer_msg.nonce, + payment_request=offer_msg.payment_request, + host=offer_msg.host, + port=offer_msg.port, + ) + + +def offer_to_msg(offer: Offer) -> squeak_server_pb2.Offer: + return squeak_server_pb2.Offer( + squeak_hash=offer.squeak_hash, + nonce=offer.nonce, + payment_request=offer.payment_request, + host=offer.host, + port=offer.port, + ) diff --git a/squeaknode/network/peer_client.py b/squeaknode/network/peer_client.py index 67164bc8..d9f93f2c 100644 --- a/squeaknode/network/peer_client.py +++ b/squeaknode/network/peer_client.py @@ -3,12 +3,15 @@ from contextlib import contextmanager from typing import List import grpc -from squeak.core import CheckSqueak from squeak.core import CSqueak from proto import squeak_server_pb2 from proto import squeak_server_pb2_grpc -from squeaknode.core.util import get_hash +from squeaknode.core.offer import Offer +from squeaknode.network.messages import offer_from_msg +from squeaknode.network.messages import squeak_from_msg +from squeaknode.network.messages import squeak_to_msg + logger = logging.getLogger(__name__) @@ -48,42 +51,26 @@ class PeerClient: ) return lookup_response - def upload_squeak(self, squeak: CSqueak): - squeak_msg = self._build_squeak_msg(squeak) + def upload_squeak(self, squeak: CSqueak) -> None: + squeak_msg = squeak_to_msg(squeak) self.stub.UploadSqueak( squeak_server_pb2.UploadSqueakRequest( squeak=squeak_msg, ) ) - def download_squeak(self, squeak_hash: bytes): + def download_squeak(self, squeak_hash: bytes) -> CSqueak: get_response = self.stub.DownloadSqueak( squeak_server_pb2.DownloadSqueakRequest( hash=squeak_hash, ) ) - get_response_squeak = self._squeak_from_msg(get_response.squeak) - CheckSqueak(get_response_squeak, skipDecryptionCheck=True) - return get_response_squeak + return squeak_from_msg(get_response.squeak) - def download_offer(self, squeak_hash: bytes): + def download_offer(self, squeak_hash: bytes) -> Offer: download_offer_response = self.stub.DownloadOffer( squeak_server_pb2.DownloadOfferRequest( hash=squeak_hash, ) ) - offer_msg = download_offer_response.offer - return offer_msg - - def _build_squeak_msg(self, squeak: CSqueak): - return squeak_server_pb2.Squeak( - hash=get_hash(squeak), - serialized_squeak=squeak.serialize(), - ) - - def _squeak_from_msg(self, squeak_msg: squeak_server_pb2.Squeak): - if not squeak_msg: - return None - if not squeak_msg.serialized_squeak: - return None - return CSqueak.deserialize(squeak_msg.serialized_squeak) + return offer_from_msg(download_offer_response.offer) diff --git a/squeaknode/server/squeak_server_servicer.py b/squeaknode/server/squeak_server_servicer.py index 75cf7cc0..2b6ed8bb 100644 --- a/squeaknode/server/squeak_server_servicer.py +++ b/squeaknode/server/squeak_server_servicer.py @@ -2,11 +2,12 @@ import logging from concurrent import futures import grpc -from squeak.core import CSqueak from proto import squeak_server_pb2 from proto import squeak_server_pb2_grpc -from squeaknode.core.util import get_hash +from squeaknode.network.messages import offer_to_msg +from squeaknode.network.messages import squeak_from_msg +from squeaknode.network.messages import squeak_to_msg from squeaknode.server.util import parse_ip_address logger = logging.getLogger(__name__) @@ -23,45 +24,22 @@ class SqueakServerServicer(squeak_server_pb2_grpc.SqueakServerServicer): def UploadSqueak(self, request, context): squeak_msg = request.squeak - - squeak_hash = squeak_msg.hash - squeak = CSqueak.deserialize(squeak_msg.serialized_squeak) - # Check is squeak deserialized correctly - if squeak is None: - context.set_code(grpc.StatusCode.INVALID_ARGUMENT) - return squeak_server_pb2.UploadSqueakReply() - - # Check if squeak hash is correct - if get_hash(squeak) != squeak_hash: - context.set_code(grpc.StatusCode.INVALID_ARGUMENT) - return squeak_server_pb2.UploadSqueakReply() - - # Check if squeak is unlocked - if not squeak.HasDecryptionKey(): - context.set_code(grpc.StatusCode.INVALID_ARGUMENT) - return squeak_server_pb2.UploadSqueakReply() - - # Insert the squeak in database. + squeak = squeak_from_msg(squeak_msg) + # Handle the uploaded squeak self.handler.handle_posted_squeak(squeak) return squeak_server_pb2.UploadSqueakReply() def DownloadSqueak(self, request: squeak_server_pb2.DownloadSqueakRequest, context): squeak_hash = request.hash - # TODO: check if hash is valid - + # Basic hash validity check + if len(squeak_hash) != 32: + raise Exception("Invalid squeak hash length.") squeak = self.handler.handle_get_squeak(squeak_hash) if squeak is None: - context.set_code(grpc.StatusCode.NOT_FOUND) - context.set_details("Squeak not found.") - return squeak_server_pb2.DownloadSqueakReply( - squeak=None, - ) - + raise Exception("Squeak not found.") + squeak_msg = squeak_to_msg(squeak) return squeak_server_pb2.DownloadSqueakReply( - squeak=squeak_server_pb2.Squeak( - hash=get_hash(squeak), - serialized_squeak=squeak.serialize(), - ) + squeak=squeak_msg, ) def LookupSqueaksToDownload(self, request, context): @@ -75,26 +53,13 @@ class SqueakServerServicer(squeak_server_pb2_grpc.SqueakServerServicer): # TODO: check if hash is valid client_addr = context.peer() ip_addr = parse_ip_address(client_addr) - - buy_response = self.handler.handle_get_offer(squeak_hash, ip_addr) - - if buy_response is None: - context.set_code(grpc.StatusCode.NOT_FOUND) - context.set_details("Offer not found.") - return squeak_server_pb2.DownloadOfferReply( - offer=None, - ) - - logger.info("Sending buy offer: {}".format(buy_response)) - + offer = self.handler.handle_get_offer(squeak_hash, ip_addr) + if offer is None: + raise Exception("Offer not found.") + logger.info("Sending offer: {}".format(offer)) + offer_msg = offer_to_msg(offer) return squeak_server_pb2.DownloadOfferReply( - offer=squeak_server_pb2.Offer( - squeak_hash=buy_response.squeak_hash, - nonce=buy_response.nonce, - payment_request=buy_response.payment_request, - host=buy_response.host, - port=buy_response.port, - ), + offer=offer_msg, ) def serve(self): diff --git a/squeaknode/sync/peer_connection.py b/squeaknode/sync/peer_connection.py index 290c72bf..5f8e5792 100644 --- a/squeaknode/sync/peer_connection.py +++ b/squeaknode/sync/peer_connection.py @@ -4,7 +4,6 @@ from typing import Optional from squeaknode.core.received_offer_with_peer import ReceivedOfferWithPeer from squeaknode.network.peer_client import PeerClient -from squeaknode.sync.util import parse_buy_offer logger = logging.getLogger(__name__) @@ -138,10 +137,10 @@ class PeerConnection: def _download_offer(self, squeak_hash: bytes): squeak = self.squeak_controller.get_squeak(squeak_hash) - offer_msg = self.peer_client.download_offer(squeak_hash) - buy_offer = parse_buy_offer(offer_msg) + offer = self.peer_client.download_offer(squeak_hash) + # buy_offer = parse_buy_offer(offer_msg) decoded_offer = self.squeak_controller.get_offer( - squeak, buy_offer, self.peer) + squeak, offer, self.peer) self.squeak_controller.save_offer(decoded_offer) logger.info("Downloaded offer for squeak {} from peer {}".format( squeak_hash.hex(), self.peer diff --git a/squeaknode/sync/util.py b/squeaknode/sync/util.py deleted file mode 100644 index 28002bc6..00000000 --- a/squeaknode/sync/util.py +++ /dev/null @@ -1,17 +0,0 @@ -import logging - -from proto import squeak_server_pb2 -from squeaknode.core.offer import Offer - - -logger = logging.getLogger(__name__) - - -def parse_buy_offer(buy_offer_msg: squeak_server_pb2.Offer) -> Offer: - return Offer( - squeak_hash=buy_offer_msg.squeak_hash, - nonce=buy_offer_msg.nonce, - payment_request=buy_offer_msg.payment_request, - host=buy_offer_msg.host, - port=buy_offer_msg.port, - )