class ParallelTSPCLI(CLIShell): BANNER = """ Parallel Traveling Salesman. Sends out paths to be computed by remote hosts. Results are collected until the best path is known. Execute 'start' to begin the computation. Execute 'status' to see how things are going. """ def __init__(self, ptsp): CLIShell.__init__(self, banner = self.BANNER) self.ptsp = ptsp self.options = {} self.__poll = None self.__pollingCallback = None self.__started = False startHandler = CLIShell.CommandHandler("start",helpTxt="Start the parallelTsp", defaultCb=self.start, mode=CLIShell.CommandHandler.STANDARD_MODE) self.registerCommand(startHandler) #configHandler = CLIShell.CommandHandler("config",helpTxt="Show current config (can't change yet)", # defaultCb=self.config, # mode=CLIShell.CommandHandler.STANDARD_MODE) #self.registerCommand(configHandler) statusHandler = CLIShell.CommandHandler("status",helpTxt="Show current status", defaultCb=self.status, mode=CLIShell.CommandHandler.STANDARD_MODE) statusHandler.configure(1, self.status, helpTxt="Show status and set to poll the status", usage="[polling time]") self.registerCommand(statusHandler) #checkbalanceHandler = CLIShell.CommandHandler("balance", helpTxt="Check the current account balance", # defaultCb=self.checkBalance, # mode=CLIShell.CommandHandler.STANDARD_MODE) #self.registerCommand(checkbalanceHandler) sampleCodeString = CLIShell.CommandHandler("sample", helpTxt="Generate A sample remote code string", mode=CLIShell.CommandHandler.STANDARD_MODE) sampleCodeString.configure(3, self.getSampleCodeString, helpTxt="Get a sample code string for the given parameters", usage="[startpath] [endpath] [filename]") self.registerCommand(sampleCodeString) #blacklistCommand = CLIShell.CommandHandler("blacklist", helpTxt="Get the list of blacklisted nodes", # mode=CLIShell.CommandHandler.STANDARD_MODE, # defaultCb=self.blacklistedAddrs) #self.registerCommand(blacklistCommand) def __checkBalanceResponse(self, f, writer): e = f.exception() if not e: self.transport.write("Current balance in account: %d\n" % f.result()) else: self.transport.write("Check balance failed: {}\n".format(e)) def checkBalance(self, writer): f = self.ptsp.wallet.checkBalance() f.add_done_callback(lambda f: self.__checkBalanceResponse(f, writer)) def config(self, writer): for k, v in self.options.items(): self.transport.write("%s: %s\n" % (k,v)) def getSampleCodeString(self, writer, startPath, endPath, filename): try: startPath = int(startPath) except: writer("Invalid start path\n") return try: endPath = int(endPath) except: writer("Invalid end path\n") return codeStr = self.ptsp.getCodeString(startPath, endPath) with open(filename, "w+") as f: f.write(codeStr) writer("Wrote file %s\n" % filename) def blacklistedAddrs(self, writer): if not self.__started: self.transport.write("Can't get blacklist Not yet started\n") return bl = self.ptsp.auth.getBlacklist() writer("Blacklisted Addresses:\n") for addr in bl: writer(" %s\n" % addr) writer("\n") def status(self, writer, poll=None): if not self.__started: self.transport.write("Can't get status. Not yet started\n") return if poll != None: # We're changing the polling time. Cancel the current, then # set the new polling time try: poll = int(poll) except: self.transport.write("Polling time must be an integer. Got %s" % poll) return if poll < 0: self.transport.write("Polling time must be a positive integer. Got %d" % poll) return if self.__pollingCallback: self.__pollingCallback.cancel() if poll == 0: self.__pollingCallback = None self.__poll = poll template = """ Max Paths: %(Max_Path_Count)s Completed Paths: %(Completed_Path_Count)s Currently Executing Paths: %(Current_Path_Count)s %(Current_Execution_Details)s Address Data: %(Addr_Stats)s""" if self.ptsp.finished(): template = ("FINISHED: %s\n" % str(self.ptsp.finalResult())) + template templateData = {} templateData["Max_Path_Count"] = self.ptsp.maxPaths() templateData["Completed_Path_Count"] = self.ptsp.completedPathCount() currStr = '' currentExecutions = self.ptsp.currentExecutions() currentPathCount = 0 for execId, paths, addr, finished in currentExecutions: currStr += "\t\t%s:\t%s\t%s\n" % (addr, execId, paths) start, end = paths currentPathCount += (end-start)+1 templateData["Current_Path_Count"] = currentPathCount addrStr = "\t\t%-15s\t%-10s\t%-10s\t%-10s\t%s\n" % ("Address", "Jobs Sent", "Completed Jobs", "Errors", "Paid") for addrData in self.ptsp.iterAddrStats(): addrStr += "\t\t%-15s\t%-10s\t%-10s\t%s\t%s\n" % (addrData.addr, addrData.jobsSent, addrData.jobsCompleted, addrData.jobErrors, addrData.totalPaid()) for payto in addrData.paid: addrStr += "\t\t%-15s\t%-10s\t%-10s\t%-10s\t%s\n" % (" ", " ", " ", " ", "{}: {}".format(payto, addrData.paid[payto])) templateData["Current_Execution_Details"] = currStr templateData["Addr_Stats"] = addrStr self.transport.write((template % templateData)+"\n") if self.__poll: # if we have a polling time set, fire. self.__pollingCallback = Timer(lambda: self.status(writer)) self.__pollingCallback.run(self.__poll) def start(self, writer): if self.__started: self.transport("Program already started.\n") return self.__started=True coro = self.ptsp.start() future = asyncio.get_event_loop().create_task(coro) future.add_done_callback(lambda future: self.finish()) #kargs = {} #parameters = self.options.getSection("ptsp.parameters") #if parameters.has_key("n"): # kargs["n"] = int(parameters["n"]) #if parameters.has_key("paths_per_parallel_execution"): # kargs["pathsPerParallel"] = int(parameters["paths_per_parallel_execution"]) #self.ptsp = ParallelTSP()#**kargs) #Parallel(self.ptsp, self.finish) def finish(self): #resultsFile = "tsp_results."+str(time.time())+".txt" self.transport.write("Finished computation\n") self.transport.write("\tResult: %s\n" % str(self.ptsp.finalResult())) if self.__pollingCallback: self.__pollingCallback.cancel() self.__pollingCallback = None
class RIP(StackingProtocol): def __init__(self): super().__init__() self.transport = None self.identity = None self.timeoutValue = 10 #the RIP layer will wait for 10 seconds until resending the packet self.SequenceNo = random.randrange(0, 101, 2) self.stateCon = 0 #open server self.sentBoxData = [ ] # tupple(Sequence Number, Packet object, Timer, Acked or Not) self.recieveBoxData = [ ] # tupple(Sequence Number, Packet object, Acked or Not) self.sentHand = None #sent message from handshake self.recHand = None #recieved message from hanshake self.timHand = None #timer for hanshake self.firstCon = True #first packet flag self.lastPacket = None #lastPacket in order in the recieve end self._deserializer = RIPPacket.Deserializer() # 1 = SYN, 2 = ACK, 3 = FIN 4 = DATA def connection_made(self, transport): print("Received a connection from {}".format( transport.get_extra_info("peername"))) self.transport = transport self.PassTransport = ATPtransport(self.transport, self) self.identity = "server" #import pdb; pdb.set_trace() print("im here in connection made in " + self.identity) #loop = asyncio.new_event_loop() #asyncio.set_event_loop(loop) def connection_lost(self, exc): # self.send("FIN", b"") # self.send("FIN", b"") # self.send("FIN", b"")#third time is the charm self.higherProtocol().connection_lost(exc) #loop = asyncio.get_event_loop() #loop.stop() def data_received(self, data): print("data_recieved start from " + self.identity) self._deserializer.update(data) for atppacket in self._deserializer.nextPackets(): print(atppacket.Data) print("Got {} from the sender.".format(atppacket.Type)) #check for doublicate and hash if self.recieveBoxData or self.recHand: if not self.checkPacket(atppacket): print("error packet") return #add to list print("recieved Type ={}, Seq= {}, ACK= {} ".format( atppacket.Type, atppacket.SeqNo, atppacket.AckNo)) print("And the Connection is {}".format(self.stateCon)) #end check #states: Connecring - 0, Ongoing - 1, Established - 2, FIN - 3 if "SYN" in atppacket.Type and self.stateCon == 0: #SYN SENT and Connection is open((server)) self.handleHandshake(1, atppacket) elif "SYN" in atppacket.Type and "ACK" in atppacket.Type and self.stateCon == 1: #SYN ACK and Connection is ongoing((client)) print("the timer object is: {}".format(self.timHand)) timerHandshake = self.timHand self.timHand.cancel() self.timHand = timerHandshake print("Timer is canceled") self.handleHandshake(2, atppacket) elif "ACK" in atppacket.Type: if self.stateCon == 3: if self.sentBoxData[-1][0] + len( self.sentBoxData[-1][1].Data) == atppacket.AckNo: finTimer = self.sentBoxData[-1][2] print("Timer is canceled") finTimer.cancel() self.sentBoxData[-1] = ((self.sentBoxData[-1][0], self.sentBoxData[-1][1], finTimer, True)) self.transport.close() if self.stateCon == 1: #SYN ACK ACK and Connection is established((server)) print("the timer object is: {}".format(self.timHand)) timerHandshake = self.timHand self.timHand.cancel() self.timHand = timerHandshake print("Timer is canceled") self.handleHandshake(3, atppacket) elif self.stateCon == 2: self.recieveAck(atppacket) print("ACKnowledged") #the end of the handshake elif "DATA" in atppacket.Type.upper( ) and self.stateCon == 2: #DATA and connection is established((serverANDclient)) print("Got a packet {}".format(atppacket)) self.recieveData(atppacket) elif "FIN" in atppacket.Type.upper( ) and self.stateCon == 2: #FIN((server)) print("Got a FIN packet {}".format(atppacket)) self.stateCon = 3 self.connection_lost("FIN") self.sendAck(atppacket) for n in range(len(self.recieveBoxData)): if self.recieveBoxData[n][ 2] is False and "DATA" in self.recieveBoxData[n][ 1].Type.upper(): #Acked is True return self.transport.close() #close when you get an Ack for the fin else: print("the packet has a wrong type") if self.stateCon == 0: self.transport.close() def handleHandshake(self, Type, handPacket): if Type == 1 and self.recHand is None: #SYN self.recHand = handPacket self.send("SYN ACK", b"") #SYN ACK self.stateCon = 1 #Ongoing #self.timHand.cancel() print("The connection is {}".format(self.stateCon)) print("SYN and an ACK is sent,and the Ack number is {}".format( handPacket.SeqNo + 1)) elif Type == 2 and self.recHand is None: #SYN ACK if handPacket.AckNo - 1 == self.sentHand.SeqNo: self.recHand = handPacket self.send("ACK", b"") #SYN ACK ACK print( "SYN:REC and an ACK is sent. The packet state is Established. The Ack number is{}" .format(handPacket.SeqNo + 1)) self.higherProtocol().connection_made(self.PassTransport) self.stateCon = 2 #established with server #self.timHand.cancel() print("\nconnection is made with server") self.SequenceNo = self.SequenceNo - 1 #for the first Data packet else: print("wrong SYN ACK") elif Type == 3 and "SYN" in self.recHand.Type: #SYN ACK ACK if handPacket.AckNo - 1 == self.sentHand.SeqNo: self.recHand = handPacket print("Got SYN ACK ACK, and the sequence number is {}".format( handPacket.SeqNo)) print("\nconnection is made with client") #self.timHand.cancel() self.higherProtocol().connection_made( self.PassTransport) #server connection self.stateCon = 2 #established else: print("wrong SYN ACK ACK") def recieveData(self, dataPacket): #add to the list self.recieveBoxData.append( (dataPacket.SeqNo, dataPacket, False)) #Acked is false #sort self.recieveBoxData.sort() #print the list indexx = 0 completeFlag = True for seq, packet, acked in self.recieveBoxData: print("recieveBoxList:----Seq= {}, Acked= {}, Next= {}".format( seq, acked, seq + len(packet.Data))) if acked is False and packet.Type.upper() == "DATA": completeFlag = False if dataPacket.Type == "FIN" and completeFlag: self.sendAck(dataPacket) self.transport.close() print("Number of Packets are: {}".format(len(self.recieveBoxData))) #send to higher protocol and remove packets appData = b"" index = 1 if len(self.recieveBoxData) != 1: for index in range(len(self.recieveBoxData)): pefIndex = index - 1 #if self.recieveBoxData[index][2] is False and self.recieveBoxData[index][0] == self.recieveBoxData[pefIndex][0] + len(self.recieveBoxData[pefIndex][1].Data): if self.recieveBoxData[index][ 2] is False and self.recieveBoxData[index][0] == ( self.recieveBoxData[pefIndex][0] + len(self.recieveBoxData[pefIndex][1].Data) ) and self.recieveBoxData[pefIndex][2]: #send current packet data to application self.lastPacket = self.recieveBoxData[index][1] self.recieveBoxData[index] = ( self.recieveBoxData[index][0], self.recieveBoxData[index][1], True ) #because tuples dont support update, so reassigment to the index with Acked True print(" A: This acked packet seq no is {}".format( self.recieveBoxData[index][0])) appData = appData + self.recieveBoxData[index][ 1].Data #add data #index = index + 1 else: self.recieveBoxData[0] = (self.recieveBoxData[0][0], self.recieveBoxData[0][1], True) self.lastPacket = self.recieveBoxData[0][1] appData = self.lastPacket.Data #acked all data packets self.sendAck(self.lastPacket) #print # #send data to the application layer self.higherProtocol().data_received(appData) def recieveAck(self, ackPacket): #packetIndex = 0 for Seq, dataPacket, timer, acked in self.sentBoxData: print( "SentBoxList:---- for Seq= {}, Data packet ACK= {}, Acked= {} and recieved ACK is= {}" .format(Seq, Seq + len(dataPacket.Data), acked, ackPacket.AckNo)) if ( Seq + len(dataPacket.Data) ) == ackPacket.AckNo and acked is False: #if the ack matches the list value print("It's a match with a sent packet= {}".format(Seq)) packetIndex = self.sentBoxData.index( (Seq, dataPacket, timer, acked )) + 1 #index starts with 0, while range starts with 1 print("the packet index is= {}".format(packetIndex)) for n in range( packetIndex ): #find the timer in the dictionary using the seq number #cancel all the timer less than the seq number currentTimer = self.sentBoxData[n][2] #timer cancelation currentTimer.cancel() print("timer is canceled") self.sentBoxData[n] = (self.sentBoxData[n][0], self.sentBoxData[n][1], currentTimer, True) #self.timerDict[packetSeq] = timer.cancel() return def checkPacket(self, packet): #loop dic if exist send from to last acked packet and check doublications if "DATA" in packet.Type.upper(): for packetSeq, DataPacket, acked in self.recieveBoxData: if packetSeq == packet.SeqNo: if acked is True: self.sendAck( DataPacket) #acked data packet, resend ACK print( "resending ACK since the packet is already acked by the protocol" ) return False elif acked is False: #for doubliction Data packets print("double Data packets is recieved") return False #check Hash checkedHash = self.hashPacket(packet) print("Checked Checksum is: " + checkedHash.decode()) if packet.CRC != checkedHash: print("the packet has been modefied") return False return True def hashPacket(self, hashPacket): print("start hashing") ATPpacket = RIPPacket(Type=hashPacket.Type, SeqNo=hashPacket.SeqNo, AckNo=hashPacket.AckNo, CRC=b"", Data=hashPacket.Data) checksum = hashlib.sha256(ATPpacket.__serialize__()).hexdigest() checksum = checksum.encode() return checksum def sendAck(self, packetAck): sentAck = RIPPacket() #add Ack number sentAck.AckNo = packetAck.SeqNo + len( packetAck.Data ) #sequence number and data length of previouse recieved packet #add Seq sentAck.SeqNo = 0 #add Type sentAck.Type = "ACK" #add Data sentAck.Data = b"" #add checksum sentAck.CRC = self.hashPacket(sentAck) print("checksum is: {}".format(sentAck.CRC.decode())) print("send Type ={}, Seq= {}, ACK= {}".format(sentAck.Type, sentAck.SeqNo, sentAck.AckNo)) #add packet to the sent list self.transport.write(sentAck.__serialize__()) print("the ACK is sent for: {}".format(sentAck.AckNo)) def send(self, pacType, PacData): sentPacket = RIPPacket() print("the packet type is: {}".format(pacType)) #calculateSeqAck if "SYN" in pacType.upper() and "ACK" in pacType.upper(): print("SYN ACK") #add Ack number sentPacket.AckNo = self.recHand.SeqNo + 1 #add Seq sentPacket.SeqNo = self.SequenceNo #random seq elif "ACK" in pacType.upper(): if self.stateCon == 1: print("1 ACK") #add Ack number sentPacket.AckNo = self.recHand.SeqNo + 1 #add Seq sentPacket.SeqNo = self.sentHand.SeqNo + 1 elif "SYN" in pacType.upper(): print("SYN") #add Ack number sentPacket.AckNo = 0 #add Seq sentPacket.SeqNo = self.SequenceNo #random seq elif "DATA" in pacType.upper() or "FIN" in pacType.upper(): if self.sentHand is not None: print("1st Packet after the Handshake") #add Ack number sentPacket.AckNo = 0 #add Seq sentPacket.SeqNo = self.recHand.AckNo #empty hands self.recHand = None self.sentHand = None else: #add Ack number sentPacket.AckNo = 0 #add Seq sentPacket.SeqNo = self.sentBoxData[-1][0] + len( self.sentBoxData[-1][1].Data ) #sequence number and data length of previouse sent packet if "FIN" in pacType.upper(): self.stateCon = 3 #FIN state else: print("IM NOTHING{}".format(sentPacket.AckNo)) #add Type sentPacket.Type = pacType #add Data sentPacket.Data = PacData #add checksum sentPacket.CRC = self.hashPacket(sentPacket) print("checksum is: {}".format(sentPacket.CRC.decode())) print("send Type ={}, Seq= {}, ACK= {}".format(sentPacket.Type, sentPacket.SeqNo, sentPacket.AckNo)) #add packet to the sent list if "DATA" in pacType.upper() or "FIN" in pacType.upper( ): #not SYN ACK since it will go to the first option pacTimer = Timer( Seconds(self.timeoutValue), self.timeout, sentPacket ) #self.timeoutValue = 10 :the RIP layer will wait for 10 seconds until resending the packet pacTimer.start() self.sentBoxData.append( (sentPacket.SeqNo, sentPacket, pacTimer, False)) #packet seq, packet, timer, acked or not print("the packe is sent and next Seq number is:{}".format( sentPacket.SeqNo + len(sentPacket.Data))) elif "SYN" in pacType.upper( ) or "SYN" in pacType.upper() and "ACK" in pacType.upper(): print("starting a SYN or SYN ACK handshake packets timer") self.sentHand = sentPacket self.timHand = Timer(Seconds(self.timeoutValue), self.timeout, self.sentHand) self.timHand.start() print("the timer object is: {}".format(self.timHand)) print("the packe is sent from {} and next Seq number is:{}".format( self.identity, sentPacket.SeqNo + 1)) for seq, packet, timer, acked in self.sentBoxData: print("sentBoxData:--- seq= {}, ack= {}, ACKED= {}".format( seq, seq + len(packet.Data), acked)) #write packet serPacket = sentPacket.__serialize__() self.transport.write(sentPacket.__serialize__()) def resend(self, resntPacket): if "DATA" in resntPacket.Type.upper(): #start timer again #get timer for seq, packet, timer, acked in self.sentBoxData: if seq == resntPacket.SeqNo: timer.cancel() index = self.sentBoxData.index((seq, packet, timer, acked)) pacTimer = Timer(Seconds(self.timeoutValue), self.timeout, packet) pacTimer.start() self.sentBoxData[index] = ( seq, packet, pacTimer, False ) #packet seq, packet, timer, acked or not #start timer elif "FIN" in resntPacket.Type.upper(): currentTimer = self.sentBoxData[-1][2] currentTimer.cancel() currentTimer = Timer(Seconds(self.timeoutValue), self.timeout, self.sentBoxData[-1][1]) currentTimer.start() self.sentBoxData[-1] = (self.sentBoxData[-1][0], self.sentBoxData[-1][1], currentTimer, False) #last packet since its FIN elif "ACK" in resntPacket.Type.upper(): if "SYN" in resntPacket.Type.upper(): self.timHand.cancel() self.timHand = Timer(Seconds(self.timeoutValue), self.timeout, self.sentHand) self.timHand.start() elif "SYN" in resntPacket.Type.upper(): self.stateCon = 0 print("Im here") self.timHand.cancel() self.timHand = Timer(Seconds(self.timeoutValue), self.timeout, self.sentHand) self.timHand.start() resendPacket = RIPPacket(Type=resntPacket.Type, SeqNo=resntPacket.SeqNo, AckNo=resntPacket.AckNo, CRC=resntPacket.CRC, Data=resntPacket.Data) print("resend packet: Type = {}, SeqNo = {}, AckNo = {},\n CRC = {}". format(resntPacket.Type, resntPacket.SeqNo, resntPacket.AckNo, resntPacket.CRC.decode())) self.transport.write(resendPacket.__serialize__()) def timeout(self, timedPacket): #import pdb; pdb.set_trace() print("\ntimeout\nresend packet {} to {}".format( timedPacket.SeqNo, self.identity)) self.resend(timedPacket)