lbry-sdk/lbrynet/dht/msgformat.py

91 lines
3.8 KiB
Python
Raw Normal View History

2015-08-20 17:27:15 +02:00
#!/usr/bin/env python
#
# This library is free software, distributed under the terms of
# the GNU Lesser General Public License Version 3, or any later version.
# See the COPYING file included in this archive
#
# The docstrings in this module contain epytext markup; API documentation
# may be created by processing this file with epydoc: http://epydoc.sf.net
import msgtypes
2017-03-31 19:32:43 +02:00
2015-08-20 17:27:15 +02:00
class MessageTranslator(object):
""" Interface for RPC message translators/formatters
2016-12-14 00:08:29 +01:00
2015-08-20 17:27:15 +02:00
Classes inheriting from this should provide a translation services between
the classes used internally by this Kademlia implementation and the actual
data that is transmitted between nodes.
"""
2017-03-31 19:32:43 +02:00
2015-08-20 17:27:15 +02:00
def fromPrimitive(self, msgPrimitive):
""" Create an RPC Message from a message's string representation
2016-12-14 00:08:29 +01:00
2015-08-20 17:27:15 +02:00
@param msgPrimitive: The unencoded primitive representation of a message
@type msgPrimitive: str, int, list or dict
2016-12-14 00:08:29 +01:00
2015-08-20 17:27:15 +02:00
@return: The translated message object
@rtype: entangled.kademlia.msgtypes.Message
"""
2016-12-14 00:08:29 +01:00
2015-08-20 17:27:15 +02:00
def toPrimitive(self, message):
""" Create a string representation of a message
2016-12-14 00:08:29 +01:00
2015-08-20 17:27:15 +02:00
@param message: The message object
@type message: msgtypes.Message
2016-12-14 00:08:29 +01:00
2015-08-20 17:27:15 +02:00
@return: The message's primitive representation in a particular
messaging format
@rtype: str, int, list or dict
"""
2016-12-14 00:08:29 +01:00
2017-03-31 19:32:43 +02:00
2015-08-20 17:27:15 +02:00
class DefaultFormat(MessageTranslator):
""" The default on-the-wire message format for this library """
typeRequest, typeResponse, typeError = range(3)
headerType, headerMsgID, headerNodeID, headerPayload, headerArgs = range(5) # TODO: make str
@staticmethod
def get(primitive, key):
try:
return primitive[key]
except KeyError:
return primitive[str(key)] # TODO: switch to int()
2016-12-14 00:08:29 +01:00
2015-08-20 17:27:15 +02:00
def fromPrimitive(self, msgPrimitive):
2018-03-23 17:50:18 +01:00
msgType = self.get(msgPrimitive, self.headerType)
2015-08-20 17:27:15 +02:00
if msgType == self.typeRequest:
msg = msgtypes.RequestMessage(self.get(msgPrimitive, self.headerNodeID),
self.get(msgPrimitive, self.headerPayload),
self.get(msgPrimitive, self.headerArgs),
self.get(msgPrimitive, self.headerMsgID))
2015-08-20 17:27:15 +02:00
elif msgType == self.typeResponse:
msg = msgtypes.ResponseMessage(self.get(msgPrimitive, self.headerMsgID),
self.get(msgPrimitive, self.headerNodeID),
self.get(msgPrimitive, self.headerPayload))
2015-08-20 17:27:15 +02:00
elif msgType == self.typeError:
msg = msgtypes.ErrorMessage(self.get(msgPrimitive, self.headerMsgID),
self.get(msgPrimitive, self.headerNodeID),
self.get(msgPrimitive, self.headerPayload),
self.get(msgPrimitive, self.headerArgs))
2015-08-20 17:27:15 +02:00
else:
# Unknown message, no payload
msg = msgtypes.Message(msgPrimitive[self.headerMsgID], msgPrimitive[self.headerNodeID])
return msg
2016-12-14 00:08:29 +01:00
def toPrimitive(self, message):
2017-03-31 19:32:43 +02:00
msg = {self.headerMsgID: message.id,
2015-08-20 17:27:15 +02:00
self.headerNodeID: message.nodeID}
if isinstance(message, msgtypes.RequestMessage):
msg[self.headerType] = self.typeRequest
msg[self.headerPayload] = message.request
msg[self.headerArgs] = message.args
elif isinstance(message, msgtypes.ErrorMessage):
msg[self.headerType] = self.typeError
msg[self.headerPayload] = message.exceptionType
msg[self.headerArgs] = message.response
elif isinstance(message, msgtypes.ResponseMessage):
msg[self.headerType] = self.typeResponse
msg[self.headerPayload] = message.response
return msg