//----------------------------------------------------------------- // CSE 461 Project 1: Provided client code // // iface.java A queuing network interface for you to use //----------------------------------------------------------------- import java.io.*; import java.util.*; //----------------------------------------------------------------- // NetworkInterface: interface between a sender and the actual // network. This class uses an infinite buffer // to smooth out the network transmission delays. // A client of this class can send packets in // zero simulated time (which is important for // code running in response to callbacks). //----------------------------------------------------------------- class NetworkInterface implements Runnable, PacketReceiver { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Constructor: sets up the connection to the link. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public NetworkInterface (Timer timer, Link l, PacketReceiver n, Address addr) { queue = new Vector (); link = l; link.AddReceiver (this, addr); node = n; address = addr; this.timer = timer; thread = new Thread (this); timer.RegisterThread (thread); thread.start (); queueTime = 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // SuhtDown: should disconnect and allow garbage-collection. // Not really necessary. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public void ShutDown () { thread.stop (); timer.UnregisterThread (thread); link.RemoveReceiver (this); link = null; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // This is our callback, just pass the message on // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public void PacketArrived (Packet p) { node.PacketArrived (p); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Same for MTU, pass requests on to the link. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public int MTU () { return link.MTU (); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // This is the main interface. Clients can call this to // queue packets for transmission as soon as the link is // available. // // The return value is the expected time that it will take // from now to send the packet (accounting for the current // queue length and network performance). This is useful // for setting your timeouts relative to the time a packet // is actually transmitted rather than when it is queued. // This value is in microseconds from now. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public synchronized int SendPacket (Packet p) { queue.addElement (p); queueTime += TimeToSend (p); if (!p.ack) Debug.println ('s', " Inside NI: queue length now " + queue.size () + " predicting " + queueTime + " us to clear"); // Okay, this is slightly weird: the run thread becomes active // now, as soon as it has work to do before time may advance. // It became active before it started waiting Debug.println ('i', "NI for " + address + " queued packet, notifying"); timer.RegisterThread (thread); notify (); return queueTime; } private int TimeToSend (Packet p) { double bandwidth = (double) project1.LINK_BW; return (int) ((p.data.length*8) / bandwidth); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // The following two functions implement the background loop // that dequeues packets and transmits them. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Need this to localize the locking: run cannot by synchronized // since it might block in the timer and lock out the client, thereby // preventing timer advance private synchronized Packet GetNextPacketToSend () { while (queue.size () == 0) { // Need to unregister to prevent deadlock Debug.println ('i', "NI for " + address + " waiting for queue"); timer.UnregisterThread (thread); try { wait (); } catch (InterruptedException e) { } } Debug.println ('i', "NI for " + address + " got packet"); Packet p = (Packet) queue.elementAt (0); queue.removeElementAt (0); queueTime -= TimeToSend (p); return p; } public void run () { Thread.currentThread ().setName ("NetworkInterface for " + address); // Wait for packets and send them. for (;;) { link.TransmitPacket (GetNextPacketToSend ()); } } private Vector queue; private Link link; private PacketReceiver node; private Address address; private Timer timer; private Thread thread; private int queueTime; }