def lookup(self, dest_ip6): logging.pktdump("Lookup: {0} pending lookup:{1}".format(dest_ip6, self.lookup_req)) if dest_ip6 in self.lookup_req: return # If no response from the lookup_request message at a certain time. Cancel the # request self.lookup_req[dest_ip6] = { "ttl" : CONFIG["multihop_ihc"]} timer = Timer(CONFIG["multihop_tl"], self.lookup_timeout, args=[dest_ip6]) timer.start() self.flood(dest_ip6, CONFIG["multihop_ihc"])
def lookup(self, dest_ip6): logging.pktdump("Lookup: {0} pending lookup:{1}".format(dest_ip6, \ self.lookup_req)) if dest_ip6 in self.lookup_req: return # If no response from the lookup_request message at a certain time. # Cancel the request self.lookup_req[dest_ip6] = { "ttl" : CONFIG["multihop_ihc"]} timer = Timer(CONFIG["multihop_tl"], self.lookup_timeout, \ args=[dest_ip6]) timer.start() self.flood(dest_ip6, CONFIG["multihop_ihc"])
def multihop_handle(self, data): if data[0] != ipop_ver: logging.error("ipop version mismatch: tincan:{0} controller:{1}" "".format(data[0].encode("hex"), ipop_ver.encode("hex"))) if data[1] == tincan_control: msg = json.loads(data[2:]) logging.debug("multihop control message recv {0}".format(msg)) msg_type = msg.get("msg_type", None) if msg_type == "lookup_request": #If this message visit here before, just drop it for via in msg["via"][:-1]: if self.ipop_state["_ip6"] == via: return # found in peer, do lookup_reply for k, v in self.peers.iteritems(): if "ip6" in v and v["ip6"] == msg["target_ip6"]: # IP is found in my peers, # send reply message back to previous sender make_remote_call(sock=self.cc_sock,\ dest_addr=msg["via"][-2],\ dest_port=CONFIG["icc_port"], m_type=tincan_control,\ payload=None, msg_type="lookup_reply",\ target_ip6=msg["target_ip6"], via=msg["via"], via_idx=-2) return # not found in peer, add current node to via then flood # lookup_request for k, v in self.peers.iteritems(): #Do not send lookup_request back to previous hop logging.pktdump("k:{0}, v:{1}".format(k, v)) if "ip6" in v and msg["via"][-2] == v["ip6"]: continue # Flood lookup_request if "ip6" in v and msg["ttl"] > 1: make_remote_call(sock=self.cc_sock, dest_addr=v["ip6"],\ dest_port=CONFIG["icc_port"], m_type=tincan_control,\ payload=None, msg_type="lookup_request",\ ttl=msg["ttl"]-1, target_ip6=msg["target_ip6"],\ via=msg["via"] + [v["ip6"]]) if msg_type == "lookup_reply": if CONFIG["multihop_sr"]: if ~msg["via_idx"] + 1 == len(msg["via"]): # In source route mode, only source node updates route # information self.update_farpeers(msg["target_ip6"], len(msg["via"]), msg["via"]) if msg["target_ip6"] in self.lookup_req: del self.lookup_req[msg["target_ip6"]] return else: # Non source route mode, route information is kept at each # hop. Each node only keeps the next hop info self.update_farpeers(msg["target_ip6"], len(msg["via"]),\ msg["via"][msg["via_idx"]+1]) # Send lookup_reply message back to the source make_remote_call(sock=self.cc_sock,\ dest_addr=msg["via"][msg["via_idx"]-1],\ dest_port=CONFIG["icc_port"], m_type=tincan_control,\ payload=None, msg_type="lookup_reply",\ target_ip6=msg["target_ip6"],\ via=msg["via"], via_idx=msg["via_idx"]-1) if msg_type == "route_error": if msg["index"] == 0: del self.far_peers[msg["via"][-1]] else: make_remote_call(sock=self.cc_sock,\ dest_addr=msg["via"][msg["index"]-1],\ dest_port=CONFIG["icc_port"], m_type=tincan_control,\ payload=None, msg_type="route_error",\ index=msg["index"]-1, via=msg["via"])\ if data[1] == tincan_packet: target_ip6 = ip6_b2a(data[40:56]) logging.pktdump( "Multihop Packet Destined to {0}".format(target_ip6)) if target_ip6 == self.ipop_state["_ip6"]: make_call(self.sock, payload=null_uid + null_uid + data[2:]) return # The packet destined to its direct peers for k, v in self.peers.iteritems(): if "ip6" in v and v["ip6"] == target_ip6: make_remote_call(sock=self.cc_sock, dest_addr=target_ip6,\ dest_port=CONFIG["icc_port"], m_type=tincan_packet,\ payload=data[2:]) return # The packet is not in direct peers but have route information if ip6_b2a(data[40:56]) in self.far_peers: make_remote_call(sock=self.cc_sock,\ dest_addr=self.far_peers[target_ip6]["via"],\ dest_port=CONFIG["icc_port"], m_type=tincan_packet,\ payload=data[2:]) return logging.error("Unroutable packet. Oops this should not happen") if data[1] == tincan_sr6: logging.pktdump("Multihop packet received", dump=data) hop_index = ord(data[2]) + 1 hop_count = ord(data[3]) if hop_index == hop_count: make_call(self.sock, payload=null_uid + null_uid +\ data[4+(hop_index)*16:]) return packet = chr(hop_index) packet += data[3:] next_addr_offset = 4 + (hop_index) * 16 next_hop_addr = data[next_addr_offset:next_addr_offset + 16] for k, v in self.peers.iteritems(): if v["ip6"] == ip6_b2a( next_hop_addr) and v["status"] == "online": make_remote_call(sock=self.cc_sock,\ dest_addr=ip6_b2a(next_hop_addr),\ dest_port=CONFIG["icc_port"], m_type=tincan_sr6,\ payload=packet) return via = [] for i in range(hop_count): via.append(ip6_b2a(data[4 + i * 16:4 + 16 * i + 16])) make_remote_call(sock=self.cc_sock, dest_addr=via[hop_index-2],\ dest_port=CONFIG["icc_port"], m_type=tincan_control,\ payload=None, msg_type="route_error", via=via, index=hop_index-2) logging.debug( "Link lost send back route_error message to source{0}" "".format(via[hop_index - 2]))
def multihop_handle(self, data): if data[0] != ipop_ver: logging.error("ipop version mismatch: tincan:{0} controller:{1}" "".format(data[0].encode("hex"), ipop_ver.encode("hex"))) if data[1] == tincan_control: msg = json.loads(data[2:]) logging.debug("multihop control message recv {0}".format(msg)) msg_type = msg.get("msg_type", None) if msg_type == "lookup_request": #If this message visit here before, just drop it for via in msg["via"][:-1]: if self.ipop_state["_ip6"] == via: return # found in peer, do lookup_reply for k, v in self.peers.iteritems(): if "ip6" in v and v["ip6"] == msg["target_ip6"]: # IP is found in my peers, # send reply message back to previous sender make_remote_call(sock=self.cc_sock,\ dest_addr=msg["via"][-2],\ dest_port=CONFIG["icc_port"], m_type=tincan_control,\ payload=None, msg_type="lookup_reply",\ target_ip6=msg["target_ip6"], via=msg["via"], via_idx=-2) return # not found in peer, add current node to via then flood # lookup_request for k, v in self.peers.iteritems(): #Do not send lookup_request back to previous hop logging.pktdump("k:{0}, v:{1}".format(k, v)) if "ip6" in v and msg["via"][-2] == v["ip6"]: continue # Flood lookup_request if "ip6" in v and msg["ttl"] > 1: make_remote_call(sock=self.cc_sock, dest_addr=v["ip6"],\ dest_port=CONFIG["icc_port"], m_type=tincan_control,\ payload=None, msg_type="lookup_request",\ ttl=msg["ttl"]-1, target_ip6=msg["target_ip6"],\ via=msg["via"] + [v["ip6"]]) if msg_type == "lookup_reply": if CONFIG["multihop_sr"]: if ~msg["via_idx"]+1==len(msg["via"]): # In source route mode, only source node updates route # information self.update_farpeers(msg["target_ip6"],len(msg["via"]), msg["via"]) if msg["target_ip6"] in self.lookup_req: del self.lookup_req[msg["target_ip6"]] return else: # Non source route mode, route information is kept at each # hop. Each node only keeps the next hop info self.update_farpeers(msg["target_ip6"], len(msg["via"]),\ msg["via"][msg["via_idx"]+1]) # Send lookup_reply message back to the source make_remote_call(sock=self.cc_sock,\ dest_addr=msg["via"][msg["via_idx"]-1],\ dest_port=CONFIG["icc_port"], m_type=tincan_control,\ payload=None, msg_type="lookup_reply",\ target_ip6=msg["target_ip6"],\ via=msg["via"], via_idx=msg["via_idx"]-1) if msg_type == "route_error": if msg["index"] == 0: del self.far_peers[msg["via"][-1]] else: make_remote_call(sock=self.cc_sock,\ dest_addr=msg["via"][msg["index"]-1],\ dest_port=CONFIG["icc_port"], m_type=tincan_control,\ payload=None, msg_type="route_error",\ index=msg["index"]-1, via=msg["via"])\ if data[1] == tincan_packet: target_ip6=ip6_b2a(data[40:56]) logging.pktdump("Multihop Packet Destined to {0}".format(target_ip6)) if target_ip6 == self.ipop_state["_ip6"]: make_call(self.sock, payload=null_uid + null_uid + data[2:]) return # The packet destined to its direct peers for k, v in self.peers.iteritems(): if "ip6" in v and v["ip6"] == target_ip6: make_remote_call(sock=self.cc_sock, dest_addr=target_ip6,\ dest_port=CONFIG["icc_port"], m_type=tincan_packet,\ payload=data[2:]) return # The packet is not in direct peers but have route information if ip6_b2a(data[40:56]) in self.far_peers: make_remote_call(sock=self.cc_sock,\ dest_addr=self.far_peers[target_ip6]["via"],\ dest_port=CONFIG["icc_port"], m_type=tincan_packet,\ payload=data[2:]) return logging.error("Unroutable packet. Oops this should not happen") if data[1] == tincan_sr6: logging.pktdump("Multihop packet received", dump=data) hop_index = ord(data[2]) + 1 hop_count = ord(data[3]) if hop_index == hop_count: make_call(self.sock, payload=null_uid + null_uid +\ data[4+(hop_index)*16:]) return packet = chr(hop_index) packet += data[3:] next_addr_offset = 4+(hop_index)*16 next_hop_addr = data[next_addr_offset:next_addr_offset+16] for k, v in self.peers.iteritems(): if v["ip6"]==ip6_b2a(next_hop_addr) and v["status"]=="online": make_remote_call(sock=self.cc_sock,\ dest_addr=ip6_b2a(next_hop_addr),\ dest_port=CONFIG["icc_port"], m_type=tincan_sr6,\ payload=packet) return via = [] for i in range(hop_count): via.append(ip6_b2a(data[4+i*16:4+16*i+16])) make_remote_call(sock=self.cc_sock, dest_addr=via[hop_index-2],\ dest_port=CONFIG["icc_port"], m_type=tincan_control,\ payload=None, msg_type="route_error", via=via, index=hop_index-2) logging.debug("Link lost send back route_error message to source{0}" "".format(via[hop_index-2]))