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