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