dimples 0.4.1__tar.gz → 0.4.3__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 (142) hide show
  1. {dimples-0.4.1 → dimples-0.4.3}/PKG-INFO +1 -1
  2. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/terminal.py +5 -0
  3. {dimples-0.4.1 → dimples-0.4.3}/dimples/conn/gate.py +7 -5
  4. {dimples-0.4.1 → dimples-0.4.3}/dimples/conn/gatekeeper.py +46 -15
  5. {dimples-0.4.1 → dimples-0.4.3}/dimples/edge/octopus.py +25 -4
  6. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/archivist.py +2 -0
  7. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/messenger.py +1 -0
  8. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/processor.py +56 -17
  9. {dimples-0.4.1 → dimples-0.4.3}/dimples.egg-info/PKG-INFO +1 -1
  10. {dimples-0.4.1 → dimples-0.4.3}/dimples.egg-info/requires.txt +3 -3
  11. {dimples-0.4.1 → dimples-0.4.3}/setup.py +4 -4
  12. {dimples-0.4.1 → dimples-0.4.3}/README.md +0 -0
  13. {dimples-0.4.1 → dimples-0.4.3}/dimples/__init__.py +0 -0
  14. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/__init__.py +0 -0
  15. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/archivist.py +0 -0
  16. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/checkpoint.py +0 -0
  17. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/cpu/__init__.py +0 -0
  18. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/cpu/commands.py +0 -0
  19. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/cpu/creator.py +0 -0
  20. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/cpu/group.py +0 -0
  21. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/cpu/grp_expel.py +0 -0
  22. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/cpu/grp_invite.py +0 -0
  23. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/cpu/grp_join.py +0 -0
  24. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/cpu/grp_query.py +0 -0
  25. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/cpu/grp_quit.py +0 -0
  26. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/cpu/grp_reset.py +0 -0
  27. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/cpu/grp_resign.py +0 -0
  28. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/cpu/handshake.py +0 -0
  29. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/facebook.py +0 -0
  30. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/messenger.py +0 -0
  31. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/network/__init__.py +0 -0
  32. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/network/session.py +0 -0
  33. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/network/state.py +0 -0
  34. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/network/transition.py +0 -0
  35. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/packer.py +0 -0
  36. {dimples-0.4.1 → dimples-0.4.3}/dimples/client/processor.py +0 -0
  37. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/__init__.py +0 -0
  38. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/anonymous.py +0 -0
  39. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/ans.py +0 -0
  40. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/archivist.py +0 -0
  41. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/compat/__init__.py +0 -0
  42. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/compat/btc.py +0 -0
  43. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/compat/compatible.py +0 -0
  44. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/compat/entity.py +0 -0
  45. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/compat/meta.py +0 -0
  46. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/compat/network.py +0 -0
  47. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/dbi/__init__.py +0 -0
  48. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/dbi/account.py +0 -0
  49. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/dbi/message.py +0 -0
  50. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/dbi/session.py +0 -0
  51. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/facebook.py +0 -0
  52. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/messenger.py +0 -0
  53. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/packer.py +0 -0
  54. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/protocol/__init__.py +0 -0
  55. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/protocol/ans.py +0 -0
  56. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/protocol/block.py +0 -0
  57. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/protocol/handshake.py +0 -0
  58. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/protocol/login.py +0 -0
  59. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/protocol/mute.py +0 -0
  60. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/protocol/report.py +0 -0
  61. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/register.py +0 -0
  62. {dimples-0.4.1 → dimples-0.4.3}/dimples/common/session.py +0 -0
  63. {dimples-0.4.1 → dimples-0.4.3}/dimples/conn/__init__.py +0 -0
  64. {dimples-0.4.1 → dimples-0.4.3}/dimples/conn/mars.py +0 -0
  65. {dimples-0.4.1 → dimples-0.4.3}/dimples/conn/mtp.py +0 -0
  66. {dimples-0.4.1 → dimples-0.4.3}/dimples/conn/protocol/__init__.py +0 -0
  67. {dimples-0.4.1 → dimples-0.4.3}/dimples/conn/protocol/mars.py +0 -0
  68. {dimples-0.4.1 → dimples-0.4.3}/dimples/conn/protocol/ws.py +0 -0
  69. {dimples-0.4.1 → dimples-0.4.3}/dimples/conn/queue.py +0 -0
  70. {dimples-0.4.1 → dimples-0.4.3}/dimples/conn/seeker.py +0 -0
  71. {dimples-0.4.1 → dimples-0.4.3}/dimples/conn/session.py +0 -0
  72. {dimples-0.4.1 → dimples-0.4.3}/dimples/conn/ws.py +0 -0
  73. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/__init__.py +0 -0
  74. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/account.py +0 -0
  75. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/dos/__init__.py +0 -0
  76. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/dos/base.py +0 -0
  77. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/dos/document.py +0 -0
  78. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/dos/group.py +0 -0
  79. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/dos/group_history.py +0 -0
  80. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/dos/group_keys.py +0 -0
  81. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/dos/login.py +0 -0
  82. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/dos/meta.py +0 -0
  83. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/dos/private.py +0 -0
  84. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/dos/station.py +0 -0
  85. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/dos/user.py +0 -0
  86. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/message.py +0 -0
  87. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/session.py +0 -0
  88. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/t_cipherkey.py +0 -0
  89. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/t_document.py +0 -0
  90. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/t_group.py +0 -0
  91. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/t_group_history.py +0 -0
  92. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/t_group_keys.py +0 -0
  93. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/t_login.py +0 -0
  94. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/t_message.py +0 -0
  95. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/t_meta.py +0 -0
  96. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/t_private.py +0 -0
  97. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/t_station.py +0 -0
  98. {dimples-0.4.1 → dimples-0.4.3}/dimples/database/t_user.py +0 -0
  99. {dimples-0.4.1 → dimples-0.4.3}/dimples/edge/__init__.py +0 -0
  100. {dimples-0.4.1 → dimples-0.4.3}/dimples/edge/shared.py +0 -0
  101. {dimples-0.4.1 → dimples-0.4.3}/dimples/edge/start.py +0 -0
  102. {dimples-0.4.1 → dimples-0.4.3}/dimples/group/__init__.py +0 -0
  103. {dimples-0.4.1 → dimples-0.4.3}/dimples/group/admin.py +0 -0
  104. {dimples-0.4.1 → dimples-0.4.3}/dimples/group/builder.py +0 -0
  105. {dimples-0.4.1 → dimples-0.4.3}/dimples/group/delegate.py +0 -0
  106. {dimples-0.4.1 → dimples-0.4.3}/dimples/group/emitter.py +0 -0
  107. {dimples-0.4.1 → dimples-0.4.3}/dimples/group/helper.py +0 -0
  108. {dimples-0.4.1 → dimples-0.4.3}/dimples/group/manager.py +0 -0
  109. {dimples-0.4.1 → dimples-0.4.3}/dimples/group/packer.py +0 -0
  110. {dimples-0.4.1 → dimples-0.4.3}/dimples/register/__init__.py +0 -0
  111. {dimples-0.4.1 → dimples-0.4.3}/dimples/register/base.py +0 -0
  112. {dimples-0.4.1 → dimples-0.4.3}/dimples/register/ext.py +0 -0
  113. {dimples-0.4.1 → dimples-0.4.3}/dimples/register/run.py +0 -0
  114. {dimples-0.4.1 → dimples-0.4.3}/dimples/register/shared.py +0 -0
  115. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/__init__.py +0 -0
  116. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/cpu/__init__.py +0 -0
  117. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/cpu/ans.py +0 -0
  118. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/cpu/document.py +0 -0
  119. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/cpu/handshake.py +0 -0
  120. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/cpu/login.py +0 -0
  121. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/cpu/report.py +0 -0
  122. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/dispatcher.py +0 -0
  123. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/packer.py +0 -0
  124. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/push.py +0 -0
  125. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/session.py +0 -0
  126. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/session_center.py +0 -0
  127. {dimples-0.4.1 → dimples-0.4.3}/dimples/server/trace.py +0 -0
  128. {dimples-0.4.1 → dimples-0.4.3}/dimples/station/__init__.py +0 -0
  129. {dimples-0.4.1 → dimples-0.4.3}/dimples/station/handler.py +0 -0
  130. {dimples-0.4.1 → dimples-0.4.3}/dimples/station/shared.py +0 -0
  131. {dimples-0.4.1 → dimples-0.4.3}/dimples/station/start.py +0 -0
  132. {dimples-0.4.1 → dimples-0.4.3}/dimples/utils/__init__.py +0 -0
  133. {dimples-0.4.1 → dimples-0.4.3}/dimples/utils/cache.py +0 -0
  134. {dimples-0.4.1 → dimples-0.4.3}/dimples/utils/config.py +0 -0
  135. {dimples-0.4.1 → dimples-0.4.3}/dimples/utils/dos.py +0 -0
  136. {dimples-0.4.1 → dimples-0.4.3}/dimples/utils/log.py +0 -0
  137. {dimples-0.4.1 → dimples-0.4.3}/dimples/utils/singleton.py +0 -0
  138. {dimples-0.4.1 → dimples-0.4.3}/dimples.egg-info/SOURCES.txt +0 -0
  139. {dimples-0.4.1 → dimples-0.4.3}/dimples.egg-info/dependency_links.txt +0 -0
  140. {dimples-0.4.1 → dimples-0.4.3}/dimples.egg-info/entry_points.txt +0 -0
  141. {dimples-0.4.1 → dimples-0.4.3}/dimples.egg-info/top_level.txt +0 -0
  142. {dimples-0.4.1 → dimples-0.4.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dimples
3
- Version: 0.4.1
3
+ Version: 0.4.3
4
4
  Summary: DIMP Library for Edges and Stations
5
5
  Home-page: https://github.com/dimchat/demo-py
6
6
  Author: Albert Moky
@@ -81,6 +81,11 @@ class Terminal(Runner, StateDelegate, Logging):
81
81
  now = time.time()
82
82
  return now < (self.__last_time + 600)
83
83
 
84
+ # @property # Override
85
+ # def running(self) -> bool:
86
+ # if super().running:
87
+ # return self.is_alive
88
+
84
89
  def start(self):
85
90
  thread = threading.Thread(target=self.run, daemon=True)
86
91
  thread.start()
@@ -72,12 +72,14 @@ class BaseGate(StarGate, Generic[H], ABC):
72
72
  return super()._get_docker(remote=remote, local=None)
73
73
 
74
74
  # Override
75
- def _set_docker(self, remote: SocketAddress, local: Optional[SocketAddress], docker: Docker):
76
- super()._set_docker(remote=remote, local=None, docker=docker)
75
+ def _set_docker(self, docker: Docker,
76
+ remote: SocketAddress, local: Optional[SocketAddress]):
77
+ super()._set_docker(docker=docker, remote=remote, local=None)
77
78
 
78
79
  # Override
79
- def _remove_docker(self, remote: SocketAddress, local: Optional[SocketAddress], docker: Optional[Docker]):
80
- super()._remove_docker(remote=remote, local=None, docker=docker)
80
+ def _remove_docker(self, docker: Optional[Docker],
81
+ remote: SocketAddress, local: Optional[SocketAddress]) -> Optional[Docker]:
82
+ return super()._remove_docker(docker=docker, remote=remote, local=None)
81
83
 
82
84
  # Override
83
85
  def _heartbeat(self, connection: Connection):
@@ -194,7 +196,7 @@ class CommonGate(BaseGate, Logging, Generic[H], ABC):
194
196
  if docker is None:
195
197
  assert False, 'failed to create docker: %s, %s' % (remote, local)
196
198
  else:
197
- self._set_docker(remote=remote, local=local, docker=docker)
199
+ self._set_docker(docker=docker, remote=docker.remote_address, local=docker.local_address)
198
200
  return docker
199
201
 
200
202
 
@@ -35,7 +35,8 @@ from typing import Optional, Tuple
35
35
 
36
36
  from dimsdk import ReliableMessage
37
37
 
38
- from startrek import Hub
38
+ from startrek.types import SocketAddress
39
+ from startrek import Channel, Hub
39
40
  from startrek import BaseChannel
40
41
  from startrek import Connection, ConnectionDelegate, BaseConnection
41
42
  from startrek import Arrival, Departure
@@ -57,39 +58,69 @@ from .queue import MessageQueue, MessageWrapper
57
58
  class StreamServerHub(ServerHub):
58
59
 
59
60
  def put_channel(self, channel: StreamChannel):
60
- self._set_channel(remote=channel.remote_address, local=channel.local_address, channel=channel)
61
+ self._set_channel(channel=channel, remote=channel.remote_address, local=None)
61
62
 
62
63
  # Override
63
- def _get_connection(self, remote: Tuple[str, int], local: Optional[Tuple[str, int]]) -> Optional[Connection]:
64
+ def _get_channel(self, remote: Optional[SocketAddress], local: Optional[SocketAddress]) -> Optional[Channel]:
65
+ return super()._get_channel(remote=remote, local=None)
66
+
67
+ # Override
68
+ def _set_channel(self, channel: Channel,
69
+ remote: Optional[SocketAddress], local: Optional[SocketAddress]):
70
+ super()._set_channel(channel=channel, remote=remote, local=None)
71
+
72
+ # Override
73
+ def _remove_channel(self, channel: Optional[Channel],
74
+ remote: Optional[SocketAddress], local: Optional[SocketAddress]) -> Optional[Channel]:
75
+ return super()._remove_channel(channel=channel, remote=remote, local=None)
76
+
77
+ # Override
78
+ def _get_connection(self, remote: SocketAddress, local: Optional[SocketAddress]) -> Optional[Connection]:
64
79
  return super()._get_connection(remote=remote, local=None)
65
80
 
66
81
  # Override
67
- def _set_connection(self, remote: Tuple[str, int], local: Optional[Tuple[str, int]], connection: Connection):
68
- super()._set_connection(remote=remote, local=None, connection=connection)
82
+ def _set_connection(self, connection: Connection,
83
+ remote: SocketAddress, local: Optional[SocketAddress]):
84
+ super()._set_connection(connection=connection, remote=remote, local=None)
69
85
 
70
86
  # Override
71
- def _remove_connection(self, remote: Tuple[str, int], local: Optional[Tuple[str, int]],
72
- connection: Optional[Connection]):
73
- super()._remove_connection(remote=remote, local=None, connection=connection)
87
+ def _remove_connection(self, connection: Optional[Connection],
88
+ remote: SocketAddress, local: Optional[SocketAddress]) -> Optional[Connection]:
89
+ return super()._remove_connection(connection=connection, remote=remote, local=None)
74
90
 
75
91
 
76
92
  class StreamClientHub(ClientHub):
77
93
 
78
94
  def put_channel(self, channel: StreamChannel):
79
- self._set_channel(remote=channel.remote_address, local=channel.local_address, channel=channel)
95
+ self._set_channel(channel=channel, remote=channel.remote_address, local=None)
96
+
97
+ # Override
98
+ def _get_channel(self, remote: Optional[SocketAddress], local: Optional[SocketAddress]) -> Optional[Channel]:
99
+ return super()._get_channel(remote=remote, local=None)
100
+
101
+ # Override
102
+ def _set_channel(self, channel: Channel,
103
+ remote: Optional[SocketAddress], local: Optional[SocketAddress]):
104
+ super()._set_channel(channel=channel, remote=remote, local=None)
105
+
106
+ # Override
107
+ def _remove_channel(self, channel: Optional[Channel],
108
+ remote: Optional[SocketAddress], local: Optional[SocketAddress]) -> Optional[Channel]:
109
+ return super()._remove_channel(channel=channel, remote=remote, local=None)
80
110
 
81
111
  # Override
82
- def _get_connection(self, remote: Tuple[str, int], local: Optional[Tuple[str, int]]) -> Optional[Connection]:
112
+ def _get_connection(self, remote: SocketAddress, local: Optional[SocketAddress]) -> Optional[Connection]:
83
113
  return super()._get_connection(remote=remote, local=None)
84
114
 
85
115
  # Override
86
- def _set_connection(self, remote: Tuple[str, int], local: Optional[Tuple[str, int]], connection: Connection):
87
- super()._set_connection(remote=remote, local=None, connection=connection)
116
+ def _set_connection(self, connection: Connection,
117
+ remote: SocketAddress, local: Optional[SocketAddress]):
118
+ super()._set_connection(connection=connection, remote=remote, local=None)
88
119
 
89
120
  # Override
90
- def _remove_connection(self, remote: Tuple[str, int], local: Optional[Tuple[str, int]],
91
- connection: Optional[Connection]):
92
- super()._remove_connection(remote=remote, local=None, connection=connection)
121
+ def _remove_connection(self, connection: Optional[Connection],
122
+ remote: SocketAddress, local: Optional[SocketAddress]) -> Optional[Connection]:
123
+ return super()._remove_connection(connection=connection, remote=remote, local=None)
93
124
 
94
125
 
95
126
  def reset_send_buffer_size(conn: Connection) -> bool:
@@ -112,9 +112,21 @@ class Octopus(Runner, Logging):
112
112
  self.__outer_map[identifier] = terminal
113
113
 
114
114
  def connect(self, host: str, port: int = 9394):
115
- terminal = self.create_outer_terminal(host=host, port=port)
115
+ # create a new terminal for remote host:port
116
116
  with self.__outer_lock:
117
+ # check exist terminals
118
+ outers = set(self.__outers)
119
+ for out in outers:
120
+ # check station
121
+ station = out.session.station
122
+ if port == station.port and host == station.host:
123
+ self.warning(msg='connection already exists: (%s, %d)' % (host, port))
124
+ # self.__outers.discard(out)
125
+ return None
126
+ # create new terminal
127
+ terminal = self.create_outer_terminal(host=host, port=port)
117
128
  self.__outers.add(terminal)
129
+ return terminal
118
130
 
119
131
  def start(self):
120
132
  thread = threading.Thread(target=self.run)
@@ -139,24 +151,33 @@ class Octopus(Runner, Logging):
139
151
  assert len(providers) > 0, 'service provider not found'
140
152
  gsp = providers[0].identifier
141
153
  neighbors = db.all_stations(provider=gsp)
154
+ if neighbors is not None:
155
+ neighbors = neighbors.copy()
142
156
  # get all outer terminals
143
157
  with self.__outer_lock:
144
158
  outers = set(self.__outers)
159
+ self.debug(msg='checking %d client(s) with %d neighbor(s)' % (len(outers), len(neighbors)))
145
160
  for out in outers:
146
161
  # check station
147
162
  station = out.session.station
163
+ sid = station.identifier
148
164
  host = station.host
149
165
  port = station.port
166
+ # reduce neighbors
150
167
  for item in neighbors:
151
168
  if item.port == port and item.host == host:
152
169
  # got
153
170
  neighbors.remove(item)
154
171
  break
172
+ # check outer client
155
173
  if out.is_alive:
156
- # outer terminal alive, ignore it
174
+ # skip running client
157
175
  continue
176
+ else:
177
+ self.warning(msg='stop timeout client: %s (%s:%d)' % (sid, host, port))
178
+ out.stop()
158
179
  # remove dead terminal
159
- sid = station.identifier
180
+ self.debug(msg='removing inactive client: %s (%s:%d)' % (sid, host, port))
160
181
  with self.__outer_lock:
161
182
  self.__outers.discard(out)
162
183
  if sid is not None:
@@ -165,7 +186,7 @@ class Octopus(Runner, Logging):
165
186
  for item in neighbors:
166
187
  host = item.host
167
188
  port = item.port
168
- self.info(msg='connecting neighbor station (%s:%d)' % (host, port))
189
+ self.debug(msg='connecting neighbor station (%s:%d), client count: %d' % (host, port, len(self.__outers)))
169
190
  self.connect(host=host, port=port)
170
191
  return False
171
192
 
@@ -138,6 +138,8 @@ class ServerArchivist(CommonArchivist, ABC):
138
138
  # dispatch
139
139
  dispatcher = Dispatcher()
140
140
  neighbors = self.all_neighbors
141
+ # avoid the new recipients redirect it to same targets
142
+ r_msg['recipients'] = ID.revert(neighbors)
141
143
  for receiver in neighbors:
142
144
  if receiver == sid:
143
145
  self.debug(msg='skip cycled message: %s -> %s' % (sid, receiver))
@@ -58,6 +58,7 @@ class ServerMessenger(CommonMessenger):
58
58
  assert isinstance(packer, CommonMessagePacker), 'message packer error: %s' % packer
59
59
  messages = packer.resume_reliable_messages()
60
60
  for msg in messages:
61
+ msg.pop('error', None)
61
62
  self.info(msg='processing suspended message: %s -> %s' % (msg.sender, msg.receiver))
62
63
  try:
63
64
  responses = self.process_reliable_message(msg=msg)
@@ -132,14 +132,14 @@ class ServerMessageProcessor(MessageProcessor, Logging):
132
132
  # we can trust it too;
133
133
  if receiver == Station.EVERY or receiver == EVERYONE:
134
134
  # broadcast message (to neighbor stations)
135
- # e.g.: 'stations@everywhere'
135
+ # e.g.: 'stations@everywhere', 'everyone@everywhere'
136
136
  self._broadcast_message(msg=msg, station=station)
137
137
  # if receiver == 'everyone@everywhere':
138
138
  # broadcast message to all destinations,
139
139
  # current station is it's receiver too.
140
140
  elif receiver.is_broadcast:
141
141
  # broadcast message (to station bots)
142
- # e.g.: 'archivist@anywhere', 'announcer@anywhere', 'monitor@anywhere'
142
+ # e.g.: 'archivist@anywhere', 'announcer@anywhere', 'monitor@anywhere', ...
143
143
  self._broadcast_message(msg=msg, station=station)
144
144
  return []
145
145
  elif receiver.is_group:
@@ -186,24 +186,63 @@ class ServerMessageProcessor(MessageProcessor, Logging):
186
186
  return [r_msg]
187
187
 
188
188
  def _broadcast_message(self, msg: ReliableMessage, station: ID):
189
- """ broadcast message to neighbor stations """
190
- archivist = self.facebook.archivist
191
- assert isinstance(archivist, ServerArchivist)
192
- neighbors = archivist.all_neighbors
189
+ """ broadcast message to actual recipients """
193
190
  sender = msg.sender
194
- self.info(msg='broadcast message %s -> %s (%s): from station %s to %s'
195
- % (sender, msg.receiver, msg.group, station, neighbors))
191
+ receiver = msg.receiver
192
+ assert receiver.is_broadcast, 'broadcast message error: %s -> %s' % (sender, receiver)
193
+ self.info(msg='broadcast message %s -> %s (%s)' % (sender, receiver, msg.group))
194
+ if receiver.is_user:
195
+ # broadcast message to station bots
196
+ # e.g.: 'archivist@anywhere', 'announcer@anywhere', 'monitor@anywhere', ...
197
+ name = receiver.name
198
+ assert name is not None and name != 'station' and name != 'anyone', 'receiver error: %s' % receiver
199
+ bot = AnsCommandProcessor.ans_id(name=name)
200
+ if bot is None:
201
+ self.warning(msg='failed to get receiver: %s' % receiver)
202
+ return False
203
+ candidates = set()
204
+ candidates.add(bot)
205
+ self.info(msg='forward to station bot: %s -> %s' % (name, bot))
206
+ elif receiver == Station.EVERY or receiver == EVERYONE:
207
+ # broadcast message to neighbor stations
208
+ # e.g.: 'stations@everywhere', 'everyone@everywhere'
209
+ archivist = self.facebook.archivist
210
+ assert isinstance(archivist, ServerArchivist)
211
+ candidates = archivist.all_neighbors
212
+ if len(candidates) == 0:
213
+ self.warning(msg='failed to get neighbors: %s' % receiver)
214
+ return False
215
+ self.info(msg='forward to neighbor stations: %s -> %s' % (receiver, candidates))
216
+ else:
217
+ self.warning(msg='unknown receiver: %s' % receiver)
218
+ return False
219
+ # check recipients
220
+ new_recipients = candidates.copy()
221
+ old_recipients = msg.get('recipients')
222
+ if old_recipients is None:
223
+ all_recipients = []
224
+ else:
225
+ all_recipients = ID.convert(old_recipients)
226
+ # check duplicated
227
+ self.info(msg='discard recipients: %s, new recipients: %s' % (old_recipients, new_recipients))
228
+ for item in all_recipients:
229
+ new_recipients.discard(item)
230
+ if len(new_recipients) == 0:
231
+ self.info(msg='new recipients empty: %s => %s' % (receiver, candidates))
232
+ return False
233
+ self.info(msg='append new recipients: %s, %s => %s' % (receiver, new_recipients, all_recipients))
234
+ for item in new_recipients:
235
+ all_recipients.append(item)
236
+ # avoid the new recipients redirect it to same targets
237
+ msg['recipients'] = ID.revert(all_recipients)
196
238
  # dispatch
197
239
  dispatcher = Dispatcher()
198
- for receiver in neighbors:
199
- if receiver == sender:
200
- self.debug(msg='skip cycled message: %s -> %s' % (sender, receiver))
201
- continue
202
- elif receiver == station:
203
- self.debug(msg='skip current station: %s -> %s' % (sender, receiver))
204
- continue
205
- dispatcher.deliver_message(msg=msg, receiver=receiver)
206
- return len(neighbors) > 0
240
+ for target in new_recipients:
241
+ if target == sender or target == station:
242
+ self.info(msg='skip cycled message: %s -> %s, %s' % (sender, receiver, target))
243
+ else:
244
+ dispatcher.deliver_message(msg=msg, receiver=target)
245
+ return True
207
246
 
208
247
  def _split_group_message(self, msg: ReliableMessage, station: ID):
209
248
  """ redirect group message to assistant """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dimples
3
- Version: 0.4.1
3
+ Version: 0.4.3
4
4
  Summary: DIMP Library for Edges and Stations
5
5
  Home-page: https://github.com/dimchat/demo-py
6
6
  Author: Albert Moky
@@ -3,6 +3,6 @@ dimsdk>=1.0.3
3
3
  dimp>=1.0.3
4
4
  dkd>=1.0.2
5
5
  mkm>=1.0.2
6
- startrek>=1.0.0
7
- tcp>=1.0.0
8
- udp>=1.0.0
6
+ startrek>=1.0.3
7
+ tcp>=1.0.3
8
+ udp>=1.0.3
@@ -14,7 +14,7 @@ import io
14
14
 
15
15
  from setuptools import setup, find_packages
16
16
 
17
- __version__ = '0.4.1'
17
+ __version__ = '0.4.3'
18
18
  __author__ = 'Albert Moky'
19
19
  __contact__ = 'albert.moky@gmail.com'
20
20
 
@@ -58,8 +58,8 @@ setup(
58
58
  'dkd>=1.0.2',
59
59
  'mkm>=1.0.2',
60
60
 
61
- 'startrek>=1.0.0',
62
- 'tcp>=1.0.0',
63
- 'udp>=1.0.0',
61
+ 'startrek>=1.0.3',
62
+ 'tcp>=1.0.3',
63
+ 'udp>=1.0.3',
64
64
  ]
65
65
  )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes