Improved link error handling. Fixes #387.
This commit is contained in:
parent
3d645ae2f4
commit
a4143cfe6d
215
RNS/Link.py
215
RNS/Link.py
|
@ -392,19 +392,20 @@ class Link:
|
|||
try:
|
||||
measured_rtt = time.time() - self.request_time
|
||||
plaintext = self.decrypt(packet.data)
|
||||
rtt = umsgpack.unpackb(plaintext)
|
||||
self.rtt = max(measured_rtt, rtt)
|
||||
self.status = Link.ACTIVE
|
||||
self.activated_at = time.time()
|
||||
if plaintext != None:
|
||||
rtt = umsgpack.unpackb(plaintext)
|
||||
self.rtt = max(measured_rtt, rtt)
|
||||
self.status = Link.ACTIVE
|
||||
self.activated_at = time.time()
|
||||
|
||||
if self.rtt != None and self.establishment_cost != None and self.rtt > 0 and self.establishment_cost > 0:
|
||||
self.establishment_rate = self.establishment_cost/self.rtt
|
||||
if self.rtt != None and self.establishment_cost != None and self.rtt > 0 and self.establishment_cost > 0:
|
||||
self.establishment_rate = self.establishment_cost/self.rtt
|
||||
|
||||
try:
|
||||
if self.owner.callbacks.link_established != None:
|
||||
self.owner.callbacks.link_established(self)
|
||||
except Exception as e:
|
||||
RNS.log("Error occurred in external link establishment callback. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
try:
|
||||
if self.owner.callbacks.link_established != None:
|
||||
self.owner.callbacks.link_established(self)
|
||||
except Exception as e:
|
||||
RNS.log("Error occurred in external link establishment callback. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
except Exception as e:
|
||||
RNS.log("Error occurred while processing RTT packet, tearing down link. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
|
@ -748,65 +749,68 @@ class Link:
|
|||
should_query = False
|
||||
if packet.context == RNS.Packet.NONE:
|
||||
plaintext = self.decrypt(packet.data)
|
||||
if self.callbacks.packet != None:
|
||||
thread = threading.Thread(target=self.callbacks.packet, args=(plaintext, packet))
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
if self.destination.proof_strategy == RNS.Destination.PROVE_ALL:
|
||||
packet.prove()
|
||||
should_query = True
|
||||
if plaintext != None:
|
||||
if self.callbacks.packet != None:
|
||||
thread = threading.Thread(target=self.callbacks.packet, args=(plaintext, packet))
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
if self.destination.proof_strategy == RNS.Destination.PROVE_ALL:
|
||||
packet.prove()
|
||||
should_query = True
|
||||
|
||||
elif self.destination.proof_strategy == RNS.Destination.PROVE_APP:
|
||||
if self.destination.callbacks.proof_requested:
|
||||
try:
|
||||
if self.destination.callbacks.proof_requested(packet):
|
||||
packet.prove()
|
||||
should_query = True
|
||||
except Exception as e:
|
||||
RNS.log("Error while executing proof request callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
elif self.destination.proof_strategy == RNS.Destination.PROVE_APP:
|
||||
if self.destination.callbacks.proof_requested:
|
||||
try:
|
||||
if self.destination.callbacks.proof_requested(packet):
|
||||
packet.prove()
|
||||
should_query = True
|
||||
except Exception as e:
|
||||
RNS.log("Error while executing proof request callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
self.__update_phy_stats(packet, query_shared=should_query)
|
||||
self.__update_phy_stats(packet, query_shared=should_query)
|
||||
|
||||
elif packet.context == RNS.Packet.LINKIDENTIFY:
|
||||
plaintext = self.decrypt(packet.data)
|
||||
if plaintext != None:
|
||||
if not self.initiator and len(plaintext) == RNS.Identity.KEYSIZE//8 + RNS.Identity.SIGLENGTH//8:
|
||||
public_key = plaintext[:RNS.Identity.KEYSIZE//8]
|
||||
signed_data = self.link_id+public_key
|
||||
signature = plaintext[RNS.Identity.KEYSIZE//8:RNS.Identity.KEYSIZE//8+RNS.Identity.SIGLENGTH//8]
|
||||
identity = RNS.Identity(create_keys=False)
|
||||
identity.load_public_key(public_key)
|
||||
|
||||
if not self.initiator and len(plaintext) == RNS.Identity.KEYSIZE//8 + RNS.Identity.SIGLENGTH//8:
|
||||
public_key = plaintext[:RNS.Identity.KEYSIZE//8]
|
||||
signed_data = self.link_id+public_key
|
||||
signature = plaintext[RNS.Identity.KEYSIZE//8:RNS.Identity.KEYSIZE//8+RNS.Identity.SIGLENGTH//8]
|
||||
identity = RNS.Identity(create_keys=False)
|
||||
identity.load_public_key(public_key)
|
||||
|
||||
if identity.validate(signature, signed_data):
|
||||
self.__remote_identity = identity
|
||||
if self.callbacks.remote_identified != None:
|
||||
try:
|
||||
self.callbacks.remote_identified(self, self.__remote_identity)
|
||||
except Exception as e:
|
||||
RNS.log("Error while executing remote identified callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
self.__update_phy_stats(packet, query_shared=True)
|
||||
if identity.validate(signature, signed_data):
|
||||
self.__remote_identity = identity
|
||||
if self.callbacks.remote_identified != None:
|
||||
try:
|
||||
self.callbacks.remote_identified(self, self.__remote_identity)
|
||||
except Exception as e:
|
||||
RNS.log("Error while executing remote identified callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
self.__update_phy_stats(packet, query_shared=True)
|
||||
|
||||
elif packet.context == RNS.Packet.REQUEST:
|
||||
try:
|
||||
request_id = packet.getTruncatedHash()
|
||||
packed_request = self.decrypt(packet.data)
|
||||
unpacked_request = umsgpack.unpackb(packed_request)
|
||||
self.handle_request(request_id, unpacked_request)
|
||||
self.__update_phy_stats(packet, query_shared=True)
|
||||
if packed_request != None:
|
||||
unpacked_request = umsgpack.unpackb(packed_request)
|
||||
self.handle_request(request_id, unpacked_request)
|
||||
self.__update_phy_stats(packet, query_shared=True)
|
||||
except Exception as e:
|
||||
RNS.log("Error occurred while handling request. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
elif packet.context == RNS.Packet.RESPONSE:
|
||||
try:
|
||||
packed_response = self.decrypt(packet.data)
|
||||
unpacked_response = umsgpack.unpackb(packed_response)
|
||||
request_id = unpacked_response[0]
|
||||
response_data = unpacked_response[1]
|
||||
transfer_size = len(umsgpack.packb(response_data))-2
|
||||
self.handle_response(request_id, response_data, transfer_size, transfer_size)
|
||||
self.__update_phy_stats(packet, query_shared=True)
|
||||
if packed_response != None:
|
||||
unpacked_response = umsgpack.unpackb(packed_response)
|
||||
request_id = unpacked_response[0]
|
||||
response_data = unpacked_response[1]
|
||||
transfer_size = len(umsgpack.packb(response_data))-2
|
||||
self.handle_response(request_id, response_data, transfer_size, transfer_size)
|
||||
self.__update_phy_stats(packet, query_shared=True)
|
||||
except Exception as e:
|
||||
RNS.log("Error occurred while handling response. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
|
||||
|
@ -821,63 +825,67 @@ class Link:
|
|||
|
||||
elif packet.context == RNS.Packet.RESOURCE_ADV:
|
||||
packet.plaintext = self.decrypt(packet.data)
|
||||
self.__update_phy_stats(packet, query_shared=True)
|
||||
if packet.plaintext != None:
|
||||
self.__update_phy_stats(packet, query_shared=True)
|
||||
|
||||
if RNS.ResourceAdvertisement.is_request(packet):
|
||||
RNS.Resource.accept(packet, callback=self.request_resource_concluded)
|
||||
elif RNS.ResourceAdvertisement.is_response(packet):
|
||||
request_id = RNS.ResourceAdvertisement.read_request_id(packet)
|
||||
for pending_request in self.pending_requests:
|
||||
if pending_request.request_id == request_id:
|
||||
RNS.Resource.accept(packet, callback=self.response_resource_concluded, progress_callback=pending_request.response_resource_progress, request_id = request_id)
|
||||
pending_request.response_size = RNS.ResourceAdvertisement.read_size(packet)
|
||||
pending_request.response_transfer_size = RNS.ResourceAdvertisement.read_transfer_size(packet)
|
||||
pending_request.started_at = time.time()
|
||||
elif self.resource_strategy == Link.ACCEPT_NONE:
|
||||
pass
|
||||
elif self.resource_strategy == Link.ACCEPT_APP:
|
||||
if self.callbacks.resource != None:
|
||||
try:
|
||||
resource_advertisement = RNS.ResourceAdvertisement.unpack(packet.plaintext)
|
||||
resource_advertisement.link = self
|
||||
if self.callbacks.resource(resource_advertisement):
|
||||
RNS.Resource.accept(packet, self.callbacks.resource_concluded)
|
||||
except Exception as e:
|
||||
RNS.log("Error while executing resource accept callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
elif self.resource_strategy == Link.ACCEPT_ALL:
|
||||
RNS.Resource.accept(packet, self.callbacks.resource_concluded)
|
||||
if RNS.ResourceAdvertisement.is_request(packet):
|
||||
RNS.Resource.accept(packet, callback=self.request_resource_concluded)
|
||||
elif RNS.ResourceAdvertisement.is_response(packet):
|
||||
request_id = RNS.ResourceAdvertisement.read_request_id(packet)
|
||||
for pending_request in self.pending_requests:
|
||||
if pending_request.request_id == request_id:
|
||||
RNS.Resource.accept(packet, callback=self.response_resource_concluded, progress_callback=pending_request.response_resource_progress, request_id = request_id)
|
||||
pending_request.response_size = RNS.ResourceAdvertisement.read_size(packet)
|
||||
pending_request.response_transfer_size = RNS.ResourceAdvertisement.read_transfer_size(packet)
|
||||
pending_request.started_at = time.time()
|
||||
elif self.resource_strategy == Link.ACCEPT_NONE:
|
||||
pass
|
||||
elif self.resource_strategy == Link.ACCEPT_APP:
|
||||
if self.callbacks.resource != None:
|
||||
try:
|
||||
resource_advertisement = RNS.ResourceAdvertisement.unpack(packet.plaintext)
|
||||
resource_advertisement.link = self
|
||||
if self.callbacks.resource(resource_advertisement):
|
||||
RNS.Resource.accept(packet, self.callbacks.resource_concluded)
|
||||
except Exception as e:
|
||||
RNS.log("Error while executing resource accept callback from "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
elif self.resource_strategy == Link.ACCEPT_ALL:
|
||||
RNS.Resource.accept(packet, self.callbacks.resource_concluded)
|
||||
|
||||
elif packet.context == RNS.Packet.RESOURCE_REQ:
|
||||
plaintext = self.decrypt(packet.data)
|
||||
self.__update_phy_stats(packet, query_shared=True)
|
||||
if ord(plaintext[:1]) == RNS.Resource.HASHMAP_IS_EXHAUSTED:
|
||||
resource_hash = plaintext[1+RNS.Resource.MAPHASH_LEN:RNS.Identity.HASHLENGTH//8+1+RNS.Resource.MAPHASH_LEN]
|
||||
else:
|
||||
resource_hash = plaintext[1:RNS.Identity.HASHLENGTH//8+1]
|
||||
if plaintext != None:
|
||||
self.__update_phy_stats(packet, query_shared=True)
|
||||
if ord(plaintext[:1]) == RNS.Resource.HASHMAP_IS_EXHAUSTED:
|
||||
resource_hash = plaintext[1+RNS.Resource.MAPHASH_LEN:RNS.Identity.HASHLENGTH//8+1+RNS.Resource.MAPHASH_LEN]
|
||||
else:
|
||||
resource_hash = plaintext[1:RNS.Identity.HASHLENGTH//8+1]
|
||||
|
||||
for resource in self.outgoing_resources:
|
||||
if resource.hash == resource_hash:
|
||||
# We need to check that this request has not been
|
||||
# received before in order to avoid sequencing errors.
|
||||
if not packet.packet_hash in resource.req_hashlist:
|
||||
resource.req_hashlist.append(packet.packet_hash)
|
||||
resource.request(plaintext)
|
||||
for resource in self.outgoing_resources:
|
||||
if resource.hash == resource_hash:
|
||||
# We need to check that this request has not been
|
||||
# received before in order to avoid sequencing errors.
|
||||
if not packet.packet_hash in resource.req_hashlist:
|
||||
resource.req_hashlist.append(packet.packet_hash)
|
||||
resource.request(plaintext)
|
||||
|
||||
elif packet.context == RNS.Packet.RESOURCE_HMU:
|
||||
plaintext = self.decrypt(packet.data)
|
||||
self.__update_phy_stats(packet, query_shared=True)
|
||||
resource_hash = plaintext[:RNS.Identity.HASHLENGTH//8]
|
||||
for resource in self.incoming_resources:
|
||||
if resource_hash == resource.hash:
|
||||
resource.hashmap_update_packet(plaintext)
|
||||
if plaintext != None:
|
||||
self.__update_phy_stats(packet, query_shared=True)
|
||||
resource_hash = plaintext[:RNS.Identity.HASHLENGTH//8]
|
||||
for resource in self.incoming_resources:
|
||||
if resource_hash == resource.hash:
|
||||
resource.hashmap_update_packet(plaintext)
|
||||
|
||||
elif packet.context == RNS.Packet.RESOURCE_ICL:
|
||||
plaintext = self.decrypt(packet.data)
|
||||
self.__update_phy_stats(packet)
|
||||
resource_hash = plaintext[:RNS.Identity.HASHLENGTH//8]
|
||||
for resource in self.incoming_resources:
|
||||
if resource_hash == resource.hash:
|
||||
resource.cancel()
|
||||
if plaintext != None:
|
||||
self.__update_phy_stats(packet)
|
||||
resource_hash = plaintext[:RNS.Identity.HASHLENGTH//8]
|
||||
for resource in self.incoming_resources:
|
||||
if resource_hash == resource.hash:
|
||||
resource.cancel()
|
||||
|
||||
elif packet.context == RNS.Packet.KEEPALIVE:
|
||||
if not self.initiator and packet.data == bytes([0xFF]):
|
||||
|
@ -909,13 +917,15 @@ class Link:
|
|||
# else:
|
||||
# packet.prove()
|
||||
# plaintext = self.decrypt(packet.data)
|
||||
# self._channel._receive(plaintext)
|
||||
# if plaintext != None:
|
||||
# self._channel._receive(plaintext)
|
||||
############################################
|
||||
|
||||
packet.prove()
|
||||
plaintext = self.decrypt(packet.data)
|
||||
self.__update_phy_stats(packet)
|
||||
self._channel._receive(plaintext)
|
||||
if plaintext != None:
|
||||
self.__update_phy_stats(packet)
|
||||
self._channel._receive(plaintext)
|
||||
|
||||
elif packet.packet_type == RNS.Packet.PROOF:
|
||||
if packet.context == RNS.Packet.RESOURCE_PRF:
|
||||
|
@ -953,6 +963,7 @@ class Link:
|
|||
|
||||
except Exception as e:
|
||||
RNS.log("Decryption failed on link "+str(self)+". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
return None
|
||||
|
||||
|
||||
def sign(self, message):
|
||||
|
|
Loading…
Reference in New Issue