View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.example.proxy;
21  
22  import java.net.InetSocketAddress;
23  import java.net.URL;
24  import java.util.ArrayList;
25  import java.util.HashMap;
26  import java.util.List;
27  
28  import org.apache.mina.core.RuntimeIoException;
29  import org.apache.mina.core.future.ConnectFuture;
30  import org.apache.mina.core.session.IdleStatus;
31  import org.apache.mina.core.session.IoSession;
32  import org.apache.mina.filter.logging.LoggingFilter;
33  import org.apache.mina.proxy.ProxyConnector;
34  import org.apache.mina.proxy.handlers.ProxyRequest;
35  import org.apache.mina.proxy.handlers.http.HttpAuthenticationMethods;
36  import org.apache.mina.proxy.handlers.http.HttpProxyConstants;
37  import org.apache.mina.proxy.handlers.http.HttpProxyRequest;
38  import org.apache.mina.proxy.handlers.socks.SocksProxyConstants;
39  import org.apache.mina.proxy.handlers.socks.SocksProxyRequest;
40  import org.apache.mina.proxy.session.ProxyIoSession;
41  import org.apache.mina.transport.socket.nio.NioSocketConnector;
42  
43  /**
44   * ProxyTestClient.java - Base test class for mina proxy
45   * 
46   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
47   * @since MINA 2.0.0-M3
48   */
49  public class ProxyTestClient {
50      
51      /**
52       * The global variables used when creating the HTTP proxy connection.
53       */
54      
55      /**
56       * The user login.
57       */
58      public final static String USER = "TED_KODS";
59  
60      /**
61       * The user password.
62       */
63      public final static String PWD = "EDOUARD";
64  
65      /**
66       * The domain name. (used in NTLM connections)
67       */
68      public final static String DOMAIN = "MYDOMAIN";
69  
70      /**
71       * The workstation name. (used in NTLM connections)
72       */    
73      public final static String WORKSTATION = "MYWORKSTATION";
74  
75      /**
76       * Set this variable to true in order to generate HTTP/1.1 requests.
77       */
78      private final static boolean USE_HTTP_1_1 = false;
79  
80      /**
81       * Creates a connection to the endpoint through a proxy server using the specified
82       * authentication method.
83       * 
84       * Command line arguments: 
85       *       ProxyTestClient <proxy-hostname> <proxy-port> <url> <proxy-method> 
86       *       
87       * Note that <proxy-method> is OPTIONNAL a HTTP proxy connection will be used if not 
88       * specified.
89       * 
90       * Examples:
91       *          ProxyTestClient myproxy 8080 http://mina.apache.org SOCKS4
92       *          ProxyTestClient squidsrv 3128 http://mina.apache.org:80
93       *       
94       * @param args parse arguments to get proxy hostaname, proxy port, the url to connect to 
95       * and optionnaly the proxy authentication method 
96       * @throws Exception
97       */
98      public ProxyTestClient(String[] args) throws Exception {
99          if (args.length < 3) {
100             System.out
101                     .println(ProxyTestClient.class.getName()
102                             + " <proxy-hostname> <proxy-port> <url> <proxy-method> (<proxy-method> is OPTIONNAL)");
103             return;
104         }
105 
106         // Create proxy connector.
107         NioSocketConnector socketConnector = new NioSocketConnector(Runtime
108                 .getRuntime().availableProcessors() + 1);
109 
110         ProxyConnector connector = new ProxyConnector(socketConnector);
111 
112         // Set connect timeout.
113         connector.setConnectTimeoutMillis(5000);
114 
115         URL url = new URL(args[2]);
116         int port = url.getPort() == -1 ? url.getDefaultPort() : url.getPort();
117 
118         ProxyRequest req = null;
119 
120         if (args.length == 4) {
121             if ("SOCKS4".equals(args[3])) {
122                 req = new SocksProxyRequest(
123                         SocksProxyConstants.SOCKS_VERSION_4,
124                         SocksProxyConstants.ESTABLISH_TCPIP_STREAM,
125                         new InetSocketAddress(url.getHost(), port), USER);
126             } else if ("SOCKS4a".equals(args[3])) {
127                 req = new SocksProxyRequest(
128                         SocksProxyConstants.ESTABLISH_TCPIP_STREAM, url
129                                 .getHost(), port, USER);
130             } else if ("SOCKS5".equals(args[3])) {
131                 req = new SocksProxyRequest(
132                         SocksProxyConstants.SOCKS_VERSION_5,
133                         SocksProxyConstants.ESTABLISH_TCPIP_STREAM,
134                         new InetSocketAddress(url.getHost(), port), USER);
135                 ((SocksProxyRequest) req).setPassword(PWD);
136                 ((SocksProxyRequest) req)
137                         .setServiceKerberosName(Socks5GSSAPITestServer.SERVICE_NAME);
138             } else {
139                 req = createHttpProxyRequest(args[2]);
140             }
141         } else {
142             req = createHttpProxyRequest(args[2]);
143         }
144 
145         ProxyIoSession proxyIoSession = new ProxyIoSession(
146                 new InetSocketAddress(args[0], Integer.parseInt(args[1])), req);
147 
148         // Tests modifying authentication order preferences. First algorithm in list available on server 
149         // will be used for authentication.
150         List<HttpAuthenticationMethods> l = new ArrayList<HttpAuthenticationMethods>();
151         l.add(HttpAuthenticationMethods.DIGEST);
152         l.add(HttpAuthenticationMethods.BASIC);
153         proxyIoSession.setPreferedOrder(l);
154 
155         connector.setProxyIoSession(proxyIoSession);
156 
157         socketConnector.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 5);
158 
159         connector.getFilterChain().addLast("logger", new LoggingFilter());
160 
161         // This command is sent when using a socks proxy to request a page from the web server.
162         String cmd = "GET " + url.toExternalForm() + " HTTP/1.0"
163                 + HttpProxyConstants.CRLF + HttpProxyConstants.CRLF;
164 
165         connector.setHandler(new ClientSessionHandler(cmd));
166 
167         IoSession session;
168         for (;;) {
169             try {
170                 ConnectFuture future = connector.connect();
171                 future.awaitUninterruptibly();
172                 session = future.getSession();
173                 break;
174             } catch (RuntimeIoException e) {
175                 System.err.println("Failed to connect. Retrying in 5 secs ...");
176                 Thread.sleep(5000);
177             }
178         }
179 
180         // Wait until done
181         if (session != null) {
182             session.getCloseFuture().awaitUninterruptibly();
183         }
184         connector.dispose();
185         System.exit(0);
186     }
187 
188     /**
189      * Creates a {@link HttpProxyRequest} from the provided <i>uri</i> parameter.
190      * It uses the global variables defined at the top of the class to fill the 
191      * connection properties of the request. If the global variable <i>useHttp1_1</i> 
192      * is set to true, it will create a HTTP/1.1 request.
193      * 
194      * @param uri the requested uri to connect to through the HTTP proxy
195      * @return the fully initialized {@link HttpProxyRequest} object
196      */
197     private HttpProxyRequest createHttpProxyRequest(String uri) {
198         HttpProxyRequest req = new HttpProxyRequest(uri);
199         HashMap<String, String> props = new HashMap<String, String>();
200         props.put(HttpProxyConstants.USER_PROPERTY, USER);
201         props.put(HttpProxyConstants.PWD_PROPERTY, PWD);
202         props.put(HttpProxyConstants.DOMAIN_PROPERTY, DOMAIN);
203         props.put(HttpProxyConstants.WORKSTATION_PROPERTY, WORKSTATION);
204 
205         req.setProperties(props);
206         if (USE_HTTP_1_1) {
207             req.setHttpVersion(HttpProxyConstants.HTTP_1_1);
208         }
209 
210         return req;
211     }
212 
213     /**
214      * {@inheritDoc}
215      */
216     public static void main(String[] args) throws Exception {
217         new ProxyTestClient(args);
218     }
219 }