dimples 0.5.0__tar.gz → 0.5.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 (143) hide show
  1. {dimples-0.5.0 → dimples-0.5.2}/PKG-INFO +1 -1
  2. {dimples-0.5.0 → dimples-0.5.2}/dimples/__init__.py +2 -1
  3. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/messenger.py +15 -2
  4. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/processor.py +18 -12
  5. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/__init__.py +2 -0
  6. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/messenger.py +37 -6
  7. dimples-0.5.2/dimples/common/processer.py +70 -0
  8. {dimples-0.5.0 → dimples-0.5.2}/dimples/conn/gate.py +4 -2
  9. {dimples-0.5.0 → dimples-0.5.2}/dimples/conn/gatekeeper.py +2 -3
  10. {dimples-0.5.0 → dimples-0.5.2}/dimples/group/emitter.py +9 -4
  11. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/cpu/handshake.py +5 -4
  12. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/cpu/login.py +1 -1
  13. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/processor.py +2 -3
  14. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/session.py +1 -1
  15. {dimples-0.5.0 → dimples-0.5.2}/dimples.egg-info/PKG-INFO +1 -1
  16. {dimples-0.5.0 → dimples-0.5.2}/dimples.egg-info/SOURCES.txt +1 -0
  17. {dimples-0.5.0 → dimples-0.5.2}/dimples.egg-info/requires.txt +3 -3
  18. {dimples-0.5.0 → dimples-0.5.2}/setup.py +4 -4
  19. {dimples-0.5.0 → dimples-0.5.2}/README.md +0 -0
  20. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/__init__.py +0 -0
  21. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/archivist.py +0 -0
  22. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/checkpoint.py +0 -0
  23. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/cpu/__init__.py +0 -0
  24. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/cpu/commands.py +0 -0
  25. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/cpu/creator.py +0 -0
  26. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/cpu/group.py +0 -0
  27. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/cpu/grp_expel.py +0 -0
  28. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/cpu/grp_invite.py +0 -0
  29. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/cpu/grp_join.py +0 -0
  30. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/cpu/grp_query.py +0 -0
  31. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/cpu/grp_quit.py +0 -0
  32. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/cpu/grp_reset.py +0 -0
  33. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/cpu/grp_resign.py +0 -0
  34. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/cpu/handshake.py +0 -0
  35. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/facebook.py +0 -0
  36. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/network/__init__.py +0 -0
  37. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/network/session.py +0 -0
  38. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/network/state.py +0 -0
  39. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/network/transition.py +0 -0
  40. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/packer.py +0 -0
  41. {dimples-0.5.0 → dimples-0.5.2}/dimples/client/terminal.py +0 -0
  42. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/anonymous.py +0 -0
  43. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/ans.py +0 -0
  44. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/archivist.py +0 -0
  45. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/compat/__init__.py +0 -0
  46. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/compat/btc.py +0 -0
  47. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/compat/compatible.py +0 -0
  48. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/compat/entity.py +0 -0
  49. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/compat/meta.py +0 -0
  50. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/compat/network.py +0 -0
  51. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/dbi/__init__.py +0 -0
  52. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/dbi/account.py +0 -0
  53. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/dbi/message.py +0 -0
  54. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/dbi/session.py +0 -0
  55. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/facebook.py +0 -0
  56. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/packer.py +0 -0
  57. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/protocol/__init__.py +0 -0
  58. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/protocol/ans.py +0 -0
  59. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/protocol/block.py +0 -0
  60. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/protocol/handshake.py +0 -0
  61. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/protocol/login.py +0 -0
  62. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/protocol/mute.py +0 -0
  63. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/protocol/report.py +0 -0
  64. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/register.py +0 -0
  65. {dimples-0.5.0 → dimples-0.5.2}/dimples/common/session.py +0 -0
  66. {dimples-0.5.0 → dimples-0.5.2}/dimples/conn/__init__.py +0 -0
  67. {dimples-0.5.0 → dimples-0.5.2}/dimples/conn/mars.py +0 -0
  68. {dimples-0.5.0 → dimples-0.5.2}/dimples/conn/mtp.py +0 -0
  69. {dimples-0.5.0 → dimples-0.5.2}/dimples/conn/protocol/__init__.py +0 -0
  70. {dimples-0.5.0 → dimples-0.5.2}/dimples/conn/protocol/mars.py +0 -0
  71. {dimples-0.5.0 → dimples-0.5.2}/dimples/conn/protocol/ws.py +0 -0
  72. {dimples-0.5.0 → dimples-0.5.2}/dimples/conn/queue.py +0 -0
  73. {dimples-0.5.0 → dimples-0.5.2}/dimples/conn/seeker.py +0 -0
  74. {dimples-0.5.0 → dimples-0.5.2}/dimples/conn/session.py +0 -0
  75. {dimples-0.5.0 → dimples-0.5.2}/dimples/conn/ws.py +0 -0
  76. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/__init__.py +0 -0
  77. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/account.py +0 -0
  78. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/dos/__init__.py +0 -0
  79. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/dos/base.py +0 -0
  80. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/dos/document.py +0 -0
  81. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/dos/group.py +0 -0
  82. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/dos/group_history.py +0 -0
  83. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/dos/group_keys.py +0 -0
  84. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/dos/login.py +0 -0
  85. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/dos/meta.py +0 -0
  86. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/dos/private.py +0 -0
  87. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/dos/station.py +0 -0
  88. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/dos/user.py +0 -0
  89. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/message.py +0 -0
  90. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/session.py +0 -0
  91. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/t_cipherkey.py +0 -0
  92. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/t_document.py +0 -0
  93. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/t_group.py +0 -0
  94. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/t_group_history.py +0 -0
  95. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/t_group_keys.py +0 -0
  96. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/t_login.py +0 -0
  97. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/t_message.py +0 -0
  98. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/t_meta.py +0 -0
  99. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/t_private.py +0 -0
  100. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/t_station.py +0 -0
  101. {dimples-0.5.0 → dimples-0.5.2}/dimples/database/t_user.py +0 -0
  102. {dimples-0.5.0 → dimples-0.5.2}/dimples/edge/__init__.py +0 -0
  103. {dimples-0.5.0 → dimples-0.5.2}/dimples/edge/octopus.py +0 -0
  104. {dimples-0.5.0 → dimples-0.5.2}/dimples/edge/shared.py +0 -0
  105. {dimples-0.5.0 → dimples-0.5.2}/dimples/edge/start.py +0 -0
  106. {dimples-0.5.0 → dimples-0.5.2}/dimples/group/__init__.py +0 -0
  107. {dimples-0.5.0 → dimples-0.5.2}/dimples/group/admin.py +0 -0
  108. {dimples-0.5.0 → dimples-0.5.2}/dimples/group/builder.py +0 -0
  109. {dimples-0.5.0 → dimples-0.5.2}/dimples/group/delegate.py +0 -0
  110. {dimples-0.5.0 → dimples-0.5.2}/dimples/group/helper.py +0 -0
  111. {dimples-0.5.0 → dimples-0.5.2}/dimples/group/manager.py +0 -0
  112. {dimples-0.5.0 → dimples-0.5.2}/dimples/group/packer.py +0 -0
  113. {dimples-0.5.0 → dimples-0.5.2}/dimples/register/__init__.py +0 -0
  114. {dimples-0.5.0 → dimples-0.5.2}/dimples/register/base.py +0 -0
  115. {dimples-0.5.0 → dimples-0.5.2}/dimples/register/ext.py +0 -0
  116. {dimples-0.5.0 → dimples-0.5.2}/dimples/register/run.py +0 -0
  117. {dimples-0.5.0 → dimples-0.5.2}/dimples/register/shared.py +0 -0
  118. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/__init__.py +0 -0
  119. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/archivist.py +0 -0
  120. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/cpu/__init__.py +0 -0
  121. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/cpu/ans.py +0 -0
  122. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/cpu/document.py +0 -0
  123. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/cpu/report.py +0 -0
  124. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/dispatcher.py +0 -0
  125. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/messenger.py +0 -0
  126. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/packer.py +0 -0
  127. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/push.py +0 -0
  128. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/session_center.py +0 -0
  129. {dimples-0.5.0 → dimples-0.5.2}/dimples/server/trace.py +0 -0
  130. {dimples-0.5.0 → dimples-0.5.2}/dimples/station/__init__.py +0 -0
  131. {dimples-0.5.0 → dimples-0.5.2}/dimples/station/handler.py +0 -0
  132. {dimples-0.5.0 → dimples-0.5.2}/dimples/station/shared.py +0 -0
  133. {dimples-0.5.0 → dimples-0.5.2}/dimples/station/start.py +0 -0
  134. {dimples-0.5.0 → dimples-0.5.2}/dimples/utils/__init__.py +0 -0
  135. {dimples-0.5.0 → dimples-0.5.2}/dimples/utils/cache.py +0 -0
  136. {dimples-0.5.0 → dimples-0.5.2}/dimples/utils/config.py +0 -0
  137. {dimples-0.5.0 → dimples-0.5.2}/dimples/utils/dos.py +0 -0
  138. {dimples-0.5.0 → dimples-0.5.2}/dimples/utils/log.py +0 -0
  139. {dimples-0.5.0 → dimples-0.5.2}/dimples/utils/singleton.py +0 -0
  140. {dimples-0.5.0 → dimples-0.5.2}/dimples.egg-info/dependency_links.txt +0 -0
  141. {dimples-0.5.0 → dimples-0.5.2}/dimples.egg-info/entry_points.txt +0 -0
  142. {dimples-0.5.0 → dimples-0.5.2}/dimples.egg-info/top_level.txt +0 -0
  143. {dimples-0.5.0 → dimples-0.5.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dimples
3
- Version: 0.5.0
3
+ Version: 0.5.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
@@ -333,7 +333,8 @@ __all__ = [
333
333
  'AddressNameServer', 'ANSFactory',
334
334
  'CommonArchivist',
335
335
  'CommonFacebook', 'CommonMessenger',
336
- 'CommonMessagePacker', 'Transmitter',
336
+ 'CommonMessagePacker', 'CommonMessageProcessor',
337
+ 'Transmitter',
337
338
  'Session',
338
339
 
339
340
  ####################################
@@ -62,14 +62,27 @@ class ClientMessenger(CommonMessenger):
62
62
  facebook = self.facebook
63
63
  user = facebook.current_user
64
64
  assert user is not None, 'current user not found'
65
+ meta = user.meta
66
+ visa = user.visa
67
+ if visa is None:
68
+ self.warning(msg='user visa not found: %s' % user)
69
+ else:
70
+ device = {
71
+ 'os': 'Linux',
72
+ }
73
+ visa.set_property(key='sys', value=device)
74
+ # sign to update
75
+ pri_key = facebook.private_key_for_visa_signature(identifier=user.identifier)
76
+ assert pri_key is not None, 'failed to get private key for visa: %s' % visa
77
+ visa.sign(private_key=pri_key)
65
78
  env = Envelope.create(sender=user.identifier, receiver=srv_id)
66
79
  cmd = HandshakeCommand.start()
67
80
  # send first handshake command as broadcast message
68
81
  cmd.group = Station.EVERY
69
82
  # create instant message with meta & visa
70
83
  i_msg = InstantMessage.create(head=env, body=cmd)
71
- i_msg.set_map(key='meta', value=user.meta)
72
- i_msg.set_map(key='visa', value=user.visa)
84
+ i_msg.set_map(key='meta', value=meta)
85
+ i_msg.set_map(key='visa', value=visa)
73
86
  self.send_instant_message(msg=i_msg, priority=-1)
74
87
  else:
75
88
  # handshake again
@@ -37,18 +37,17 @@ from dimsdk import ReliableMessage
37
37
  from dimsdk import Content, TextContent
38
38
  from dimsdk import ReceiptCommand
39
39
  from dimsdk import ContentProcessorCreator
40
- from dimsdk import MessageProcessor
41
40
 
42
- from ..utils import Logging
43
41
  from ..common import HandshakeCommand
44
42
  from ..common import CommonMessenger
43
+ from ..common import CommonMessageProcessor
45
44
 
46
45
  from .cpu import ClientContentProcessorCreator
47
46
 
48
47
  from .archivist import ClientArchivist
49
48
 
50
49
 
51
- class ClientMessageProcessor(MessageProcessor, Logging):
50
+ class ClientMessageProcessor(CommonMessageProcessor):
52
51
 
53
52
  @property
54
53
  def messenger(self) -> CommonMessenger:
@@ -56,10 +55,11 @@ class ClientMessageProcessor(MessageProcessor, Logging):
56
55
  assert isinstance(transceiver, CommonMessenger), 'messenger error: %s' % transceiver
57
56
  return transceiver
58
57
 
59
- def __check_group_times(self, content: Content, r_msg: ReliableMessage):
58
+ # private
59
+ def _check_group_times(self, content: Content, r_msg: ReliableMessage) -> bool:
60
60
  group = content.group
61
61
  if group is None:
62
- return
62
+ return False
63
63
  facebook = self.facebook
64
64
  archivist = facebook.archivist
65
65
  assert isinstance(archivist, ClientArchivist), 'client archivist error: %s' % archivist
@@ -70,27 +70,33 @@ class ClientMessageProcessor(MessageProcessor, Logging):
70
70
  last_doc_time = r_msg.get_datetime(key='GDT', default=None)
71
71
  if last_doc_time is not None:
72
72
  if last_doc_time.after(now):
73
+ # calibrate the clock
73
74
  last_doc_time = now
74
75
  doc_updated = archivist.set_last_document_time(identifier=group, last_time=last_doc_time)
76
+ # check whether needs update
77
+ if doc_updated:
78
+ self.info(msg='checking for new bulletin: %s' % group)
79
+ facebook.documents(identifier=group)
75
80
  # check group history time
76
81
  last_his_time = r_msg.get_datetime(key='GHT', default=None)
77
82
  if last_his_time is not None:
78
83
  if last_his_time.after(now):
84
+ # calibrate the clock
79
85
  last_his_time = now
80
86
  mem_updated = archivist.set_last_group_history_time(group=group, last_time=last_his_time)
81
- # check whether needs update
82
- if doc_updated:
83
- facebook.documents(identifier=group)
84
- if mem_updated:
85
- archivist.set_last_active_member(member=r_msg.sender, group=group)
86
- facebook.members(identifier=group)
87
+ # check whether needs update
88
+ if mem_updated:
89
+ archivist.set_last_active_member(member=r_msg.sender, group=group)
90
+ self.info(msg='checking for group members: %s' % group)
91
+ facebook.members(identifier=group)
92
+ return doc_updated or mem_updated
87
93
 
88
94
  # Override
89
95
  def process_content(self, content: Content, r_msg: ReliableMessage) -> List[Content]:
90
96
  responses = super().process_content(content=content, r_msg=r_msg)
91
97
  # check group document & history times from the message
92
98
  # to make sure the group info synchronized
93
- self.__check_group_times(content=content, r_msg=r_msg)
99
+ self._check_group_times(content=content, r_msg=r_msg)
94
100
  # check responses
95
101
  if len(responses) == 0:
96
102
  # respond nothing
@@ -40,6 +40,7 @@ from .archivist import CommonArchivist
40
40
  from .facebook import CommonFacebook
41
41
  from .messenger import CommonMessenger
42
42
  from .packer import CommonMessagePacker
43
+ from .processer import CommonMessageProcessor
43
44
  from .session import Transmitter, Session
44
45
 
45
46
  from .compat import register_compatible_factories
@@ -87,6 +88,7 @@ __all__ = [
87
88
  'CommonFacebook',
88
89
  'CommonMessenger',
89
90
  'CommonMessagePacker',
91
+ 'CommonMessageProcessor',
90
92
  'Transmitter',
91
93
  'Session',
92
94
 
@@ -168,26 +168,57 @@ class CommonMessenger(Messenger, Transmitter, Logging, ABC):
168
168
  r_msg = self.send_instant_message(msg=i_msg, priority=priority)
169
169
  return i_msg, r_msg
170
170
 
171
+ # private
172
+ def _attach_visa_time(self, sender: ID, msg: InstantMessage) -> bool:
173
+ if isinstance(msg.content, Command):
174
+ # no need to attach times for command
175
+ return False
176
+ doc = self.facebook.visa(identifier=sender)
177
+ if doc is None:
178
+ self.error(msg='failed to get visa document for sender: %s' % sender)
179
+ return False
180
+ # attach sender document time
181
+ last_doc_time = doc.time
182
+ if last_doc_time is None:
183
+ self.error(msg='document error: %s' % doc)
184
+ return False
185
+ else:
186
+ msg.set_datetime(key='SDT', value=last_doc_time)
187
+ return True
188
+
171
189
  # Override
172
190
  def send_instant_message(self, msg: InstantMessage, priority: int = 0) -> Optional[ReliableMessage]:
173
191
  """ send instant message with priority """
192
+ sender = msg.sender
174
193
  # 0. check cycled message
175
- if msg.sender == msg.receiver:
176
- self.warning(msg='drop cycled message: %s => %s, %s' % (msg.sender, msg.receiver, msg.group))
194
+ if sender == msg.receiver:
195
+ self.warning(msg='drop cycled message: %s => %s, %s' % (sender, msg.receiver, msg.group))
196
+ # return None
177
197
  else:
178
198
  self.debug(msg='send instant message message (type=%d): %s => %s, %s'
179
- % (msg.content.type, msg.sender, msg.receiver, msg.group))
180
- # 1. encrypt message
199
+ % (msg.content.type, sender, msg.receiver, msg.group))
200
+ # attach sender's document times
201
+ # for the receiver to check whether user info synchronized
202
+ ok = self._attach_visa_time(sender=sender, msg=msg)
203
+ assert ok or isinstance(msg.content, Command), \
204
+ 'failed to attach document time: %s => %s' % (sender, msg.content)
205
+ #
206
+ # 1. encrypt message
207
+ #
181
208
  s_msg = self.encrypt_message(msg=msg)
182
209
  if s_msg is None:
183
210
  # public key not found?
184
211
  return None
185
- # 2. sign message
212
+ #
213
+ # 2. sign message
214
+ #
186
215
  r_msg = self.sign_message(msg=s_msg)
187
216
  if r_msg is None:
188
217
  # TODO: set msg.state = error
189
218
  raise AssertionError('failed to sign message: %s' % s_msg)
190
- # 3. send message
219
+ #
220
+ # 3. send message
221
+ #
191
222
  if self.send_reliable_message(msg=r_msg, priority=priority):
192
223
  return r_msg
193
224
  # failed
@@ -0,0 +1,70 @@
1
+ # -*- coding: utf-8 -*-
2
+ # ==============================================================================
3
+ # MIT License
4
+ #
5
+ # Copyright (c) 2023 Albert Moky
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ # SOFTWARE.
24
+ # ==============================================================================
25
+
26
+ from abc import ABC
27
+ from typing import List
28
+
29
+ from dimsdk import DateTime
30
+ from dimsdk import Content
31
+ from dimsdk import ReliableMessage
32
+ from dimsdk import MessageProcessor
33
+
34
+ from ..utils import Logging
35
+
36
+ from .archivist import CommonArchivist
37
+
38
+
39
+ # noinspection PyAbstractClass
40
+ class CommonMessageProcessor(MessageProcessor, Logging, ABC):
41
+
42
+ # private
43
+ # noinspection PyUnusedLocal
44
+ def _check_visa_time(self, content: Content, r_msg: ReliableMessage) -> bool:
45
+ facebook = self.facebook
46
+ archivist = facebook.archivist
47
+ assert isinstance(archivist, CommonArchivist), 'archivist error: %s' % archivist
48
+ doc_updated = False
49
+ # check sender document time
50
+ last_doc_time = r_msg.get_datetime(key='SDT', default=None)
51
+ if last_doc_time is not None:
52
+ now = DateTime.now()
53
+ if last_doc_time.after(now):
54
+ # calibrate the clock
55
+ last_doc_time = now
56
+ sender = r_msg.sender
57
+ doc_updated = archivist.set_last_document_time(identifier=sender, last_time=last_doc_time)
58
+ # check whether needs update
59
+ if doc_updated:
60
+ self.info(msg='checking for new visa: %s' % sender)
61
+ facebook.documents(identifier=sender)
62
+ return doc_updated
63
+
64
+ # Override
65
+ def process_content(self, content: Content, r_msg: ReliableMessage) -> List[Content]:
66
+ responses = super().process_content(content=content, r_msg=r_msg)
67
+ # check sender's document times from the message
68
+ # to make sure the user info synchronized
69
+ self._check_visa_time(content=content, r_msg=r_msg)
70
+ return responses
@@ -38,7 +38,7 @@ from startrek.net.state import StateOrder
38
38
  from startrek import Hub, Channel
39
39
  from startrek import Connection, ConnectionState, ActiveConnection
40
40
  from startrek import Docker, DockerDelegate
41
- from startrek import Arrival, StarGate
41
+ from startrek import Arrival, StarDocker, StarGate
42
42
 
43
43
  from ..utils import Logging
44
44
 
@@ -103,7 +103,9 @@ class CommonGate(StarGate, Logging, Generic[H], ABC):
103
103
  self._remove_docker(worker, remote=remote, local=local)
104
104
  worker = None
105
105
  else:
106
- worker.assign_connection(conn)
106
+ assert isinstance(worker, StarDocker), 'docker error: %s, %s' % (remote, worker)
107
+ # set connection for this docker
108
+ worker.set_connection(conn)
107
109
  return worker
108
110
 
109
111
  def send_response(self, payload: bytes, ship: Arrival,
@@ -139,8 +139,8 @@ def reset_send_buffer_size(conn: Connection = None, sock: socket.socket = None)
139
139
  size = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
140
140
  max_size = GateKeeper.SEND_BUFFER_SIZE
141
141
  if size < max_size:
142
- print('[SOCKET] change send buffer size: %d -> %d, %s' % (size, max_size, conn))
143
142
  sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, max_size)
143
+ print('[SOCKET] send buffer size changed: %d -> %d, %s' % (size, max_size, conn))
144
144
  return True
145
145
  else:
146
146
  print('[SOCKET] send buffer size: %d, %s' % (size, conn))
@@ -178,13 +178,12 @@ class GateKeeper(Runner, DockerDelegate, Logging):
178
178
  # TODO: reset send buffer size
179
179
  else:
180
180
  # server
181
- reset_send_buffer_size(sock=sock)
182
181
  sock.setblocking(False)
183
182
  # sock.settimeout(0.5)
184
183
  if address is None:
185
184
  address = get_remote_address(sock=sock)
186
185
  channel = StreamChannel(remote=address, local=get_local_address(sock=sock))
187
- channel.assign_socket(sock=sock)
186
+ channel.set_socket(sock=sock)
188
187
  hub = StreamServerHub(delegate=delegate)
189
188
  hub.put_channel(channel=channel)
190
189
  return hub
@@ -93,19 +93,21 @@ class GroupEmitter(Logging):
93
93
  def messenger(self) -> CommonMessenger:
94
94
  return self.delegate.messenger
95
95
 
96
- def __attach_group_times(self, group: ID, msg: InstantMessage):
96
+ # private
97
+ def _attach_group_times(self, group: ID, msg: InstantMessage) -> bool:
97
98
  if isinstance(msg.content, GroupCommand):
98
99
  # no need to attach times for group command
99
- return
100
+ return False
100
101
  facebook = self.facebook
101
102
  doc = facebook.bulletin(identifier=group)
102
103
  if doc is None:
103
104
  self.error(msg='failed to get bulletin document for group: %s' % group)
104
- return
105
+ return False
105
106
  # attach group document time
106
107
  last_doc_time = doc.time
107
108
  if last_doc_time is None:
108
109
  self.error(msg='document error: %s' % doc)
110
+ return False
109
111
  else:
110
112
  msg.set_datetime(key='GDT', value=last_doc_time)
111
113
  # attach group history time
@@ -113,8 +115,10 @@ class GroupEmitter(Logging):
113
115
  last_his_time = archivist.get_last_group_history_time(group=group)
114
116
  if last_his_time is None:
115
117
  self.error(msg='failed to get history time: %s' % group)
118
+ return False
116
119
  else:
117
120
  msg.set_datetime(key='GHT', value=last_his_time)
121
+ return True
118
122
 
119
123
  def send_message(self, msg: InstantMessage, priority: int = 0) -> Optional[ReliableMessage]:
120
124
  content = msg.content
@@ -125,7 +129,8 @@ class GroupEmitter(Logging):
125
129
  assert msg.receiver == group, 'group message error: %s' % msg
126
130
  # attach group document & history times
127
131
  # for the receiver to check whether group info synchronized
128
- self.__attach_group_times(group=group, msg=msg)
132
+ ok = self._attach_group_times(group=group, msg=msg)
133
+ assert ok or isinstance(msg.content, GroupCommand), 'failed to attach group times: %s => %s' % (group, content)
129
134
  # TODO: if it's a file message
130
135
  # please upload the file data first
131
136
  # before calling this
@@ -30,8 +30,9 @@
30
30
  Handshake Protocol
31
31
  """
32
32
 
33
- from typing import List
33
+ from typing import Optional, List
34
34
 
35
+ from dimsdk import DateTime
35
36
  from dimsdk import ID, Content, ReliableMessage
36
37
 
37
38
  from dimsdk.cpu import BaseCommandProcessor
@@ -75,7 +76,7 @@ class HandshakeCommandProcessor(BaseCommandProcessor):
75
76
  # session key match
76
77
  Log.info(msg='handshake accepted: %s, session: %s' % (sender, session.key))
77
78
  # verified success
78
- handshake_accepted(identifier=sender, session=session, messenger=messenger)
79
+ handshake_accepted(identifier=sender, when=content.time, session=session, messenger=messenger)
79
80
  res = HandshakeCommand.success(session=session.key)
80
81
  else:
81
82
  # session key not match
@@ -85,12 +86,12 @@ class HandshakeCommandProcessor(BaseCommandProcessor):
85
86
  return [res]
86
87
 
87
88
 
88
- def handshake_accepted(identifier: ID, session: Session, messenger: CommonMessenger):
89
+ def handshake_accepted(identifier: ID, when: Optional[DateTime], session: Session, messenger: CommonMessenger):
89
90
  from ..session_center import SessionCenter
90
91
  center = SessionCenter()
91
92
  # 1. update session ID
92
93
  center.update_session(session=session, identifier=identifier)
93
94
  # 2. update session flag
94
- session.set_active(active=True)
95
+ session.set_active(active=True, when=when)
95
96
  # 3. callback
96
97
  messenger.handshake_success()
@@ -85,7 +85,7 @@ class LoginCommandProcessor(BaseCommandProcessor, Logging):
85
85
  self.info(msg='user login: %s -> %s, forwarded by %s' % (sender, roaming, session.identifier))
86
86
  return []
87
87
  # 3. update session flag
88
- session.set_active(active=True)
88
+ session.set_active(active=True, when=content.time)
89
89
  # only respond the user login to this station
90
90
  self.info(msg='user login: %s -> %s' % (sender, roaming))
91
91
  text = 'Login received.'
@@ -38,16 +38,15 @@ from dimsdk import Envelope
38
38
  from dimsdk import Content, ContentType, Command
39
39
  from dimsdk import TextContent, ReceiptCommand
40
40
  from dimsdk import ContentProcessor, ContentProcessorCreator
41
- from dimsdk import MessageProcessor
42
41
 
43
42
  from dimsdk.cpu import BaseContentProcessor, BaseContentProcessorCreator
44
43
 
45
44
  from ..utils import get_msg_info
46
- from ..utils import Logging
47
45
  from ..common import HandshakeCommand, LoginCommand
48
46
  from ..common import ReportCommand, AnsCommand
49
47
  from ..common import CommonFacebook, CommonMessenger
50
48
  from ..common import CommonMessagePacker
49
+ from ..common import CommonMessageProcessor
51
50
 
52
51
  from .cpu import HandshakeCommandProcessor
53
52
  from .cpu import LoginCommandProcessor
@@ -61,7 +60,7 @@ from .dispatcher import Dispatcher
61
60
  from .archivist import ServerArchivist
62
61
 
63
62
 
64
- class ServerMessageProcessor(MessageProcessor, Logging):
63
+ class ServerMessageProcessor(CommonMessageProcessor):
65
64
 
66
65
  @property
67
66
  def messenger(self) -> CommonMessenger:
@@ -254,6 +254,6 @@ def remove_reliable_message(msg: ReliableMessage, receiver: ID, database: Messag
254
254
  # return False
255
255
  receiver = msg.receiver
256
256
  info = get_msg_info(msg=msg)
257
- print('[QUEUE] message sent for %s, remove from db: %s' % (receiver, info))
257
+ Log.info(msg='message sent for %s, remove from db: %s' % (receiver, info))
258
258
  # remove sent message from database
259
259
  return database.remove_reliable_message(msg=msg, receiver=receiver)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dimples
3
- Version: 0.5.0
3
+ Version: 0.5.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
@@ -38,6 +38,7 @@ dimples/common/archivist.py
38
38
  dimples/common/facebook.py
39
39
  dimples/common/messenger.py
40
40
  dimples/common/packer.py
41
+ dimples/common/processer.py
41
42
  dimples/common/register.py
42
43
  dimples/common/session.py
43
44
  dimples/common/compat/__init__.py
@@ -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.1.1
7
- tcp>=1.1.1
8
- udp>=1.1.1
6
+ startrek>=1.1.2
7
+ tcp>=1.1.2
8
+ udp>=1.1.2
@@ -14,7 +14,7 @@ import io
14
14
 
15
15
  from setuptools import setup, find_packages
16
16
 
17
- __version__ = '0.5.0'
17
+ __version__ = '0.5.2'
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.1.1',
62
- 'tcp>=1.1.1',
63
- 'udp>=1.1.1',
61
+ 'startrek>=1.1.2',
62
+ 'tcp>=1.1.2',
63
+ 'udp>=1.1.2',
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