package wifi; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; /** * This class acts as a thin layer between the GUI client code and the Java-based * 802.11~ layer. (There's a similar layer that mediates between the Java GUI code * and a C++ implementation of the 802.11~ project.) See {@link GUIClientInterface} * for full descriptions of these routines. * * @author richards */ public class JavaGUIAdapter implements GUIClientInterface { private static Dot11Interface theDot11Layer; private static CircularByteBuffer cbb; private static BufferedReader reader; /** * An array of addresses to use for the "send" buttons in the GUI. * @return An array of MAC addresses assigned to buttons by the GUI. */ public short[] getDefaultAddrs() { short[] temp = {101, 201, 301, 401, 501, 601, 701, 801, 901}; return temp; } /** * Create an instance of the 802.11~ layer. It wraps a PrintWriter around a * BufferedReader that's wrapped around a CircularByteBuffer (whew!) so that * we can read the text that the 802.11~ layer writes to the stream and * display it in the GUI's window. * * @param MACaddr The MAC address passed to the 802.11~ constructor. * @return Returns 0 on success, -1 if an error occurs. */ public int initializeLinkLayer(short MACaddr) { try { cbb = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE); reader = new BufferedReader(new InputStreamReader(cbb.getInputStream())); theDot11Layer = new LinkLayer(MACaddr, new PrintWriter(cbb.getOutputStream(), true)); } catch (Exception e) { // TODO Auto-generated catch block return -1; } return 0; } /** * This method calls the 802.11~ layer's recv() method, which should block until * data arrives. It then builds an array of bytes consisting of the the sender's * MAC address followed by the data from the recv() call. (This may seem odd, but * the approach is easy to support on both the C++ and Java side.) * @return An array of bytes containing MAC addresses and data */ public byte[] watchForIncomingData() { // Create a Transmission object, and pass it to the recv() call byte[] buf = new byte[2048]; Transmission t = new Transmission((short)0, (short)0, buf); int result = theDot11Layer.recv(t); // See if there was any data in the transmission int dataLen = 0; if (result > 0) { dataLen = result; } // Build a byte array, fill it with the source address and data, // and return the whole shebang. byte[] data = new byte[dataLen + 2]; data[0] = (byte) ((t.getSourceAddr() >>> 8) & 0xFF); data[1] = (byte) (t.getSourceAddr() & 0xFF); System.arraycopy(t.getBuf(), 0, data, 2, dataLen); return data; } /** * Wrapper around the 802.11~ layer's send routine. * @param dest The destination MAC address * @param payload The data to send * @return Returns the value returned by the linklayer's send() method. */ public int sendOutgoingData(short dest, byte[] payload) { return theDot11Layer.send(dest, payload, payload.length); } /** * This routine pulls text from the stream to which the 802.11~ layer is writing * and returns any new text as an array of bytes. * @return An array of bytes representing characters sent to output stream since last call. */ public byte[] pollForStreamOutput() { String msg = ""; try { while (reader.ready()) { msg += reader.readLine() + "\n"; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return msg.getBytes(); } /** * The GUI calls this when the user asks to pass command info to the 802.11~ layer. * @param command Specifies the command to send * @param value The value passed with the command * @return Returns the value returned by the linklayer's command() method. */ public int sendCommand(int command, int value) { return theDot11Layer.command(command, value); } }