/**
   * Accepts a connection from a specific host.
   *
   * @param s the accepted connection.
   * @param saddr the socket address of the host we do accept connection from
   * @exception IOException if an I/O error occurs when accepting the connection.
   */
  protected void acceptFrom(SocketImpl s, InetSocketAddress saddr) throws IOException {
    if (cmdsock == null) {
      // Not a Socks ServerSocket.
      return;
    }
    InputStream in = cmdIn;
    // Sends the "SOCKS BIND" request.
    socksBind(saddr);
    in.read();
    int i = in.read();
    in.read();
    SocketException ex = null;
    int nport;
    byte[] addr;
    InetSocketAddress real_end = null;
    switch (i) {
      case REQUEST_OK:
        // success!
        i = in.read();
        switch (i) {
          case IPV4:
            addr = new byte[4];
            readSocksReply(in, addr);
            nport = in.read() << 8;
            nport += in.read();
            real_end = new InetSocketAddress(new Inet4Address("", addr), nport);
            break;
          case DOMAIN_NAME:
            int len = in.read();
            addr = new byte[len];
            readSocksReply(in, addr);
            nport = in.read() << 8;
            nport += in.read();
            real_end = new InetSocketAddress(new String(addr), nport);
            break;
          case IPV6:
            addr = new byte[16];
            readSocksReply(in, addr);
            nport = in.read() << 8;
            nport += in.read();
            real_end = new InetSocketAddress(new Inet6Address("", addr), nport);
            break;
        }
        break;
      case GENERAL_FAILURE:
        ex = new SocketException("SOCKS server general failure");
        break;
      case NOT_ALLOWED:
        ex = new SocketException("SOCKS: Accept not allowed by ruleset");
        break;
      case NET_UNREACHABLE:
        ex = new SocketException("SOCKS: Network unreachable");
        break;
      case HOST_UNREACHABLE:
        ex = new SocketException("SOCKS: Host unreachable");
        break;
      case CONN_REFUSED:
        ex = new SocketException("SOCKS: Connection refused");
        break;
      case TTL_EXPIRED:
        ex = new SocketException("SOCKS: TTL expired");
        break;
      case CMD_NOT_SUPPORTED:
        ex = new SocketException("SOCKS: Command not supported");
        break;
      case ADDR_TYPE_NOT_SUP:
        ex = new SocketException("SOCKS: address type not supported");
        break;
    }
    if (ex != null) {
      cmdIn.close();
      cmdOut.close();
      cmdsock.close();
      cmdsock = null;
      throw ex;
    }

    /**
     * This is where we have to do some fancy stuff. The datastream from the socket "accepted" by
     * the proxy will come through the cmdSocket. So we have to swap the socketImpls
     */
    if (s instanceof SocksSocketImpl) {
      ((SocksSocketImpl) s).external_address = real_end;
    }
    if (s instanceof PlainSocketImpl) {
      ((PlainSocketImpl) s).setInputStream((SocketInputStream) in);
    }
    s.fd = cmdsock.getImpl().fd;
    s.address = cmdsock.getImpl().address;
    s.port = cmdsock.getImpl().port;
    s.localport = cmdsock.getImpl().localport;
    // Need to do that so that the socket won't be closed
    // when the ServerSocket is closed by the user.
    // It kinds of detaches the Socket because it is now
    // used elsewhere.
    cmdsock = null;
  }