def handle_ack(self, packet): # TODO: sequence number overflow if self.piggyback and packet.Data != FIELD_NOT_SET and len( packet.Data) > 0: self.handle_data(packet) self.acknowledgement = packet.Acknowledgement # print("ack: ", packet.Acknowledgement) i = 0 while i < len(self.timers): timer = self.timers[i] if timer._callbackArgs[0].SequenceNumber < packet.Acknowledgement: timer.cancel() self.timers = self.timers[:i] + self.timers[i + 1:] i -= 1 i += 1 if self.rip_timer != None: self.rip_timer.cancel() self.rip_timer.extend(Seconds(2)) self.rip_timer.start() return self.send_window_start = max(self.send_window_start, packet.Acknowledgement) self.send_window_data() if self.state == PEEP_Base.TEARDOWN and self.sent_all(): self.send_rip() self.rip_timer = Timer(Seconds(2), self.abort_connection) self.rip_timer.start()
def initiate_teardown(self): # print('teardown start') self.state = PEEP_Base.TEARDOWN if self.sent_all(): self.send_rip() self.rip_timer = Timer(Seconds(2), self.abort_connection) self.rip_timer.start()
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.paid) 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 send_packet(self, packet): # print(self, "send packet: ", packet) self.transport.write(packet.__serialize__()) if packet.Type != PEEPPacket.SYN and packet.Type != PEEPPacket.DATA and packet.Type != PEEPPacket.RIP: return timer = Timer(Seconds(1), self.send_packet, packet) self.timers.append(timer) timer.start()
def __init__(self, fragId, totalSize, parentContainer): self._fragId = fragId self._totalSize = totalSize self._parentContainer = parentContainer self._received = 0 self._bufferStream = io.BytesIO() self._offsetsReceived = set([]) self._cleanUpTimer = Timer(Minutes(5), self._removeFromParentContainer) self._cleanUpTimer.start()
class FragStorage: def __init__(self, fragId, totalSize, parentContainer): self._fragId = fragId self._totalSize = totalSize self._parentContainer = parentContainer self._received = 0 self._bufferStream = io.BytesIO() self._offsetsReceived = set([]) self._cleanUpTimer = Timer(Minutes(5), self._removeFromParentContainer) self._cleanUpTimer.start() def _removeFromParentContainer(self): if self._fragId in self._parentContainer: del self._parentContainer[self._fragId] def insert(self, fragOffset, fragData): if fragOffset in self._offsetsReceived: return self._offsetsReceived.add(fragOffset) self._bufferStream.seek(fragOffset) self._bufferStream.write(fragData) self._received += len(fragData) self._cleanUpTimer.extend(Minutes(5)) def isComplete(self): return self._received == self._totalSize def getData(self): return self._bufferStream.getvalue() def cleanup(self): self._cleanUpTimer.expire() return self.getData()
class PEEP_Base(StackingProtocol): INIT, HANDSHAKE, TRANS, TEARDOWN = [0, 1, 2, 3] def __init__(self): super().__init__() self.state = PEEP_Base.INIT self.window_size = 10 self.chunk_size = 1024 self.transport = None self.deserializer = None self.base_sequence_number = None self.sequence_number = None self.expected_sequence_number = None self.send_window_start = None self.send_window_end = None self.receive_window_start = None self.receive_window_end = None self.data_size = 0 self.data = bytes() self.timers = [] self.received_data = [] self.rip_timer = None self.rip_sequence_number = None self.piggyback = False def data_received(self, data): # print("data received") self.deserializer.update(data) for packet in self.deserializer.nextPackets(): if isinstance(packet, PEEPPacket) and packet.verifyChecksum(): self.handle_packets(packet) def handle_packets(self, packet): typenum = packet.Type if typenum == PEEPPacket.SYN and self.state == PEEP_Base.INIT: # print('received SYN') self.handle_syn(packet) elif typenum == PEEPPacket.SYNACK and self.state == PEEP_Base.HANDSHAKE: print('-------------PEEP received SYNACK-------------') self.handle_synack(packet) elif typenum == PEEPPacket.ACK: # print("received ACK") self.handle_ack(packet) elif typenum == PEEPPacket.DATA and (self.state == PEEP_Base.TRANS or self.state == PEEP_Base.TEARDOWN): # print('received Data') self.handle_data(packet) elif typenum == PEEPPacket.RIP and (self.state == PEEP_Base.TRANS or self.state == PEEP_Base.TEARDOWN): # print('received RIP') self.handle_rip(packet) elif typenum == PEEPPacket.RIPACK and self.state == PEEP_Base.TEARDOWN: # print('received RIPACK') self.handle_ripack(packet) else: print('received packet in bad state. type: ', typenum, " state ", self.state) def handle_syn(self, packet): # print('checksum of SYN is correct') packetback = PEEPPacket() if packet.Data != FIELD_NOT_SET and packet.Data.decode( ) == "piggyback": # print("syn: enable piggybacking") packetback.Data = "piggyback".encode() self.piggyback = True packetback.Acknowledgement = packet.SequenceNumber + 1 self.sequence_number = random.randint(0, 2**16) self.base_sequence_number = self.sequence_number + 1 self.expected_sequence_number = packet.SequenceNumber + 1 self.send_window_start = self.base_sequence_number self.send_window_end = self.base_sequence_number packetback.SequenceNumber = self.sequence_number packetback.Type = PEEPPacket.SYNACK packetback.updateChecksum() self.send_packet(packetback) self.state = PEEP_Base.HANDSHAKE # maybe set this state to trans in case the ack in handshake gets dropped # print('sent SYNACK') def handle_synack(self, packet): # print("Received synack", packet) if packet.Acknowledgement != self.sequence_number: return i = 0 while i < len(self.timers): timer = self.timers[i] if timer._callbackArgs[0].SequenceNumber < packet.Acknowledgement: timer.cancel() self.timers = self.timers[:i] + self.timers[i + 1:] i -= 1 i += 1 if packet.Data != FIELD_NOT_SET and packet.Data.decode( ) == "piggyback": # print("synack: enable piggybacking") self.piggyback = True packet_to_send = PEEPPacket() packet_to_send.Type = PEEPPacket.ACK packet_to_send.SequenceNumber = self.sequence_number # packet_to_send.SequenceNumber = packet.Acknowledgement packet_to_send.Acknowledgement = packet.SequenceNumber + 1 packet_to_send.updateChecksum() self.base_sequence_number = packet.Acknowledgement self.expected_sequence_number = packet.SequenceNumber + 1 self.send_window_start = self.base_sequence_number self.send_window_end = self.base_sequence_number self.sequence_number = self.base_sequence_number # print("Sending Back Ack") self.send_packet(packet_to_send) self.state = PEEP_Base.TRANS # transmission state # Open upper layer transport # print("connection_made to higher protocol") self.higherProtocol().connection_made( PEEP_Transport(self.transport, self)) def handle_ack(self, packet): # TODO: sequence number overflow if self.piggyback and packet.Data != FIELD_NOT_SET and len( packet.Data) > 0: self.handle_data(packet) self.acknowledgement = packet.Acknowledgement # print("ack: ", packet.Acknowledgement) i = 0 while i < len(self.timers): timer = self.timers[i] if timer._callbackArgs[0].SequenceNumber < packet.Acknowledgement: timer.cancel() self.timers = self.timers[:i] + self.timers[i + 1:] i -= 1 i += 1 if self.rip_timer != None: self.rip_timer.cancel() self.rip_timer.extend(Seconds(2)) self.rip_timer.start() return self.send_window_start = max(self.send_window_start, packet.Acknowledgement) self.send_window_data() if self.state == PEEP_Base.TEARDOWN and self.sent_all(): self.send_rip() self.rip_timer = Timer(Seconds(2), self.abort_connection) self.rip_timer.start() def handle_data(self, packet): self.received_data.append(packet) if packet.SequenceNumber == self.expected_sequence_number: self.pass_data_up() ack_packet = PEEPPacket() if self.piggyback: try_getting_piggyback_data = self.get_piggyback_data() if try_getting_piggyback_data != None: ack_packet.Data = try_getting_piggyback_data ack_packet.SequenceNumber = self.get_piggyback_sequence_number( ) ack_packet.Acknowledgement = self.expected_sequence_number ack_packet.Type = PEEPPacket.ACK ack_packet.updateChecksum() # print("sending ack") # print("ack: ", self.expected_sequence_number) self.send_packet(ack_packet) if self.state == PEEP_Base.TEARDOWN and self.received_all(): self.send_rip_ack(self.rip_sequence_number + 1) def get_piggyback_data(self): if self.sequence_number - self.base_sequence_number >= self.data_size: i = self.sequence_number - self.base_sequence_number ret = self.data[i:min( i + self.chunk_size, self.send_window_start + self.window_size * self.chunk_size)] self.sequence_number += len(ret) self.send_window_end += len(ret) return ret def get_piggyback_sequence_number(self): return self.sequence_number def pass_data_up(self): self.received_data.sort(key=lambda packet: packet.SequenceNumber) i = 0 while i < len(self.received_data): packet = self.received_data[i] if packet.SequenceNumber == self.expected_sequence_number: self.higherProtocol().data_received(packet.Data) self.expected_sequence_number += len(packet.Data) self.received_data = self.received_data[: i] + self.received_data[ i + 1:] i -= 1 i += 1 def transmit_data(self, data): self.data += data self.data_size += len(data) # print("transmitting data size: ", self.data_size) self.send_window_data() def send_window_data(self): # print('send window data') while self.send_window_end - self.send_window_start < self.window_size * self.chunk_size: if self.sequence_number - self.base_sequence_number >= self.data_size: # print("all bytes have been sent from me") return self.send_next_chunk() # print("end send window data") def send_next_chunk(self): # print('send next chunk') packet = PEEPPacket() i = self.sequence_number - self.base_sequence_number packet.Type = PEEPPacket.DATA packet.SequenceNumber = self.sequence_number packet.Data = self.data[ i:min(i + self.chunk_size, self.send_window_start + self.window_size * self.chunk_size)] packet.updateChecksum() # print("sending: " , packet.SequenceNumber) self.send_packet(packet) self.sequence_number += len(packet.Data) self.send_window_end += len(packet.Data) def connection_made(self, transport): raise NotImplementedError def connection_lost(self, exc): self.transport.close() self.transport = None asyncio.get_event_loop().stop() def send_packet(self, packet): # print(self, "send packet: ", packet) self.transport.write(packet.__serialize__()) if packet.Type != PEEPPacket.SYN and packet.Type != PEEPPacket.DATA and packet.Type != PEEPPacket.RIP: return timer = Timer(Seconds(1), self.send_packet, packet) self.timers.append(timer) timer.start() def initiate_teardown(self): # print('teardown start') self.state = PEEP_Base.TEARDOWN if self.sent_all(): self.send_rip() self.rip_timer = Timer(Seconds(2), self.abort_connection) self.rip_timer.start() def received_all(self): return self.rip_sequence_number == self.expected_sequence_number def sent_all(self): return self.sequence_number - self.base_sequence_number >= self.data_size def handle_rip(self, packet): self.state = PEEP_Base.TEARDOWN self.rip_sequence_number = packet.SequenceNumber if self.received_all(): self.send_rip_ack(self.rip_sequence_number + 1) def send_rip(self): # print("send rip :", self) rip = PEEPPacket(Type=PEEPPacket.RIP) rip.SequenceNumber = self.sequence_number self.sequence_number += 1 rip.updateChecksum() self.send_packet(rip) def send_rip_ack(self, ack): ripack = PEEPPacket(Type=PEEPPacket.RIPACK) ripack.Acknowledgement = ack ripack.updateChecksum() self.send_packet(ripack) def handle_ripack(self, packet): self.transport.close() def abort_connection(self): self.transport.close()
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 PEEP(StackingProtocol): INIT, HANDSHAKE, TRANS, TEARDOWN = [0, 1, 2, 3] def __init__(self): super().__init__() self.state = PEEP.INIT self.window_size = 100 self.chunk_size = 1024 self.transport = None self.deserializer = None self.base_sequence_number = None self.sequence_number = None self.expected_sequence_number = None self.send_window_start = None self.send_window_end = None self.receive_window_start = None self.receive_window_end = None self.data_size = 0 self.data = bytes() self.timers = [] self.received_data = [] self.rip_timer = None self.rip_sequence_number = None self.piggyback = False self.acknowledgement = None def data_received(self, data): print("data received") self.deserializer.update(data) for packet in self.deserializer.nextPackets(): if isinstance(packet, PEEPPacket) and packet.verifyChecksum(): self.handle_packets(packet) def handle_packets(self, packet): packet_type = packet.Type if packet_type == PEEPPacket.SYN and self.state == PEEP.INIT: print('received SYN') self.handle_syn(packet) elif packet_type == PEEPPacket.SYNACK and self.state == PEEP.HANDSHAKE: print('received SYNACK') self.handle_synack(packet) elif packet_type == PEEPPacket.ACK: print("received ACK") self.handle_ack(packet) elif packet_type == PEEPPacket.DATA and (self.state == PEEP.TRANS or self.state == PEEP.TEARDOWN): print('received Data') self.handle_data(packet) elif packet_type == PEEPPacket.RIP and (self.state == PEEP.TRANS or self.state == PEEP.TEARDOWN): print('received RIP') self.handle_rip(packet) elif packet_type == PEEPPacket.RIPACK and self.state == PEEP.TEARDOWN: print('received RIP-ACK') self.handle_ripack() else: print('BAD PACKET. summary: ', packet.__repr__()) def handle_syn(self, packet): print('checksum of SYN is correct') packetback = PEEPPacket() if packet.Data != FIELD_NOT_SET and packet.Data.decode( ) == "piggyback": print("syn: enable piggybacking") packetback.Data = "piggyback".encode() self.piggyback = True packetback.Acknowledgement = packet.SequenceNumber + 1 self.sequence_number = random.randint(0, 2**16) self.base_sequence_number = self.sequence_number + 1 self.expected_sequence_number = packet.SequenceNumber + 1 self.send_window_start = self.base_sequence_number self.send_window_end = self.base_sequence_number packetback.SequenceNumber = self.sequence_number packetback.Type = PEEPPacket.SYNACK packetback.updateChecksum() self.send_packet(packetback) self.state = PEEP.HANDSHAKE print('sent SYNACK') def handle_synack(self, packet): print("Received synack") if packet.Data != FIELD_NOT_SET and packet.Data.decode( ) == "piggyback": print("synack: enable piggybacking") self.piggyback = True packet_to_send = PEEPPacket() packet_to_send.Type = PEEPPacket.ACK packet_to_send.SequenceNumber = packet.Acknowledgement packet_to_send.Acknowledgement = packet.SequenceNumber + 1 packet_to_send.updateChecksum() self.base_sequence_number = packet.Acknowledgement self.expected_sequence_number = packet.SequenceNumber + 1 self.send_window_start = self.base_sequence_number self.send_window_end = self.base_sequence_number self.sequence_number = self.base_sequence_number print("Sending Back Ack") self.send_packet(packet_to_send) self.state = PEEP.TRANS # transmission state # Open upper layer transport print("connection_made to higher protocol") self.higherProtocol().connection_made( PeepTransport(self.transport, self)) def handle_ack(self, packet): if self.piggyback and packet.Data != FIELD_NOT_SET and len( packet.Data) > 0: self.handle_data(packet) self.acknowledgement = packet.Acknowledgement print("ack: ", packet.Acknowledgement) i = 0 while i < len(self.timers): timer = self.timers[i] if timer._callbackArgs[0].SequenceNumber < packet.Acknowledgement: timer.cancel() self.timers = self.timers[:i] + self.timers[i + 1:] i -= 1 i += 1 if self.rip_timer is not None: self.rip_timer.cancel() self.rip_timer.extend(Seconds(2)) self.rip_timer.start() return self.send_window_start = max(self.send_window_start, packet.Acknowledgement) self.send_window_data() if self.state == PEEP.TEARDOWN and self.sent_all(): self.send_rip() self.rip_timer = Timer(Seconds(2), self.abort_connection) self.rip_timer.start() def handle_data(self, packet): self.received_data.append(packet) if packet.SequenceNumber == self.expected_sequence_number: self.pass_data_up() ack_packet = PEEPPacket() if self.piggyback: try_getting_piggyback_data = self.get_piggyback_data() if try_getting_piggyback_data is not None: ack_packet.Data = try_getting_piggyback_data ack_packet.SequenceNumber = self.get_piggyback_sequence_number( ) ack_packet.Acknowledgement = self.expected_sequence_number ack_packet.Type = PEEPPacket.ACK ack_packet.updateChecksum() print("Sending ACK") self.send_packet(ack_packet) if self.state == PEEP.TEARDOWN and self.received_all(): self.send_rip_ack(self.rip_sequence_number + 1) def initiate_teardown(self): print('Start TEARDOWN') self.state = PEEP.TEARDOWN if self.sent_all(): self.send_rip() self.rip_timer = Timer(Seconds(2), self.abort_connection) self.rip_timer.start() def received_all(self): return self.rip_sequence_number == self.expected_sequence_number def sent_all(self): return self.sequence_number - self.base_sequence_number >= self.data_size def get_piggyback_data(self): if self.sequence_number - self.base_sequence_number >= self.data_size: i = self.sequence_number - self.base_sequence_number ret = self.data[i:min( i + self.chunk_size, self.send_window_start + self.window_size * self.chunk_size)] self.sequence_number += len(ret) self.send_window_end += len(ret) return ret def get_piggyback_sequence_number(self): return self.sequence_number def transmit_data(self, data): self.data += data self.data_size += len(data) print("transmitting data size: ", self.data_size) self.send_window_data() def send_window_data(self): print('Sending Window Data') while self.send_window_end - self.send_window_start < self.window_size * self.chunk_size: if self.sequence_number - self.base_sequence_number >= self.data_size: print("Everything sent") return self.send_next_chunk() def pass_data_up(self): self.received_data.sort( key=lambda current_packet: current_packet.SequenceNumber) i = 0 while i < len(self.received_data): packet = self.received_data[i] if packet.SequenceNumber == self.expected_sequence_number: self.higherProtocol().data_received(packet.Data) self.expected_sequence_number += len(packet.Data) self.received_data = self.received_data[: i] + self.received_data[ i + 1:] i -= 1 i += 1 def send_next_chunk(self): print('send next chunk') next_packet = PEEPPacket() i = self.sequence_number - self.base_sequence_number next_packet.Type = PEEPPacket.DATA next_packet.SequenceNumber = self.sequence_number next_packet.Data = self.data[ i:min(i + self.chunk_size, self.send_window_start + self.window_size * self.chunk_size)] next_packet.updateChecksum() print("Now sending packet with seq number:", next_packet.SequenceNumber) self.send_packet(next_packet) self.sequence_number += len(next_packet.Data) self.send_window_end += len(next_packet.Data) def connection_made(self, transport): raise NotImplementedError def connection_lost(self, exc): self.transport.close() self.transport = None asyncio.get_event_loop().stop() def send_packet(self, packet): print(self, "send packet: ", packet) self.transport.write(packet.__serialize__()) if packet.Type != PEEPPacket.SYN and packet.Type != PEEPPacket.DATA and packet.Type != PEEPPacket.RIP: return timer = Timer(Seconds(1), self.send_packet, packet) self.timers.append(timer) timer.start() """ RIP's and TEARDOWN """ def handle_rip(self, packet): self.state = PEEP.TEARDOWN self.rip_sequence_number = packet.SequenceNumber if self.received_all(): self.send_rip_ack(self.rip_sequence_number + 1) def send_rip(self): print("Sending RIP") rip_packet = PEEPPacket(Type=PEEPPacket.RIP) rip_packet.SequenceNumber = self.sequence_number self.sequence_number += 1 rip_packet.updateChecksum() self.send_packet(rip_packet) def send_rip_ack(self, ack): print("Sending RIP ACK") rip_ack_packet = PEEPPacket(Type=PEEPPacket.RIPACK) rip_ack_packet.Acknowledgement = ack rip_ack_packet.updateChecksum() self.send_packet(rip_ack_packet) def handle_ripack(self): self.transport.close() def abort_connection(self): self.transport.close()
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 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__())
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)