comparison sat/core/xmpp.py @ 2984:4bac4e734666

core (xmpp): set message timestamp on message reception: message timestamp was set during the parsing, but this could lead to misordering as async calls are done before message is parsed (so a variable delay could happen before the timestamp was set). This patch workaround this by setting timestamp as soon as message is received (in onMessage).
author Goffi <goffi@goffi.org>
date Tue, 02 Jul 2019 19:36:15 +0200
parents 97a1faca8f58
children 1d92ad95185f
comparison
equal deleted inserted replaced
2983:97a1faca8f58 2984:4bac4e734666
15 # GNU Affero General Public License for more details. 15 # GNU Affero General Public License for more details.
16 16
17 # You should have received a copy of the GNU Affero General Public License 17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19
20 import sys
21 import time
22 import calendar
23 import uuid
20 from functools import partial 24 from functools import partial
21 from sat.core.i18n import _ 25 from sat.core.i18n import _
22 from sat.core.constants import Const as C 26 from sat.core.constants import Const as C
23 from sat.memory import cache 27 from sat.memory import cache
24 from twisted.internet import defer, error as internet_error 28 from twisted.internet import defer, error as internet_error
35 from sat.core import exceptions 39 from sat.core import exceptions
36 from sat.memory import encryption 40 from sat.memory import encryption
37 from sat.memory import persistent 41 from sat.memory import persistent
38 from sat.tools import xml_tools 42 from sat.tools import xml_tools
39 from zope.interface import implements 43 from zope.interface import implements
40 import time
41 import calendar
42 import uuid
43 import sys
44 44
45 log = getLogger(__name__) 45 log = getLogger(__name__)
46 46
47 47
48 NS_X_DATA = u"jabber:x:data" 48 NS_X_DATA = u"jabber:x:data"
1012 for e in message_elt.elements(C.NS_CLIENT, "subject"): 1012 for e in message_elt.elements(C.NS_CLIENT, "subject"):
1013 subject[e.getAttribute((C.NS_XML, "lang"), "")] = unicode(e) 1013 subject[e.getAttribute((C.NS_XML, "lang"), "")] = unicode(e)
1014 1014
1015 # delay and timestamp 1015 # delay and timestamp
1016 try: 1016 try:
1017 received_timestamp = message_elt._received_timestamp
1018 except AttributeError:
1019 # message_elt._received_timestamp should have been set in onMessage
1020 # but if parseMessage is called directly, it can be missing
1021 log.debug(u"missing received timestamp for {message_elt}".format(
1022 message_elt=message_elt))
1023 received_timestamp = time.time()
1024
1025 try:
1017 delay_elt = message_elt.elements(delay.NS_DELAY, "delay").next() 1026 delay_elt = message_elt.elements(delay.NS_DELAY, "delay").next()
1018 except StopIteration: 1027 except StopIteration:
1019 data["timestamp"] = time.time() 1028 data["timestamp"] = received_timestamp
1020 else: 1029 else:
1021 parsed_delay = delay.Delay.fromElement(delay_elt) 1030 parsed_delay = delay.Delay.fromElement(delay_elt)
1022 data["timestamp"] = calendar.timegm(parsed_delay.stamp.utctimetuple()) 1031 data["timestamp"] = calendar.timegm(parsed_delay.stamp.utctimetuple())
1023 data["received_timestamp"] = unicode(time.time()) 1032 data["received_timestamp"] = received_timestamp
1024 if parsed_delay.sender: 1033 if parsed_delay.sender:
1025 data["delay_sender"] = parsed_delay.sender.full() 1034 data["delay_sender"] = parsed_delay.sender.full()
1026 1035
1027 self.host.trigger.point("message_parse", client, message_elt, data) 1036 self.host.trigger.point("message_parse", client, message_elt, data)
1028 return data 1037 return data
1045 post_treat.addErrback(self.cancelErrorTrap) 1054 post_treat.addErrback(self.cancelErrorTrap)
1046 post_treat.callback(data) 1055 post_treat.callback(data)
1047 1056
1048 def onMessage(self, message_elt): 1057 def onMessage(self, message_elt):
1049 # TODO: handle threads 1058 # TODO: handle threads
1059 message_elt._received_timestamp = time.time()
1050 client = self.parent 1060 client = self.parent
1051 if not "from" in message_elt.attributes: 1061 if not "from" in message_elt.attributes:
1052 message_elt["from"] = client.jid.host 1062 message_elt["from"] = client.jid.host
1053 log.debug(_(u"got message from: {from_}").format(from_=message_elt["from"])) 1063 log.debug(_(u"got message from: {from_}").format(from_=message_elt["from"]))
1054 1064
1077 log.debug(u"not storing empty message to history: {data}" 1087 log.debug(u"not storing empty message to history: {data}"
1078 .format(data=data)) 1088 .format(data=data))
1079 1089
1080 def bridgeSignal(self, __, data): 1090 def bridgeSignal(self, __, data):
1081 try: 1091 try:
1082 data["extra"]["received_timestamp"] = data["received_timestamp"] 1092 data["extra"]["received_timestamp"] = unicode(data["received_timestamp"])
1083 data["extra"]["delay_sender"] = data["delay_sender"] 1093 data["extra"]["delay_sender"] = data["delay_sender"]
1084 except KeyError: 1094 except KeyError:
1085 pass 1095 pass
1086 if C.MESS_KEY_ENCRYPTION in data: 1096 if C.MESS_KEY_ENCRYPTION in data:
1087 data[u"extra"][u"encrypted"] = C.BOOL_TRUE 1097 data[u"extra"][u"encrypted"] = C.BOOL_TRUE