dimples 0.5.5__tar.gz → 0.5.7__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.
- {dimples-0.5.5 → dimples-0.5.7}/PKG-INFO +1 -1
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/network/state.py +4 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/dbi/session.py +4 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/session.py +2 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/conn/protocol/mars.py +4 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/conn/session.py +10 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/edge/octopus.py +48 -19
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/archivist.py +7 -3
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/dispatcher.py +92 -16
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/processor.py +9 -41
- {dimples-0.5.5 → dimples-0.5.7}/dimples/utils/config.py +2 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples.egg-info/PKG-INFO +1 -1
- {dimples-0.5.5 → dimples-0.5.7}/setup.py +1 -1
- {dimples-0.5.5 → dimples-0.5.7}/README.md +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/archivist.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/checkpoint.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/cpu/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/cpu/commands.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/cpu/creator.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/cpu/group.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/cpu/grp_expel.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/cpu/grp_invite.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/cpu/grp_join.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/cpu/grp_query.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/cpu/grp_quit.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/cpu/grp_reset.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/cpu/grp_resign.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/cpu/handshake.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/facebook.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/messenger.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/network/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/network/session.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/network/transition.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/packer.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/processor.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/client/terminal.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/anonymous.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/ans.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/archivist.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/compat/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/compat/btc.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/compat/compatible.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/compat/entity.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/compat/meta.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/compat/network.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/dbi/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/dbi/account.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/dbi/message.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/facebook.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/messenger.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/packer.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/processer.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/protocol/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/protocol/ans.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/protocol/block.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/protocol/handshake.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/protocol/login.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/protocol/mute.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/protocol/report.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/common/register.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/conn/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/conn/gate.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/conn/gatekeeper.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/conn/mars.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/conn/mtp.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/conn/protocol/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/conn/protocol/ws.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/conn/queue.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/conn/seeker.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/conn/ws.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/account.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/dos/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/dos/base.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/dos/document.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/dos/group.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/dos/group_history.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/dos/group_keys.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/dos/login.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/dos/meta.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/dos/private.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/dos/station.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/dos/user.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/message.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/session.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/t_cipherkey.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/t_document.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/t_group.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/t_group_history.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/t_group_keys.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/t_login.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/t_message.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/t_meta.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/t_private.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/t_station.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/database/t_user.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/edge/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/edge/shared.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/edge/start.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/group/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/group/admin.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/group/builder.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/group/delegate.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/group/emitter.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/group/helper.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/group/manager.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/group/packer.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/register/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/register/base.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/register/ext.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/register/run.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/register/shared.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/cpu/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/cpu/ans.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/cpu/document.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/cpu/handshake.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/cpu/login.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/cpu/report.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/messenger.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/packer.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/push.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/session.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/session_center.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/server/trace.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/station/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/station/handler.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/station/shared.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/station/start.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/utils/__init__.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/utils/cache.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/utils/dos.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/utils/log.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples/utils/singleton.py +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples.egg-info/SOURCES.txt +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples.egg-info/dependency_links.txt +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples.egg-info/entry_points.txt +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples.egg-info/requires.txt +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/dimples.egg-info/top_level.txt +0 -0
- {dimples-0.5.5 → dimples-0.5.7}/setup.cfg +0 -0
|
@@ -136,12 +136,15 @@ class SessionState(BaseState[StateMachine, StateTransition]):
|
|
|
136
136
|
def enter_time(self) -> float:
|
|
137
137
|
return self.__time
|
|
138
138
|
|
|
139
|
+
# Override
|
|
139
140
|
def __str__(self) -> str:
|
|
140
141
|
return self.__name
|
|
141
142
|
|
|
143
|
+
# Override
|
|
142
144
|
def __repr__(self) -> str:
|
|
143
145
|
return self.__name
|
|
144
146
|
|
|
147
|
+
# Override
|
|
145
148
|
def __eq__(self, other) -> bool:
|
|
146
149
|
if isinstance(other, SessionState):
|
|
147
150
|
if self is other:
|
|
@@ -156,6 +159,7 @@ class SessionState(BaseState[StateMachine, StateTransition]):
|
|
|
156
159
|
else:
|
|
157
160
|
return False
|
|
158
161
|
|
|
162
|
+
# Override
|
|
159
163
|
def __ne__(self, other) -> bool:
|
|
160
164
|
if isinstance(other, SessionState):
|
|
161
165
|
if self is other:
|
|
@@ -63,10 +63,12 @@ class ProviderInfo:
|
|
|
63
63
|
self.identifier = identifier
|
|
64
64
|
self.chosen = chosen
|
|
65
65
|
|
|
66
|
+
# Override
|
|
66
67
|
def __str__(self) -> str:
|
|
67
68
|
clazz = self.__class__.__name__
|
|
68
69
|
return '<%s ID="%s" chosen=%d />' % (clazz, self.identifier, self.chosen)
|
|
69
70
|
|
|
71
|
+
# Override
|
|
70
72
|
def __repr__(self) -> str:
|
|
71
73
|
clazz = self.__class__.__name__
|
|
72
74
|
return '<%s ID="%s" chosen=%d />' % (clazz, self.identifier, self.chosen)
|
|
@@ -94,11 +96,13 @@ class StationInfo:
|
|
|
94
96
|
self.provider = provider
|
|
95
97
|
self.chosen = chosen
|
|
96
98
|
|
|
99
|
+
# Override
|
|
97
100
|
def __str__(self) -> str:
|
|
98
101
|
clazz = self.__class__.__name__
|
|
99
102
|
return '<%s host="%s" port=%d ID="%s" SP="%s" chosen=%d />' % (clazz, self.host, self.port, self.identifier,
|
|
100
103
|
self.provider, self.chosen)
|
|
101
104
|
|
|
105
|
+
# Override
|
|
102
106
|
def __repr__(self) -> str:
|
|
103
107
|
clazz = self.__class__.__name__
|
|
104
108
|
return '<%s host="%s" port=%d ID="%s" SP="%s" chosen=%d />' % (clazz, self.host, self.port, self.identifier,
|
|
@@ -114,10 +114,12 @@ class Session(Transmitter, ABC):
|
|
|
114
114
|
""" Update active flag and return True on changed """
|
|
115
115
|
raise NotImplemented
|
|
116
116
|
|
|
117
|
+
# Override
|
|
117
118
|
def __str__(self) -> str:
|
|
118
119
|
clazz = self.__class__.__name__
|
|
119
120
|
return '<%s:%s %s|%s active=%s />' % (clazz, self.key, self.remote_address, self.identifier, self.active)
|
|
120
121
|
|
|
122
|
+
# Override
|
|
121
123
|
def __repr__(self) -> str:
|
|
122
124
|
clazz = self.__class__.__name__
|
|
123
125
|
return '<%s:%s %s|%s active=%s />' % (clazz, self.key, self.remote_address, self.identifier, self.active)
|
|
@@ -94,10 +94,12 @@ class NetMsgHead:
|
|
|
94
94
|
self.__options = options
|
|
95
95
|
self.__body_length = body_len
|
|
96
96
|
|
|
97
|
+
# Override
|
|
97
98
|
def __str__(self) -> str:
|
|
98
99
|
cname = self.__class__.__name__
|
|
99
100
|
return '<%s: %d| cmd=%d, seq=%d, body_len=%d />' % (cname, self.version, self.cmd, self.seq, self.body_length)
|
|
100
101
|
|
|
102
|
+
# Override
|
|
101
103
|
def __repr__(self) -> str:
|
|
102
104
|
cname = self.__class__.__name__
|
|
103
105
|
return '<%s: %d| cmd=%d, seq=%d, body_len=%d />' % (cname, self.version, self.cmd, self.seq, self.body_length)
|
|
@@ -198,11 +200,13 @@ class NetMsg:
|
|
|
198
200
|
self.__head = head
|
|
199
201
|
self.__body = body
|
|
200
202
|
|
|
203
|
+
# Override
|
|
201
204
|
def __str__(self) -> str:
|
|
202
205
|
mod = self.__module__
|
|
203
206
|
cname = self.__class__.__name__
|
|
204
207
|
return '<%s body_len=%d>%s</%s module="%s">' % (cname, self.body_length, self.head, cname, mod)
|
|
205
208
|
|
|
209
|
+
# Override
|
|
206
210
|
def __repr__(self) -> str:
|
|
207
211
|
mod = self.__module__
|
|
208
212
|
cname = self.__class__.__name__
|
|
@@ -50,6 +50,16 @@ class BaseSession(GateKeeper, Session, ABC):
|
|
|
50
50
|
self.__identifier: Optional[ID] = None
|
|
51
51
|
self.__messenger: Optional[weakref.ReferenceType] = None
|
|
52
52
|
|
|
53
|
+
# Override
|
|
54
|
+
def __str__(self) -> str:
|
|
55
|
+
cname = self.__class__.__name__
|
|
56
|
+
return '<%s id="%s" remote="%s" key="%s" />' % (cname, self.identifier, self.remote_address, self.key)
|
|
57
|
+
|
|
58
|
+
# Override
|
|
59
|
+
def __repr__(self):
|
|
60
|
+
cname = self.__class__.__name__
|
|
61
|
+
return '<%s id="%s" remote="%s" key="%s" />' % (cname, self.identifier, self.remote_address, self.key)
|
|
62
|
+
|
|
53
63
|
@property # Override
|
|
54
64
|
def database(self) -> SessionDBI:
|
|
55
65
|
return self.__database
|
|
@@ -190,35 +190,64 @@ class Octopus(Runner, Logging):
|
|
|
190
190
|
|
|
191
191
|
def income_message(self, msg: ReliableMessage, priority: int = 0) -> List[ReliableMessage]:
|
|
192
192
|
""" redirect message from remote station """
|
|
193
|
+
sender = msg.sender
|
|
194
|
+
receiver = msg.receiver
|
|
193
195
|
sig = get_msg_sig(msg=msg)
|
|
194
196
|
messenger = self.inner_messenger
|
|
195
197
|
if messenger.send_reliable_message(msg=msg, priority=priority):
|
|
196
|
-
self.info(msg='redirected msg (%s)
|
|
198
|
+
self.info(msg='redirected msg (%s): %s -> %s' % (sig, sender, receiver))
|
|
197
199
|
else:
|
|
198
|
-
self.error(msg='failed to redirect msg (%s)
|
|
200
|
+
self.error(msg='failed to redirect msg (%s): %s -> %s' % (sig, sender, receiver))
|
|
199
201
|
# no need to respond receipt for station
|
|
200
202
|
return []
|
|
201
203
|
|
|
202
204
|
def outgo_message(self, msg: ReliableMessage, priority: int = 0) -> List[ReliableMessage]:
|
|
203
205
|
""" redirect message to remote station """
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
self.
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
206
|
+
receiver = msg.receiver
|
|
207
|
+
# get neighbor stations
|
|
208
|
+
neighbor = ID.parse(identifier=msg.get('neighbor'))
|
|
209
|
+
if neighbor is not None:
|
|
210
|
+
neighbors = set()
|
|
211
|
+
neighbors.add(neighbor)
|
|
212
|
+
msg.pop('neighbor', None)
|
|
213
|
+
else:
|
|
214
|
+
with self.__outer_lock:
|
|
215
|
+
neighbors = set(self.__outer_map.keys())
|
|
216
|
+
#
|
|
217
|
+
# 0. check recipients
|
|
218
|
+
#
|
|
219
|
+
new_recipients = set()
|
|
220
|
+
old_recipients = msg.get('recipients')
|
|
221
|
+
old_recipients = [] if old_recipients is None else ID.convert(old_recipients)
|
|
222
|
+
for item in neighbors:
|
|
223
|
+
if item not in old_recipients:
|
|
224
|
+
new_recipients.add(item)
|
|
225
|
+
all_recipients = []
|
|
226
|
+
for item in old_recipients:
|
|
227
|
+
all_recipients.append(item)
|
|
228
|
+
# avoid the new recipients redirect it to same targets
|
|
229
|
+
self.info(msg='append new recipients: %s, %s => %s' % (receiver, new_recipients, all_recipients))
|
|
230
|
+
for item in new_recipients:
|
|
231
|
+
all_recipients.append(item)
|
|
232
|
+
msg['recipients'] = ID.revert(all_recipients)
|
|
233
|
+
#
|
|
234
|
+
# 1. send to the new recipients (neighbor stations)
|
|
235
|
+
#
|
|
220
236
|
sig = get_msg_sig(msg=msg)
|
|
221
|
-
|
|
237
|
+
failed_neighbors = []
|
|
238
|
+
for target in new_recipients:
|
|
239
|
+
messenger = self.get_outer_messenger(identifier=target)
|
|
240
|
+
if messenger is None:
|
|
241
|
+
# target station not my neighbor
|
|
242
|
+
self.warning(msg='not my neighbor: %s (%s)' % (target, receiver))
|
|
243
|
+
failed_neighbors.append(target)
|
|
244
|
+
elif messenger.send_reliable_message(msg=msg, priority=priority):
|
|
245
|
+
self.info(msg='redirected msg (%s) to neighbor: %s (%s)' % (sig, target, receiver))
|
|
246
|
+
else:
|
|
247
|
+
self.error(msg='failed to send to neighbor: %s (%s)' % (target, receiver))
|
|
248
|
+
failed_neighbors.append(target)
|
|
249
|
+
if len(failed_neighbors) > 0:
|
|
250
|
+
self.error(msg='failed to redirect msg (%s) for receiver (%s): %s' % (sig, receiver, failed_neighbors))
|
|
222
251
|
return []
|
|
223
252
|
|
|
224
253
|
|
|
@@ -44,7 +44,6 @@ from ..common import CommonArchivist
|
|
|
44
44
|
from ..common import CommonFacebook, CommonMessenger
|
|
45
45
|
from ..common import StationInfo
|
|
46
46
|
|
|
47
|
-
from .dispatcher import Dispatcher
|
|
48
47
|
from .session_center import SessionCenter
|
|
49
48
|
|
|
50
49
|
|
|
@@ -62,6 +61,11 @@ def get_messenger(archivist: CommonArchivist):
|
|
|
62
61
|
return messenger
|
|
63
62
|
|
|
64
63
|
|
|
64
|
+
def get_dispatcher():
|
|
65
|
+
from .dispatcher import Dispatcher
|
|
66
|
+
return Dispatcher()
|
|
67
|
+
|
|
68
|
+
|
|
65
69
|
class ServerArchivist(CommonArchivist, ABC):
|
|
66
70
|
|
|
67
71
|
# each respond will be expired after 10 minutes
|
|
@@ -95,7 +99,7 @@ class ServerArchivist(CommonArchivist, ABC):
|
|
|
95
99
|
@property
|
|
96
100
|
def all_stations(self) -> List[StationInfo]:
|
|
97
101
|
""" get stations from database """
|
|
98
|
-
dispatcher =
|
|
102
|
+
dispatcher = get_dispatcher()
|
|
99
103
|
db = dispatcher.sdb
|
|
100
104
|
# TODO: get chosen provider
|
|
101
105
|
providers = db.all_providers()
|
|
@@ -136,7 +140,7 @@ class ServerArchivist(CommonArchivist, ABC):
|
|
|
136
140
|
s_msg = messenger.encrypt_message(msg=i_msg)
|
|
137
141
|
r_msg = messenger.sign_message(msg=s_msg)
|
|
138
142
|
# dispatch
|
|
139
|
-
dispatcher =
|
|
143
|
+
dispatcher = get_dispatcher()
|
|
140
144
|
neighbors = self.all_neighbors
|
|
141
145
|
# avoid the new recipients redirect it to same targets
|
|
142
146
|
r_msg['recipients'] = ID.revert(neighbors)
|
|
@@ -32,13 +32,14 @@
|
|
|
32
32
|
|
|
33
33
|
import threading
|
|
34
34
|
from abc import ABC, abstractmethod
|
|
35
|
-
from typing import Optional, List
|
|
35
|
+
from typing import Optional, Set, List
|
|
36
36
|
|
|
37
|
-
from dimsdk import EntityType, ID
|
|
37
|
+
from dimsdk import EntityType, ID, EVERYONE
|
|
38
|
+
from dimsdk import Station
|
|
38
39
|
from dimsdk import Content, ReceiptCommand
|
|
39
40
|
from dimsdk import ReliableMessage
|
|
40
41
|
|
|
41
|
-
from ..utils import Singleton, Logging, Runner, Daemon
|
|
42
|
+
from ..utils import Singleton, Log, Logging, Runner, Daemon
|
|
42
43
|
from ..common import CommonFacebook
|
|
43
44
|
from ..common import MessageDBI, SessionDBI
|
|
44
45
|
from ..common import ReliableMessageDBI
|
|
@@ -46,6 +47,7 @@ from ..common import LoginCommand
|
|
|
46
47
|
|
|
47
48
|
from .session_center import SessionCenter
|
|
48
49
|
from .push import PushCenter
|
|
50
|
+
from .archivist import ServerArchivist
|
|
49
51
|
|
|
50
52
|
|
|
51
53
|
class MessageDeliver(ABC):
|
|
@@ -64,7 +66,7 @@ class MessageDeliver(ABC):
|
|
|
64
66
|
|
|
65
67
|
|
|
66
68
|
@Singleton
|
|
67
|
-
class Dispatcher(MessageDeliver):
|
|
69
|
+
class Dispatcher(MessageDeliver, Logging):
|
|
68
70
|
|
|
69
71
|
def __init__(self):
|
|
70
72
|
super().__init__()
|
|
@@ -147,7 +149,11 @@ class Dispatcher(MessageDeliver):
|
|
|
147
149
|
def deliver_message(self, msg: ReliableMessage, receiver: ID) -> List[Content]:
|
|
148
150
|
""" Deliver message to destination """
|
|
149
151
|
worker = self.deliver_worker
|
|
150
|
-
if receiver.
|
|
152
|
+
if receiver.is_group:
|
|
153
|
+
# broadcast message to neighbor stations
|
|
154
|
+
# e.g.: 'stations@everywhere', 'everyone@everywhere'
|
|
155
|
+
return self.__deliver_group_message(msg=msg, receiver=receiver)
|
|
156
|
+
elif receiver.type == EntityType.STATION:
|
|
151
157
|
# message to other stations
|
|
152
158
|
# station won't roam to other station, so just push for it directly
|
|
153
159
|
responses = worker.redirect_message(msg=msg, neighbor=receiver)
|
|
@@ -181,6 +187,66 @@ class Dispatcher(MessageDeliver):
|
|
|
181
187
|
# message delivered
|
|
182
188
|
return responses
|
|
183
189
|
|
|
190
|
+
def __deliver_group_message(self, msg: ReliableMessage, receiver: ID) -> List[Content]:
|
|
191
|
+
if receiver == Station.EVERY or receiver == EVERYONE:
|
|
192
|
+
# broadcast message to neighbor stations
|
|
193
|
+
# e.g.: 'stations@everywhere', 'everyone@everywhere'
|
|
194
|
+
archivist = self.facebook.archivist
|
|
195
|
+
assert isinstance(archivist, ServerArchivist)
|
|
196
|
+
candidates = archivist.all_neighbors
|
|
197
|
+
if len(candidates) == 0:
|
|
198
|
+
self.warning(msg='failed to get neighbors: %s' % receiver)
|
|
199
|
+
return []
|
|
200
|
+
self.info(msg='forward to neighbor stations: %s -> %s' % (receiver, candidates))
|
|
201
|
+
return self.__broadcast_message(msg=msg, receiver=receiver, neighbors=candidates)
|
|
202
|
+
else:
|
|
203
|
+
self.warning(msg='unknown group: %s' % receiver)
|
|
204
|
+
text = 'Group message not allow for this station'
|
|
205
|
+
res = ReceiptCommand.create(text=text, envelope=msg.envelope)
|
|
206
|
+
return [res]
|
|
207
|
+
|
|
208
|
+
def __broadcast_message(self, msg: ReliableMessage, receiver: ID, neighbors: Set[ID]) -> List[Content]:
|
|
209
|
+
#
|
|
210
|
+
# 0. check recipients
|
|
211
|
+
#
|
|
212
|
+
new_recipients = set()
|
|
213
|
+
old_recipients = msg.get('recipients')
|
|
214
|
+
old_recipients = [] if old_recipients is None else ID.convert(old_recipients)
|
|
215
|
+
for item in neighbors:
|
|
216
|
+
if item not in old_recipients:
|
|
217
|
+
new_recipients.add(item)
|
|
218
|
+
all_recipients = []
|
|
219
|
+
for item in old_recipients:
|
|
220
|
+
all_recipients.append(item)
|
|
221
|
+
# avoid the new recipients redirect it to same targets
|
|
222
|
+
self.info(msg='append new recipients: %s, %s => %s' % (receiver, new_recipients, all_recipients))
|
|
223
|
+
for item in new_recipients:
|
|
224
|
+
all_recipients.append(item)
|
|
225
|
+
msg['recipients'] = ID.revert(all_recipients)
|
|
226
|
+
#
|
|
227
|
+
# 1. push to neighbor stations directly
|
|
228
|
+
#
|
|
229
|
+
indirect_neighbors = set()
|
|
230
|
+
for target in new_recipients:
|
|
231
|
+
if session_push(msg=msg, receiver=target) == 0:
|
|
232
|
+
indirect_neighbors.add(target)
|
|
233
|
+
if len(indirect_neighbors) > 0:
|
|
234
|
+
for item in indirect_neighbors:
|
|
235
|
+
all_recipients.remove(item)
|
|
236
|
+
msg['recipients'] = ID.revert(all_recipients)
|
|
237
|
+
#
|
|
238
|
+
# 2. push to other neighbor stations via station bridge
|
|
239
|
+
#
|
|
240
|
+
worker = self.deliver_worker
|
|
241
|
+
worker.redirect_message(msg=msg, neighbor=None)
|
|
242
|
+
#
|
|
243
|
+
# OK
|
|
244
|
+
#
|
|
245
|
+
text = 'Message forwarded.'
|
|
246
|
+
cmd = ReceiptCommand.create(text=text, envelope=msg.envelope)
|
|
247
|
+
cmd['recipients'] = ID.revert(new_recipients)
|
|
248
|
+
return [cmd]
|
|
249
|
+
|
|
184
250
|
def __save_reliable_message(self, msg: ReliableMessage, receiver: ID) -> bool:
|
|
185
251
|
if receiver.type == EntityType.STATION or msg.sender.type == EntityType.STATION:
|
|
186
252
|
# no need to save station message
|
|
@@ -305,7 +371,7 @@ class DeliverWorker(Logging):
|
|
|
305
371
|
# 3. redirect message to roaming station
|
|
306
372
|
return self.redirect_message(msg=msg, neighbor=roaming)
|
|
307
373
|
|
|
308
|
-
def redirect_message(self, msg: ReliableMessage, neighbor: ID) -> Optional[List[Content]]:
|
|
374
|
+
def redirect_message(self, msg: ReliableMessage, neighbor: Optional[ID]) -> Optional[List[Content]]:
|
|
309
375
|
"""
|
|
310
376
|
Redirect message to neighbor station
|
|
311
377
|
|
|
@@ -314,7 +380,7 @@ class DeliverWorker(Logging):
|
|
|
314
380
|
:return: responses
|
|
315
381
|
"""
|
|
316
382
|
""" Redirect message to neighbor station """
|
|
317
|
-
assert neighbor.type == EntityType.STATION, 'neighbor station ID error: %s' % neighbor
|
|
383
|
+
assert neighbor is None or neighbor.type == EntityType.STATION, 'neighbor station ID error: %s' % neighbor
|
|
318
384
|
self.info(msg='redirect message %s => %s to neighbor station: %s' % (msg.sender, msg.receiver, neighbor))
|
|
319
385
|
# 0. check current station
|
|
320
386
|
current = self.facebook.current_user.identifier
|
|
@@ -325,7 +391,7 @@ class DeliverWorker(Logging):
|
|
|
325
391
|
# return None to tell the push center to push notification for it.
|
|
326
392
|
return None
|
|
327
393
|
# 1. try to push message to neighbor station directly
|
|
328
|
-
if session_push(msg=msg, receiver=neighbor) > 0:
|
|
394
|
+
if neighbor is not None and session_push(msg=msg, receiver=neighbor) > 0:
|
|
329
395
|
text = 'Message redirected.'
|
|
330
396
|
cmd = ReceiptCommand.create(text=text, envelope=msg.envelope)
|
|
331
397
|
cmd['neighbor'] = str(neighbor)
|
|
@@ -334,9 +400,10 @@ class DeliverWorker(Logging):
|
|
|
334
400
|
return bridge_message(msg=msg, neighbor=neighbor, bridge=current)
|
|
335
401
|
|
|
336
402
|
|
|
337
|
-
def bridge_message(msg: ReliableMessage, neighbor: ID, bridge: ID) ->
|
|
403
|
+
def bridge_message(msg: ReliableMessage, neighbor: Optional[ID], bridge: ID) -> List[Content]:
|
|
338
404
|
"""
|
|
339
405
|
Redirect message to neighbor station via the station bridge
|
|
406
|
+
if neighbor is None, try to broadcast
|
|
340
407
|
|
|
341
408
|
:param msg: network message
|
|
342
409
|
:param neighbor: roaming station
|
|
@@ -348,16 +415,25 @@ def bridge_message(msg: ReliableMessage, neighbor: ID, bridge: ID) -> Optional[L
|
|
|
348
415
|
# be changed to another value before pushing to the bridge.
|
|
349
416
|
# clone = msg.copy_dictionary()
|
|
350
417
|
# msg = ReliableMessage.parse(msg=clone)
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
return [
|
|
418
|
+
if neighbor is None:
|
|
419
|
+
# broadcast to all neighbor stations
|
|
420
|
+
# except that ones already in msg['recipients']
|
|
421
|
+
session_push(msg=msg, receiver=bridge)
|
|
422
|
+
# no need to respond receipt for this broadcast message
|
|
423
|
+
return []
|
|
357
424
|
else:
|
|
425
|
+
assert neighbor != bridge, 'cannot bridge cycled message: %s' % neighbor
|
|
426
|
+
msg['neighbor'] = str(neighbor)
|
|
427
|
+
# push to the bridge
|
|
428
|
+
if session_push(msg=msg, receiver=bridge) == 0:
|
|
358
429
|
# station bridge not found
|
|
359
|
-
|
|
430
|
+
Log.warning(msg='failed to push message to bridge: %s, drop message: %s -> %s'
|
|
431
|
+
% (bridge, msg.sender, msg.receiver))
|
|
360
432
|
return []
|
|
433
|
+
text = 'Message redirected via station bridge.'
|
|
434
|
+
cmd = ReceiptCommand.create(text=text, envelope=msg.envelope)
|
|
435
|
+
cmd['neighbor'] = str(neighbor)
|
|
436
|
+
return [cmd]
|
|
361
437
|
|
|
362
438
|
|
|
363
439
|
def session_push(msg: ReliableMessage, receiver: ID) -> int:
|
|
@@ -56,7 +56,6 @@ from .cpu import DocumentCommandProcessor
|
|
|
56
56
|
|
|
57
57
|
from .packer import FilterManager
|
|
58
58
|
from .dispatcher import Dispatcher
|
|
59
|
-
from .archivist import ServerArchivist
|
|
60
59
|
|
|
61
60
|
|
|
62
61
|
class ServerMessageProcessor(CommonMessageProcessor):
|
|
@@ -195,49 +194,18 @@ class ServerMessageProcessor(CommonMessageProcessor):
|
|
|
195
194
|
if bot is None:
|
|
196
195
|
self.warning(msg='failed to get receiver: %s' % receiver)
|
|
197
196
|
return False
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
self.info(msg='forward to station bot: %s -> %s' % (name, bot))
|
|
201
|
-
elif receiver == Station.EVERY or receiver == EVERYONE:
|
|
202
|
-
# broadcast message to neighbor stations
|
|
203
|
-
# e.g.: 'stations@everywhere', 'everyone@everywhere'
|
|
204
|
-
archivist = self.facebook.archivist
|
|
205
|
-
assert isinstance(archivist, ServerArchivist)
|
|
206
|
-
candidates = archivist.all_neighbors
|
|
207
|
-
if len(candidates) == 0:
|
|
208
|
-
self.warning(msg='failed to get neighbors: %s' % receiver)
|
|
197
|
+
elif bot == sender:
|
|
198
|
+
self.warning(msg='skip cycled message: %s -> %s' % (sender, receiver))
|
|
209
199
|
return False
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
self.warning(msg='unknown receiver: %s' % receiver)
|
|
213
|
-
return False
|
|
214
|
-
# check recipients
|
|
215
|
-
new_recipients = candidates.copy()
|
|
216
|
-
old_recipients = msg.get('recipients')
|
|
217
|
-
if old_recipients is None:
|
|
218
|
-
all_recipients = []
|
|
219
|
-
else:
|
|
220
|
-
all_recipients = ID.convert(old_recipients)
|
|
221
|
-
# check duplicated
|
|
222
|
-
self.info(msg='discard recipients: %s, new recipients: %s' % (old_recipients, new_recipients))
|
|
223
|
-
for item in all_recipients:
|
|
224
|
-
new_recipients.discard(item)
|
|
225
|
-
if len(new_recipients) == 0:
|
|
226
|
-
self.info(msg='new recipients empty: %s => %s' % (receiver, candidates))
|
|
200
|
+
elif bot == station:
|
|
201
|
+
self.warning(msg='skip current station: %s -> %s' % (sender, receiver))
|
|
227
202
|
return False
|
|
228
|
-
self.info(msg='append new recipients: %s, %s => %s' % (receiver, new_recipients, all_recipients))
|
|
229
|
-
for item in new_recipients:
|
|
230
|
-
all_recipients.append(item)
|
|
231
|
-
# avoid the new recipients redirect it to same targets
|
|
232
|
-
msg['recipients'] = ID.revert(all_recipients)
|
|
233
|
-
# dispatch
|
|
234
|
-
dispatcher = Dispatcher()
|
|
235
|
-
for target in new_recipients:
|
|
236
|
-
if target == sender or target == station:
|
|
237
|
-
self.info(msg='skip cycled message: %s -> %s, %s' % (sender, receiver, target))
|
|
238
203
|
else:
|
|
239
|
-
|
|
240
|
-
|
|
204
|
+
self.info(msg='forward to bot: %s -> %s' % (name, bot))
|
|
205
|
+
receiver = bot
|
|
206
|
+
# deliver by dispatcher
|
|
207
|
+
dispatcher = Dispatcher()
|
|
208
|
+
dispatcher.deliver_message(msg=msg, receiver=receiver)
|
|
241
209
|
|
|
242
210
|
def _split_group_message(self, msg: ReliableMessage, station: ID):
|
|
243
211
|
""" redirect group message to assistant """
|
|
@@ -42,10 +42,12 @@ class Node(Dictionary):
|
|
|
42
42
|
if port > 0:
|
|
43
43
|
self['port'] = port
|
|
44
44
|
|
|
45
|
+
# Override
|
|
45
46
|
def __str__(self) -> str:
|
|
46
47
|
clazz = self.__class__.__name__
|
|
47
48
|
return '<%s host="%s" port=%d name="%s" />' % (clazz, self.host, self.port, self.name)
|
|
48
49
|
|
|
50
|
+
# Override
|
|
49
51
|
def __repr__(self) -> str:
|
|
50
52
|
clazz = self.__class__.__name__
|
|
51
53
|
return '<%s host="%s" port=%d name="%s" />' % (clazz, self.host, self.port, self.name)
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|