View Javadoc
1   /*
2    * junixsocket
3    *
4    * Copyright 2009-2022 Christian Kohlschütter
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * 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, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.newsclub.net.unix.demo.okhttp;
19  
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.InterruptedIOException;
23  import java.net.NoRouteToHostException;
24  import java.net.SocketAddress;
25  import java.util.concurrent.TimeUnit;
26  
27  import org.newsclub.net.unix.AFSocketFactory;
28  import org.newsclub.net.unix.AFTIPCSocketAddress;
29  import org.newsclub.net.unix.demo.DemoHelper;
30  import org.newsclub.net.unix.demo.nanohttpd.NanoHttpdServerDemo;
31  
32  import com.kohlschutter.util.IOUtil;
33  
34  import okhttp3.OkHttpClient;
35  import okhttp3.Request;
36  import okhttp3.Response;
37  import okhttp3.ResponseBody;
38  
39  /**
40   * Connects to TIPC service 8080.1 and performs an HTTP request over that socket, using the
41   * <a href="https://square.github.io/okhttp/">OkHttp</a> HTTP client library.
42   * 
43   * If that socket is bound by {@link NanoHttpdServerDemo}, the expected output is "Hello world from
44   * &lt;hostname&gt;" (start {@link NanoHttpdServerDemo} with {@code --url tipc://8080.1}.
45   * 
46   * @author Christian Kohlschütter
47   * @see NanoHttpdServerDemo
48   */
49  public class OkHttpClientTIPCDemo {
50    public static void main(String[] args) throws IOException, InterruptedException {
51  
52      SocketAddress addr = DemoHelper.parseAddress(args, //
53          AFTIPCSocketAddress.ofService(8080, 1));
54  
55      OkHttpClient client = new OkHttpClient.Builder() //
56          .socketFactory(new AFSocketFactory.FixedAddressSocketFactory(addr)) //
57          // .callTimeout(Duration.ofMinutes(1)) //
58          .retryOnConnectionFailure(true) //
59          .connectTimeout(500, TimeUnit.MILLISECONDS) //
60          .readTimeout(500, TimeUnit.MILLISECONDS) //
61          .callTimeout(500, TimeUnit.MILLISECONDS) //
62          .build();
63  
64      // We keep looping so you can try adding/removing/disconnecting TIPC nodes and see how
65      // beautifully TIPC handles these situations
66      while (!Thread.interrupted()) {
67        Request request = new Request.Builder().url("http://localhost/").build();
68        try (Response response = client.newCall(request).execute()) {
69  
70          // NOTE: Spotbugs can't make its mind up:
71          // If we use a try-with-resources statement here, it either
72          // returns NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE
73          // or RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
74          @SuppressWarnings("resource")
75          ResponseBody body = response.body();
76          if (body != null) {
77            try (InputStream in = body.byteStream()) { // NOPMD.UseTryWithResources
78              IOUtil.transferAllBytes(in, System.out);
79            } finally {
80              body.close();
81            }
82          }
83        } catch (InterruptedIOException | NoRouteToHostException e) {
84          e.printStackTrace();
85        }
86  
87        // Instead of reusing the same connection, connect to any node that exposes the TIPC service
88        client.connectionPool().evictAll();
89  
90        // sleep for convenience
91        Thread.sleep(100);
92      }
93    }
94  }