1
+ package org .ethereumphone .lightnodestats .data ;
2
+
3
+ import java .io .BufferedInputStream ;
4
+ import java .io .BufferedReader ;
5
+ import java .io .ByteArrayInputStream ;
6
+ import java .io .IOException ;
7
+ import java .io .InputStream ;
8
+ import java .io .InputStreamReader ;
9
+ import java .nio .charset .StandardCharsets ;
10
+ import java .util .Arrays ;
11
+ import java .util .HashMap ;
12
+ import java .util .List ;
13
+ import java .util .Map ;
14
+
15
+ import okhttp3 .CipherSuite ;
16
+ import okhttp3 .ConnectionSpec ;
17
+ import okhttp3 .Headers ;
18
+ import okhttp3 .MediaType ;
19
+ import okhttp3 .OkHttpClient ;
20
+ import okhttp3 .RequestBody ;
21
+ import okhttp3 .ResponseBody ;
22
+ import okhttp3 .logging .HttpLoggingInterceptor ;
23
+ import okio .Buffer ;
24
+ import okio .BufferedSource ;
25
+ import org .slf4j .Logger ;
26
+ import org .slf4j .LoggerFactory ;
27
+
28
+ import org .web3j .protocol .Service ;
29
+ import org .web3j .protocol .exceptions .ClientConnectionException ;
30
+
31
+ import static okhttp3 .ConnectionSpec .CLEARTEXT ;
32
+
33
+ /** HTTP implementation of our services API. */
34
+ public class EthHttpService extends Service {
35
+
36
+ /** Copied from {@link ConnectionSpec#APPROVED_CIPHER_SUITES}. */
37
+ @ SuppressWarnings ("JavadocReference" )
38
+ private static final CipherSuite [] INFURA_CIPHER_SUITES =
39
+ new CipherSuite [] {
40
+ CipherSuite .TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ,
41
+ CipherSuite .TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ,
42
+ CipherSuite .TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ,
43
+ CipherSuite .TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ,
44
+ CipherSuite .TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 ,
45
+ CipherSuite .TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 ,
46
+
47
+ // Note that the following cipher suites are all on HTTP/2's bad cipher suites list.
48
+ // We'll
49
+ // continue to include them until better suites are commonly available. For example,
50
+ // none
51
+ // of the better cipher suites listed above shipped with Android 4.4 or Java 7.
52
+ CipherSuite .TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA ,
53
+ CipherSuite .TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA ,
54
+ CipherSuite .TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA ,
55
+ CipherSuite .TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA ,
56
+ CipherSuite .TLS_RSA_WITH_AES_128_GCM_SHA256 ,
57
+ CipherSuite .TLS_RSA_WITH_AES_256_GCM_SHA384 ,
58
+ CipherSuite .TLS_RSA_WITH_AES_128_CBC_SHA ,
59
+ CipherSuite .TLS_RSA_WITH_AES_256_CBC_SHA ,
60
+ CipherSuite .TLS_RSA_WITH_3DES_EDE_CBC_SHA ,
61
+
62
+ // Additional INFURA CipherSuites
63
+ CipherSuite .TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 ,
64
+ CipherSuite .TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 ,
65
+ CipherSuite .TLS_RSA_WITH_AES_128_CBC_SHA256 ,
66
+ CipherSuite .TLS_RSA_WITH_AES_256_CBC_SHA256
67
+ };
68
+
69
+ private static final ConnectionSpec INFURA_CIPHER_SUITE_SPEC =
70
+ new ConnectionSpec .Builder (ConnectionSpec .MODERN_TLS )
71
+ .cipherSuites (INFURA_CIPHER_SUITES )
72
+ .build ();
73
+
74
+ /** The list of {@link ConnectionSpec} instances used by the connection. */
75
+ private static final List <ConnectionSpec > CONNECTION_SPEC_LIST =
76
+ Arrays .asList (INFURA_CIPHER_SUITE_SPEC , CLEARTEXT );
77
+
78
+ public static final MediaType JSON_MEDIA_TYPE =
79
+ MediaType .parse ("application/json; charset=utf-8" );
80
+
81
+ public static final String DEFAULT_URL = "http://localhost:8545/" ;
82
+
83
+ private static final Logger log = LoggerFactory .getLogger (org .web3j .protocol .http .HttpService .class );
84
+
85
+ private OkHttpClient httpClient ;
86
+
87
+ private final String url ;
88
+
89
+ private final boolean includeRawResponse ;
90
+
91
+ private HashMap <String , String > headers = new HashMap <>();
92
+
93
+ public EthHttpService (String url , OkHttpClient httpClient , boolean includeRawResponses ) {
94
+ super (includeRawResponses );
95
+ this .url = url ;
96
+ this .httpClient = httpClient ;
97
+ this .includeRawResponse = includeRawResponses ;
98
+ }
99
+
100
+ public EthHttpService (OkHttpClient httpClient , boolean includeRawResponses ) {
101
+ this (DEFAULT_URL , httpClient , includeRawResponses );
102
+ }
103
+
104
+ public EthHttpService (String url , OkHttpClient httpClient ) {
105
+ this (url , httpClient , false );
106
+ }
107
+
108
+ public EthHttpService (String url ) {
109
+ this (url , createOkHttpClient ());
110
+ }
111
+
112
+ public EthHttpService (String url , boolean includeRawResponse ) {
113
+ this (url , createOkHttpClient (), includeRawResponse );
114
+ }
115
+
116
+ public EthHttpService (OkHttpClient httpClient ) {
117
+ this (DEFAULT_URL , httpClient );
118
+ }
119
+
120
+ public EthHttpService (boolean includeRawResponse ) {
121
+ this (DEFAULT_URL , includeRawResponse );
122
+ }
123
+
124
+ public EthHttpService () {
125
+ this (DEFAULT_URL );
126
+ }
127
+
128
+ private static OkHttpClient createOkHttpClient () {
129
+ final OkHttpClient .Builder builder =
130
+ new OkHttpClient .Builder ().connectionSpecs (CONNECTION_SPEC_LIST );
131
+ configureLogging (builder );
132
+ return builder .build ();
133
+ }
134
+
135
+ private static void configureLogging (OkHttpClient .Builder builder ) {
136
+ if (log .isDebugEnabled ()) {
137
+ HttpLoggingInterceptor logging = new HttpLoggingInterceptor (log ::debug );
138
+ logging .setLevel (HttpLoggingInterceptor .Level .BODY );
139
+ builder .addInterceptor (logging );
140
+ }
141
+ }
142
+
143
+ @ Override
144
+ protected InputStream performIO (String request ) throws IOException {
145
+
146
+ RequestBody requestBody = RequestBody .create (request , JSON_MEDIA_TYPE );
147
+ Headers headers = buildHeaders ();
148
+
149
+
150
+ //okhttp3.Request httpRequest =
151
+ // new okhttp3.Request.Builder().url(url).headers(headers).post(requestBody).build();
152
+
153
+ String out = executeCommand ("curl -X POST -H \" Content-Type: application/json\" --data '" +request +"' " +url );
154
+ return new ByteArrayInputStream (out .getBytes (StandardCharsets .UTF_8 ));
155
+ }
156
+
157
+ protected void processHeaders (Headers headers ) {
158
+ // Default implementation is empty
159
+ }
160
+
161
+ public static String executeCommand (String command ) {
162
+ StringBuilder output = new StringBuilder ();
163
+ try {
164
+ Process proc = Runtime .getRuntime ().exec (new String [] { "sh" , "-c" , command });
165
+ BufferedReader reader = new BufferedReader (new InputStreamReader (proc .getInputStream ()));
166
+
167
+ String line ;
168
+ while ((line = reader .readLine ())!= null ) {
169
+ output .append (line + "\n " );
170
+ }
171
+ proc .waitFor ();
172
+ } catch (Exception e ) {
173
+ e .printStackTrace ();
174
+ }
175
+
176
+ return output .toString ();
177
+ }
178
+
179
+ private InputStream buildInputStream (ResponseBody responseBody ) throws IOException {
180
+ InputStream inputStream = responseBody .byteStream ();
181
+
182
+ if (includeRawResponse ) {
183
+ // we have to buffer the entire input payload, so that after processing
184
+ // it can be re-read and used to populate the rawResponse field.
185
+
186
+ BufferedSource source = responseBody .source ();
187
+ source .request (Long .MAX_VALUE ); // Buffer the entire body
188
+ Buffer buffer = source .buffer ();
189
+
190
+ long size = buffer .size ();
191
+ if (size > Integer .MAX_VALUE ) {
192
+ throw new UnsupportedOperationException (
193
+ "Non-integer input buffer size specified: " + size );
194
+ }
195
+
196
+ int bufferSize = (int ) size ;
197
+ BufferedInputStream bufferedinputStream =
198
+ new BufferedInputStream (inputStream , bufferSize );
199
+
200
+ bufferedinputStream .mark (inputStream .available ());
201
+ return bufferedinputStream ;
202
+
203
+ } else {
204
+ return inputStream ;
205
+ }
206
+ }
207
+
208
+ private Headers buildHeaders () {
209
+ return Headers .of (headers );
210
+ }
211
+
212
+ public void addHeader (String key , String value ) {
213
+ headers .put (key , value );
214
+ }
215
+
216
+ public void addHeaders (Map <String , String > headersToAdd ) {
217
+ headers .putAll (headersToAdd );
218
+ }
219
+
220
+ public HashMap <String , String > getHeaders () {
221
+ return headers ;
222
+ }
223
+
224
+ @ Override
225
+ public void close () throws IOException {}
226
+ }
0 commit comments