Advertisement
CSenshi

CN - HW3 (RTP)

Oct 29th, 2019
588
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.43 KB | None | 0 0
  1. import sys
  2. import getopt
  3. import time
  4. from random import randint as rand
  5. from pprint import pprint
  6. import Checksum
  7.  
  8. import BasicSender
  9.  
  10. '''
  11. This is a skeleton sender class. Create a fantastic transport protocol here.
  12. '''
  13.  
  14.  
  15. class Sender(BasicSender.BasicSender):
  16.     def __init__(self, dest, port, filename, debug=True, sackMode=False):
  17.         super(Sender, self).__init__(dest, port, filename, debug)
  18.         self.sackMode = sackMode
  19.         self.debug = debug
  20.         self.start_seq_num = 1
  21.         self.timeout = 0.5
  22.         self.chunk_size = 1024
  23.         self.max_bytes = 1472
  24.         self.window_size = 7
  25.  
  26.         self.msg_queue = self.generate_queue()
  27.  
  28.     def generate_queue(self):
  29.         queue = []
  30.         seq_num = self.start_seq_num + 1
  31.         while 1:
  32.             chunk = self.infile.read(self.chunk_size)
  33.             if not chunk:
  34.                 break
  35.             msg = self.make_packet('dat', seq_num, chunk)
  36.             seq_num += 1
  37.             queue += [msg]
  38.         return queue
  39.  
  40.     # Main sending loop.
  41.     def start(self):
  42.         self.log("Starting RTP Connection")
  43.         self.handshake()
  44.         self.data_transfer()
  45.         self.send_fin()
  46.  
  47.         # while 1: pass
  48.  
  49.     def handshake(self):
  50.         self.log("Starting Handshake...")
  51.         while True:
  52.             hello_msg = self.make_packet('syn', self.start_seq_num, '')
  53.             self.send(hello_msg)
  54.             ans = self.receive(self.timeout)
  55.             if ans:
  56.                 msg_type, seqno, data, checksum = self.split_packet(ans)
  57.                 if Checksum.validate_checksum(ans) and \
  58.                         ((msg_type == 'ack' and seqno == str(self.start_seq_num + 1)) or
  59.                          (msg_type == 'sack' and seqno == str(self.start_seq_num + 1) + ';')):
  60.                     break
  61.             self.log("Trying Handshake Again...")
  62.         self.log("Done Handshake\n")
  63.  
  64.     def data_transfer(self):
  65.         self.log("Starting Data Transfer...")
  66.         index = len(self.msg_queue)
  67.         vis = []
  68.         counter, last_index = 0, 0
  69.         start_time = time.time()
  70.         while True:
  71.             if counter >= 3:
  72.                 # print 'a', counter, last_index, index
  73.                 self.send(self.msg_queue[last_index])
  74.             else:
  75.                 for i in range(self.window_size):
  76.                     if index >= len(self.msg_queue):
  77.                         break
  78.                     if str(i + 1 + self.start_seq_num) not in vis:
  79.                         packet = self.msg_queue[index]
  80.                         self.send(packet)
  81.                     index += 1
  82.             ans = self.receive(self.timeout)
  83.             # print ans, len(self.msg_queue), counter
  84.             if ans and Checksum.validate_checksum(ans):
  85.                 msg_type, seqno, data, checksum = self.split_packet(ans)
  86.                 if msg_type == 'sack':
  87.                     res = self.treat_sack_msg(seqno, index)
  88.                     if res is True:
  89.                         break
  90.                     else:
  91.                         vis, index = res
  92.                         if index == last_index:
  93.                             counter += 1
  94.                         else:
  95.                             counter = 0
  96.                             last_index = index
  97.                     continue
  98.                 elif msg_type == 'ack':
  99.                     vis = []
  100.                     index = int(seqno) - 2 - self.start_seq_num + 1
  101.                 else :
  102.                     index = max(index - self.window_size, 0)
  103.             else:
  104.                 index = max(index - self.window_size, 0)
  105.             if index == last_index:
  106.                 counter += 1
  107.             else:
  108.                 counter = 0
  109.                 last_index = index
  110.             if index >= len(self.msg_queue):
  111.                 break
  112.         elapsed_time = time.time() - start_time
  113.  
  114.         print 'Time ', elapsed_time
  115.         self.log("Done Data Transfer\n")
  116.  
  117.     def log(self, text):
  118.         if self.debug:
  119.             print text
  120.  
  121.     def send_fin(self):
  122.         seq_no = self.start_seq_num + len(self.msg_queue) + 1
  123.         final_msg = self.make_packet('fin', seq_no, '')
  124.         self.log("Starting fin Transfer...")
  125.         while True:
  126.             self.send(final_msg)
  127.             ans = self.receive(self.timeout)
  128.             if ans:
  129.                 msg_type, seqno, data, checksum = self.split_packet(ans)
  130.                 if Checksum.validate_checksum(ans) and \
  131.                         ((msg_type == 'ack' and seqno == str(seq_no+1)) or
  132.                          (msg_type == 'sack' and seqno == str(seq_no+1) + ';')):
  133.                     break
  134.         self.log("Done fin Transfer...")
  135.  
  136.     def treat_sack_msg(self, seqno, index):
  137.         cum_ack, sacks = seqno.split(';')
  138.         cum_ack = int(cum_ack)
  139.         if cum_ack > len(self.msg_queue) + self.start_seq_num:
  140.             return True
  141.         sacks = sacks.split(',')
  142.         return sacks, cum_ack - 1 - self.start_seq_num
  143.  
  144.  
  145. '''
  146. This will be run if you run this script from the command line. You should not
  147. change any of this; the grader may rely on the behavior here to test your
  148. submission.
  149. '''
  150. if __name__ == "__main__":
  151.     def usage():
  152.         print "BEARS-TP Sender"
  153.         print "-f FILE | --file=FILE The file to transfer; if empty reads from STDIN"
  154.         print "-p PORT | --port=PORT The destination port, defaults to 33122"
  155.         print "-a ADDRESS | --address=ADDRESS The receiver address or hostname, defaults to localhost"
  156.         print "-d | --debug Print debug messages"
  157.         print "-h | --help Print this usage message"
  158.         print "-k | --sack Enable selective acknowledgement mode"
  159.  
  160.  
  161.     try:
  162.         opts, args = getopt.getopt(sys.argv[1:],
  163.                                    "f:p:a:dk", ["file=", "port=", "address=", "debug=", "sack="])
  164.     except:
  165.         usage()
  166.         exit()
  167.  
  168.     port = 33122
  169.     dest = "localhost"
  170.     filename = None
  171.     debug = False
  172.     sackMode = False
  173.  
  174.     for o, a in opts:
  175.         if o in ("-f", "--file="):
  176.             filename = a
  177.         elif o in ("-p", "--port="):
  178.             port = int(a)
  179.         elif o in ("-a", "--address="):
  180.             dest = a
  181.         elif o in ("-d", "--debug="):
  182.             debug = True
  183.         elif o in ("-k", "--sack="):
  184.             sackMode = True
  185.  
  186.     s = Sender(dest, port, filename, debug, sackMode)
  187.     try:
  188.         s.start()
  189.     except (KeyboardInterrupt, SystemExit):
  190.         exit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement