dimples 1.0.0__tar.gz → 1.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. {dimples-1.0.0 → dimples-1.0.2}/PKG-INFO +1 -1
  2. {dimples-1.0.0 → dimples-1.0.2}/dimples/conn/__init__.py +2 -0
  3. dimples-1.0.2/dimples/conn/flexible.py +168 -0
  4. {dimples-1.0.0 → dimples-1.0.2}/dimples/conn/gate.py +9 -11
  5. {dimples-1.0.0 → dimples-1.0.2}/dimples/conn/gatekeeper.py +1 -1
  6. {dimples-1.0.0 → dimples-1.0.2}/dimples/conn/mars.py +1 -1
  7. {dimples-1.0.0 → dimples-1.0.2}/dimples/conn/mtp.py +1 -1
  8. {dimples-1.0.0 → dimples-1.0.2}/dimples/conn/protocol/__init__.py +4 -2
  9. {dimples-1.0.0 → dimples-1.0.2}/dimples/conn/protocol/ws.py +1 -1
  10. {dimples-1.0.0 → dimples-1.0.2}/dimples/conn/session.py +2 -1
  11. {dimples-1.0.0 → dimples-1.0.2}/dimples/conn/ws.py +1 -1
  12. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/dos/base.py +4 -15
  13. {dimples-1.0.0 → dimples-1.0.2}/dimples/edge/octopus.py +6 -1
  14. {dimples-1.0.0 → dimples-1.0.2}/dimples/edge/shared.py +2 -2
  15. {dimples-1.0.0 → dimples-1.0.2}/dimples/register/run.py +2 -2
  16. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/session.py +0 -12
  17. {dimples-1.0.0 → dimples-1.0.2}/dimples/station/shared.py +2 -2
  18. {dimples-1.0.0 → dimples-1.0.2}/dimples/utils/__init__.py +1 -1
  19. {dimples-1.0.0 → dimples-1.0.2}/dimples/utils/cache.py +1 -2
  20. {dimples-1.0.0 → dimples-1.0.2}/dimples/utils/dos.py +99 -48
  21. {dimples-1.0.0 → dimples-1.0.2}/dimples.egg-info/PKG-INFO +1 -1
  22. {dimples-1.0.0 → dimples-1.0.2}/dimples.egg-info/SOURCES.txt +2 -2
  23. {dimples-1.0.0 → dimples-1.0.2}/setup.py +1 -1
  24. dimples-1.0.0/dimples/utils/singleton.py +0 -43
  25. {dimples-1.0.0 → dimples-1.0.2}/README.md +0 -0
  26. {dimples-1.0.0 → dimples-1.0.2}/dimples/__init__.py +0 -0
  27. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/__init__.py +0 -0
  28. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/archivist.py +0 -0
  29. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/checkpoint.py +0 -0
  30. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/cpu/__init__.py +0 -0
  31. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/cpu/commands.py +0 -0
  32. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/cpu/creator.py +0 -0
  33. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/cpu/group.py +0 -0
  34. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/cpu/grp_expel.py +0 -0
  35. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/cpu/grp_invite.py +0 -0
  36. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/cpu/grp_join.py +0 -0
  37. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/cpu/grp_query.py +0 -0
  38. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/cpu/grp_quit.py +0 -0
  39. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/cpu/grp_reset.py +0 -0
  40. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/cpu/grp_resign.py +0 -0
  41. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/cpu/handshake.py +0 -0
  42. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/facebook.py +0 -0
  43. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/messenger.py +0 -0
  44. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/network/__init__.py +0 -0
  45. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/network/session.py +0 -0
  46. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/network/state.py +0 -0
  47. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/network/transition.py +0 -0
  48. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/packer.py +0 -0
  49. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/processor.py +0 -0
  50. {dimples-1.0.0 → dimples-1.0.2}/dimples/client/terminal.py +0 -0
  51. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/__init__.py +0 -0
  52. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/anonymous.py +0 -0
  53. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/ans.py +0 -0
  54. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/archivist.py +0 -0
  55. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/compat/__init__.py +0 -0
  56. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/compat/btc.py +0 -0
  57. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/compat/compatible.py +0 -0
  58. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/compat/entity.py +0 -0
  59. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/compat/meta.py +0 -0
  60. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/compat/network.py +0 -0
  61. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/dbi/__init__.py +0 -0
  62. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/dbi/account.py +0 -0
  63. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/dbi/message.py +0 -0
  64. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/dbi/session.py +0 -0
  65. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/facebook.py +0 -0
  66. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/messenger.py +0 -0
  67. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/packer.py +0 -0
  68. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/processer.py +0 -0
  69. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/protocol/__init__.py +0 -0
  70. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/protocol/ans.py +0 -0
  71. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/protocol/block.py +0 -0
  72. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/protocol/handshake.py +0 -0
  73. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/protocol/login.py +0 -0
  74. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/protocol/mute.py +0 -0
  75. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/protocol/report.py +0 -0
  76. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/register.py +0 -0
  77. {dimples-1.0.0 → dimples-1.0.2}/dimples/common/session.py +0 -0
  78. {dimples-1.0.0 → dimples-1.0.2}/dimples/conn/protocol/mars.py +0 -0
  79. {dimples-1.0.0 → dimples-1.0.2}/dimples/conn/queue.py +0 -0
  80. {dimples-1.0.0 → dimples-1.0.2}/dimples/conn/seeker.py +0 -0
  81. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/__init__.py +0 -0
  82. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/account.py +0 -0
  83. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/dos/__init__.py +0 -0
  84. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/dos/document.py +0 -0
  85. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/dos/group.py +0 -0
  86. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/dos/group_history.py +0 -0
  87. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/dos/group_keys.py +0 -0
  88. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/dos/login.py +0 -0
  89. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/dos/meta.py +0 -0
  90. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/dos/private.py +0 -0
  91. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/dos/station.py +0 -0
  92. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/dos/user.py +0 -0
  93. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/message.py +0 -0
  94. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/session.py +0 -0
  95. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/t_cipherkey.py +0 -0
  96. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/t_document.py +0 -0
  97. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/t_group.py +0 -0
  98. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/t_group_history.py +0 -0
  99. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/t_group_keys.py +0 -0
  100. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/t_login.py +0 -0
  101. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/t_message.py +0 -0
  102. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/t_meta.py +0 -0
  103. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/t_private.py +0 -0
  104. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/t_station.py +0 -0
  105. {dimples-1.0.0 → dimples-1.0.2}/dimples/database/t_user.py +0 -0
  106. {dimples-1.0.0 → dimples-1.0.2}/dimples/edge/__init__.py +0 -0
  107. {dimples-1.0.0 → dimples-1.0.2}/dimples/edge/start.py +0 -0
  108. {dimples-1.0.0 → dimples-1.0.2}/dimples/group/__init__.py +0 -0
  109. {dimples-1.0.0 → dimples-1.0.2}/dimples/group/admin.py +0 -0
  110. {dimples-1.0.0 → dimples-1.0.2}/dimples/group/builder.py +0 -0
  111. {dimples-1.0.0 → dimples-1.0.2}/dimples/group/delegate.py +0 -0
  112. {dimples-1.0.0 → dimples-1.0.2}/dimples/group/emitter.py +0 -0
  113. {dimples-1.0.0 → dimples-1.0.2}/dimples/group/helper.py +0 -0
  114. {dimples-1.0.0 → dimples-1.0.2}/dimples/group/manager.py +0 -0
  115. {dimples-1.0.0 → dimples-1.0.2}/dimples/group/packer.py +0 -0
  116. {dimples-1.0.0 → dimples-1.0.2}/dimples/register/__init__.py +0 -0
  117. {dimples-1.0.0 → dimples-1.0.2}/dimples/register/base.py +0 -0
  118. {dimples-1.0.0 → dimples-1.0.2}/dimples/register/ext.py +0 -0
  119. {dimples-1.0.0 → dimples-1.0.2}/dimples/register/shared.py +0 -0
  120. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/__init__.py +0 -0
  121. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/archivist.py +0 -0
  122. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/cpu/__init__.py +0 -0
  123. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/cpu/ans.py +0 -0
  124. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/cpu/document.py +0 -0
  125. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/cpu/handshake.py +0 -0
  126. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/cpu/login.py +0 -0
  127. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/cpu/report.py +0 -0
  128. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/dispatcher.py +0 -0
  129. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/messenger.py +0 -0
  130. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/packer.py +0 -0
  131. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/processor.py +0 -0
  132. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/push.py +0 -0
  133. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/session_center.py +0 -0
  134. {dimples-1.0.0 → dimples-1.0.2}/dimples/server/trace.py +0 -0
  135. {dimples-1.0.0 → dimples-1.0.2}/dimples/station/__init__.py +0 -0
  136. {dimples-1.0.0 → dimples-1.0.2}/dimples/station/handler.py +0 -0
  137. {dimples-1.0.0 → dimples-1.0.2}/dimples/station/start.py +0 -0
  138. {dimples-1.0.0 → dimples-1.0.2}/dimples/utils/config.py +0 -0
  139. {dimples-1.0.0 → dimples-1.0.2}/dimples/utils/log.py +0 -0
  140. {dimples-1.0.0 → dimples-1.0.2}/dimples.egg-info/dependency_links.txt +0 -0
  141. {dimples-1.0.0 → dimples-1.0.2}/dimples.egg-info/entry_points.txt +0 -0
  142. {dimples-1.0.0 → dimples-1.0.2}/dimples.egg-info/requires.txt +0 -0
  143. {dimples-1.0.0 → dimples-1.0.2}/dimples.egg-info/top_level.txt +0 -0
  144. {dimples-1.0.0 → dimples-1.0.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dimples
3
- Version: 1.0.0
3
+ Version: 1.0.2
4
4
  Summary: DIMP Library for Edges and Stations
5
5
  Home-page: https://github.com/dimchat/demo-py
6
6
  Author: Albert Moky
@@ -63,6 +63,7 @@ from .protocol import WebSocket, NetMsg, NetMsgHead, NetMsgSeq
63
63
  from .ws import WSArrival, WSDeparture, WSDocker
64
64
  from .mars import MarsStreamArrival, MarsStreamDeparture, MarsStreamDocker
65
65
  from .mtp import MTPStreamArrival, MTPStreamDeparture, MTPStreamDocker
66
+ from .flexible import FlexibleDocker
66
67
  from .gate import CommonGate, TCPServerGate, TCPClientGate, UDPServerGate, UDPClientGate
67
68
  # from .gatekeeper import GateKeeper
68
69
  from .queue import MessageWrapper, MessageQueue
@@ -107,6 +108,7 @@ __all__ = [
107
108
  'WSArrival', 'WSDeparture', 'WSDocker',
108
109
  'MarsStreamArrival', 'MarsStreamDeparture', 'MarsStreamDocker',
109
110
  'MTPStreamArrival', 'MTPStreamDeparture', 'MTPStreamDocker',
111
+ 'FlexibleDocker',
110
112
  'CommonGate', 'TCPServerGate', 'TCPClientGate', 'UDPServerGate', 'UDPClientGate',
111
113
  # 'GateKeeper',
112
114
  'MessageWrapper', 'MessageQueue',
@@ -0,0 +1,168 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Star Gate: Interfaces for network connection
4
+ #
5
+ # Written in 2024 by Moky <albert.moky@gmail.com>
6
+ #
7
+ # ==============================================================================
8
+ # MIT License
9
+ #
10
+ # Copyright (c) 2024 Albert Moky
11
+ #
12
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ # of this software and associated documentation files (the "Software"), to deal
14
+ # in the Software without restriction, including without limitation the rights
15
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ # copies of the Software, and to permit persons to whom the Software is
17
+ # furnished to do so, subject to the following conditions:
18
+ #
19
+ # The above copyright notice and this permission notice shall be included in all
20
+ # copies or substantial portions of the Software.
21
+ #
22
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ # SOFTWARE.
29
+ # ==============================================================================
30
+
31
+ from typing import Optional, Union, List
32
+
33
+ from startrek.types import SocketAddress
34
+ from startrek.fsm import Runner
35
+ from startrek import Connection
36
+ from startrek import Arrival, Departure
37
+ from startrek import StarDocker
38
+
39
+ from .protocol import DeparturePacker
40
+
41
+ from .ws import WSDocker
42
+ from .mtp import MTPStreamDocker, TransactionID, MTPHelper
43
+ from .mars import MarsStreamDocker, MarsHelper
44
+
45
+
46
+ class FlexibleDocker(StarDocker, DeparturePacker):
47
+
48
+ def __init__(self, remote: SocketAddress, local: Optional[SocketAddress]):
49
+ super().__init__(remote=remote, local=local)
50
+ self.__docker: Optional[StarDocker] = None
51
+
52
+ def _get_docker(self, data: bytes) -> Optional[StarDocker]:
53
+ docker = self.__docker
54
+ if docker is not None or len(data) == 0:
55
+ return docker
56
+ # check data for packer
57
+ if WSDocker.check(data=data):
58
+ docker = WSDocker(remote=self.remote_address, local=self.local_address)
59
+ elif MTPStreamDocker.check(data=data):
60
+ docker = MTPStreamDocker(remote=self.remote_address, local=self.local_address)
61
+ elif MarsStreamDocker.check(data=data):
62
+ docker = MarsStreamDocker(remote=self.remote_address, local=self.local_address)
63
+ else:
64
+ print('[FlexibleDocker] unsupported data format: %s' % data)
65
+ return None
66
+ # OK
67
+ docker.delegate = self.delegate
68
+ Runner.async_run(coroutine=docker.set_connection(conn=self.connection))
69
+ self.__docker = docker
70
+ return docker
71
+
72
+ # Override
73
+ async def set_connection(self, conn: Optional[Connection]):
74
+ await super().set_connection(conn=conn)
75
+ docker = self.__docker
76
+ if docker is not None:
77
+ await docker.set_connection(conn=conn)
78
+
79
+ # Override
80
+ async def send_ship(self, ship: Departure) -> bool:
81
+ docker = self.__docker
82
+ if docker is not None:
83
+ return await docker.send_ship(ship=ship)
84
+
85
+ # Override
86
+ async def process_received(self, data: bytes):
87
+ docker = self._get_docker(data=data)
88
+ if docker is not None:
89
+ return await docker.process_received(data=data)
90
+
91
+ # Override
92
+ def _get_arrivals(self, data: bytes) -> List[Arrival]:
93
+ raise AssertionError('should not happen')
94
+
95
+ # Override
96
+ async def _check_arrival(self, ship: Arrival) -> Optional[Arrival]:
97
+ raise AssertionError('should not happen')
98
+
99
+ # Override
100
+ async def _check_response(self, ship: Arrival) -> Optional[Departure]:
101
+ raise AssertionError('should not happen')
102
+
103
+ # Override
104
+ def _assemble_arrival(self, ship: Arrival) -> Optional[Arrival]:
105
+ raise AssertionError('should not happen')
106
+
107
+ # Override
108
+ def _next_departure(self, now: float) -> Optional[Departure]:
109
+ raise AssertionError('should not happen')
110
+
111
+ # Override
112
+ def purge(self, now: float = 0) -> int:
113
+ cnt = super().purge(now=now)
114
+ docker = self.__docker
115
+ if docker is not None:
116
+ cnt += docker.purge(now=now)
117
+ return cnt
118
+
119
+ # Override
120
+ async def close(self):
121
+ await self.set_connection(conn=None)
122
+ docker = self.__docker
123
+ if docker is not None:
124
+ self.__docker = None
125
+ await docker.close()
126
+
127
+ # Override
128
+ async def process(self) -> bool:
129
+ docker = self.__docker
130
+ if docker is not None:
131
+ return await docker.process()
132
+
133
+ # Override
134
+ async def send_data(self, payload: Union[bytes, bytearray]) -> bool:
135
+ docker = self.__docker
136
+ if docker is None:
137
+ # docker not ready
138
+ return False
139
+ elif isinstance(docker, WSDocker):
140
+ ship = docker.pack(payload=payload)
141
+ return await docker.send_ship(ship=ship)
142
+ elif isinstance(docker, MTPStreamDocker):
143
+ # sn = TransactionID.from_data(data=ship.sn)
144
+ sn = TransactionID.generate()
145
+ pack = MTPHelper.create_message(body=payload, sn=sn)
146
+ return await docker.send_package(pack=pack)
147
+ elif isinstance(docker, MarsStreamDocker):
148
+ mars = MarsHelper.create_push(payload=payload)
149
+ ship = MarsStreamDocker.create_departure(mars=mars)
150
+ return await docker.send_ship(ship=ship)
151
+ else:
152
+ # error
153
+ return await docker.send_data(payload=payload)
154
+
155
+ # Override
156
+ async def heartbeat(self):
157
+ docker = self.__docker
158
+ if docker is not None:
159
+ await docker.heartbeat()
160
+
161
+ # Override
162
+ def pack(self, payload: bytes, priority: int = 0) -> Optional[Departure]:
163
+ docker = self.__docker
164
+ if docker is None:
165
+ return None
166
+ else:
167
+ assert isinstance(docker, DeparturePacker), 'docker error: %s' % docker
168
+ return docker.pack(payload=payload, priority=priority)
@@ -45,6 +45,7 @@ from ..utils import Logging
45
45
  from .mtp import TransactionID, MTPStreamDocker, MTPHelper
46
46
  from .mars import MarsStreamArrival, MarsStreamDocker, MarsHelper
47
47
  from .ws import WSDocker
48
+ from .flexible import FlexibleDocker
48
49
 
49
50
 
50
51
  H = TypeVar('H')
@@ -112,7 +113,9 @@ class CommonGate(StarGate, Logging, Generic[H], ABC):
112
113
  async def send_response(self, payload: bytes, ship: Arrival,
113
114
  remote: SocketAddress, local: Optional[SocketAddress]) -> bool:
114
115
  worker = self._get_docker(remote=remote, local=local)
115
- if isinstance(worker, MTPStreamDocker):
116
+ if isinstance(worker, FlexibleDocker):
117
+ return await worker.send_data(payload=payload)
118
+ elif isinstance(worker, MTPStreamDocker):
116
119
  # sn = TransactionID.from_data(data=ship.sn)
117
120
  sn = TransactionID.generate()
118
121
  pack = MTPHelper.create_message(body=payload, sn=sn)
@@ -204,16 +207,11 @@ class TCPServerGate(CommonGate, Generic[H]):
204
207
  def _create_docker(self, parties: List[bytes],
205
208
  remote: SocketAddress, local: Optional[SocketAddress]) -> Docker:
206
209
  count = len(parties)
207
- if count == 0:
208
- # return MTPStreamDocker(remote=remote, local=local, gate=self)
209
- assert False, 'data empty'
210
- data = parties[0]
211
- for i in range(1, count):
212
- data = data + parties[i]
213
- if len(data) == 0:
214
- assert False, 'data empty'
210
+ data = b'' if count == 0 else parties[count - 1]
215
211
  # check data format before creating docker
216
- if MTPStreamDocker.check(data=data):
212
+ if len(data) == 0:
213
+ docker = FlexibleDocker(remote=remote, local=local)
214
+ elif MTPStreamDocker.check(data=data):
217
215
  docker = MTPStreamDocker(remote=remote, local=local)
218
216
  elif MarsStreamDocker.check(data=data):
219
217
  docker = MarsStreamDocker(remote=remote, local=local)
@@ -233,7 +231,7 @@ class UDPServerGate(CommonGate, Generic[H]):
233
231
  count = len(parties)
234
232
  if count == 0:
235
233
  # return MTPStreamDocker(remote=remote, local=local, gate=self)
236
- assert False, 'data empty'
234
+ assert False, 'data empty: %s -> %s' % (remote, local)
237
235
  data = parties[count - 1]
238
236
  # check data format before creating docker
239
237
  if MTPStreamDocker.check(data=data):
@@ -276,7 +276,7 @@ class GateKeeper(Runner, DockerDelegate, Logging):
276
276
  self.error(msg='gate error, failed to send data')
277
277
  return ok
278
278
 
279
- async def _docker_pack(self, payload: bytes, priority: int = 0) -> Departure:
279
+ async def _docker_pack(self, payload: bytes, priority: int = 0) -> Optional[Departure]:
280
280
  docker = await self.gate.fetch_docker([], remote=self.remote_address, local=None)
281
281
  assert isinstance(docker, DeparturePacker), 'departure packer error: %s' % docker
282
282
  return docker.pack(payload=payload, priority=priority)
@@ -292,7 +292,7 @@ class MarsStreamDocker(PlainDocker, DeparturePacker):
292
292
  pass
293
293
 
294
294
  # Override
295
- def pack(self, payload: bytes, priority: int = 0) -> Departure:
295
+ def pack(self, payload: bytes, priority: int = 0) -> Optional[Departure]:
296
296
  mars = MarsHelper.create_push(payload=payload)
297
297
  return self.create_departure(mars=mars, priority=priority)
298
298
 
@@ -197,7 +197,7 @@ class MTPStreamDocker(PackageDocker, DeparturePacker):
197
197
  return MTPHelper.respond_message(sn=sn, pages=pages, index=index, body=OK)
198
198
 
199
199
  # Override
200
- def pack(self, payload: bytes, priority: int = 0) -> Departure:
200
+ def pack(self, payload: bytes, priority: int = 0) -> Optional[Departure]:
201
201
  pkg = MTPHelper.create_message(body=payload)
202
202
  return self._create_departure(pack=pkg, priority=priority)
203
203
 
@@ -28,7 +28,8 @@
28
28
  # SOFTWARE.
29
29
  # ==============================================================================
30
30
 
31
- from abc import ABC
31
+ from abc import ABC, abstractmethod
32
+ from typing import Optional
32
33
 
33
34
  from startrek import Departure
34
35
 
@@ -38,7 +39,8 @@ from .mars import NetMsg, NetMsgHead, NetMsgSeq
38
39
 
39
40
  class DeparturePacker(ABC):
40
41
 
41
- def pack(self, payload: bytes, priority: int = 0) -> Departure:
42
+ @abstractmethod
43
+ def pack(self, payload: bytes, priority: int = 0) -> Optional[Departure]:
42
44
  raise NotImplemented
43
45
 
44
46
 
@@ -172,7 +172,7 @@ class WebSocket:
172
172
  mask = None
173
173
  # 4. get payload
174
174
  if stream_len < pos + msg_len:
175
- Log.info(msg='incomplete ws package for payload: %d' % stream_len)
175
+ Log.info(msg='incomplete ws package for payload: %d, msg len: %d' % (stream_len, msg_len))
176
176
  return None, stream
177
177
  payload = stream[pos:pos+msg_len]
178
178
  pos += msg_len
@@ -87,7 +87,8 @@ class BaseSession(GateKeeper, Session, ABC):
87
87
  # Override
88
88
  async def queue_message_package(self, msg: ReliableMessage, data: bytes, priority: int = 0) -> bool:
89
89
  ship = await self._docker_pack(payload=data, priority=priority)
90
- return self._queue_append(msg=msg, ship=ship)
90
+ if ship is not None:
91
+ return self._queue_append(msg=msg, ship=ship)
91
92
 
92
93
  #
93
94
  # Transmitter
@@ -217,7 +217,7 @@ class WSDocker(PlainDocker, DeparturePacker):
217
217
  pass
218
218
 
219
219
  # Override
220
- def pack(self, payload: bytes, priority: int = 0) -> Departure:
220
+ def pack(self, payload: bytes, priority: int = 0) -> Optional[Departure]:
221
221
  req_pack = WebSocket.pack(payload=payload)
222
222
  return WSDeparture(package=req_pack, payload=payload, priority=priority)
223
223
 
@@ -23,12 +23,12 @@
23
23
  # SOFTWARE.
24
24
  # ==============================================================================
25
25
 
26
- import os
27
26
  from typing import Optional, Union
28
27
 
29
28
  from ...utils import template_replace
30
29
  from ...utils import Log
31
- from ...utils import File, TextFile, JSONFile
30
+ from ...utils import Path
31
+ from ...utils import TextFile, JSONFile
32
32
 
33
33
 
34
34
  """
@@ -69,7 +69,7 @@ class Storage:
69
69
  return template
70
70
  else:
71
71
  # relative path
72
- return os.path.join(self._public, template)
72
+ return Path.join(self._public, template)
73
73
 
74
74
  def private_path(self, template: str):
75
75
  """ replace '{PRIVATE}' with private directory """
@@ -82,11 +82,7 @@ class Storage:
82
82
  return template
83
83
  else:
84
84
  # relative path
85
- return os.path.join(self._public, template)
86
-
87
- @classmethod
88
- def exists(cls, path: str) -> bool:
89
- return File(path=path).exists(path=path)
85
+ return Path.join(self._public, template)
90
86
 
91
87
  @classmethod
92
88
  def read_text(cls, path: str) -> Optional[str]:
@@ -123,13 +119,6 @@ class Storage:
123
119
  except Exception as error:
124
120
  Log.error(msg='Storage >\t%s' % error)
125
121
 
126
- @classmethod
127
- def remove(cls, path: str) -> bool:
128
- try:
129
- return File(path=path).remove()
130
- except Exception as error:
131
- Log.error(msg='Storage >\t%s' % error)
132
-
133
122
  #
134
123
  # Logging
135
124
  #
@@ -380,10 +380,15 @@ def create_messenger(facebook: ClientFacebook, database: MessageDBI,
380
380
  def create_terminal(messenger: OctopusMessenger) -> Terminal:
381
381
  terminal = Terminal(messenger=messenger)
382
382
  messenger.terminal = terminal
383
- Runner.async_run(coroutine=terminal.start())
383
+ thr = threading.Thread(target=_start_terminal, args=(terminal,))
384
+ thr.start()
384
385
  return terminal
385
386
 
386
387
 
388
+ def _start_terminal(terminal: Terminal):
389
+ Runner.sync_run(main=terminal.start())
390
+
391
+
387
392
  async def update_station(station: Station, database: SessionDBI):
388
393
  Log.info(msg='update station: %s' % station)
389
394
  # SP ID
@@ -31,10 +31,10 @@ from typing import Optional, Tuple
31
31
  from dimsdk import ID, Station
32
32
 
33
33
  from ..utils import Singleton, Config
34
+ from ..utils import Path
34
35
  from ..common import AccountDBI, MessageDBI, SessionDBI
35
36
  from ..common import ProviderInfo
36
37
  from ..database import AccountDatabase, MessageDatabase, SessionDatabase
37
- from ..database import Storage
38
38
  from ..client import ClientSession, ClientFacebook, ClientArchivist
39
39
 
40
40
 
@@ -85,7 +85,7 @@ def create_config(app_name: str, default_config: str) -> Config:
85
85
  # check config filepath
86
86
  if ini_file is None:
87
87
  ini_file = default_config
88
- if not Storage.exists(path=ini_file):
88
+ if not Path.exists(path=ini_file):
89
89
  show_help(cmd=cmd, app_name=app_name, default_config=default_config)
90
90
  print('')
91
91
  print('!!! config file not exists: %s' % ini_file)
@@ -37,8 +37,8 @@ path = os.path.dirname(path)
37
37
  sys.path.insert(0, path)
38
38
 
39
39
  from dimples.utils import Log, Config
40
+ from dimples.utils import Path
40
41
  from dimples.utils import Runner
41
- from dimples.database import Storage
42
42
 
43
43
  from dimples.register.shared import GlobalVariable
44
44
  from dimples.register.shared import create_database
@@ -93,7 +93,7 @@ async def main():
93
93
  # check config filepath
94
94
  if ini_file is None:
95
95
  ini_file = DEFAULT_CONFIG
96
- if not Storage.exists(path=ini_file):
96
+ if not Path.exists(path=ini_file):
97
97
  show_help()
98
98
  print('')
99
99
  print('!!! config file not exists: %s' % ini_file)
@@ -37,7 +37,6 @@
37
37
 
38
38
  import socket
39
39
  import traceback
40
- import weakref
41
40
  from typing import Optional, List, Tuple
42
41
 
43
42
  from dimsdk import ID, EntityType
@@ -45,7 +44,6 @@ from dimsdk import ReliableMessage
45
44
 
46
45
  from startrek import Docker, DockerStatus
47
46
  from startrek import Arrival, Departure
48
- from startrek.net.channel import is_closed
49
47
 
50
48
  from ..utils import Log, Runner
51
49
  from ..utils import hex_encode, random_bytes
@@ -85,7 +83,6 @@ class ServerSession(BaseSession):
85
83
 
86
84
  def __init__(self, remote: Tuple[str, int], sock: socket.socket, database: SessionDBI):
87
85
  super().__init__(remote=remote, sock=sock, database=database)
88
- self.__sock = weakref.ref(sock)
89
86
  self.__key = generate_session_key()
90
87
 
91
88
  @property
@@ -109,15 +106,6 @@ class ServerSession(BaseSession):
109
106
  Runner.async_run(coroutine=load_cached_messages(session=self))
110
107
  return True
111
108
 
112
- @property # Override
113
- def running(self) -> bool:
114
- if super().running:
115
- # gate = self.gate
116
- # conn = gate.get_channel(remote=self.remote_address, local=None)
117
- # return not (conn is None or conn.closed)
118
- sock = self.__sock()
119
- return not (sock is None or is_closed(sock=sock))
120
-
121
109
  # Override
122
110
  async def start(self):
123
111
  await super().start()
@@ -31,12 +31,12 @@ from typing import Optional, Tuple
31
31
  from dimsdk import ID
32
32
 
33
33
  from ..utils import Singleton, Config
34
+ from ..utils import Path
34
35
  from ..common import AddressNameServer, ANSFactory
35
36
  from ..common import CommonFacebook, CommonMessenger
36
37
  from ..common import AccountDBI, MessageDBI, SessionDBI
37
38
  from ..common import ProviderInfo
38
39
  from ..database import AccountDatabase, MessageDatabase, SessionDatabase
39
- from ..database import Storage
40
40
  from ..server import ServerArchivist
41
41
  from ..server import ServerSession
42
42
  from ..server import ServerMessenger
@@ -93,7 +93,7 @@ def create_config(app_name: str, default_config: str) -> Config:
93
93
  # check config filepath
94
94
  if ini_file is None:
95
95
  ini_file = default_config
96
- if not Storage.exists(path=ini_file):
96
+ if not Path.exists(path=ini_file):
97
97
  show_help(cmd=cmd, app_name=app_name, default_config=default_config)
98
98
  print('')
99
99
  print('!!! config file not exists: %s' % ini_file)
@@ -50,12 +50,12 @@ from dimsdk import DocumentHelper
50
50
 
51
51
  from dimplugins.crypto.aes import random_bytes
52
52
 
53
+ from startrek.fsm import Singleton
53
54
  from startrek.fsm import Runnable, Runner, Daemon, DaemonRunner
54
55
  from startrek.fsm import Delegate as StateDelegate
55
56
  from startrek.net.channel import get_remote_address, get_local_address
56
57
 
57
58
 
58
- from .singleton import Singleton
59
59
  from .log import Log, Logging
60
60
  from .dos import Path, File, TextFile, JSONFile
61
61
  from .cache import CachePool, CacheHolder, CacheManager
@@ -31,11 +31,10 @@
31
31
 
32
32
  from typing import TypeVar, Generic, Optional, Dict, Set, Tuple
33
33
 
34
+ from startrek.fsm import Singleton
34
35
  from startrek.fsm import Runnable, Runner, Daemon
35
36
  from dimsdk import DateTime
36
37
 
37
- from .singleton import Singleton
38
-
39
38
 
40
39
  K = TypeVar('K')
41
40
  V = TypeVar('V')