View Javadoc
1   /*
2    * junixsocket
3    *
4    * Copyright 2009-2024 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  @SuppressWarnings("CatchAndPrintStackTrace" /* errorprone */)
50  public class OkHttpClientTIPCDemo {
51    public static void main(String[] args) throws IOException, InterruptedException {
52  
53      SocketAddress addr = DemoHelper.parseAddress(args, //
54          AFTIPCSocketAddress.ofService(8080, 1));
55  
56      OkHttpClient client = new OkHttpClient.Builder() //
57          .socketFactory(new AFSocketFactory.FixedAddressSocketFactory(addr)) //
58          // .callTimeout(Duration.ofMinutes(1)) //
59          .retryOnConnectionFailure(true) //
60          .connectTimeout(500, TimeUnit.MILLISECONDS) //
61          .readTimeout(500, TimeUnit.MILLISECONDS) //
62          .callTimeout(500, TimeUnit.MILLISECONDS) //
63          .build();
64  
65      // We keep looping so you can try adding/removing/disconnecting TIPC nodes and see how
66      // beautifully TIPC handles these situations
67      while (!Thread.interrupted()) {
68        Request request = new Request.Builder().url("http://localhost/").build();
69        try (Response response = client.newCall(request).execute()) {
70  
71          // NOTE: Spotbugs can't make its mind up:
72          // If we use a try-with-resources statement here, it either
73          // returns NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE
74          // or RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
75          @SuppressWarnings("resource")
76          ResponseBody body = response.body();
77          if (body != null) {
78            try (InputStream in = body.byteStream()) { // NOPMD.UseTryWithResources
79              IOUtil.transferAllBytes(in, System.out);
80            } finally {
81              body.close();
82            }
83          }
84        } catch (InterruptedIOException | NoRouteToHostException e) {
85          e.printStackTrace();
86        }
87  
88        // Instead of reusing the same connection, connect to any node that exposes the TIPC service
89        client.connectionPool().evictAll();
90  
91        // sleep for convenience
92        Thread.sleep(100);
93      }
94    }
95  }