network simulations
Project description: In this Phase, we will develop two nodes for the network simulator. The first node is a trasmitter and the second node is a receiver. Each node is defined by a unique node_ID. That is, there are no two nodes in the network with the same ID. Since we are using a single machine to perform PHY transmissions, the node_ID values can be arbitrary IP address. Each node has five layers namely: application_layer, transport_layer, network_layer, link_layer and PHY_layer. For this phase of the project, we develop protocols for three layers: application_layer, transport_layer and PHY_layer Each layer (depending on its location) has allocated buffers to establish communication with the other layers above or below it. For instance, the transport_layer has four buffers: to_network_layer, from_network_layer, from_application_layer, to_application_layer For the application_layer, we will develop file transfer protocol (FTP). The FTP class has two sides, the transmitter and receiver sides. The transmitter sides reads a file (specified by user) and convert that into application_layer_messages. The receiver side gets application_layer_messages from the transport_layer converts them into single file. For the transport_layer, we will develop UDP protocol. This protocol has two sides, the transmitter and receiver sides. The transmitter side gets the application_layer_messages from the application_layer and converts them into transport_layer segments. Note that the length of each segment should be maximum segment size MSS (excluding UDP header). The value of MSS usually depends on the PHY link that each node is connected to. Each segment should have the following fields: # application_layer_messages_no: 4bytes: 32 bits # segment_no: packet number : 4bytes: 32 bits # source_port: this field identifies the sender's port : 2 bytes: 16 bits # destination_port: This field identifies the receiver's port: 2 bytes : 16 bits # Length: the length in bytes of the UDP header and UDP data : 2 bytes : 16 bits # Checksum: the checksum field is used for error-checking of the header and data. 2 bytes : 16 bits # Reference flag: indicates the beginning of a set of segments for an individual application message It is important to note that each application_layer_messages is divided to a set of segments. The reference byte represent the beginning of each set. The receiver side of the transport_layer gets the set of segments and concatenated them to makes a single application_layer_messages. For the PHY layer, we use python socket library to send and receive messages over ports. This is because, we will use a single machine for the network simulator. The PHY sender simply transfers packets over the specified port. The PHY receiver listens to that port and send the received packets to the upper layer. For this Phase, you need to develop the following files: application_layer.py: contains FTP class transport_layer.py: contains UDP class PHY_layer.py: contains PHY class node.py: contains node class that defines an individual node in the network simulator network_simulator.py: that defines the topology of the network (for this phase there are only two nodes, sender and receiver) The program should run by the following command: ./network_simulator.py --FTP_filename = filename.txt The output of the program should contains the following information: 1. generate filename_RX.txt (the received file name) 2. generate network_simulator.log (this is the log file for the network_simulator operations) This file should contains the follwoing information: # node_num_log: <number of the nodes in the netwok> # node_ID_log: <list of the nodes IP address in a form of node_ID:IP_address> # application_layer_messages_log: <the number of messages generated by application_layer> # transport_layer_segments_log: <the number of segments generated by the transport_layer> # segment_length_log: the length of each segment **************************************************************************************** # Physical layer file *********Completed*********** # we will define different classes for the phy layer communicaiton import socket class PHY: def __init__(self,app_port,pkt_size): # define private variables # buffer for processing link layer pkts self.from_link_layer = dict() # buffer to send to the link layer self.to_link_layer = dict() # Define TX and RX socket objects self.TX_sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) self.RX_sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # Define TX and RX IP and ports self.IP = "127.0.0.1" # app_port is configured by the application layer self.TX_port = app_port self.RX_port = app_port + 1 self.pkt_size = pkt_size def transmitter(self,pkt): # send a single packet over the port <loopback ip> self.TX_sock.sendto(str(pkt), (self.IP, self.TX_port)) def transmitter_wrapper(self): # give packets one by one to the PHY TX for pktno in self.self.from_link_layer: self.transmitter(self.self.from_link_layer[pktno]) def receiver(self): # get each packet from the RX port pkt, addr = self.RX_sock.recvfrom(self.pkt_size) return eval(pkt) def receiver_wrapper(self): while True: pkt = self.receiver() pktno = pkt['pktno'] #app_payload = pkt['app_payload'] self.to_link_layer[pktno] = pkt *************************************************************************************** *************************************************************************************** # run this with python3--transport laye---Partially completed # This function defines necessary classes for the transport layer # This class implements UDP protocol at the transport layer import math # we use md5 library for checksum import md5 # use bitarray to convert sequence of bits to bytes from bitstring import BitArray # BitArray().tobytes() converts sequence of bits to bytes # BitArray().bin converts bytes to sequence of bits # UDP_payload: data content for the application layer class UDP: def __init__(self,MSS,source_port,destination_port): # define private variables here #define a buffer to store UDP segments to send to the network layer ################# ## ## Your Code Here ## ################## # define a buffer that stored datagrams provided by the network layer ################# ## ## Your Code Here ## ################## # define a buffer to store concatenated packets into data payload to send to the application layer ################# ## ## Your Code Here ## ################## # define a buffer to get data payload from application layer to convert them into UDP segments ################# ## ## Your Code Here ## ################## # define a maximum segment size MSS, source_port and destination_port ################# ## ## Your Code Here ## ################## # convert source_port and destination_port to byte format ################# ## ## Your Code Here ## ################## # segment_no : keeps track of segments we generate ################# ## ## Your Code Here ## ################## def transmitter(self,application_message,application_message_no): # define the transmitter function that get application data payload and convert them into UDP segments # function input parameters: application_message # lenght of application_message is in bytes # application_message in represented in bytes # each segment have the following fields <here we assume UDP packets> ###### packet header contains # pktno: packet number : 4bytes: 32 bits # source_port: this field identifies the sender's port : 2 bytes: 16 bits # destination_port: This field identifies the receiver's port: 2 bytes : 16 bits # Length: the length in bytes of the UDP header and UDP data : 2 bytes : 16 bits # Checksum: the checksum field is used for error-checking of the header and data. 2 bytes : 16 bits # Reference flag: indicates the beginning of a set of segments for an individual application message ###### # generates appropriate number of segments for each application payload # length of each segment should be MSS (excluding UDP header) # define pktno 32 bits = 4 bytes # calculate number of segments necessary to convert the payload into segments ################# ## ## Your Code Here ## ################## # Generate UDP segments: each segments should contain MSS bytes of application payload + 12 bytes of UDP header (pktno + source_port + destination_port + lenght + checksum) ################# ## ## Your Code Here ## ################## # reference byte is one for the very first segment of each set. ################# ## ## Your Code Here ## ################## # add segment_no + checksum to each segment_no ################# ## ## Your Code Here ## ################## # store the application_message number associated with this segment ################# ## ## Your Code Here ## ################## # store the generated segment into the self.to_network_layer buffer ################# ## ## Your Code Here ## ################## def transmitter_wrapper(self): # the transmitter_wrapper function fetch one application_message from self.from_application_layer buffer # and pass it to transmitter function to generate UDP segments for that message ################# ## ## Your Code Here ## ################## def receiver(self,segment_set): # this function concatenates a set of segments that represent a single application message # input: a set of segments # output: a single data message # define an empty data message ################# ## ## Your Code Here ## ################## # go through each segment and extract the data payload and concatinate it to the data_message ################# ## ## Your Code Here ## ################## def receiver_wrapper(self): # the receiver_wrapper function fetch transport layer segments received from network layer and # it look at the reference byte to finds the beginning of the segment set that represent a single data message ################# ## ## Your Code Here ## ################## *************************************************************************************** # define applicaiton layer classess ---*********Partially completed************* # define ftp class class FTP: def __init__(self,node_IP,port_number): # define necessary private variables for this class # define buffer to send FTP data to transport layer ################ ### your code ################ #define buffer to receive data from transport layer ################ ### your code ################ # make a local variables for IP and port numbers # IP and port numbers will be passed down to the transport_layer ################ ### your code ################ def transmitter(self,filename): # define transmitter function # this function read from a file <given by filename> line by line # and insert the data to buffer for transport layer # open a file < we assume the file is ASCII ################ ### your code ################ # read from a file line-by-line and store it in the buffer for ################ ### your code ################ def receiver(self,filename): # define a receiver function # this function gets the segmented packets from the transport layer buffer and # create a file < we assume an ASCII file> specified by filename # open a file to write into ################ ### your code ################ # read from the transport layer buffer and write the packet application paylod into the file ################ ### your code ################ **************************************************************************************