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()
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 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__())
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 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 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)