NXJSocketProxy

This is where you talk about the NXJ software itself, installation issues, and programming talk.

Moderators: roger, 99jonathan, imaqine

NXJSocketProxy

Postby ChefFD » Thu Jan 17, 2013 4:31 pm

He guys,

i'm looking now the whole day on the source code of NXJSocketProxy.class:

Can somebody tall me with a few words, what exactly happens when execute it?

Thanks for your help!

Greetz
ChefFD


Code of the class:
Code: Select all
package lejos.pc.tools;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import lejos.pc.comm.NXTCommFactory;
import lejos.pc.comm.NXTConnector;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.ParseException;

/**
* 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 NXJSocketProxy
{
   /* TODO fix design problem
    * There are several problem with this proxy. First of all, a socket
    * consists of two streams, which can be closed separately. However,
    * currently the proxy does not support to close the streams independently.
    * Also, if the peer closes the InputStream, it is not possible to signal
    * EOF to the NXT. Escape sequences are only allowed in one direction, which
    * is one of the main causes of this problem. Also, there does not seem to be
    * any way of reporting errors back to NXT in case connecting or writing fails.
    */
   

   /**
    * Run the Socket Proxy.
    * An instance of SocketProxy will allow for transparent forwarding
    * of messages between server and NXT using a socket connection
    * @throws IOException
    * @throws InterruptedException
    */
   private int run(String[] args) throws IOException, InterruptedException {
      SocketProxyCommandLineParser fParser = new SocketProxyCommandLineParser(NXJSocketProxy.class, "[options]");
      CommandLine commandLine;
      
      try
      {
         commandLine = fParser.parse(args);
      }
      catch (ParseException e)
      {
         fParser.printHelp(System.err, e);
         return 1;
      }
      
      if (commandLine.hasOption("h"))
      {
         fParser.printHelp(System.out);
         return 0;
      }
      
      int protocols = 0;
      boolean blueTooth = commandLine.hasOption("b");
      boolean usb = commandLine.hasOption("u");
      String name = AbstractCommandLineParser.getLastOptVal(commandLine, "n");
      String address = AbstractCommandLineParser.getLastOptVal(commandLine, "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");
         return 1;
      }

      DataInputStream inFromNXT = new DataInputStream(conn.getInputStream());
      DataOutputStream outToNXT = new DataOutputStream(conn.getOutputStream());
      
      // Check to see if socket is a server or a client
      boolean isServer = inFromNXT.readBoolean();
      if (isServer) {
         newSocketServer(inFromNXT, outToNXT);
      } else {
         newSocketConnection(inFromNXT, outToNXT);
      }
      return 0;
   }

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

            handleNewConnection(sock, inFromNXT, outToNXT);
         }
      }
   }

   /**
    * Allows negotiation of the accept() method of Socket server
    * Executes a single accept and waits until the Socket is closed
    * @param outToNXT
    * @param inFromNXT
    * @param serverSocket
    *
    * @throws IOException
    * @throws InterruptedException
    */
   private void handleNewConnection(Socket sock, DataInputStream inFromNXT, DataOutputStream outToNXT) throws IOException, InterruptedException {
      //   inform the NXT of the new Connection
      outToNXT.writeBoolean(true);
      outToNXT.flush();

      pipeData(sock, inFromNXT, outToNXT);      
      sock.close();
   }

   private void pipeData(Socket sock, DataInputStream inFromNXT, DataOutputStream outToNXT)
      throws IOException, InterruptedException
   {
      InputStream inFromSocket = sock.getInputStream();
      OutputStream outToSocket = sock.getOutputStream();

      // Listen for incoming data from socket
      Thread t1 = new ForwardSocketToNXT(sock, inFromSocket, outToNXT);
      // Listen for incoming data from NXT
      Thread t2 = new ForwardNXTToSocket(sock, inFromNXT, outToSocket);
      
      t1.start();
      t2.start();
      t1.join();
      t2.join();
   }

   /**
    * Allows for a connection to be made using the details supplied from the NXT
    * @throws UnknownHostException
    * @throws IOException
    * @throws InterruptedException
    */
   private void newSocketConnection(DataInputStream inFromNXT, DataOutputStream outToNXT) throws UnknownHostException, IOException, InterruptedException
   {
      // 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
      int port = inFromNXT.readInt();
      String host = new String(hostChars);

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

      pipeData(sock, inFromNXT, outToNXT);
      sock.close();
   }

   /**
    * Allows for the forwarding of messages from Socket to NXT
    * @author Ranulf Green
    */
   private static class ForwardSocketToNXT extends Thread{
      private OutputStream dout;
      private InputStream 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 ForwardSocketToNXT(Socket sock, InputStream dis, OutputStream dos){
         super();
         this.din=dis;
         this.dout=dos;
         this.sock = sock;
      }
      /**
       * Causes a new thread to be invoked
       */
      public void run(){
         try{
            byte[] buffer = new byte[4096];
            while(true){
               int len = din.read(buffer);
               if(len < 0){
                  // TODO don't close socket and signal EOF to NXT somehow
                  // dout.close(); is not possible since stream might be reused.
                  this.sock.close();
                  break;
               }
               dout.write(buffer, 0, len);
               dout.flush();
            }
         } catch (IOException ioe) {
            //TODO print error message
         }
      }
   }

   /**
    * Class to forward messages from NXT to socket
    * @author Ranulf Green
    *
    */
   private static class ForwardNXTToSocket extends Thread {
      private static final int ESCAPE = 0xFF;
      private static final int ESCAPE_CLOSE = 1;
      
      private OutputStream dout;
      private InputStream din;
      private Socket sock;

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

      /**
       * Causes a new thread to be invoked
       */
      public void run() {
         try {
            //TODO make this more efficient by reading and writing large chunks of data
            while(true) {
               int in = din.read();
               if (in < 0) {
                  this.sock.close();
                  break;
               }
               // Process ESCAPE sequence
               if (in == ESCAPE) {
                  in = din.read();
                  if (in == ESCAPE_CLOSE) {
                     //TODO don't close socket, and signal EOF to peer and exit thread
                     // this.sock.shutdownOutput();
                     sock.close();
                     return;                     
                  }
                  
                  //TODO what to do when EOF after ESCAPE (in < 0)?
                  in = ESCAPE;
               }
               dout.write(in);
               dout.flush();
            }
         } catch (IOException ioe) {
            ioe.printStackTrace();
         }
      }
   }

   public static void main(String[] args)
   {
      ToolStarter.startTool(NXJSocketProxy.class, args);
   }

   public static int start(String[] args) throws Exception
   {
      return new NXJSocketProxy().run(args);
   }
}
ChefFD
New User
 
Posts: 5
Joined: Mon Dec 17, 2012 11:32 am

Return to NXJ Software

Who is online

Users browsing this forum: Google [Bot] and 1 guest

more stuff