예제 #1
0
    def response(self, typ, addr, id, rtr):
        if self.mode == SCUMode.SendMode:
            raise Exception
        if typ == SCUPacketType.Rtr.value:
            header = SCUHeader()
            header.from_dict({
                "typ": typ,
                "id": id,
                "seq": rtr,
            })
            packet = SCUPacket()
            packet.from_dict({
                "header": header,
                "payload": b'',
            })
            self.socket.sendto(packet.raw(), addr)

        elif typ == SCUPacketType.Fin.value:
            header = SCUHeader()
            header.from_dict({
                "typ": typ,
                "id": id,
                "seq": rtr,
            })
            packet = SCUPacket()
            packet.from_dict({
                "header": header,
                "payload": b'',
            })
            self.socket.sendto(packet.raw(), addr)
예제 #2
0
 def _sender_packet_loop(self):
     if self.mode == SCUMode.RecvMode:
         raise Exception
     while True:
         try:
             packet = SCUPacket()
             packet.from_raw(self.socket.recv(2048))
             # # TODO: remove this
             # psuedo packet loss
             if random.random() >= 0.5:
                 continue
             if packet.header.id not in self.connection_manager:
                 continue
             if packet.header.typ == SCUPacketType.Fin.value:
                 self.connection_manager[packet.header.id].put(
                     (True, packet.header.seq))
             elif packet.header.typ == SCUPacketType.Rtr.value:
                 self.connection_manager[packet.header.id].put(
                     (False, packet.header.seq))
         except Exception as e:  # recvが失敗した時とputが失敗した時は(適当)
             if e == KeyboardInterrupt:
                 raise KeyboardInterrupt
             else:
                 import traceback
                 traceback.print_exc()
예제 #3
0
    def send(self, filepath, id): # will lock the thread
        if self.mode == SCUMode.RecvMode:
            raise Exception
        queue = Queue()
        self.connection_manager[id] = queue # コネクションを登録

        data_fragments = utils.split_file_into_mtu(filepath, self.mtu)

        all_packets = []
        for (seq, df) in enumerate(data_fragments):
            # create header
            header = SCUHeader()
            if seq == len(data_fragments) - 1:
                header.from_dict({ "typ": SCUPacketType.DataEnd.value, "id": id, "seq": seq, })
            else:
                header.from_dict({ "typ": SCUPacketType.Data.value, "id": id, "seq": seq, })
            # create packet
            packet = SCUPacket()
            packet.from_dict({ "header": header, "payload": df, })

            all_packets.append(packet)

        retransmit_seq = 0 # 再送の必要があるパケットを管理(どこまで受け取れてるか)
        seq = 0
        while True:
            try:
                while True:
                    try:
                        fin, sq = queue.get(block=False) # 再送要求か受信完了報告か
                        if fin: # 送信完了
                            del(self.connection_manager[id]) # コネクションを解除
                            return
                        elif sq < len(all_packets): # 再送要求
                            retransmit_seq = max(sq, retransmit_seq)
                    except Exception as e: # キューが空の時
                        if e == KeyboardInterrupt:
                            raise KeyboardInterrupt
                        else:
                            break
                with self.lock: # 複数のsendメソッドが並列に同時実行されている可能性があるため,ロックが必要
                    self.socket.sendto(all_packets[seq].raw(), self.receiver_address) # パケット送信

                seq = max(seq + 1, retransmit_seq) # seq更新
                if seq >= len(all_packets):
                    seq = retransmit_seq
            except Exception as e: # sendtoが失敗した時は(適当)
                if e == KeyboardInterrupt:
                    raise KeyboardInterrupt
                else:
                    import traceback
                    traceback.print_exc()
예제 #4
0
    def send(self, filepath, id): # will lock the thread
        if self.mode == SCUMode.RecvMode:
            raise Exception
        queue = Queue()
        self.connection_manager[id] = queue # Register a connection

        data_fragments = utils.split_file_into_mtu(filepath, self.mtu)

        all_packets = []
        for (seq, df) in enumerate(data_fragments):
            # create header
            header = SCUHeader()
            if seq == len(data_fragments) - 1:
                header.from_dict({ "typ": SCUPacketType.DataEnd.value, "id": id, "seq": seq, })
            else:
                header.from_dict({ "typ": SCUPacketType.Data.value, "id": id, "seq": seq, })
            # create packet
            packet = SCUPacket()
            packet.from_dict({ "header": header, "payload": df, })

            all_packets.append(packet)

        retransmit_seq = 0 # Manage packets that need to be resent (how far you can receive)
        seq = 0
        while True:
            try:
                while True:
                    try:
                        fin, sq = queue.get(block=False) # Resend request or reception completion report
                        if fin: # Finished sending
                            del(self.connection_manager[id]) # Disconnect
                            return
                        elif sq < len(all_packets): # Request again
                            retransmit_seq = max(sq, retransmit_seq)
                    except Exception as e: # When the queue is empty
                        if e == KeyboardInterrupt:
                            raise KeyboardInterrupt
                        else:
                            break
                with self.lock: # Lock required as multiple send methods may be running concurrently in parallel
                    self.socket.sendto(all_packets[seq].raw(), self.receiver_address) # Packet transmission

                seq = max(seq + 1, retransmit_seq) # SEQ Update
                if seq >= len(all_packets):
                    seq = retransmit_seq
            except Exception as e: # When sendto fails (appropriate)
                if e == KeyboardInterrupt:
                    raise KeyboardInterrupt
                else:
                    import traceback
                    traceback.print_exc()
예제 #5
0
    def _receiver_packet_loop(self):
        if self.mode == SCUMode.SendMode:
            raise Exception
        received_files_flag = {}
        received_files_length = {}
        while True:
            try:
                data, from_addr = self.socket.recvfrom(2048)
                packet = SCUPacket()
                packet.from_raw(data)
                # TODO: remove this
                # psuedo packet loss
                if random.random() >= 0.5:
                    continue
                key = utils.endpoint2str(from_addr, packet.header.id)
                if key not in self.received_files_data:
                    self.received_files_data[key] = [b""] * 100
                    received_files_flag[key] = False

                if received_files_flag[key]:
                    self.response(SCUPacketType.Fin.value, from_addr,
                                  packet.header.id, 0)
                    continue

                if packet.header.typ == SCUPacketType.DataEnd.value or packet.header.typ == SCUPacketType.Data.value:
                    if packet.header.typ == SCUPacketType.DataEnd.value:
                        received_files_length[key] = packet.header.seq + 1

                    self.received_files_data[key][
                        packet.header.seq] = packet.payload
                    rtr = self.calculate_rtr(key, packet.header.seq)
                    if rtr is not None:  # 再送要求する必要あり
                        self.response(SCUPacketType.Rtr.value, from_addr,
                                      packet.header.id, rtr)
                    elif key in received_files_length and self.is_all_received(
                            key, received_files_length[key]):  #  ファイル受信完了
                        received_files_flag[key] = True
                        self.response(SCUPacketType.Fin.value, from_addr,
                                      packet.header.id, 0)
                        self.file_received.put(
                            (key, received_files_length[key]))

            except Exception as e:  # recvが失敗した時とputが失敗した時は(適当)
                if e == KeyboardInterrupt:
                    raise KeyboardInterrupt
                else:
                    import traceback
                    traceback.print_exc()
예제 #6
0
    def _receiver_packet_loop(self):
        if self.mode == SCUMode.SendMode:
            raise Exception
        received_files_flag = {}
        received_files_length = {}
        while True:
            try:
                data, from_addr = self.socket.recvfrom(2048)
                packet = SCUPacket()
                packet.from_raw(data)

                key = utils.endpoint2str(from_addr, packet.header.id)
                if key not in self.received_files_data:
                    self.received_files_data[key] = [b""] * 100
                    received_files_flag[key] = False

                if received_files_flag[key]:
                    self.response(SCUPacketType.Fin.value, from_addr,
                                  packet.header.id, 0)
                    continue

                if packet.header.typ == SCUPacketType.DataEnd.value or packet.header.typ == SCUPacketType.Data.value:
                    if packet.header.typ == SCUPacketType.DataEnd.value:
                        received_files_length[key] = packet.header.seq + 1

                    self.received_files_data[key][
                        packet.header.seq] = packet.payload
                    rtr = self.calculate_rtr(key, packet.header.seq)
                    if rtr is not None:  # Need to send retransmission request
                        self.response(SCUPacketType.Rtr.value, from_addr,
                                      packet.header.id, rtr)
                    elif key in received_files_length and self.is_all_received(
                            key, received_files_length[key]):  # Received file:
                        received_files_flag[key] = True
                        self.response(SCUPacketType.Fin.value, from_addr,
                                      packet.header.id, 0)
                        self.file_received.put(
                            (key, received_files_length[key]))

            except Exception as e:  # When recv or put failed:
                if e == KeyboardInterrupt:
                    raise KeyboardInterrupt
                else:
                    import traceback
                    traceback.print_exc()
예제 #7
0
 def _sender_packet_loop(self):
     if self.mode == SCUMode.RecvMode:
         raise Exception
     while True:
         try:
             packet = SCUPacket()
             packet.from_raw(self.socket.recv(2048))
             if packet.header.id not in self.connection_manager:
                 continue
             if packet.header.typ == SCUPacketType.Fin.value:
                 self.connection_manager[packet.header.id].put((True, packet.header.seq))
             elif packet.header.typ == SCUPacketType.Rtr.value:
                 self.connection_manager[packet.header.id].put((False, packet.header.seq))
         except Exception as e: # When recv fails and when put fails (appropriate)
             if e == KeyboardInterrupt:
                 raise KeyboardInterrupt
             else:
                 import traceback
                 traceback.print_exc()
예제 #8
0
파일: myscu.py 프로젝트: k-bigboss99/robust
 def _sender_packet_loop(self):
     prev_packet = SCUPacket()
     while True:
         try:
             packet = SCUPacket()
             packet.from_raw(self.socket.recv(2048))
             # # psuedo packet loss TODO: remove
             # if random.random() >= 0.5:
             #     continue
             if packet.header.id not in self.connection_manager:
                 continue
             if prev_packet.header.__dict__ == packet.__dict__:
                 continue
             prev_packet = packet
             self.connection_manager[packet.header.id].put(packet)
         except Exception as e:  # recvが失敗した時とputが失敗した時は(適当)
             if e == KeyboardInterrupt:
                 raise KeyboardInterrupt
             else:
                 import traceback
                 traceback.print_exc()
예제 #9
0
파일: myscu.py 프로젝트: k-bigboss99/robust
 def _receiver_packet_loop(self):
     prev_packet = SCUPacket()
     while True:
         try:
             data, from_addr = self.socket.recvfrom(2048)
             # # # TODO: remove this
             # # psuedo packet loss
             # if random.random() >= 0.5:
             #     continue
             packet = SCUPacket()
             packet.from_raw(data)
             if prev_packet.__dict__ == packet.__dict__:
                 continue
             prev_packet = packet
             self.task_manager.put((packet, from_addr))
         except Exception as e:
             if e == KeyboardInterrupt:
                 raise KeyboardInterrupt
             else:
                 import traceback
                 traceback.print_exc()
예제 #10
0
파일: myscu.py 프로젝트: k-bigboss99/robust
    def response(self, typ, addr, key, seq, resendID, content=b""):
        """
        responses a single packet of retry, or fin.

        it can be used to just send packets.
        """
        if self.mode == SCUMode.SendMode:
            raise Exception
        header = SCUHeader()
        packet = SCUPacket()
        header.from_dict({
            "typ": typ,
            "id": key,
            "seq": seq,
            "resendID": resendID
        })
        if typ == SCUPacketType.Rtr.value:
            packet.from_dict({"header": header, "payload": content.encode()})
        elif typ == SCUPacketType.Fin.value:
            packet.from_dict({"header": header, "payload": b''})
        else:
            raise Exception()
        self.socket.sendto(packet.raw(), addr)
예제 #11
0
파일: myscu.py 프로젝트: k-bigboss99/robust
 def send(self, filepath, fileno):
     if self.mode == SCUMode.RecvMode:
         raise Exception
     queue = Queue()
     self.connection_manager[fileno] = queue  # register queue
     data_fragments = utils.split_file_into_mtu(filepath, self.mtu)
     all_packets = []
     current_resendID = 0
     for (seq, df) in enumerate(data_fragments):
         header = SCUHeader()
         if seq == len(data_fragments) - 1:
             header.from_dict({
                 "typ": SCUPacketType.DataEnd.value,
                 "id": fileno,
                 "seq": seq,
                 "resendID": 0
             })
         else:
             header.from_dict({
                 "typ": SCUPacketType.Data.value,
                 "id": fileno,
                 "seq": seq,
                 "resendID": 0
             })
         packet = SCUPacket()
         packet.from_dict({"header": header, "payload": df})
         all_packets.append(packet)
     while True:  # main loop
         if self.send_mode == SendMode.SendNewFile:
             for seq in range(len(all_packets) - 1):
                 with self.lock:
                     self.socket.sendto(all_packets[seq].raw(),
                                        self.receiver_address)
             # for seq in range(len(all_packets) - 1):
             #     with self.lock:
             #         self.socket.sendto(all_packets[seq].raw(), self.receiver_address)
             self.send_mode = SendMode.KeepSendingDataEndUntilResendReqComes
         elif self.send_mode == SendMode.KeepSendingDataEndUntilResendReqComes:
             dataEnd = all_packets[-1]
             dataEnd.header.resendID = 0
             while True:
                 if random.random() >= 0.8:
                     with self.lock:
                         self.socket.sendto(dataEnd.raw(),
                                            self.receiver_address)
                 try:
                     packet = queue.get(block=False)
                 except Exception as e:
                     if e == KeyboardInterrupt:
                         raise KeyboardInterrupt
                     else:
                         pass
                 else:
                     if packet.header.typ == SCUPacketType.Rtr.value and packet.header.resendID >= 1:
                         current_resendID = packet.header.resendID
                         self.missing_seqs_str = packet.payload.decode()
                         self.send_mode = SendMode.SendMissingSeqs
                         break
                     elif packet.header.typ == SCUPacketType.Fin.value:
                         return
         elif self.send_mode == SendMode.SendMissingSeqs:
             missing_seqs = list(map(int, self.missing_seqs_str.split(",")))
             # 言われてた欠損ファイルを一回送る、それか二周送る
             for i in range(len(missing_seqs) - 1):
                 data = all_packets[missing_seqs[i]]
                 data.header.resendID = current_resendID
                 with self.lock:
                     self.socket.sendto(data.raw(), self.receiver_address)
             end_packet = all_packets[missing_seqs[-1]]
             end_packet.header.resendID = current_resendID
             end_packet.header.typ = SCUPacketType.End.value
             self.end_packet = end_packet
             self.send_mode = SendMode.KeepSendingEndUntilResendReqComes
         elif self.send_mode == SendMode.KeepSendingEndUntilResendReqComes:
             while True:
                 if random.random() >= 0.9:
                     with self.lock:
                         self.socket.sendto(self.end_packet.raw(),
                                            self.receiver_address)
                 try:
                     packet = self.connection_manager[fileno].get(
                         block=False)
                 except Exception as e:  # queue is empty
                     if e == KeyboardInterrupt:
                         raise KeyboardInterrupt
                     else:
                         pass
                 else:
                     if packet.header.typ == SCUPacketType.Rtr.value and packet.header.resendID > current_resendID:
                         current_resendID = packet.header.resendID
                         self.missing_seqs_str = packet.payload.decode()
                         missing_seqs_count = len(
                             self.missing_seqs_str.split(','))
                         if missing_seqs_count <= n:
                             self.send_mode = SendMode.SendingMissingSeqLoopUntilFinComes
                             break
                         else:
                             self.send_mode = SendMode.SendMissingSeqs
                             break
                     elif packet.header.typ == SCUPacketType.Fin.value:
                         return
         elif self.send_mode == SendMode.SendingMissingSeqLoopUntilFinComes:
             index = 0
             remained_seqs = list(map(int,
                                      self.missing_seqs_str.split(',')))
             while True:
                 data = all_packets[remained_seqs[index]]
                 data.header.resendID = current_resendID
                 with self.lock:  # lock
                     self.socket.sendto(data.raw(), self.receiver_address)
                 if index == len(remained_seqs) - 1:
                     index = 0
                 else:
                     index += 1
                 try:
                     packet = self.connection_manager[fileno].get(
                         block=False)
                 except Exception as e:
                     if e == KeyboardInterrupt:
                         raise KeyboardInterrupt
                     else:
                         continue
                 else:
                     if packet.header.typ == SCUPacketType.Fin.value:
                         del (self.connection_manager[fileno])
                         self.send_mode = SendMode.SendNewFile
                         return
         else:
             raise Exception
예제 #12
0
    def send(self, filepath, id):  # Will lock the thread
        if self.mode == SCUMode.RecvMode:
            raise Exception
        queue = Queue()
        self.connection_manager[id] = queue  # Register the connection

        data_fragments = utils.split_file_into_mtu(filepath, self.mtu)

        all_packets = []
        for (seq, df) in enumerate(data_fragments):
            # create header
            header = SCUHeader()
            if seq == len(data_fragments) - 1:
                header.from_dict({
                    "typ": SCUPacketType.DataEnd.value,
                    "id": id,
                    "seq": seq,
                })
            else:
                header.from_dict({
                    "typ": SCUPacketType.Data.value,
                    "id": id,
                    "seq": seq,
                })
            # create packet
            packet = SCUPacket()
            packet.from_dict({
                "header": header,
                "payload": df,
            })

            all_packets.append(packet)

        retransmit_seq = 0  # Manage the packets which needs retransmission (how much is it received correctly)
        seq = 0
        while True:
            try:
                while True:
                    try:
                        fin, sq = queue.get(
                            block=False
                        )  # Retransmission Request or Transmission Done Report
                        if fin:  # 送信完了
                            del (self.connection_manager[id]
                                 )  # Remove connection
                            return
                        elif sq < len(all_packets):  # Retransmission Request
                            retransmit_seq = max(sq, retransmit_seq)
                    except Exception as e:  # When queue is empty:
                        if e == KeyboardInterrupt:
                            raise KeyboardInterrupt
                        else:
                            break
                with self.lock:  # Multiple send method might be running in parallel, so lock is required.
                    self.socket.sendto(all_packets[seq].raw(),
                                       self.receiver_address)  # Send packet

                seq = max(seq + 1, retransmit_seq)  # Update seq
                if seq >= len(all_packets):
                    seq = retransmit_seq
            except Exception as e:  # When sendto has failed:
                if e == KeyboardInterrupt:
                    raise KeyboardInterrupt
                else:
                    import traceback
                    traceback.print_exc()