diff --git a/synapse/handlers/directory.py b/synapse/handlers/directory.py
index 3cc6348906..df98e39f69 100644
--- a/synapse/handlers/directory.py
+++ b/synapse/handlers/directory.py
@@ -35,9 +35,11 @@ class DirectoryHandler(BaseHandler):
def __init__(self, hs):
super(DirectoryHandler, self).__init__(hs)
- self.hs = hs
- self.http_client = hs.get_http_client()
- self.clock = hs.get_clock()
+
+ self.federation = hs.get_replication_layer()
+ self.federation.register_query_handler(
+ "directory", self.on_directory_query
+ )
@defer.inlineCallbacks
def create_association(self, room_alias, room_id, servers):
@@ -58,9 +60,7 @@ class DirectoryHandler(BaseHandler):
)
@defer.inlineCallbacks
- def get_association(self, room_alias, local_only=False):
- # TODO(erikj): Do auth
-
+ def get_association(self, room_alias):
room_id = None
if room_alias.is_mine:
result = yield self.store.get_association_from_room_alias(
@@ -70,22 +70,13 @@ class DirectoryHandler(BaseHandler):
if result:
room_id = result.room_id
servers = result.servers
- elif not local_only:
- path = "%s/ds/room/%s?local_only=1" % (
- PREFIX,
- urllib.quote(room_alias.to_string())
+ else:
+ result = yield self.federation.make_query(
+ destination=room_alias.domain,
+ query_type="directory",
+ args={"room_alias": room_alias.to_string()},
)
- result = None
- try:
- result = yield self.http_client.get_json(
- destination=room_alias.domain,
- path=path,
- )
- except:
- # TODO(erikj): Handle this better?
- logger.exception("Failed to get remote room alias")
-
if result and "room_id" in result and "servers" in result:
room_id = result["room_id"]
servers = result["servers"]
@@ -99,3 +90,20 @@ class DirectoryHandler(BaseHandler):
"servers": servers,
})
return
+
+ @defer.inlineCallbacks
+ def on_directory_query(self, args):
+ room_alias = self.hs.parse_roomalias(args["room_alias"])
+ if not room_alias.is_mine:
+ raise SynapseError(
+ 400, "Room Alias is not hosted on this Home Server"
+ )
+
+ result = yield self.store.get_association_from_room_alias(
+ room_alias
+ )
+
+ defer.returnValue({
+ "room_id": result.room_id,
+ "servers": result.servers,
+ })
diff --git a/synapse/handlers/presence.py b/synapse/handlers/presence.py
index 1c24efd454..8bdb0fe5c7 100644
--- a/synapse/handlers/presence.py
+++ b/synapse/handlers/presence.py
@@ -56,6 +56,8 @@ class PresenceHandler(BaseHandler):
self.homeserver = hs
+ self.clock = hs.get_clock()
+
distributor = hs.get_distributor()
distributor.observe("registered_user", self.registered_user)
@@ -168,14 +170,15 @@ class PresenceHandler(BaseHandler):
state = yield self.store.get_presence_state(
target_user.localpart
)
- defer.returnValue(state)
else:
raise SynapseError(404, "Presence information not visible")
else:
# TODO(paul): Have remote server send us permissions set
- defer.returnValue(
- self._get_or_offline_usercache(target_user).get_state()
- )
+ state = self._get_or_offline_usercache(target_user).get_state()
+
+ if "mtime" in state:
+ state["mtime_age"] = self.clock.time_msec() - state.pop("mtime")
+ defer.returnValue(state)
@defer.inlineCallbacks
def set_state(self, target_user, auth_user, state):
@@ -209,6 +212,8 @@ class PresenceHandler(BaseHandler):
),
])
+ state["mtime"] = self.clock.time_msec()
+
now_online = state["state"] != PresenceState.OFFLINE
was_polling = target_user in self._user_cachemap
@@ -361,6 +366,8 @@ class PresenceHandler(BaseHandler):
observed_user = self.hs.parse_userid(p.pop("observed_user_id"))
p["observed_user"] = observed_user
p.update(self._get_or_offline_usercache(observed_user).get_state())
+ if "mtime" in p:
+ p["mtime_age"] = self.clock.time_msec() - p.pop("mtime")
defer.returnValue(presence)
@@ -546,10 +553,15 @@ class PresenceHandler(BaseHandler):
def _push_presence_remote(self, user, destination, state=None):
if state is None:
state = yield self.store.get_presence_state(user.localpart)
+
yield self.distributor.fire(
"collect_presencelike_data", user, state
)
+ if "mtime" in state:
+ state = dict(state)
+ state["mtime_age"] = self.clock.time_msec() - state.pop("mtime")
+
yield self.federation.send_edu(
destination=destination,
edu_type="m.presence",
@@ -585,6 +597,9 @@ class PresenceHandler(BaseHandler):
state = dict(push)
del state["user_id"]
+ if "mtime_age" in state:
+ state["mtime"] = self.clock.time_msec() - state.pop("mtime_age")
+
statuscache = self._get_or_make_usercache(user)
self._user_cachemap_latest_serial += 1
@@ -631,9 +646,14 @@ class PresenceHandler(BaseHandler):
def push_update_to_clients(self, observer_user, observed_user,
statuscache):
+ state = statuscache.make_event(user=observed_user, clock=self.clock)
+
self.notifier.on_new_user_event(
observer_user.to_string(),
- event_data=statuscache.make_event(user=observed_user),
+ event_data=statuscache.make_event(
+ user=observed_user,
+ clock=self.clock
+ ),
stream_type=PresenceStreamData,
store_id=statuscache.serial
)
@@ -652,8 +672,10 @@ class PresenceStreamData(StreamData):
if from_key < cachemap[k].serial <= to_key]
if updates:
+ clock = self.presence.clock
+
latest_serial = max([x[1].serial for x in updates])
- data = [x[1].make_event(user=x[0]) for x in updates]
+ data = [x[1].make_event(user=x[0], clock=clock) for x in updates]
return ((data, latest_serial))
else:
return (([], self.presence._user_cachemap_latest_serial))
@@ -674,6 +696,8 @@ class UserPresenceCache(object):
self.serial = None
def update(self, state, serial):
+ assert("mtime_age" not in state)
+
self.state.update(state)
# Delete keys that are now 'None'
for k in self.state.keys():
@@ -691,8 +715,11 @@ class UserPresenceCache(object):
# clone it so caller can't break our cache
return dict(self.state)
- def make_event(self, user):
+ def make_event(self, user, clock):
content = self.get_state()
content["user_id"] = user.to_string()
+ if "mtime" in content:
+ content["mtime_age"] = clock.time_msec() - content.pop("mtime")
+
return {"type": "m.presence", "content": content}
|