2020-06-30 13:09:04 +00:00
|
|
|
"""Sans I/O wire protocol for Hypercore"""
|
2020-08-03 20:23:24 +00:00
|
|
|
from typing import List, Optional, Tuple
|
2020-06-30 13:09:04 +00:00
|
|
|
|
2020-06-30 14:02:55 +00:00
|
|
|
import attr
|
2020-08-01 16:53:28 +00:00
|
|
|
from pyvarint import encode, encoding_length
|
2020-06-30 14:02:55 +00:00
|
|
|
|
2020-07-07 22:20:39 +00:00
|
|
|
__all__ = ["SimpleMessageChannel"]
|
2020-06-30 14:02:55 +00:00
|
|
|
|
2020-08-01 16:53:28 +00:00
|
|
|
|
2020-06-30 14:02:55 +00:00
|
|
|
@attr.s(auto_attribs=True)
|
2020-06-30 13:09:04 +00:00
|
|
|
class SimpleMessageChannel:
|
|
|
|
"""A simple message channel."""
|
|
|
|
|
2020-08-03 20:33:51 +00:00
|
|
|
messages: List[Tuple[int, int, bytes]] = attr.Factory(list)
|
2020-08-03 20:23:24 +00:00
|
|
|
varint: int = 0
|
|
|
|
factor: int = 1
|
|
|
|
length: int = 0
|
|
|
|
header: int = 0
|
|
|
|
state: int = 0
|
|
|
|
consumed = 0
|
|
|
|
max_size = 8 * 1024 * 1024
|
|
|
|
|
2020-08-03 19:56:44 +00:00
|
|
|
def send(self, channel: int, type: int, message: bytes) -> bytes:
|
2020-08-01 16:53:28 +00:00
|
|
|
"""Encode a channel, type and message data to be sent.
|
|
|
|
|
|
|
|
:param channel: the message channel identifier
|
|
|
|
:param type: the type of message
|
|
|
|
:param message: the message data
|
|
|
|
"""
|
2020-07-07 22:20:50 +00:00
|
|
|
header = channel << 4 or type
|
2020-08-01 16:53:28 +00:00
|
|
|
length = len(message) + encoding_length(header)
|
|
|
|
return encode(length) + encode(header) + message
|
2020-07-07 22:20:50 +00:00
|
|
|
|
2020-08-03 19:56:44 +00:00
|
|
|
def send_batch(self, messages: List[Tuple[int, int, bytes]]) -> bytes:
|
2020-08-01 16:53:28 +00:00
|
|
|
"""Encodes a series of messages into a single payload of bytes.
|
|
|
|
|
|
|
|
:param messages: Several data messages
|
|
|
|
"""
|
|
|
|
payload = b""
|
|
|
|
for (channel, type, message) in messages:
|
2020-08-03 19:56:44 +00:00
|
|
|
payload += self.send(channel, type, message)
|
2020-08-01 16:53:28 +00:00
|
|
|
return payload
|
2020-06-30 13:09:04 +00:00
|
|
|
|
2020-08-03 20:23:24 +00:00
|
|
|
def recv(self, data: bytes) -> None:
|
2020-08-01 16:53:28 +00:00
|
|
|
"""Encode a channel, type, message to be sent.
|
2020-07-07 22:20:50 +00:00
|
|
|
|
2020-08-01 16:53:28 +00:00
|
|
|
:param data: the message data
|
|
|
|
"""
|
2020-08-03 20:23:24 +00:00
|
|
|
offset = 0
|
|
|
|
|
|
|
|
while offset < len(data):
|
|
|
|
if self.state == 2:
|
|
|
|
offset = self._read_msg(data, offset)
|
|
|
|
else:
|
|
|
|
offset = self._read_varint(data, offset)
|
|
|
|
|
|
|
|
if self.state == 2 and self.length == 0:
|
|
|
|
self._read_msg(data, offset)
|
|
|
|
|
|
|
|
def _read_msg(self, data: bytes, offset: int) -> int:
|
|
|
|
"""TODO."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
def _read_varint(self, data: bytes, offset: int) -> int:
|
|
|
|
"""TODO."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
def _next_state(self, data: bytes, offset: int) -> None:
|
|
|
|
"""TODO."""
|
2020-07-07 22:20:50 +00:00
|
|
|
pass
|