Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: mindbright/net/WebProxyTunnelSocket.java


1   /******************************************************************************
2    *
3    * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden.
4    *                 www.mindbright.se, info@mindbright.se
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation; either version 2 of the License, or
9    * (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   *****************************************************************************
17   * $Author: nallen $
18   * $Date: 2001/11/12 16:31:14 $
19   * $Name:  $
20   *****************************************************************************/
21  package mindbright.net;
22  
23  import java.io.InputStream;
24  import java.io.OutputStream;
25  import java.io.IOException;
26  import java.net.Socket;
27  import java.net.UnknownHostException;
28  import java.net.SocketException;
29  
30  import mindbright.util.Base64;
31  
32  /**
33   * Socket that implements web proxy tunnelling (using CONNECT)
34   *
35   * (described in an Internet Draft (expired Feb. 1999) titled
36   * 'Tunneling TCP based protocols through Web proxy servers'
37   * by: Ari Luotonen)
38   *
39   * proxy-authentication is described in RFC2616 and RFC2617
40   *
41   * @author  Mats Andersson (originally by John Pallister)
42   */
43  public class WebProxyTunnelSocket extends Socket {
44  
45      private String proxyHost;
46      private int    proxyPort;
47      private String targetHost;
48      private int    targetPort;
49  
50      HttpHeader responseHeader;
51      String     serverDesc;
52  
53      public HttpHeader getResponseHeader() {
54    return responseHeader;
55      }
56  
57      public String getServerDesc() {
58    return serverDesc;
59      }
60  
61      private WebProxyTunnelSocket(String host, int port, String proxyHost, int proxyPort)
62    throws IOException, UnknownHostException
63      {
64    super(proxyHost, proxyPort);
65  
66    this.proxyHost  = proxyHost;
67    this.proxyPort  = proxyPort;
68    this.targetHost = targetHost;
69    this.targetPort = targetPort;
70      }
71  
72      public static WebProxyTunnelSocket getProxy(String host, int port, String proxyHost, int proxyPort, String protoStr,
73              ProxyAuthenticator authenticator, String userAgent)
74    throws IOException, UnknownHostException
75      {
76    WebProxyTunnelSocket proxySocket = new WebProxyTunnelSocket(host, port, proxyHost, proxyPort);
77    int status = -1;
78    String serverDesc;
79  
80    try {
81        InputStream  proxyIn  = proxySocket.getInputStream();
82        OutputStream proxyOut = proxySocket.getOutputStream();
83        HttpHeader   requestHeader = new HttpHeader();
84  
85        if(protoStr == null)
86      protoStr = "";
87  
88        requestHeader.setStartLine("CONNECT " + protoStr + host + ":" + port + " HTTP/1.0");
89        requestHeader.setHeaderField("User-Agent", userAgent);
90        requestHeader.setHeaderField("Pragma", "No-Cache");
91        requestHeader.setHeaderField("Proxy-Connection", "Keep-Alive");
92  
93        requestHeader.writeTo(proxyOut);
94        proxySocket.responseHeader = new HttpHeader(proxyIn);
95  
96        serverDesc = proxySocket.responseHeader.getHeaderField("server");
97  
98        // If proxy requires authentication
99        //
100       if(proxySocket.responseHeader.getStatus() == 407 && authenticator != null) {
101     String method = proxySocket.responseHeader.getProxyAuthMethod();
102     String realm  = proxySocket.responseHeader.getProxyAuthRealm();
103 
104     if(realm == null)
105         realm = "";
106 
107     if("basic".equalsIgnoreCase(method)) {
108         // OK
109     } else if("digest".equalsIgnoreCase(method)) {
110         throw new IOException("We don't support 'Digest' HTTP Authentication");
111     } else {
112         throw new IOException("Unknown HTTP Authentication method '" + method + "'");
113     }
114 
115     proxySocket.close();
116     proxySocket = new WebProxyTunnelSocket(host, port, proxyHost, proxyPort);
117     proxyIn  = proxySocket.getInputStream();
118     proxyOut = proxySocket.getOutputStream();
119 
120     String username = authenticator.getProxyUsername("HTTP Proxy", realm);
121     String password = authenticator.getProxyPassword("HTTP Proxy", realm);
122 
123     requestHeader.setBasicProxyAuth(username, password);
124     requestHeader.writeTo(proxyOut);
125     proxySocket.responseHeader = new HttpHeader(proxyIn);
126       }
127 
128       status = proxySocket.responseHeader.getStatus();
129 
130   } catch (SocketException e) {
131       throw new SocketException("Error communicating with proxy server " +
132               proxyHost + ":" + proxyPort + " (" + e.getMessage()  + ")");
133   }
134 
135   if((status < 200) || (status > 299))
136       throw new WebProxyException("Proxy tunnel setup failed: " +
137           proxySocket.responseHeader.getStartLine());
138 
139   proxySocket.serverDesc = serverDesc;
140 
141   return proxySocket;
142     }
143 
144     public String toString() {
145   return "WebProxyTunnelSocket[addr=" + getInetAddress() +
146       ",port=" + getPort() +
147       ",localport=" + getLocalPort() + "]";
148     }
149 }