MP Transport Protocol Assignment

Your goal in this MP is to implement a reliable transport protocol that supports congestion and flow control. You will build your protocol on top of UDP. Your protocol should have the following features:

Handshake

Your client and server should perform a handshake to establish a connection. If there is no response from the server, you should return an error. Unlike TCP, you don't have to support multiple simultaneous connections to the same port. Reliable Data Transfer

You should ensure data is delivered reliably and in order even if the network drops, delays, or reorders packets. You can assume that the network never corrupts the packets. Flow Control

When sending data, you should use flow control to ensure that data does not get sent faster than it is processed at the receiver. You may allow a little buffering in your system but no more than 100 KB or so.

Congestion Control

You should implement congestion control to avoid congesting the network. Your system should dynamically adjust its sending rate to avoid congestion and maintain high overall throughput. Fairness

Two connections using your transport protocol should converge to fairly sharing the link; i.e., have roughly the same throughput (+/- 10%). This should happen within about 100 RTTs, even if the two connections were not started at the same time.

TCP Friendliness

Your protocol must be somewhat TCP friendly: if you share a connection with a TCP flow, your flow should have between 60% and 70% of the aggregate throughput. Utilization

In the absence of packet loss (other than due to congestion) or reordering, and when there are no competing flows, your protocol should utilize at least 70% of the bandwidth in the steady state.

Implementation

You may implement this project in C/C++ or Python. Unlike MP1, C/C++ is a reasonable implementation choice for this project and you may see somewhat higher performance. In Python, you should implement a socket-like object, described in the file transport.py. In C/C++, you should implement the functions described in the file transport.h. The functions implement a slightly simplified version of the standard socket interface.

Python function                C function              Description 
MP2Socket.__init__()           mp2_socket_init()       Initialize the socket 
MP2Socket.connect()            mp2_socket_connect()    Connect to a remote socket. The remote endpoint is specified by a hostname (string) and a UDP port number (integer, host byte order) 
MP2Socket.accept()             mp2_socket_accept()     Wait for a connection on the specified UDP port. This essentially combines TCP's bind, listen, and accept calls. Unlike TCP, accept will be called on a socket only once, since you don't need to handle multiple connections to the same socket. 
MP2Socket.send()               mp2_socket_send()       Send data to the remote endpoint. Data may be of arbitrary size and you may need to break it up into packets. This call may block due to flow control. send should always send all the data, partial sends are unacceptable. 
MP2Socket.recv()               mp2_socket_recv()       Receive some data from the socket. Wait until data is available and deliver however much is available to the reader. A single send() may be received through multiple recv()calls, and vice versa, but data must be delivered in the same order that it is sent (as in TCP). 
MP2Socket.close()              mp2_socket_close()      Close the socket and let the remote end know that the connection is closed. 

Working in Python, you should modify transport.py to implement the MP2Socket class. (You may use other .py files and import them in transport.py.) Working in C/C++, you should not modify transport.h and instead implement the needed functions in one or more .c or .ccfiles.

Network Environment

The test network environment will have a bandwidth of at most 10 Mbps and round-trip delay of at most 50 ms. If you want to replicate it, we suggest setting up a Linux virtual machine in VirtualBox or VMWare and using the tc (traffic control) command together with the network emulation module:

Delete any old tc rules 
% sudo tc qdisc del dev eth0 root 
(eth0 here is your network interface; you can find its name by running ifconfig) Add a 40 ms delay and 5% packet loss: 
% sudo tc qdisc add dev eth0 root handle 1:0 netem delay 40ms loss 5% 
(You can omit loss 5% if you don't want any loss) Set a bandwidth limit of 10 Mbps: 
% sudo tc qdisc add dev eth0 parent 1:1 handle 10:0 tbf rate 10Mbit burst 1mb latency 1ms 

If you are running on two VMs, you want to do this on the VM that is sending data, as tc only affects outgoing traffic on the interface. If you are running the server and client on the same machine, you should be able to use dev lo instead to apply the limits to the loopback device, but note that you'll want to cut the delay in half because it will be applied in both directions.

Note that if you want to have two VirtualBox VMs that talk to each other, you should create a "NAT Network" in VirtualBox network preference and configure both of them to use that network; otherwise they will not be able to forward traffic to each other.