Skip to content

Commit 35de586

Browse files
authored
Merge pull request #13 from Code-Partners/feat-memory-protocol
Feat memory protocol
2 parents d93f906 + dea6943 commit 35de586

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

protocols/memory_protocol.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import io
2+
import typing
3+
4+
from common.protocol_command import ProtocolCommand
5+
from connections.builders import ConnectionsBuilder
6+
from formatters import BinaryFormatter
7+
from formatters.text_formatter import TextFormatter
8+
from packets.packet import Packet
9+
from packets.packet_queue import PacketQueue
10+
from protocols.protocol import Protocol
11+
12+
13+
class MemoryProtocol(Protocol):
14+
_HEADER: bytes = b"SILF"
15+
_BOM: bytes = bytes((0xEF, 0xBB, 0xBF))
16+
_DEFAULT_INDENT = False
17+
_DEFAULT_PATTERN = "[/%timestamp/%] /%level/%: /%title/%"
18+
19+
def __init__(self):
20+
super().__init__()
21+
self._max_size: int = 2048
22+
self._as_text: bool = False
23+
self._pattern: str = self._DEFAULT_PATTERN
24+
self._indent: bool = self._DEFAULT_INDENT
25+
self._queue: typing.Optional[PacketQueue] = None
26+
self._formatter: typing.Union[TextFormatter, BinaryFormatter, None] = None
27+
self._load_options()
28+
29+
def _internal_connect(self) -> None:
30+
self._queue = PacketQueue()
31+
self._queue.backlog = self._max_size
32+
33+
def _internal_disconnect(self) -> None:
34+
if self._queue is not None:
35+
self._queue.clear()
36+
self._queue = None
37+
38+
def _internal_write_packet(self, packet: Packet) -> None:
39+
self._queue.push(packet)
40+
41+
def _internal_dispatch(self, command: ProtocolCommand) -> None:
42+
if command is None:
43+
return
44+
45+
state = command.get_state()
46+
47+
if state is None:
48+
return
49+
50+
if isinstance(state, io.BufferedIOBase) or isinstance(state, io.RawIOBase):
51+
stream = state
52+
self._flush_to_stream(stream)
53+
elif isinstance(state, Protocol):
54+
protocol = state
55+
self._flush_to_protocol(protocol)
56+
57+
def _flush_to_stream(self, stream: typing.Union[io.BufferedIOBase, io.RawIOBase]) -> None:
58+
if self._as_text:
59+
stream.write(self._BOM)
60+
else:
61+
stream.write(self._HEADER)
62+
63+
packet = self._queue.pop()
64+
while packet is not None:
65+
self._formatter.format(packet, stream)
66+
packet = self._queue.pop()
67+
68+
def _flush_to_protocol(self, protocol: Protocol) -> None:
69+
packet = self._queue.pop()
70+
while packet is not None:
71+
protocol.write_packet(packet)
72+
packet = self._queue.pop()
73+
74+
@staticmethod
75+
def _get_name() -> str:
76+
return "mem"
77+
78+
def _initialize_formatter(self) -> None:
79+
if self._as_text:
80+
self._formatter = TextFormatter()
81+
self._formatter.pattern = self._pattern
82+
self._formatter.indent = self._indent
83+
else:
84+
self._formatter = BinaryFormatter()
85+
86+
def _build_options(self, builder: ConnectionsBuilder) -> None:
87+
super()._build_options(builder)
88+
builder.add_option("maxsize", int(self._max_size / 1024))
89+
builder.add_option("astext", self._as_text)
90+
builder.add_option("indent", self._indent)
91+
builder.add_option("pattern", self._pattern)
92+
93+
def _is_valid_option(self, option_name: str) -> bool:
94+
is_valid = (bool(option_name in ("astext",
95+
"pattern",
96+
"maxsize",
97+
"indent",
98+
))
99+
or super()._is_valid_option(option_name))
100+
return is_valid
101+
102+
def _load_options(self) -> None:
103+
super()._load_options()
104+
self._max_size = self._get_size_option("maxsize", 2048)
105+
self._as_text = self._get_boolean_option("astext", False)
106+
self._pattern = self._get_string_option("pattern", self._DEFAULT_PATTERN)
107+
self._indent = self._get_boolean_option("indent", self._DEFAULT_INDENT)
108+
self._initialize_formatter()

protocols/protocol_factory.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from protocols.cloud.cloud_protocol import CloudProtocol
55
from protocols.file_protocol.file_protocol import FileProtocol
6+
from protocols.memory_protocol import MemoryProtocol
67
from protocols.protocol import Protocol
78
from common.exceptions import SmartInspectError
89
from protocols.tcp_protocol import TcpProtocol
@@ -16,6 +17,7 @@ class ProtocolFactory:
1617
"cloud": CloudProtocol,
1718
"file": FileProtocol,
1819
"text": TextProtocol,
20+
"mem": MemoryProtocol,
1921
}
2022
__PROTOCOL_NOT_FOUND = "The requested protocol is unknown"
2123
__lock = threading.Lock()

0 commit comments

Comments
 (0)