// Private methods
  /////////////////
  private void startSession() throws IOException {
    sock.setSoTimeout(iddleTimeout);

    try {
      auth = auth.startSession(sock);
    } catch (IOException ioe) {
      log("Auth throwed exception:" + ioe);
      auth = null;
      return;
    }

    if (auth == null) { // Authentication failed
      log("Authentication failed");
      return;
    }

    in = auth.getInputStream();
    out = auth.getOutputStream();

    msg = readMsg(in);
    handleRequest(msg);
  }
 // Runnable interface
 ////////////////////
 public void run() {
   switch (mode) {
     case START_MODE:
       try {
         startSession();
       } catch (IOException ioe) {
         handleException(ioe);
         // ioe.printStackTrace();
       } finally {
         abort();
         if (auth != null) auth.endSession();
         log("Main thread(client->remote)stopped.");
       }
       break;
     case ACCEPT_MODE:
       try {
         doAccept();
         mode = PIPE_MODE;
         pipe_thread1.interrupt(); // Tell other thread that connection have
         // been accepted.
         pipe(remote_in, out);
       } catch (IOException ioe) {
         // log("Accept exception:"+ioe);
         handleException(ioe);
       } finally {
         abort();
         log("Accept thread(remote->client) stopped");
       }
       break;
     case PIPE_MODE:
       try {
         pipe(remote_in, out);
       } catch (IOException ioe) {
       } finally {
         abort();
         log("Support thread(remote->client) stopped");
       }
       break;
     case ABORT_MODE:
       break;
     default:
       log("Unexpected MODE " + mode);
   }
 }
  private void handleRequest(ProxyMessage msg) throws IOException {
    if (!auth.checkRequest(msg)) throw new SocksException(CProxy.SOCKS_FAILURE);

    if (msg.ip == null) {
      if (msg instanceof Socks5Message) {
        msg.ip = null; // InetAddress.getByName(msg.host);
      } else throw new SocksException(CProxy.SOCKS_FAILURE);
    }
    log(msg);

    switch (msg.command) {
      case CProxy.SOCKS_CMD_CONNECT:
        onConnect(msg);
        break;
      case CProxy.SOCKS_CMD_BIND:
        onBind(msg);
        break;
      case CProxy.SOCKS_CMD_UDP_ASSOCIATE:
        onUDP(msg);
        break;
      default:
        throw new SocksException(CProxy.SOCKS_CMD_NOT_SUPPORTED);
    }
  }