+// Copyright 2000-2005 the Contributors, as shown in the revision logs.
+// Licensed under the Apache Public Source License 2.0 ("the License").
+// You may not use this file except in compliance with the License.
+
+package org.ibex.net;
+
+import java.net.*;
+import java.io.*;
+import org.ibex.io.*;
+import org.ibex.util.*;
+import javax.net.ssl.*;
+
+/** a stream backed by a socket */
+public class Connection extends Stream {
+ protected final Socket s;
+ public final String vhost;
+ public Connection(Socket s, String vhost) { super(s); this.vhost = vhost; this.s = s; }
+ protected Connection(InputStream i, OutputStream o) { super(i, o); vhost = null; s = null; }
+ public Socket getSocket() { return s; }
+
+ public int getLocalPort() { return s.getLocalPort(); }
+ public InetAddress getLocalAddress() { return ((InetSocketAddress)s.getLocalSocketAddress()).getAddress(); }
+ public int getRemotePort() { return s.getPort(); }
+ public InetAddress getRemoteAddress() { return ((InetSocketAddress)s.getRemoteSocketAddress()).getAddress(); }
+ public String getRemoteHostname() { return getRemoteAddress().getHostName(); }
+ public String getVirtualHost() { return vhost; }
+ public void setTimeout(int ms) { try { s.setSoTimeout(ms); } catch(IOException e) { ioe(e); } }
+ public void setTcpNoDelay(boolean delay) { try { s.setTcpNoDelay(delay); } catch(IOException e) { ioe(e); } }
+
+ /** never throws an exception */
+ public void close() { try{if (s!=null) s.close();}catch(Exception e){/*ignore*/} super.close(); }
+
+ public Connection negotiateSSL(boolean server) {
+ try {
+ SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
+ SSLSocket ssl = (SSLSocket) sslsocketfactory.createSocket(s, vhost, s.getLocalPort(), true);
+ ssl.setUseClientMode(!server);
+ return new Connection(ssl, vhost);
+ } catch (IOException e) { ioe(e); }
+ return null;
+ }
+
+ static int ioe(IOException e) {
+ if (e instanceof SocketException && e.toString().indexOf("Connection reset")!=-1)
+ throw new Closed(e.getMessage());
+ throw new StreamException(e);
+ }
+
+ // FEATURE: SOCKSv5
+ // FEATURE: SSL
+ // FEATURE: password authentication (inside SSL)
+ /**
+ * Implements SOCKSv4 with v4a DNS extension
+ * @see http://www.socks.nec.com/protocol/socks4.protocol
+ * @see http://www.socks.nec.com/protocol/socks4a.protocol
+ */
+ public static class SOCKS extends Connection {
+ public SOCKS(String proxyHost, int proxyPort, String host, int port, boolean ssl) throws IOException {
+ super(new SSL(proxyHost, proxyPort, ssl), host);
+ //((SSL)s).negotiateSSL();
+ try {
+ DataOutputStream dos = new DataOutputStream(s.getOutputStream());
+ dos.writeByte(0x04); // SOCKSv4(a)
+ dos.writeByte(0x01); // CONNECT
+ dos.writeShort(port & 0xffff); // port
+ //if (addr == null) {
+ dos.writeInt(0x00000001); // bogus IP
+ //} else dos.write(addr.getAddress()); // actual IP
+ dos.writeByte(0x00); // no userid
+ //if (addr == null) {
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter(dos));
+ pw.print(host);
+ pw.flush();
+ dos.writeByte(0x00); // hostname null terminator
+ //}
+ dos.flush();
+
+ DataInputStream dis = new DataInputStream(s.getInputStream());
+ dis.readByte(); // reply version
+ byte success = dis.readByte(); // success/fail
+ dis.skip(6); // ip/port
+
+ if ((int)(success & 0xff) != 90)
+ throw new StreamException("SOCKS error code "+(success & 0xff));
+
+ } catch (IOException e) { ioe(e); }
+ }
+ }
+
+}
+