//----------------------------------------------------------------- // CSE 461 Project 1: Provided client code // // sender.java: implementation of the sender algorithm //----------------------------------------------------------------- import java.io.*; import java.util.*; //----------------------------------------------------------------- // Declaration of an exception that Project1Sender throws //----------------------------------------------------------------- class NoDestinationSet extends Exception { } //----------------------------------------------------------------- // Project1Sender: the implementation of the send algorithm // // Provided implementation shows stop-and-wait protocol, // plus all the general setup and use of the SendBuffer // // This implementation uses both the SendBuffer and // NetworkInterface classes. You are not required to use // these, but they simplify interaction with the timer and // the underlying network. If you want to modify or replace // them, be sure to understand them first. //----------------------------------------------------------------- class Project1Sender implements PacketReceiver, TimerClient { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Standard constructor for a node. Takes the global timer, // the link to transmit on, and the address of this node. // Sets up the send buffer, you will probably have to adjust // the size. // // This constructor also sets up a new NetworkInterface // object to buffer between the send algorithm and the actual // transmission delays on the network // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public Project1Sender (Timer timer, Link link, Address address) { this.timer = timer; this.address = address; destinationAddress = null; buffer = new SendBuffer (timer, 50 * link.MTU ()); network = new NetworkInterface (timer, link, this, address); // The following is for stop-and-wait, feel free to remove currentPacket = null; currentSequenceNum = 0; currentTimeout = null; } private Timer timer; private NetworkInterface network; private Address address; private SendBuffer buffer; private Address destinationAddress; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // SetDestination: set the destination address. External // interface to be called before Send // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public void SetDestination (Address dest) { destinationAddress = dest; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send: external interface to append data to the send stream. // This operation may block because of the call to // SendBuffer.AppendBytes. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public void Send (byte[] data) throws NoDestinationSet { if (destinationAddress == null) throw new NoDestinationSet (); int previous = buffer.AppendBytes (data); if (previous == 0) // Not currently sending SendNextPacket (); // so start again } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // PacketArrived: processing that happens when we receive a // packet // // For stop-and-wait: send the next packet // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public synchronized void PacketArrived (Packet p) { if (p.sequenceNum == currentSequenceNum) SendNextPacket (); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Timeout: processing that happens when we get a timeout // // For stop-and-wait: resend the current packet // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public synchronized void Timeout (Object info) { SendCurrentPacket (); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Stop-and-wait implementation. Feel free to use/adapt/toss // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - private Packet currentPacket; private int currentSequenceNum; private TimeoutID currentTimeout; private void SendNextPacket () { byte[] data = buffer.RemoveBytes (network.MTU ()); if (data.length > 0) { currentPacket = new Packet (); currentPacket.sourceAddr = address; currentPacket.destinationAddr = destinationAddress; ++currentSequenceNum; currentPacket.sequenceNum = currentSequenceNum; currentPacket.ack = false; currentPacket.data = data; if (currentTimeout != null) timer.CancelTimeout (currentTimeout); network.SendPacket (currentPacket); currentTimeout = timer.SetTimeout (this, 1000, Timer.US, null); } } private void SendCurrentPacket () { if (currentPacket != null) { network.SendPacket (currentPacket); } currentTimeout = timer.SetTimeout (this, 1000, Timer.US, null); } } //----------------------------------------------------------------- // SendBuffer: a specialized bounded-buffer for sending. This // buffer has the semantics that appends will wait for // space but removes will always return immediately. //----------------------------------------------------------------- class SendBuffer { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Constructor: set up the buffer with the given size. Needs // the global timer to ensure that waiting threads // are properly woken // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public SendBuffer (Timer timer, int size) { waitingThread = null; this.timer = timer; buffer = new byte[size]; numBytes = 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // AppendBytes: append data to the end of the buffer/queue. // If there is no room, then block until space // becomes available. // // returns the old number of bytes in the buffer (before the // insertion) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public synchronized int AppendBytes (byte[] data) { while (numBytes + data.length > buffer.length) { try { waitingThread = Thread.currentThread (); timer.UnregisterThread (waitingThread); wait (); } catch (InterruptedException e) { } } for (int i=0; i