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 * <hostname>" (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 }