View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.conn.routing;
29  
30  import java.net.InetAddress;
31  
32  import org.apache.http.HttpHost;
33  import org.apache.http.conn.routing.RouteInfo.LayerType;
34  import org.apache.http.conn.routing.RouteInfo.TunnelType;
35  import org.junit.Assert;
36  import org.junit.Test;
37  
38  /**
39   * Tests for {@link BasicRouteDirector}.
40   */
41  public class TestRouteDirector {
42  
43      // a selection of constants for generating routes
44      public final static
45          HttpHost TARGET1 = new HttpHost("target1.test.invalid");
46      public final static
47          HttpHost TARGET2 = new HttpHost("target2.test.invalid", 8080);
48      // It is not necessary to have extra targets for https.
49      // The 'layered' and 'secure' flags are specified explicitly
50      // for routes, they will not be determined from the scheme.
51  
52      public final static
53          HttpHost PROXY1 = new HttpHost("proxy1.test.invalid");
54      public final static
55          HttpHost PROXY2 = new HttpHost("proxy2.test.invalid", 1080);
56      public final static
57          HttpHost PROXY3 = new HttpHost("proxy3.test.invalid", 88);
58  
59      public final static InetAddress LOCAL41;
60      public final static InetAddress LOCAL42;
61      public final static InetAddress LOCAL61;
62      public final static InetAddress LOCAL62;
63  
64      // need static initializer to deal with exceptions
65      static {
66          try {
67              LOCAL41 = InetAddress.getByAddress(new byte[]{ 127, 0, 0, 1 });
68              LOCAL42 = InetAddress.getByAddress(new byte[]{ 127, 0, 0, 2 });
69  
70              LOCAL61 = InetAddress.getByAddress(new byte[]{
71                  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
72              });
73              LOCAL62 = InetAddress.getByAddress(new byte[]{
74                  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2
75              });
76  
77          } catch (final Exception x) {
78              throw new ExceptionInInitializerError(x);
79          }
80      }
81  
82      @Test(expected=IllegalArgumentException.class)
83      public void testIllegal() {
84          final HttpRouteDirector rowdy = new BasicRouteDirector();
85          final HttpRoute route = new HttpRoute(TARGET1);
86          rowdy.nextStep(null, route);
87      }
88  
89      @Test
90      public void testDirect() {
91  
92          final HttpRouteDirector rowdy = new BasicRouteDirector();
93          final HttpRoute route1   = new HttpRoute(TARGET1);
94          final HttpRoute route2   = new HttpRoute(TARGET2);
95          final HttpRoute route1p1 = new HttpRoute(TARGET1, null, PROXY1, false);
96  
97          int step = rowdy.nextStep(route1, null);
98          Assert.assertEquals("wrong step to route1",
99                       HttpRouteDirector.CONNECT_TARGET, step);
100 
101         step = rowdy.nextStep(route2, null);
102         Assert.assertEquals("wrong step to route2",
103                      HttpRouteDirector.CONNECT_TARGET, step);
104 
105         step = rowdy.nextStep(route1, route1);
106         Assert.assertEquals("complete route1 not detected",
107                      HttpRouteDirector.COMPLETE, step);
108 
109         step = rowdy.nextStep(route2, route2);
110         Assert.assertEquals("complete route2 not detected",
111                      HttpRouteDirector.COMPLETE, step);
112 
113         step = rowdy.nextStep(route1, route2);
114         Assert.assertEquals("unreachable target not detected",
115                      HttpRouteDirector.UNREACHABLE, step);
116 
117         step = rowdy.nextStep(route1, route1p1);
118         Assert.assertEquals("invalid proxy not detected",
119                      HttpRouteDirector.UNREACHABLE, step);
120     }
121 
122     @Test
123     public void testProxy() {
124 
125         final HttpRouteDirector rowdy = new BasicRouteDirector();
126         final HttpRoute route1p1 = new HttpRoute(TARGET1, null, PROXY1, false);
127         final HttpRoute route1p2 = new HttpRoute(TARGET1, null, PROXY2, false);
128         final HttpRoute route2p1 = new HttpRoute(TARGET2, null, PROXY1, false);
129         final HttpRoute route0   = new HttpRoute(PROXY1);
130         final HttpRoute route1   = new HttpRoute(TARGET1);
131 
132         int step = rowdy.nextStep(route1p1, null);
133         Assert.assertEquals("wrong step to route1p1",
134                      HttpRouteDirector.CONNECT_PROXY, step);
135 
136         step = rowdy.nextStep(route1p2, null);
137         Assert.assertEquals("wrong step to route1p2",
138                      HttpRouteDirector.CONNECT_PROXY, step);
139 
140         step = rowdy.nextStep(route1p1, route1p1);
141         Assert.assertEquals("complete route1p1 not detected",
142                      HttpRouteDirector.COMPLETE, step);
143 
144         step = rowdy.nextStep(route1p2, route1p2);
145         Assert.assertEquals("complete route1p2 not detected",
146                      HttpRouteDirector.COMPLETE, step);
147 
148         step = rowdy.nextStep(route2p1, route2p1);
149         Assert.assertEquals("complete route2p1 not detected",
150                      HttpRouteDirector.COMPLETE, step);
151 
152         step = rowdy.nextStep(route1p1, route1p2);
153         Assert.assertEquals("unreachable route1p1 via route1p2 not detected",
154                      HttpRouteDirector.UNREACHABLE, step);
155 
156         step = rowdy.nextStep(route1p1, route2p1);
157         Assert.assertEquals("unreachable route1p1 via route2p1 not detected",
158                      HttpRouteDirector.UNREACHABLE, step);
159 
160         step = rowdy.nextStep(route1p1, route0);
161         Assert.assertEquals("unreachable route1p1 via route0 not detected",
162                      HttpRouteDirector.UNREACHABLE, step);
163 
164         step = rowdy.nextStep(route1p1, route1);
165         Assert.assertEquals("unreachable route1p1 via route1 not detected",
166                      HttpRouteDirector.UNREACHABLE, step);
167     }
168 
169     @Test
170     public void testProxyChain() {
171         final HttpHost[] chainA = { PROXY1 };
172         final HttpHost[] chainB = { PROXY1, PROXY2 };
173         final HttpHost[] chainC = { PROXY2, PROXY1 };
174 
175         final HttpRouteDirector rowdy = new BasicRouteDirector();
176         final HttpRoute route1cA  = new HttpRoute(TARGET1, null, chainA, false,
177                                             TunnelType.PLAIN, LayerType.PLAIN);
178         final HttpRoute route1cB  = new HttpRoute(TARGET1, null, chainB, false,
179                                             TunnelType.PLAIN, LayerType.PLAIN);
180         final HttpRoute route1cC  = new HttpRoute(TARGET1, null, chainC, false,
181                                             TunnelType.PLAIN, LayerType.PLAIN);
182         final HttpRoute route1cD  = new HttpRoute(TARGET1, null, chainC, false,
183                                             TunnelType.PLAIN, LayerType.PLAIN);
184 
185         int step = rowdy.nextStep(route1cA, null);
186         Assert.assertEquals("wrong step to route1cA",
187                      HttpRouteDirector.CONNECT_PROXY, step);
188 
189         step = rowdy.nextStep(route1cB, null);
190         Assert.assertEquals("wrong step to route1cB",
191                      HttpRouteDirector.CONNECT_PROXY, step);
192 
193         step = rowdy.nextStep(route1cC, null);
194         Assert.assertEquals("wrong step to route1cC",
195                      HttpRouteDirector.CONNECT_PROXY, step);
196 
197         step = rowdy.nextStep(route1cD, null);
198         Assert.assertEquals("wrong step to route1cD",
199                      HttpRouteDirector.CONNECT_PROXY, step);
200 
201 
202         step = rowdy.nextStep(route1cB, route1cA);
203         Assert.assertEquals("wrong step to route 1cB from 1cA",
204                      HttpRouteDirector.TUNNEL_PROXY, step);
205 
206         step = rowdy.nextStep(route1cB, route1cB);
207         Assert.assertEquals("complete route 1cB not detected",
208                      HttpRouteDirector.COMPLETE, step);
209 
210         step = rowdy.nextStep(route1cB, route1cC);
211         Assert.assertEquals("unreachable route 1cB from 1cC not detected",
212                      HttpRouteDirector.UNREACHABLE, step);
213 
214         step = rowdy.nextStep(route1cB, route1cD);
215         Assert.assertEquals("unreachable route 1cB from 1cD not detected",
216                      HttpRouteDirector.UNREACHABLE, step);
217 
218 
219         step = rowdy.nextStep(route1cA, route1cB);
220         Assert.assertEquals("unreachable route 1cA from 1cB not detected",
221                      HttpRouteDirector.UNREACHABLE, step);
222     }
223 
224     @Test
225     public void testLocalDirect() {
226 
227         final HttpRouteDirector rowdy = new BasicRouteDirector();
228         final HttpRoute route1l41 = new HttpRoute(TARGET1, LOCAL41, false);
229         final HttpRoute route1l42 = new HttpRoute(TARGET1, LOCAL42, false);
230         final HttpRoute route1l61 = new HttpRoute(TARGET1, LOCAL61, false);
231         final HttpRoute route1l00 = new HttpRoute(TARGET1, null, false);
232 
233         int step = rowdy.nextStep(route1l41, null);
234         Assert.assertEquals("wrong step to route1l41",
235                      HttpRouteDirector.CONNECT_TARGET, step);
236 
237         step = rowdy.nextStep(route1l42, null);
238         Assert.assertEquals("wrong step to route1l42",
239                      HttpRouteDirector.CONNECT_TARGET, step);
240 
241         step = rowdy.nextStep(route1l61, null);
242         Assert.assertEquals("wrong step to route1l61",
243                      HttpRouteDirector.CONNECT_TARGET, step);
244 
245         step = rowdy.nextStep(route1l00, null);
246         Assert.assertEquals("wrong step to route1l00",
247                      HttpRouteDirector.CONNECT_TARGET, step);
248 
249         step = rowdy.nextStep(route1l41, route1l41);
250         Assert.assertEquals("complete route1l41 not detected",
251                      HttpRouteDirector.COMPLETE, step);
252 
253         step = rowdy.nextStep(route1l42, route1l42);
254         Assert.assertEquals("complete route1l42 not detected",
255                      HttpRouteDirector.COMPLETE, step);
256 
257         step = rowdy.nextStep(route1l61, route1l61);
258         Assert.assertEquals("complete route1l61 not detected",
259                      HttpRouteDirector.COMPLETE, step);
260 
261         step = rowdy.nextStep(route1l00, route1l00);
262         Assert.assertEquals("complete route1l00 not detected",
263                      HttpRouteDirector.COMPLETE, step);
264 
265 
266         step = rowdy.nextStep(route1l41, route1l42);
267         Assert.assertEquals("unreachable route1l41 via route1l42 not detected",
268                      HttpRouteDirector.UNREACHABLE, step);
269 
270         step = rowdy.nextStep(route1l41, route1l61);
271         Assert.assertEquals("unreachable route1l41 via route1l61 not detected",
272                      HttpRouteDirector.UNREACHABLE, step);
273 
274         step = rowdy.nextStep(route1l41, route1l00);
275         Assert.assertEquals("unreachable route1l41 via route1l00 not detected",
276                      HttpRouteDirector.UNREACHABLE, step);
277 
278 
279         step = rowdy.nextStep(route1l00, route1l41);
280         Assert.assertEquals("complete route1l00 as route1l41 not detected",
281                      HttpRouteDirector.COMPLETE, step);
282 
283         step = rowdy.nextStep(route1l00, route1l42);
284         Assert.assertEquals("complete route1l00 as route1l42 not detected",
285                      HttpRouteDirector.COMPLETE, step);
286 
287         step = rowdy.nextStep(route1l00, route1l61);
288         Assert.assertEquals("complete route1l00 as route1l61 not detected",
289                      HttpRouteDirector.COMPLETE, step);
290     }
291 
292     @Test
293     public void testDirectSecure() {
294 
295         final HttpRouteDirector rowdy = new BasicRouteDirector();
296         final HttpRoute route1u   = new HttpRoute(TARGET1, null, false);
297         final HttpRoute route1s   = new HttpRoute(TARGET1, null, true);
298         final HttpRoute route1p1u = new HttpRoute(TARGET1, null, PROXY1, false);
299         final HttpRoute route1p1s = new HttpRoute(TARGET1, null, PROXY1, true);
300 
301         int step = rowdy.nextStep(route1u, null);
302         Assert.assertEquals("wrong step to route1u",
303                      HttpRouteDirector.CONNECT_TARGET, step);
304 
305         step = rowdy.nextStep(route1s, null);
306         Assert.assertEquals("wrong step to route1s",
307                      HttpRouteDirector.CONNECT_TARGET, step);
308 
309         // unrequested security is currently not tolerated
310         step = rowdy.nextStep(route1u, route1s);
311         Assert.assertEquals("unreachable route 1u from 1s not detected",
312                      HttpRouteDirector.UNREACHABLE, step);
313 
314         // secure layering of direct connections is currently not supported
315         step = rowdy.nextStep(route1s, route1u);
316         Assert.assertEquals("unreachable route 1s from 1u not detected",
317                      HttpRouteDirector.UNREACHABLE, step);
318 
319 
320 
321         step = rowdy.nextStep(route1s, route1p1u);
322         Assert.assertEquals("unreachable route 1s from 1p1u not detected",
323                      HttpRouteDirector.UNREACHABLE, step);
324 
325         step = rowdy.nextStep(route1s, route1p1s);
326         Assert.assertEquals("unreachable route 1s from 1p1s not detected",
327                      HttpRouteDirector.UNREACHABLE, step);
328     }
329 
330     @Test
331     public void testProxyTLS() {
332 
333         final HttpRouteDirector rowdy = new BasicRouteDirector();
334         final HttpRoute route1    = new HttpRoute
335             (TARGET1, null, PROXY1, false,
336              TunnelType.PLAIN, LayerType.PLAIN);
337         final HttpRoute route1t   = new HttpRoute
338             (TARGET1, null, PROXY1, false,
339              TunnelType.TUNNELLED, LayerType.PLAIN);
340         final HttpRoute route1tl  = new HttpRoute
341             (TARGET1, null, PROXY1, false,
342              TunnelType.TUNNELLED, LayerType.LAYERED);
343         final HttpRoute route1s   = new HttpRoute
344             (TARGET1, null, PROXY1, true,
345              TunnelType.PLAIN, LayerType.PLAIN);
346         final HttpRoute route1ts  = new HttpRoute
347             (TARGET1, null, PROXY1, true,
348              TunnelType.TUNNELLED, LayerType.PLAIN);
349         final HttpRoute route1tls = new HttpRoute
350             (TARGET1, null, PROXY1, true,
351              TunnelType.TUNNELLED, LayerType.LAYERED);
352 
353         // we don't consider a route that is layered but not tunnelled
354 
355         int step = rowdy.nextStep(route1, null);
356         Assert.assertEquals("wrong step to route1",
357                      HttpRouteDirector.CONNECT_PROXY, step);
358 
359         step = rowdy.nextStep(route1t, null);
360         Assert.assertEquals("wrong step to route1t",
361                      HttpRouteDirector.CONNECT_PROXY, step);
362 
363         step = rowdy.nextStep(route1tl, null);
364         Assert.assertEquals("wrong step to route1tl",
365                      HttpRouteDirector.CONNECT_PROXY, step);
366 
367         step = rowdy.nextStep(route1s, null);
368         Assert.assertEquals("wrong step to route1s",
369                      HttpRouteDirector.CONNECT_PROXY, step);
370 
371         step = rowdy.nextStep(route1ts, null);
372         Assert.assertEquals("wrong step to route1ts",
373                      HttpRouteDirector.CONNECT_PROXY, step);
374 
375         step = rowdy.nextStep(route1tls, null);
376         Assert.assertEquals("wrong step to route1tls",
377                      HttpRouteDirector.CONNECT_PROXY, step);
378 
379 
380         step = rowdy.nextStep(route1, route1);
381         Assert.assertEquals("complete route1 not detected",
382                      HttpRouteDirector.COMPLETE, step);
383 
384         step = rowdy.nextStep(route1t, route1t);
385         Assert.assertEquals("complete route1t not detected",
386                      HttpRouteDirector.COMPLETE, step);
387 
388         step = rowdy.nextStep(route1tl, route1tl);
389         Assert.assertEquals("complete route1tl not detected",
390                      HttpRouteDirector.COMPLETE, step);
391 
392         step = rowdy.nextStep(route1s, route1s);
393         Assert.assertEquals("complete route1s not detected",
394                      HttpRouteDirector.COMPLETE, step);
395 
396         step = rowdy.nextStep(route1ts, route1ts);
397         Assert.assertEquals("complete route1ts not detected",
398                      HttpRouteDirector.COMPLETE, step);
399 
400         step = rowdy.nextStep(route1tls, route1tls);
401         Assert.assertEquals("complete route1tls not detected",
402                      HttpRouteDirector.COMPLETE, step);
403 
404 
405 
406         step = rowdy.nextStep(route1, route1t);
407         Assert.assertEquals("unreachable route1 from 1t not detected",
408                      HttpRouteDirector.UNREACHABLE, step);
409 
410         step = rowdy.nextStep(route1, route1tl);
411         Assert.assertEquals("unreachable route1 from 1tl not detected",
412                      HttpRouteDirector.UNREACHABLE, step);
413 
414         // unrequested security is currently not tolerated
415         step = rowdy.nextStep(route1, route1s);
416         Assert.assertEquals("unreachable route1 from 1s not detected",
417                      HttpRouteDirector.UNREACHABLE, step);
418 
419         step = rowdy.nextStep(route1, route1ts);
420         Assert.assertEquals("unreachable route1 from 1ts not detected",
421                      HttpRouteDirector.UNREACHABLE, step);
422 
423         step = rowdy.nextStep(route1, route1tls);
424         Assert.assertEquals("unreachable route1 from 1tls not detected",
425                      HttpRouteDirector.UNREACHABLE, step);
426 
427 
428         // securing requires layering
429         step = rowdy.nextStep(route1s, route1);
430         Assert.assertEquals("unreachable route1s from 1 not detected",
431                      HttpRouteDirector.UNREACHABLE, step);
432 
433         // securing requires layering, and multiple layers are not supported
434         step = rowdy.nextStep(route1tls, route1tl);
435         Assert.assertEquals("unreachable route1tls from 1tl not detected",
436                      HttpRouteDirector.UNREACHABLE, step);
437 
438 
439         // cases where tunnelling to the target is required
440         step = rowdy.nextStep(route1t, route1);
441         Assert.assertEquals("wrong step to route1t from 1",
442                      HttpRouteDirector.TUNNEL_TARGET, step);
443 
444         step = rowdy.nextStep(route1tl, route1);
445         Assert.assertEquals("wrong step to route1tl from 1",
446                      HttpRouteDirector.TUNNEL_TARGET, step);
447 
448         step = rowdy.nextStep(route1tls, route1);
449         Assert.assertEquals("wrong step to route1tls from 1",
450                      HttpRouteDirector.TUNNEL_TARGET, step);
451 
452 
453         // cases where layering on the tunnel is required
454         step = rowdy.nextStep(route1tl, route1t);
455         Assert.assertEquals("wrong step to route1tl from 1t",
456                      HttpRouteDirector.LAYER_PROTOCOL, step);
457 
458         step = rowdy.nextStep(route1tl, route1ts);
459         Assert.assertEquals("wrong step to route1tl from 1ts",
460                      HttpRouteDirector.LAYER_PROTOCOL, step);
461 
462         step = rowdy.nextStep(route1tls, route1t);
463         Assert.assertEquals("wrong step to route1tls from 1t",
464                      HttpRouteDirector.LAYER_PROTOCOL, step);
465 
466         step = rowdy.nextStep(route1tls, route1ts);
467         Assert.assertEquals("wrong step to route1tls from 1ts",
468                      HttpRouteDirector.LAYER_PROTOCOL, step);
469 
470         // There are some odd cases left over, like having a secure tunnel
471         // that becomes unsecure by layering, or a secure connection to a
472         // proxy that becomes unsecure by tunnelling to another proxy.
473     }
474 
475 }