class SimpleDhcp(Thread): def __init__(self, socket): Thread.__init__(self) self.sim = Simulation() self.dhcp_sock = socket self.arp_table = {} self.network_number = "192.168.1." self.arp_table[self.sim.get_gateway_recv_mac()] = self.sim.get_gateway_recv_ip() self.running = True def get_dhcp_sock(self): return self.dhcp_sock def find_available_ip_address(self): host_number = 2 if len(self.arp_table.values()) != 0: host_number = int(max(self.arp_table.values(), key = lambda x: int(x.split(".")[3])).split(".")[3]) + 1 if len(self.arp_table.values()) == 254: return "0.0.0.0" return str(self.network_number) + str(host_number) def get_arp_table(self): return self.arp_table def run(self): while self.running: print('\n\rWaiting to receive message...') # ascolto richieste di indirizzi ip data, address = self.dhcp_sock.recvfrom(1024) utils.print_pkt_size(data) pkt = pickle.loads(data) utils.print_packet_header(pkt, "IOT DEVICE") mac_address = pkt.get_source_mac() print("Received request for:",mac_address) if mac_address not in self.arp_table.keys(): print("New device is requiring IP address") new_available_ip_address = self.find_available_ip_address() print("Device ", mac_address, " is granted of ", new_available_ip_address, " ip address") self.arp_table[mac_address] = new_available_ip_address self.dhcp_sock.sendto(pickle.dumps(Packet( self.sim.get_gateway_recv_mac(), pkt.get_source_mac(), self.sim.get_gateway_recv_ip(), pkt.get_source_ip(), self.arp_table[pkt.get_source_mac()] )) , address) def stop_thread(self): self.running = False
class Gateway: DHCP_PORT = 1075 devices = {} # {ip_address: measurements} def __init__(self): self.sim = Simulation() self.rcv_sock = sk.socket(sk.AF_INET, sk.SOCK_DGRAM) # socket per invio delle misurazioni self.dhcp_sock = sk.socket(sk.AF_INET, sk.SOCK_DGRAM) self.dhcp_sock.bind(nc.dhcp_address) self.rcv_sock.bind(nc.gateway_address) self.dhcp = SimpleDhcp(self.dhcp_sock) self.dhcp.start() def get_rcv_ip_address(self): return self.sim.get_gateway_recv_ip() def get_udp_sock(self): return self.rcv_sock def get_devices(self): return self.devices def close_gateway(): self.dhcp.stop_thread() self.dhcp_sock.close() self.recv_sock.close() def send_data_to_server(self): try: server_socket = sk.socket(sk.AF_INET, sk.SOCK_STREAM) server_socket.connect(nc.server_address) print("SENDING DEVICES DATA TO SERVER") server_socket.send( pickle.dumps(Packet(self.sim.get_gateway_send_mac(), self.sim.get_server_mac(), self.sim.get_gateway_send_ip(), self.sim.get_server_ip(), self.get_devices() )) ) message = server_socket.recv(1024) utils.print_pkt_size(message) pkt = pickle.loads(message) utils.print_packet_header(pkt, "SERVER") print("Server answer:", pkt.get_payload()) utils.print_divider() print() except Exception as error: print(error) finally: server_socket.close() self.clear_measurments() def clear_measurments(self): self.get_devices().clear() def __send_answer(self, address, pkt, message): self.get_udp_sock().sendto( pickle.dumps(Packet(self.sim.get_gateway_recv_mac(), pkt.get_source_mac(), self.sim.get_gateway_recv_ip(), pkt.get_source_ip(), message ) ), address) def confirm_reception(self, address, pkt): self.__send_answer(address, pkt, "Measurements received") def discard_reception(self, address, pkt): self.__send_answer(address, pkt, "Wrong Ip address")
class Device: daily_measurements = [] maximum_number_of_measurements_to_be_sent = 6 empty_payload = "" unassigned_ip = "0.0.0.0" def __init__(self, mac_address): self.sim = Simulation() self.log_filename = "DailyDeviceLog_" + str(mac_address).replace( ":", "_") + ".json" self.mac_address = mac_address # richiesta di un indirizzo ip dal dhcp print("Device requesting Ip address from DHCP server") self.ip_address = self.obtain_ip_address() print("Ip address received from DHCP server on gateway: ", self.ip_address) self.create_file() def obtain_ip_address(self): dhcp_request_socket = sk.socket(sk.AF_INET, sk.SOCK_DGRAM) dhcp_request_socket.sendto( pickle.dumps( Packet(self.mac_address, self.sim.gateway_recv_mac, self.unassigned_ip, self.sim.get_gateway_recv_ip(), self.empty_payload)), nc.dhcp_address) data, server = dhcp_request_socket.recvfrom(1024) utils.print_pkt_size(data) pkt = pickle.loads(data) utils.print_packet_header(pkt, "DHCP SERVER") dhcp_request_socket.close() if data: return pkt.get_payload() return self.unassigned_ip def add_new_measurement(self, measurement): self.daily_measurements.append(measurement) if os.path.exists(self.log_filename): with open(self.log_filename, 'a') as file: file.write(measurement.to_string()) if len(self.daily_measurements ) == self.maximum_number_of_measurements_to_be_sent: self.send_data() #To erase content from file open(self.log_filename, 'a').close() def send_data(self): print("\nDevice is sending data to GATEWAY...\n") # creo la socket e la richiudo non appena ho terminato l'invio dei dati # non impegnando inultimente le risorse allocate sending_socket = sk.socket(sk.AF_INET, sk.SOCK_DGRAM) received = False while not received: try: sending_socket.sendto( pickle.dumps( Packet(self.mac_address, self.sim.get_gateway_recv_mac(), self.ip_address, self.sim.get_gateway_recv_ip(), self.daily_measurements)), nc.gateway_address) sending_socket.settimeout(2) data, address = sending_socket.recvfrom( 1024) # attesa di conferma da parte del gateway utils.print_pkt_size(data) if data: pkt = pickle.loads(data) utils.print_divider() utils.print_packet_header(pkt, "GATEWAY") received = True print("Gateway answer:", pkt.get_payload()) utils.print_divider() #empty print for spacing print() except sk.timeout: print("Timeout occurred, trying again...") except Exception as err: print(err) time.sleep(3) sending_socket.close() # after sending data I reset the dictionary to not keep in ram useless data self.daily_measurements.clear() def create_file(self): open(str(self.log_filename), 'w').close()