Package lejos.pc.tools

Source Code of lejos.pc.tools.SocketProxy$Forward

package lejos.pc.tools;

import java.io.*;
import java.net.*;

import js.tinyvm.TinyVMException;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import lejos.pc.comm.*;

/**
* Socket Proxy for NXT
* Has two main functions. The first is to connect to an existing
* server socket on the specified port. The second function is to
* create a socket server. In this case the proxy assumes that the
* NXT will then send a command to inform the proxy of the next action
* to take
*
* Currently only supports TCP connections
*
* @author Ranulf Green and Lawrie Griffiths
*/
public class SocketProxy {
  private String host;
  private int port;
  private DataInputStream inFromNXT;
  private DataOutputStream outToNXT;
  private ServerSocket serverSocket;
  private Socket sock;

  /**
   * Run the Socket Proxy.
   * An instance of SocketProxy will allow for transparent forwarding
   * of messages between server and NXT using a socket connection
   */
  public void run(String[] args) throws TinyVMException {
    try {
      int protocols = 0;
      ProxyCommandLineParser fParser = new ProxyCommandLineParser();
      CommandLine commandLine = fParser.parse(args);
      boolean blueTooth = commandLine.hasOption("b");
      boolean usb = commandLine.hasOption("u");
      String name = commandLine.getOptionValue("n");
      String address = commandLine.getOptionValue("d");
      NXTConnector conn = new NXTConnector();
      conn.addLogListener(new ToolsLogger());
      if (blueTooth) protocols |= NXTCommFactory.BLUETOOTH;
      if (usb) protocols |= NXTCommFactory.USB;
      if (protocols == 0) protocols = NXTCommFactory.ALL_PROTOCOLS;
      boolean connected = conn.connectTo(name, address, protocols);
      if (!connected) {
        System.err.println("Failed to connect to NXT");
        System.exit(1);
      }

      inFromNXT = conn.getDataIn();
      outToNXT = conn.getDataOut();
     
      // Check to see if socket is a server or a client
      boolean isServer = inFromNXT.readBoolean();
      if (isServer) {
        newSocketServer();
      } else {
        newSocketConnection();
      }
    }
    catch (UnknownHostException e) {e.printStackTrace();}
    catch (IOException e) {e.printStackTrace();}
  }

  /**
   * Creates a new socket server if instructed by the NXT
   * @throws IOException
   */
  private void newSocketServer() throws IOException {
    int port = inFromNXT.readInt();
    System.out.println("Waiting on " + port);
    serverSocket = new ServerSocket(port);
    while (true) {
      // Wait for command from NXT
      byte command = inFromNXT.readByte();
      if(command == 1){
        waitForConnection();
      }
    }
  }

  /**
   * Allows negotiation of the accept() method of Socket server
   * Executes a single accept and waits until the Socket is closed
   *
   * @throws IOException
   */
  private void waitForConnection() throws IOException {
    sock = serverSocket.accept();
    //System.out.println("Accepted");

    //  inform the NXT of the new Connection
    outToNXT.writeBoolean(true);
    outToNXT.flush();

    DataInputStream inFromSocket = new DataInputStream(sock.getInputStream());
    DataOutputStream outToSocket = new DataOutputStream(sock.getOutputStream());

    // Listen for incoming data from socket
    new Forward(sock, inFromSocket, outToNXT);

    // Listen for incoming data from NXT
    new ForwardNXT(sock, inFromNXT, outToSocket);
   
    // Wait for socket to close 
    while (!sock.isClosed()) Thread.yield();
  }

  /**
   * Allows for a connection to be made using the details supplied from the NXT
   * @throws UnknownHostException
   * @throws IOException
   */
  private void newSocketConnection() throws UnknownHostException, IOException
  {
    // The first byte from the NXT contains the length of the host name in chars
    int len = inFromNXT.readByte();
    char[] hostChars = new char[len];

    // Following the first byte the host name is transmitted
    for(int i=0;i<len;i++){
      hostChars[i] = inFromNXT.readChar();
    }
   
    // Following the host name an int containing the port number of the socket to connect to
    // is transmitted
    port = inFromNXT.readInt();
    host = new String(hostChars);

    System.out.println("Host: " + host + " port: " + port);
   
    // Create a socket connection with the specified host using the specified port
    sock = new Socket(host, port);
    outToNXT.writeBoolean(true);
    outToNXT.flush();

    DataInputStream inFromSocket = new DataInputStream(sock.getInputStream());

    DataOutputStream outToSocket = new
    DataOutputStream(sock.getOutputStream());

    // Listen for incoming data from socket
    new Forward(sock, inFromSocket, outToNXT);

    // Listen for incoming data from NXT
    new ForwardNXT(sock, inFromNXT, outToSocket);
  }

  /**
   * Allows for the forwarding of messages from Socket to NXT
   * @author Ranulf Green
   */
  private class Forward extends Thread{
    private DataOutputStream dout;
    private DataInputStream din;
    private Socket sock;

    /**
     * Constructor.
     * @param sock the socket with which the connection is made
     * @param dis the input stream to read
     * @param dos the output stream to forward to
     */
    public Forward(Socket sock, DataInputStream dis, DataOutputStream dos){
      super();
      din=dis;
      dout=dos;
      this.sock = sock;
      start();
    }
    /**
     * Causes a new thread to be invoked
     */
    public void run(){
      try{
        while(true){
          int in = din.read();
          if(in<0){
            sock.close();
            return;
          }
          dout.writeByte(in);
          dout.flush();
        }
      } catch (IOException ioe) {}
    }
  }

  /**
   * Class to forward messages from NXT to socket
   * @author Ranulf Green
   *
   */
  private class ForwardNXT extends Thread {
    private static final byte ESCAPE = (byte) 0xFF;
    private static final byte ESCAPE_CLOSE = 1;
   
    private DataOutputStream dout;
    private DataInputStream din;

    private Socket sock;

    /**
     * Constructor.
     * @param sock
     * @param dis input stream from NXT
     * @param dos output stream to socket
     */
    public ForwardNXT(Socket sock, DataInputStream dis, DataOutputStream dos){
      super();
      din=dis;
      dout=dos;
      this.sock = sock;
      start();
    }

    /**
     * Causes a new thread to be invoked
     */
    public void run() {
      try {
        while(true) {
          int in = din.read();
          if (in < 0) {
            sock.close();
            return;
          }
          // Process ESCAPE sequence
          if ((byte) in == ESCAPE) {
            in = din.read();
            if ((byte) in == ESCAPE_CLOSE) {
              sock.close();
              return;             
            } else in = ESCAPE;
          }
          dout.writeByte(in);
          dout.flush();
        }
      } catch (IOException ioe) {ioe.printStackTrace();}
    }
  }

  public static void main(String[] args) {
    try {
      (new SocketProxy()).run(args);
    } catch (Throwable t) {
      System.err.println("An error has occurred: " + t.getMessage());
    }
  }
 
  /**
   * CommandLineParser
   */
  class ProxyCommandLineParser
  {
     /**
      * Parse commandline.
      *
      * @param args command line
      * @throws TinyVMException
      */
     public CommandLine parse (String[] args) throws TinyVMException
     {
        assert args != null: "Precondition: args != null";

        Options options = new Options();
        options.addOption("h", "help", false, "help");
        options.addOption("b", "bluetooth", false, "use bluetooth");
        options.addOption("u", "usb", false, "use usb");
       
        Option nameOption = new Option("n", "name", true,"look for named NXT");
        nameOption.setArgName("name");
        options.addOption(nameOption);
       
        Option addressOption = new Option("d", "address", true,
           "look for NXT with given address");
        addressOption.setArgName("address");
        options.addOption(addressOption);
       
        CommandLine result;
        try
        {
           try
           {
              result = new GnuParser().parse(options, args);
           }
           catch (ParseException e)
           {
              throw new TinyVMException(e.getMessage(), e);
           }

           if (result.hasOption("h"))
           {
              throw new TinyVMException("Help:");
           }
        }
        catch (TinyVMException e)
        {
           StringWriter writer = new StringWriter();
           PrintWriter printWriter = new PrintWriter(writer);
           printWriter.println(e.getMessage());
          
           String commandName = System.getProperty("COMMAND_NAME", "lejos.pc.tools.SocketProxy");

           String usage = commandName + " [options]";
           new HelpFormatter().printHelp(printWriter, 80, usage.toString(), null,
              options, 0, 2, null);

           throw new TinyVMException(writer.toString());
        }

        assert result != null: "Postconditon: result != null";
        return result;
     }
  }
}



TOP

Related Classes of lejos.pc.tools.SocketProxy$Forward

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.