Skip to content

Commit ed9dc6f

Browse files
authored
Merge pull request #44 from Sifir-io/feat/rn65_timeout
feat: [example] add rn67 example and refactor kotlin
2 parents f1ebefd + 07affca commit ed9dc6f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+30771
-9984
lines changed

android/src/main/java/com/reactnativetor/TcpStreamStart.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import com.sifir.tor.TorServiceParam
1111
class TcpStreamStart constructor(
1212
private val target: String,
1313
private val proxy:String,
14-
private val timeoutMs:Long,
14+
private val timeoutMs:Double,
1515
private val onSuccess: (stream: TcpSocksStream) -> Unit,
1616
private val onError: (e: Throwable) -> Unit
1717
) {
1818
fun run() {
1919
try {
20-
val stream = TcpSocksStream(target,proxy,timeoutMs);
20+
val stream = TcpSocksStream(target,proxy,timeoutMs.toLong());
2121
onSuccess(stream);
2222
} catch (e: Error) {
2323
Log.d("TorBridge:TcpStream", "error $e")

android/src/main/java/com/reactnativetor/TorBridgeRequest.kt

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import android.util.Base64
44
import android.util.Log
55
import com.facebook.react.bridge.*
66
import okhttp3.*
7+
import okhttp3.MediaType.Companion.toMediaType
8+
import okhttp3.RequestBody.Companion.toRequestBody
79
import org.json.JSONObject
810
import java.io.IOException
911

@@ -27,7 +29,7 @@ class TorBridgeRequest constructor(
2729
protected val param: TaskParam
2830
) {
2931

30-
protected fun onPostExecute(result: RequestResult?){
32+
protected fun onPostExecute(result: RequestResult?) {
3133
when (result) {
3234
is RequestResult.Error -> {
3335
if (result.error !== null) {
@@ -37,7 +39,10 @@ class TorBridgeRequest constructor(
3739
}
3840
}
3941
is RequestResult.Success -> mPromise!!.resolve(result.result)
40-
else -> mPromise!!.reject("Unable to process RequestResult: Exhaustive Clause")
42+
else -> mPromise!!.reject(
43+
"Unable to process RequestResult",
44+
"RequestResult Exhaustive Clause"
45+
)
4146
}
4247
mPromise = null
4348
}
@@ -47,15 +52,13 @@ class TorBridgeRequest constructor(
4752
val request = when (param.method.toUpperCase()) {
4853
"POST" -> {
4954
// Check Content-Type headers provided
50-
// Currently only support application/x-www-form-urlencoded
55+
// Currently only supports application/x-www-form-urlencoded
5156
// If not provided defaults to application/json
5257
// TODO Expand supported content formats ?
5358
val body = when (param.headers?.get("Content-Type") ?: "application/json") {
54-
"application/x-www-form-urlencoded" -> FormBody.create(
55-
MediaType.get("application/x-www-form-urlencoded; charset=utf-8"),
56-
param.json!!
57-
)
58-
else -> RequestBody.create(MediaType.get("application/json; charset=utf-8"), param.json!!)
59+
"application/x-www-form-urlencoded" ->
60+
param.json!!.toRequestBody("application/x-www-form-urlencoded; charset=utf-8".toMediaType())
61+
else -> param.json!!.toRequestBody("application/json; charset=utf-8".toMediaType())
5962
}
6063
Request.Builder().url(param.url)
6164
.post(body)
@@ -76,16 +79,16 @@ class TorBridgeRequest constructor(
7679
val resp = Arguments.createMap()
7780
val headersMap = Arguments.createMap()
7881

79-
response.headers().toMultimap().map {
82+
response.headers.toMultimap().map {
8083
headersMap.putArray(it.key.toString(), Arguments.fromList(it.value))
8184
}
8285
resp.putMap("headers", headersMap)
8386

84-
val respCode = response.code()
87+
val respCode = response.code
8588
resp.putInt("respCode", respCode)
8689

8790
val contentType = response.header("content-type").toString();
88-
val body = response.body()?.bytes()
91+
val body = response.body?.bytes()
8992
if (contentType is String) {
9093
resp.putString("mimeType", contentType)
9194
if (contentType.startsWith("application/json") || contentType.startsWith("application/javascript")) {
@@ -96,7 +99,7 @@ class TorBridgeRequest constructor(
9699
}
97100
resp.putString("b64Data", Base64.encodeToString(body, Base64.DEFAULT))
98101

99-
if (response.code() > 299) {
102+
if (response.code > 299) {
100103
onPostExecute(
101104
RequestResult.Error(
102105
"Request Response Code ($respCode)",

android/src/main/java/com/reactnativetor/TorModule.kt

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.reactnativetor
22

3+
import android.content.Context
34
import android.util.Log
45
import com.facebook.react.bridge.*
56
import com.sifir.tor.DataObserver
@@ -11,12 +12,11 @@ import java.net.InetSocketAddress
1112
import java.net.ServerSocket
1213
import java.net.Proxy;
1314
import java.security.cert.X509Certificate
14-
import javax.net.ssl.SSLContext
15-
import javax.net.ssl.TrustManager
16-
import javax.net.ssl.X509TrustManager
1715
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter
16+
import org.json.JSONObject
1817
import java.util.UUID;
1918
import java.util.concurrent.*
19+
import javax.net.ssl.*
2020

2121

2222
/**
@@ -52,13 +52,17 @@ class DataObserverEmitter(
5252
}
5353
}
5454

55+
5556
class TorModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
57+
private var _client: OkHttpClient? = null;
5658
private var service: OwnedTorService? = null;
5759
private var proxy: Proxy? = null;
5860
private var _starting: Boolean = false;
5961
private var _streams: HashMap<String, TcpSocksStream> = HashMap();
60-
// private val executorService: ExecutorService = Executors.newFixedThreadPool(4)
61-
private val executorService : ThreadPoolExecutor = ThreadPoolExecutor(4,4, 0L, TimeUnit.MILLISECONDS, LinkedBlockingQueue<Runnable>());
62+
63+
// private val executorService: ExecutorService = Executors.newFixedThreadPool(4)
64+
private val executorService: ThreadPoolExecutor =
65+
ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, LinkedBlockingQueue<Runnable>(50));
6266

6367

6468
/**
@@ -87,7 +91,7 @@ class TorModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
8791

8892
return OkHttpClient.Builder()
8993
.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
90-
.hostnameVerifier { _, _ -> true }
94+
.hostnameVerifier(HostnameVerifier { _: String, _: SSLSession -> true })
9195
}
9296

9397
override fun getName(): String {
@@ -124,24 +128,33 @@ class TorModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
124128
method: String,
125129
jsonBody: String,
126130
headers: ReadableMap,
131+
// FIXME move this to startDeamon call
127132
trustAllSSl: Boolean,
128133
promise: Promise
129134
) {
130135
if (service == null) {
131136
promise.reject(Throwable("Service Not Initialized!, Call startDaemon first"));
137+
return;
132138
}
133139

134-
var client = (if (trustAllSSl) getUnsafeOkHttpClient() else OkHttpClient().newBuilder())
135-
.proxy(proxy)
136-
.connectTimeout(10, TimeUnit.SECONDS)
137-
.writeTimeout(10, TimeUnit.SECONDS)
138-
.readTimeout(10, TimeUnit.SECONDS)
139-
.build()
140+
// if(_client !is OkHttpClient){
141+
// _client = (if (trustAllSSl) getUnsafeOkHttpClient() else OkHttpClient().newBuilder())
142+
// .proxy(proxy)
143+
// .connectTimeout(10, TimeUnit.SECONDS)
144+
// .writeTimeout(10, TimeUnit.SECONDS)
145+
// .readTimeout(10, TimeUnit.SECONDS)
146+
// .build()
147+
// }
148+
149+
if(_client !is OkHttpClient){
150+
promise.reject(Throwable("Request http client not Initialized!, Call startDaemon first"));
151+
return;
152+
}
140153

141154
val param = TaskParam(method, url, jsonBody, headers.toHashMap())
142155
executorService.execute {
143156
try {
144-
val task = TorBridgeRequest(promise, client, param);
157+
val task = TorBridgeRequest(promise, _client!!, param);
145158
task.run()
146159
} catch (e: Exception) {
147160
Log.d("TorBridge", "error on request: $e")
@@ -152,27 +165,38 @@ class TorModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
152165

153166

154167
@ReactMethod
155-
fun startDaemon(timeoutMs: Double, promise: Promise) {
168+
fun startDaemon(timeoutMs: Double, clientTimeoutSeconds: Double, promise: Promise) {
169+
Log.d("TorBridge", "->startDaemon")
156170
if (service != null) {
157171
promise.reject(Throwable("Service already running, call stopDaemon first"))
172+
return;
158173
}
159174
if (this._starting) {
160175
promise.reject(Throwable("Service already starting"))
176+
return;
161177
}
162178
_starting = true;
163179
executorService.execute {
164180
val socksPort = findFreePort();
165181
val path = this.reactApplicationContext.cacheDir.toString();
166-
val param = StartParam(socksPort, path, timeoutMs.toLong())
182+
val param = StartParam(socksPort, path, timeoutMs)
167183
try {
168184
TorBridgeStartAsync(param, {
169185
service = it
170186
proxy = Proxy(Proxy.Type.SOCKS, InetSocketAddress("0.0.0.0", socksPort))
171187
_starting = false;
188+
189+
_client = getUnsafeOkHttpClient()
190+
.proxy(proxy)
191+
.connectTimeout(clientTimeoutSeconds.toLong(), TimeUnit.SECONDS)
192+
.writeTimeout(clientTimeoutSeconds.toLong(), TimeUnit.SECONDS)
193+
.readTimeout(clientTimeoutSeconds.toLong(), TimeUnit.SECONDS)
194+
.build();
195+
172196
promise.resolve(socksPort);
173197
}, {
174198
_starting = false;
175-
promise.reject(it);
199+
promise.reject("StartDaemon Error", "Error starting Tor Daemon", it);
176200
}).run();
177201

178202
} catch (e: Exception) {
@@ -217,7 +241,7 @@ class TorModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
217241
if (service == null) {
218242
throw Exception("Tor service not running, call startDaemon first")
219243
}
220-
TcpStreamStart(target, "0.0.0.0:${service?.socksPort}", timeoutMs.toLong(), {
244+
TcpStreamStart(target, "0.0.0.0:${service?.socksPort}", timeoutMs, {
221245
// Assign UUID to connection to manage it
222246
val uuid = UUID.randomUUID();
223247
val connId = uuid.toString();
@@ -243,7 +267,7 @@ class TorModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
243267
throw Throwable("Tor Service not running, call startDaemon first")
244268
}
245269
var stream = _streams[connId]
246-
?: throw Throwable("Stream for connectionId $connId is not initialized, call startTcpConn first");
270+
?: throw Throwable("Stream for connectionId $connId is not initialized, call startTcpConn first");
247271
stream.send_data(msg, timeoutSec.toLong());
248272
promise.resolve(true);
249273
} catch (e: Exception) {
@@ -265,4 +289,7 @@ class TorModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
265289
promise.reject(e)
266290
}
267291
}
292+
268293
}
294+
295+

android/src/main/java/com/reactnativetor/TorPackage.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ class TorPackage : ReactPackage {
1515
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
1616
val manager = reactContext.getPackageManager();
1717
val ai = manager.getApplicationInfo(reactContext.packageName, PackageManager.GET_META_DATA);
18-
System.load("${ai.nativeLibraryDir}/libsifir_android.so");
18+
System.loadLibrary("sifir_android")
19+
// System.load("${ai.nativeLibraryDir}/libsifir_android.so");
1920
return Arrays.asList<NativeModule>(TorModule(reactContext))
2021
}
2122

android/src/main/java/com/reactnativetor/TorStartAsync.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import com.sifir.tor.TorServiceParam
1010
class StartParam(
1111
val socksPort: Int,
1212
var path: String,
13-
val timeoutMs: Long
13+
val timeoutMs: Double
1414
);
1515

1616
class TorBridgeStartAsync constructor(
@@ -21,7 +21,7 @@ class TorBridgeStartAsync constructor(
2121
fun run() {
2222
try {
2323
Log.d("TorBridge", "Starting Tor with ${param.path} ${param.socksPort} ${param.timeoutMs}")
24-
val ownedTor = OwnedTorService(TorServiceParam(param.path, param.socksPort,param.timeoutMs));
24+
val ownedTor = OwnedTorService(TorServiceParam(param.path, param.socksPort,param.timeoutMs.toLong()));
2525
onSuccess(ownedTor);
2626
} catch (e: Exception) {
2727
Log.d("TorBridge:StartAsync", "error onPostExecute$e")

example_rn66/.buckconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
[android]
3+
target = Google Inc.:Google APIs:23
4+
5+
[maven_repositories]
6+
central = https://repo1.maven.org/maven2

example_rn66/.eslintrc.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module.exports = {
2+
root: true,
3+
extends: '@react-native-community',
4+
parser: '@typescript-eslint/parser',
5+
plugins: ['@typescript-eslint'],
6+
overrides: [
7+
{
8+
files: ['*.ts', '*.tsx'],
9+
rules: {
10+
'@typescript-eslint/no-shadow': ['error'],
11+
'no-shadow': 'off',
12+
'no-undef': 'off',
13+
},
14+
},
15+
],
16+
};

example_rn66/.gitignore

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# OSX
2+
#
3+
.DS_Store
4+
5+
# Xcode
6+
#
7+
build/
8+
*.pbxuser
9+
!default.pbxuser
10+
*.mode1v3
11+
!default.mode1v3
12+
*.mode2v3
13+
!default.mode2v3
14+
*.perspectivev3
15+
!default.perspectivev3
16+
xcuserdata
17+
*.xccheckout
18+
*.moved-aside
19+
DerivedData
20+
*.hmap
21+
*.ipa
22+
*.xcuserstate
23+
24+
# Android/IntelliJ
25+
#
26+
build/
27+
.idea
28+
.gradle
29+
local.properties
30+
*.iml
31+
*.hprof
32+
33+
# node.js
34+
#
35+
node_modules/
36+
npm-debug.log
37+
yarn-error.log
38+
39+
# BUCK
40+
buck-out/
41+
\.buckd/
42+
*.keystore
43+
!debug.keystore
44+
45+
# fastlane
46+
#
47+
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
48+
# screenshots whenever they are needed.
49+
# For more information about the recommended setup visit:
50+
# https://docs.fastlane.tools/best-practices/source-control/
51+
52+
*/fastlane/report.xml
53+
*/fastlane/Preview.html
54+
*/fastlane/screenshots
55+
56+
# Bundle artifact
57+
*.jsbundle
58+
59+
# CocoaPods
60+
/ios/Pods/

example_rn66/.prettierrc.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
bracketSpacing: false,
3+
jsxBracketSameLine: true,
4+
singleQuote: true,
5+
trailingComma: 'all',
6+
arrowParens: 'avoid',
7+
};

example_rn66/.watchmanconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

0 commit comments

Comments
 (0)