add Connection to org.ibex.net
[org.ibex.net.git] / src / org / ibex / net / Connection.java
1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
4
5 package org.ibex.net;
6
7 import java.net.*;
8 import java.io.*;
9 import org.ibex.io.*;
10 import org.ibex.util.*;
11 import javax.net.ssl.*;
12
13 /** a stream backed by a socket */
14 public class Connection extends Stream {
15     protected final Socket s;
16     public final String vhost;
17     public Connection(Socket s, String vhost) { super(s); this.vhost = vhost; this.s = s; }
18     protected Connection(InputStream i, OutputStream o) { super(i, o); vhost = null; s = null; }
19     public Socket getSocket() { return s; }
20
21     public int getLocalPort()                 { return s.getLocalPort(); }
22     public InetAddress getLocalAddress()      { return ((InetSocketAddress)s.getLocalSocketAddress()).getAddress(); }
23     public int getRemotePort()                { return s.getPort(); }
24     public InetAddress getRemoteAddress()     { return ((InetSocketAddress)s.getRemoteSocketAddress()).getAddress(); }
25     public String getRemoteHostname()         { return getRemoteAddress().getHostName(); }
26     public String getVirtualHost()            { return vhost; }
27     public void setTimeout(int ms)            { try { s.setSoTimeout(ms);     } catch(IOException e) { ioe(e); } }
28     public void setTcpNoDelay(boolean delay)  { try { s.setTcpNoDelay(delay); } catch(IOException e) { ioe(e); } }
29
30     /** never throws an exception */
31     public void close()                       { try{if (s!=null) s.close();}catch(Exception e){/*ignore*/} super.close(); }
32
33     public Connection negotiateSSL(boolean server) {
34         try {
35             SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
36             SSLSocket ssl = (SSLSocket) sslsocketfactory.createSocket(s, vhost, s.getLocalPort(), true);
37             ssl.setUseClientMode(!server);
38             return new Connection(ssl, vhost);
39         } catch (IOException e) { ioe(e); }
40         return null;
41     }
42
43     static int ioe(IOException e) {
44         if (e instanceof SocketException && e.toString().indexOf("Connection reset")!=-1)
45             throw new Closed(e.getMessage());
46         throw new StreamException(e);
47     }
48
49     // FEATURE: SOCKSv5
50     // FEATURE: SSL
51     // FEATURE: password authentication (inside SSL)
52     /**
53      *  Implements SOCKSv4 with v4a DNS extension
54      *  @see http://www.socks.nec.com/protocol/socks4.protocol
55      *  @see http://www.socks.nec.com/protocol/socks4a.protocol
56      */
57     public static class SOCKS extends Connection {
58         public SOCKS(String proxyHost, int proxyPort, String host, int port, boolean ssl) throws IOException {
59             super(new SSL(proxyHost, proxyPort, ssl), host);
60             //((SSL)s).negotiateSSL();
61             try {
62                 DataOutputStream dos = new DataOutputStream(s.getOutputStream());
63                 dos.writeByte(0x04);                         // SOCKSv4(a)
64                 dos.writeByte(0x01);                         // CONNECT
65                 dos.writeShort(port & 0xffff);               // port
66                 //if (addr == null) {
67                 dos.writeInt(0x00000001);  // bogus IP
68                 //} else dos.write(addr.getAddress());       // actual IP
69                 dos.writeByte(0x00);                         // no userid
70                 //if (addr == null) {
71                     PrintWriter pw = new PrintWriter(new OutputStreamWriter(dos));
72                     pw.print(host);
73                     pw.flush();
74                     dos.writeByte(0x00);                     // hostname null terminator
75                     //}
76                 dos.flush();
77
78                 DataInputStream dis = new DataInputStream(s.getInputStream());
79                 dis.readByte();                              // reply version
80                 byte success = dis.readByte();               // success/fail
81                 dis.skip(6);                                 // ip/port
82             
83                 if ((int)(success & 0xff) != 90)
84                     throw new StreamException("SOCKS error code "+(success & 0xff));
85
86             } catch (IOException e) { ioe(e); }
87         }
88     }
89
90 }
91