def check_duplex_connection(self): logging.debug("Remote: checking duplex with '%s'" % self.display_hostname) ret = self.stub.CheckDuplexConnection( warp_pb2.LookupName(id=self.local_ident, readable_name=util.get_hostname())) return ret.response
def wait_for_duplex(self): logging.debug("Remote: waiting for duplex from '%s'" % self.display_hostname) future = self.stub.WaitingForDuplex.future( warp_pb2.LookupName(id=self.local_ident, readable_name=util.get_hostname())) return future
def update_remote_machine_avatar(self): logging.debug("Remote RPC: calling GetRemoteMachineAvatar on '%s'" % self.display_hostname) iterator = self.stub.GetRemoteMachineAvatar( warp_pb2.LookupName(id=self.local_ident, readable_name=util.get_hostname())) loader = None try: for info in iterator: if loader == None: loader = util.CairoSurfaceLoader() loader.add_bytes(info.avatar_chunk) except grpc.RpcError as e: logging.debug( "Remote RPC: could not fetch remote avatar, using a generic one. (%s, %s)" % (e.code(), e.details())) self.get_avatar_surface(loader)
def update_remote_machine_info(self): logging.debug("Remote RPC: calling GetRemoteMachineInfo on '%s'" % self.display_hostname) def get_info_finished(future): info = future.result() self.display_name = info.display_name self.user_name = info.user_name self.favorite = prefs.get_is_favorite(self.ident) valid = GLib.utf8_make_valid(self.display_name, -1) self.sort_key = GLib.utf8_collate_key(valid.lower(), -1) self.emit_machine_info_changed() self.set_remote_status(RemoteStatus.ONLINE) future = self.stub.GetRemoteMachineInfo.future( warp_pb2.LookupName(id=self.local_ident, readable_name=util.get_hostname())) future.add_done_callback(get_info_finished)
def run_secure_loop(): logging.debug( "Remote: Starting a new connection loop for %s (%s:%d)" % (self.display_hostname, self.ip_address, self.port)) cert = auth.get_singleton().load_cert(self.hostname, self.ip_address) creds = grpc.ssl_channel_credentials(cert) with grpc.secure_channel("%s:%d" % (self.ip_address, self.port), creds) as channel: future = grpc.channel_ready_future(channel) try: future.result(timeout=4) self.stub = warp_pb2_grpc.WarpStub(channel) except grpc.FutureTimeoutError: self.set_remote_status(RemoteStatus.UNREACHABLE) future.cancel() if not self.ping_timer.is_set(): logging.debug( "Remote: Unable to establish secure connection with %s (%s:%d). Trying again in %ds" % (self.display_hostname, self.ip_address, self.port, CHANNEL_RETRY_WAIT_TIME)) self.ping_timer.wait(CHANNEL_RETRY_WAIT_TIME) return True # run_secure_loop() return False # run_secure_loop() duplex_fail_counter = 0 one_ping = False # A successful duplex response lets us finish setting things up. while not self.ping_timer.is_set(): if self.busy: logging.debug( "Remote Ping: Skipping keepalive ping to %s (%s:%d) (busy)" % (self.display_hostname, self.ip_address, self.port)) self.busy = False else: try: # t = GLib.get_monotonic_time() logging.debug("Remote Ping: to %s (%s:%d)" % (self.display_hostname, self.ip_address, self.port)) self.stub.Ping(warp_pb2.LookupName( id=self.local_ident, readable_name=util.get_hostname()), timeout=5) # logging.debug("Latency: %s (%s)" # % (util.precise_format_time_span(GLib.get_monotonic_time() - t), self.display_hostname)) if not one_ping: self.set_remote_status( RemoteStatus.AWAITING_DUPLEX) if self.check_duplex_connection(): logging.debug( "Remote: Connected to %s (%s:%d)" % (self.display_hostname, self.ip_address, self.port)) self.set_remote_status(RemoteStatus.ONLINE) self.rpc_call( self.update_remote_machine_info) self.rpc_call( self.update_remote_machine_avatar) one_ping = True else: duplex_fail_counter += 1 if duplex_fail_counter > DUPLEX_MAX_FAILURES: logging.debug( "Remote: CheckDuplexConnection to %s (%s:%d) failed too many times" % (self.display_hostname, self.ip_address, self.port)) self.ping_timer.wait( CHANNEL_RETRY_WAIT_TIME) return True except grpc.RpcError as e: logging.debug( "Remote: Ping failed, shutting down %s (%s:%d)" % (self.display_hostname, self.ip_address, self.port)) break self.ping_timer.wait( CONNECTED_PING_TIME if self.status == RemoteStatus.ONLINE else DUPLEX_WAIT_PING_TIME) # This is reached by the RpcError break above. If the remote is still discoverable, start # the secure loop over. This could have happened as a result of a quick disco/reconnect, # And we don't notice until it has already come back. In this case, try a new connection. if self.has_zc_presence and not self.ping_timer.is_set(): return True # run_secure_loop() # The ping timer has been triggered, this is an orderly shutdown. return False # run_secure_loop()
def check_duplex_connection(self): ret = self.stub.CheckDuplexConnection( warp_pb2.LookupName(id=self.local_ident)) return ret.response