Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

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 address

Explanation / 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)

============================================================

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote