Expert Q&A; Done Using python laguage, create a per-to-per UDP chat that meets t
ID: 3605651 • Letter: E
Question
Expert Q&A; Done Using python laguage, create a per-to-per UDP chat that meets the fowlling criteria. * The chat protocol communicates through UDP using a peer-to-peer network architecture * "Keep alive:" A keep alive packet is a message sent to confirm that a recipient is still capable of exchanging messages to the sender The peer sets a port range for searching for other peers (Default: 12000 12010) *The peer sets an IP range for searching for other peers (Default: 10.31.21.0 10.31.21.255) *If a peer already has a peer table, merge the tables and find duplicate entries. If there is a duplicate entry, keep rows that have a "True" boolean. Discard the remaining duplicate rows. Remove any entry that matches the host's addressExplanation / Answer
p2p.py
from multiprocessing import Queue
import socket
from p2p import *
import json
from gui import *
import random
from p2p.KeepAliveThread import KeepAliveThread
from p2p.SendRoutingTableThread import SendRoutingTableThread
from threading import Thread
import time
class P2P(object):
def __init__(self, port=1234, uuid=""):
self.sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind(('',port))
self.uuid = uuid
self.neighborTable = [] # [ {'dest': <uuid_neighbor0>, 'ipaddress': <ipaddress_neightbor0>}, {...} ]
self.routingTable = [] # [ {'dest': <uuid_dest0>, 'via':<uuid_nexthop>}, {...} ]
self.aliveTable = {} # { 'uuid0' : <is_alive>, 'uuid1': <is_alive>, ... }
ip="127.0.0.1"
port=1111
#I KNOW FROM THE BEGGING HOW TO REACH MYSELF
self.routingTable.append({'dest' : self.uuid, 'via' : self.uuid, 'cost' : 0})
self.handler = []
self.packetHandler = {} #{0x01:[callback1,callback2],0x04:[callback4],0x08:[callback1,callback4]}
self.send_queue = queue.Queue()
self.out_queue = queue.Queue()
self.data_out = []
self.receiveThread = ReceiveThread(self.sock, self)
self.sendThread = SendThread(self.sock, self.send_queue, self.out_queue, self.data_out)
self.watchThread = WatchThread(self.out_queue, self.send_queue, self.data_out)
self.sendKeepAlive = KeepAliveThread(self, True)
self.checkKeepAlive = KeepAliveThread(self, False)
self.sendRoutingTable = SendRoutingTableThread(self)
self.receiveThread.start()
self.sendThread.start()
self.watchThread.start()
self.addHandler(VerifyHandler(self))
def stop(self):
self.receiveThread.stop()
self.sendThread.stop()
self.watchThread.stop()
self.checkKeepAlive.stop()
self.sendKeepAlive.stop()
self.sendRoutingTable.stop()
def close(self):
self.stop()
def __del__(self):
self.stop()
def addHandler(self, handler):
self.handler.append(handler)
def handle(self, packet):
if packet.type in self.packetHandler:
for callback in self.packetHandler[packet.type]:
callback(packet)
def send(self, packet):
self.sock.sendto(Packet.pack(packet),packet.nextHop)
def getNextHop(self, uuid):
via = None
for info_routing in self.routingTable:
if info_routing['dest'] == uuid:
via = info_routing['via']
break
if via == None : return None
nextHop = None
for info_neighbor in self.neighborTable:
if info_neighbor['dest'] == via:
nextHop = info_neighbor['address']
break
return nextHop
def updateRoutingTable(self, packet):
routingTableReceived = json.loads(packet.data)
for other_row in routingTableReceived:
if other_row['dest'] not in [r['dest'] for r in self.routingTable]:
if other_row['via'] != self.uuid:
self.routingTable.append({'dest' : other_row['dest'], 'via' : packet.sourceUUID, 'cost': other_row['cost'] + 1 })
else:
for my_row in self.routingTable:
if my_row['dest'] == other_row['dest']:
if other_row['cost'] + 1 < my_row['cost']:
my_row['cost'] = other_row['cost'] + 1
my_row['via'] = packet.sourceUUID
for row in self.routingTable:
if row['dest'] not in [r['dest'] for r in routingTableReceived ]:
if row['via'] == packet.sourceUUID:
self.routingTable.remove(row)
def startTimers(self):
self.checkKeepAlive.start()
self.sendKeepAlive.start()
self.sendRoutingTable.start()
def addPeer(self, uuid, ip, port):
self.neighborTable.append({'dest':uuid, 'address': (ip, port)})
if uuid not in [r['dest'] for r in self.routingTable]:
self.routingTable.append({'dest' : uuid , 'via' : uuid, 'cost' : 1})
else:
for my_row in self.routingTable:
if my_row['dest'] == uuid:
my_row['cost'] = 1
my_row['via'] = uuid
self.aliveTable[uuid] = False
def sendText(self, dest, text):
packet = Packet(self.getNextHop(dest),self.uuid,dest,PacketTypes.DATA,15,Flag.TEXTMESSAGE, 90, text)
self.send(packet)
====================================================================================
WatchThread.py
import queue, threading, datetime
#from p2p.Packet import Packet
class WatchThread(threading.Thread):
def __init__(self, out_queue, send_queue, data_out):
self.out_queue = out_queue
self.send_queue = send_queue
self.data_out = data_out
threading.Thread.__init__(self)
def stop(self):
self.running = 0
def run(self):
self.running = 1
while self.running:
packet = self.out_queue.get(True)
if packet.verified == False:
if packet.tries < 4:
if (datetime.datetime.now() - packet.last_sent).seconds >= 3:
self.send_queue.put(packet)
self.data_out.remove(packet)
else:
self.out_queue.put(packet)
=================================================================================
User.py
class User(object):
def __init__(self, uuid, port):
self.uuid=uuid
self.port=port
==================================================================================
Types.py
def enum(**enums):
return type('Enum', (), enums)
Types = enum(
VERIFYHANDLER = 1,
MESSAGEHANDLER = 2
)
Types.ACKTYPE = b'00000100'
==============================================================================
SendThread.py
import socket, queue, threading, datetime
#from p2p.Packet import Packet
#from p2p.Types import Types
from p2p import *
from p2p.NetworkPacket import NetworkPacket
class SendThread(threading.Thread):
def __init__(self, socket, send_queue, out_queue, data_out):
self.socket = socket
self.send_queue = send_queue
self.out_queue = out_queue
self.data_out = data_out
threading.Thread.__init__(self)
def stop(self):
self.running = 0
def run(self):
self.running = 1
while self.running:
packet = self.send_queue.get(True)
networkPacket = NetworkPacket(packet)
try:
self.socket.sendto(networkPacket.pack(), packet.nextHop)
except:
print("Error")
====================================================================================
SendRoutingTableThread.py
import queue, threading, datetime
import time
from p2p.Packet import Packet
from p2p.PacketTypes import PacketTypes
from p2p.Flag import Flag
import json
class SendRoutingTableThread(threading.Thread):
def __init__(self, p2p):
self.p2p = p2p
threading.Thread.__init__(self)
def stop(self):
self.running = 0
def run(self):
self.running = 1
self.sendRoutingTable()
def sendRoutingTable(self):
while self.running:
time.sleep(10) # 30
string_routingTable = json.dumps(self.p2p.routingTable)
for row in self.p2p.neighborTable:
print("I SEND ROUTING TABLE PACKET TO " + row['dest'] + " " + string_routingTable)
nextHop = self.p2p.getNextHop(row['dest'])
self.p2p.send(Packet(nextHop, self.p2p.uuid, row['dest'], PacketTypes.DATA, 15, Flag.ROUTINGUPDATE, len(string_routingTable),string_routingTable))
===============================================================
ReceiveThread.py
import socket, threading, struct, select
from p2p import *
from p2p.Packet import Packet
from p2p.PacketTypes import PacketTypes
from p2p.Flag import Flag
from p2p.Types import Types
class ReceiveThread(threading.Thread):
def __init__(self, sock, p2p):
self.sock = sock
self.p2p = p2p
threading.Thread.__init__(self)
def stop(self):
self.running = 0
def run(self):
self.running = 1
while self.running:
inputready,outputready,exceptready = select.select([self.sock],[],[])
for sock in inputready:
try:
data, addr = sock.recvfrom(1024)
#version = struct.unpack(">h", data[:2])
version, = struct.unpack(">B", data[:1])
#print("v: " + str(version))
source_uuid = str(data[1:5], "UTF-8")
#print("source: " + source_uuid)
dest_uuid = str(data[5:9], "UTF-8")
#print("dest: " + dest_uuid)
type_p = bin(struct.unpack(">B",data[9:10])[0])
#print("type: " + str(type_p))
flag_p = bin(struct.unpack(">B",data[10:11])[0])
#print("flag: " + str(flag_p) + ", KEEPALIVE: " + str(Flag.KEEPALIVE))
hopCount, = struct.unpack(">B", data[11:12])
#print("hopCount: " + str(hopCount))
lenght, = struct.unpack(">B", data[12:13])
#print("lenght: " + str(lenght))
if type_p == PacketTypes.DATA:
pkt_data = str(data[13:],"UTF-8")
packet = Packet(self.p2p.getNextHop(dest_uuid), source_uuid, dest_uuid, type_p, hopCount, flag_p, len(data), pkt_data)
elif type_p == PacketTypes.CONTROL:
packet = Packet(self.p2p.getNextHop(dest_uuid), source_uuid, dest_uuid, type_p, hopCount, flag_p, len(data), None)
elif type_p == PacketTypes.AUTHENTICATION:
packet = Packet(addr,source_uuid, dest_uuid,type_p, hopCount, flag_p, len(data), None)
self.p2p.handle(packet)
except:
print("Errore connessinoe")
break
'''''
packet = Packet(addr, handlerId, pkt_data)
if packet.handlerId != Types.VERIFYHANDLER:
self.p2p.send(Packet(addr, Types.VERIFYHANDLER, packet.hash))
self.p2p.handle(packet)
'''''
================================================================
Peer.py
class Peer(object):
def __init__(self, addr, id):
self.address = addr
self.id = id
==================================================================
PacketTypes.py
import hashlib, struct
class PacketTypes(object):
CONTROL = bin(2) #b'00000010'
DATA = bin(1) #b'00000001'
AUTHENTICATION = bin(4) #b'00000100'
===================================================================
Packet.py
import hashlib, struct
from p2p.Flag import *
from p2p.PacketTypes import *
class Packet(object):
def __init__(self, nextHop, source, destination, type,hopCount,flags,length, data):
self.nextHop = nextHop
self.type = type
self.data = data
self.sourceUUID = source # sourceUUID
self.destinationUUID = destination # destinationUUID;
self.type = type
self.hopCount = hopCount
self.flags = flags
self.length = length
def pack(self):
pck = struct.pack(">B",0x01)
pck += str(self.sourceUUID).encode()
pck += str(self.destinationUUID).encode()
pck += struct.pack(">B", int(self.type,2))
pck += struct.pack(">B", int(self.flags,2))
pck += struct.pack(">B", self.hopCount)
pck += struct.pack(">B", self.length)
pck += str(self.data).encode()
print(pck)
print("Sending Packet: " + str(pck))
return pck
def changeInAck(self, nextHop):
self.type = PacketTypes.CONTROL
self.flags = Flag.ACK
self.hopCount = 15
self.data = None
tmp = self.destinationUUID
self.destinationUUID = self.sourceUUID
self.sourceUUID = tmp
self.nextHop = nextHop
=================================================================
NetworkPacket.py
import hashlib, struct
class NetworkPacket(object):
def __init__(self, packet):
self.data = packet.data
self.sourceUUID = packet.sourceUUID # sourceUUID
self.destinationUUID = packet.destinationUUID # destinationUUID;
self.type = packet.type
self.hopCount = packet.hopCount
self.flags = packet.flags
self.length = packet.length
def pack(self):
pck = struct.pack(">B", 0x01)
pck += str(self.sourceUUID).encode()
pck += str(self.destinationUUID).encode()
pck += struct.pack(">B", int(self.type, 2))
pck += struct.pack(">B", int(self.flags, 2))
pck += struct.pack(">B", self.hopCount)
pck += struct.pack(">B", self.length)
if self.data != None:
pck += str(self.data).encode()
return pck
===================================================================
KeepAliveThread.py
import queue, threading, datetime
import time
from p2p.Packet import Packet
from p2p.PacketTypes import PacketTypes
from p2p.Flag import Flag
class KeepAliveThread(threading.Thread):
def __init__(self, p2p, isSend):
self.p2p = p2p
self.isSend = isSend
threading.Thread.__init__(self)
def stop(self):
self.running = 0
def run(self):
self.running = 1
if self.isSend:
self.sendKeepAlive()
else:
self.checkKeepAlive()
def sendKeepAlive(self):
while self.running:
time.sleep(5)
print("I send keep alive")
for row in self.p2p.neighborTable:
self.p2p.send(Packet(row['address'], self.p2p.uuid, row['dest'], PacketTypes.CONTROL, 1, Flag.KEEPALIVE, 0, None))
print("Keep alive send to + " + row['dest'])
def checkKeepAlive(self):
while self.running:
time.sleep(1)
for row in self.p2p.neighborTable:
print(row)
row['timer'] = row['timer']-1
if(row['timer'] == 0 ):
self.p2p.neighborTable.remove(row)
for record in self.p2p.routingTable:
if(row['dest'] == record['via']):
self.p2p.routingTable.remove(record)
===================================================================
Flag.py
class Flag(object):
ROUTINGUPDATE = bin(32) #b'00100000'
SESSION = bin(16)#b'00010000'
FILEDATA = bin(8)#b'00001000'
TEXTMESSAGE = bin(4)#b'00000100'
SEQUENCENUMBER = bin(2)#b'00000010'
LASTFRAGMENT = bin(1)#b'00000001'
SESSION = bin(64)#b'01000000'
FILETRANSER = bin(32)#b'00100000'
ROUTINGUPDATEINIT = bin(16)#b'00010000'
KEEPALIVE = bin(8)#b'00001000'
ACK = bin(4)#b'00000100'
SEQUENCENUMBER = bin(2)#b'00000010'
RST = bin(1)#b'00000001'
AUTH_SUCCESS = bin(2)
NO_AUTH = bin(1)
============================================================
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.