Skip to content

Commit 8e8d691

Browse files
committed
feat: added options to android native
1 parent 22232af commit 8e8d691

File tree

3 files changed

+416
-37
lines changed

3 files changed

+416
-37
lines changed

android/src/main/java/com/openvpn/OpenvpnModule.kt

Lines changed: 287 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import android.content.Intent
66
import android.content.ServiceConnection
77
import android.os.Handler
88
import android.os.IBinder
9-
import android.util.Log
9+
import android.os.RemoteException
10+
import androidx.core.content.edit
1011
import com.facebook.react.bridge.Promise
1112
import com.facebook.react.bridge.ReactApplicationContext
1213
import com.facebook.react.bridge.ReadableMap
@@ -16,6 +17,9 @@ import de.blinkt.openvpn.core.ConfigParser
1617
import de.blinkt.openvpn.core.ConnectionStatus
1718
import de.blinkt.openvpn.core.IOpenVPNServiceInternal
1819
import de.blinkt.openvpn.core.OpenVPNService
20+
import de.blinkt.openvpn.core.Preferences
21+
import de.blinkt.openvpn.core.ProfileManager
22+
import de.blinkt.openvpn.core.VPNLaunchHelper
1923
import de.blinkt.openvpn.core.VpnStatus
2024
import de.blinkt.openvpn.fragments.Utils
2125
import java.io.BufferedReader
@@ -78,38 +82,65 @@ class OpenvpnModule(reactContext: ReactApplicationContext) :
7882
*/
7983
override fun connect(params: ReadableMap?, promise: Promise?) {
8084

81-
val address:String = params?.getString("address").toString()
82-
val username:String = params?.getString("username").toString()
83-
val password:String = params?.getString("password").toString()
84-
if(address.isEmpty() || username.isEmpty() || password.isEmpty()){
85-
promise?.reject("ERR_CREDENTIALS","NO CREDENTIALS PROVIDED");
86-
return;
85+
try {
86+
87+
val address: String = params?.getString("address").toString()
88+
val username: String = params?.getString("username").toString()
89+
val password: String = params?.getString("password").toString()
90+
if (address.isEmpty() || username.isEmpty() || password.isEmpty()) {
91+
promise?.reject("ERR_CREDENTIALS", "NO CREDENTIALS PROVIDED");
92+
return;
93+
}
94+
95+
val openVPNConfigString: String = params?.getString("openVPNConfig").toString()
96+
val openVPNConfigLocalFile: String = params?.getString("openVPNConfigLocalFile").toString()
97+
98+
var openVPNConfigData = "";
99+
if (openVPNConfigString.isNotEmpty()) {
100+
openVPNConfigData = openVPNConfigString
101+
} else {
102+
openVPNConfigData = readFile(openVPNConfigLocalFile);
103+
}
104+
if (openVPNConfigData.isEmpty()) {
105+
promise?.reject("ERR_CONFIG", "NO CONFIG PROVIDED");
106+
return;
107+
}
108+
109+
//Start Parsing Config
110+
val cParser = ConfigParser()
111+
cParser.parseConfig(StringReader(openVPNConfigData));
112+
var openProfile: VpnProfile = cParser.convertProfile();
113+
114+
//Start Mapping Options.
115+
openProfile = populateVPNProfile(openProfile, params!!)
116+
117+
//check profile
118+
if (openProfile.checkProfile(reactApplicationContext) != R.string.no_error_found) {
119+
throw RemoteException(reactApplicationContext.getString(openProfile.checkProfile(reactApplicationContext)));
120+
}
121+
122+
123+
//Starting Connection
124+
ProfileManager.setTemporaryProfile(reactApplicationContext, openProfile);
125+
VPNLaunchHelper.startOpenVpn(openProfile, reactApplicationContext,"user requested",true);
126+
127+
128+
promise?.resolve(null);
129+
}catch (e:Exception){
130+
promise?.reject("ERR_PARSE","ERROR PARSING AND CONNECTING " + e.localizedMessage)
87131
}
88132

89-
val openVPNConfig:String = params?.getString("openVPNConfig").toString()
90-
val openVPNConfigLocalFile:String = params?.getString("openVPNConfigLocalFile").toString()
91133

92-
var openVPNConfigData = "";
93-
if(openVPNConfig.isNotEmpty()){
94-
openVPNConfigData = openVPNConfig
95-
}else {
96-
openVPNConfigData = readFile(openVPNConfigLocalFile);
97-
}
98-
if(openVPNConfigData.isEmpty()){
99-
promise?.reject("ERR_CONFIG","NO CONFIG PROVIDED");
100-
return;
101-
}
134+
}
102135

103-
val cParser:ConfigParser = ConfigParser()
104-
cParser.parseConfig(StringReader(openVPNConfigData));
105-
var openProfile:VpnProfile = cParser.convertProfile();
106136

107-
openProfile.mCompatMode = Utils.mapCompatMode()
108137

109138

139+
override fun getCurrentState(promise: Promise?) {
110140
}
111141

112-
override fun getCurrentState(promise: Promise?) {
142+
override fun requestCurrentState(promise: Promise?) {
143+
113144
}
114145

115146
override fun disconnect(promise: Promise?) {
@@ -160,4 +191,236 @@ class OpenvpnModule(reactContext: ReactApplicationContext) :
160191
return "";
161192
}
162193

194+
fun setUseOpenVPN3(enableOVPN3:Boolean){
195+
val prefs = Preferences.getDefaultSharedPreferences(reactApplicationContext)
196+
prefs.edit {
197+
putBoolean("ovpn3",enableOVPN3)
198+
}
199+
}
200+
201+
fun setUseSystemProxy(enableSystemProxy:Boolean){
202+
val prefs = Preferences.getDefaultSharedPreferences(reactApplicationContext)
203+
prefs.edit {
204+
putBoolean("usesystemproxy",enableSystemProxy)
205+
}
206+
}
207+
208+
fun setReconnectOnNetworkChange(enableReconnectOnNetworkChange:Boolean){
209+
val prefs = Preferences.getDefaultSharedPreferences(reactApplicationContext)
210+
prefs.edit {
211+
putBoolean("netchangereconnect",enableReconnectOnNetworkChange)
212+
}
213+
}
214+
215+
fun setPauseOnScreenOff(pauseOnScreenOff:Boolean){
216+
val prefs = Preferences.getDefaultSharedPreferences(reactApplicationContext)
217+
prefs.edit {
218+
putBoolean("screenoff",pauseOnScreenOff)
219+
}
220+
}
221+
222+
fun setDisableConfirmationDialogs(disableConfirmationDialogs:Boolean){
223+
val prefs = Preferences.getDefaultSharedPreferences(reactApplicationContext)
224+
prefs.edit {
225+
putBoolean("disableconfirmation",disableConfirmationDialogs)
226+
}
227+
}
228+
229+
fun setEncryptProfiles(encryptProfiles:Boolean){
230+
val prefs = Preferences.getDefaultSharedPreferences(reactApplicationContext)
231+
prefs.edit {
232+
putBoolean("preferencryption",encryptProfiles)
233+
}
234+
}
235+
236+
fun setKeepVPNConnected(keepVPNConnected:Boolean){
237+
val prefs = Preferences.getDefaultSharedPreferences(reactApplicationContext)
238+
prefs.edit {
239+
putBoolean("restartvpnonboot",keepVPNConnected)
240+
}
241+
}
242+
243+
244+
fun populateVPNProfile(vpnProfile:VpnProfile, params:ReadableMap):VpnProfile{
245+
var temporaryProfile = vpnProfile.copy("temporaryProfile")
246+
247+
//No Options, just send back profile.
248+
if(!params.hasKey("androidOptions")){
249+
return temporaryProfile
250+
}
251+
252+
val options = params.getMap("androidOptions")!!
253+
//Internal Settings
254+
if(options.hasKey("useOpenVPN3")){
255+
setUseOpenVPN3(options.getBoolean("useOpenVPN3"))
256+
}
257+
if(options.hasKey("useSystemProxy")){
258+
setUseSystemProxy(options.getBoolean("useSystemProxy"))
259+
}
260+
if(options.hasKey("useReconnectOnNetworkChange")){
261+
setReconnectOnNetworkChange(options.getBoolean("useReconnectOnNetworkChange"))
262+
}
263+
if(options.hasKey("usePauseOnScreenOff")){
264+
setPauseOnScreenOff(options.getBoolean("usePauseOnScreenOff"))
265+
}
266+
if(options.hasKey("useDisableConfirmDialog")){
267+
setPauseOnScreenOff(options.getBoolean("useDisableConfirmDialog"))
268+
}
269+
if(options.hasKey("useProfileEncryption")){
270+
setEncryptProfiles(options.getBoolean("useProfileEncryption"))
271+
}
272+
if(options.hasKey("useKeepVPNConnected")){
273+
setKeepVPNConnected(options.getBoolean("useKeepVPNConnected"))
274+
}
275+
276+
//Profile Settings
277+
if(options.hasKey("compatibilityMode")){
278+
temporaryProfile.mCompatMode = Utils.mapCompatMode(options.getInt("compatibilityMode"))
279+
}
280+
if(options.hasKey("useLegacyProvider")){
281+
temporaryProfile.mUseLegacyProvider = options.getBoolean("useLegacyProvider")
282+
}
283+
if(options.hasKey("useLZOCompression")){
284+
temporaryProfile.mUseLzo = options.getBoolean("useLZOCompression")
285+
}
286+
if(options.hasKey("checkPeerFingerprint")){
287+
temporaryProfile.mCheckPeerFingerprint = options.getBoolean("checkPeerFingerprint")
288+
}
289+
if(options.hasKey("peerFingerPrints")){
290+
temporaryProfile.mPeerFingerPrints = options.getString("peerFingerPrints")
291+
}
292+
if(options.hasKey("pullSettings")){
293+
temporaryProfile.mUsePull = options.getBoolean("pullSettings")
294+
}
295+
if(options.hasKey("ipv4")){
296+
temporaryProfile.mIPv4Address = options.getString("ipv4")
297+
}
298+
if(options.hasKey("ipv6")){
299+
temporaryProfile.mIPv6Address = options.getString("ipv6")
300+
}
301+
if(options.hasKey("noLocalBinding")){
302+
temporaryProfile.mNobind = options.getBoolean("noLocalBinding")
303+
}
304+
if(options.hasKey("overrideDNS")){
305+
temporaryProfile.mOverrideDNS = options.getBoolean("overrideDNS")
306+
}
307+
if(options.hasKey("searchDomain")){
308+
temporaryProfile.mSearchDomain = options.getString("searchDomain")
309+
}
310+
if(options.hasKey("DNS1")){
311+
temporaryProfile.mDNS1 = options.getString("DNS1")
312+
}
313+
if(options.hasKey("DNS2")){
314+
temporaryProfile.mDNS2 = options.getString("DNS2")
315+
}
316+
if(options.hasKey("ignorePushedRoutes")){
317+
temporaryProfile.mRoutenopull = options.getBoolean("ignorePushedRoutes")
318+
}
319+
if(options.hasKey("blockUnusedAddressFamilies")){
320+
temporaryProfile.mBlockUnusedAddressFamilies = options.getBoolean("blockUnusedAddressFamilies")
321+
}
322+
if(options.hasKey("allowLocalLAN")){
323+
temporaryProfile.mAllowLocalLAN = options.getBoolean("allowLocalLAN")
324+
}
325+
326+
327+
if(options.hasKey("useDefaultRoute")){
328+
temporaryProfile.mUseDefaultRoute = options.getBoolean("useDefaultRoute")
329+
}
330+
//set options if useDefaultRoute option disabled.
331+
if(!options.getBoolean("useDefaultRoute")){
332+
if(options.hasKey("customRoutes")){
333+
temporaryProfile.mCustomRoutes = options.getString("customRoutes")
334+
}
335+
if(options.hasKey("excludedRoutes")){
336+
temporaryProfile.mExcludedRoutes = options.getString("excludedRoutes")
337+
}
338+
}
339+
340+
if(options.hasKey("useDefaultRouteV6")){
341+
temporaryProfile.mUseDefaultRoutev6 = options.getBoolean("useDefaultRouteV6")
342+
}
343+
//set options if useDefaultRouteV6 option disabled.
344+
if(!options.getBoolean("useDefaultRoute")){
345+
if(options.hasKey("customRoutesV6")){
346+
temporaryProfile.mCustomRoutesv6 = options.getString("customRoutesV6")
347+
}
348+
if(options.hasKey("excludedRoutesV6")){
349+
temporaryProfile.mExcludedRoutesv6 = options.getString("excludedRoutesV6")
350+
}
351+
}
352+
353+
if(options.hasKey("allowedVPNApps")){
354+
for(app in options.getArray("allowedVPNApps")!!.toArrayList()){
355+
temporaryProfile.mAllowedAppsVpn.add(app.toString())
356+
}
357+
}
358+
if(options.hasKey("allowedVPNAppsAreDisallowed")){
359+
temporaryProfile.mAllowedAppsVpnAreDisallowed = options.getBoolean("allowedVPNAppsAreDisallowed")
360+
}
361+
if(options.hasKey("allowAppVpnBypass")){
362+
temporaryProfile.mAllowAppVpnBypass = options.getBoolean("allowAppVpnBypass")
363+
}
364+
365+
if(options.hasKey("tlsProfileSecurity")){
366+
temporaryProfile.mTlSCertProfile = options.getString("tlsProfileSecurity")
367+
}
368+
if(options.hasKey("expectServerTLSCert")){
369+
temporaryProfile.mExpectTLSCert = options.getBoolean("expectServerTLSCert")
370+
}
371+
if(options.hasKey("certificateHostnameCheck")){
372+
temporaryProfile.mCheckRemoteCN = options.getBoolean("certificateHostnameCheck")
373+
}
374+
if(options.hasKey("remoteCertificateSubject")){
375+
temporaryProfile.mRemoteCN = options.getString("remoteCertificateSubject")
376+
}
377+
if(options.hasKey("remoteX509UsernameField")){
378+
temporaryProfile.mx509UsernameField = options.getString("remoteX509UsernameField")
379+
}
380+
381+
if(options.hasKey("useTLSAuth")){
382+
temporaryProfile.mUseTLSAuth = options.getBoolean("useTLSAuth")
383+
}
384+
if(options.hasKey("dataCiphers")){
385+
temporaryProfile.mDataCiphers = options.getString("dataCiphers")
386+
}
387+
if(options.hasKey("packetDigests")){
388+
temporaryProfile.mAuth = options.getString("packetDigests")
389+
}
390+
391+
if(options.hasKey("persistTun")){
392+
temporaryProfile.mPersistTun = options.getBoolean("persistTun")
393+
}
394+
if(options.hasKey("pushPeerInfo")){
395+
temporaryProfile.mPushPeerInfo = options.getBoolean("pushPeerInfo")
396+
}
397+
if(options.hasKey("useRandomHostname")){
398+
temporaryProfile.mUseRandomHostname = options.getBoolean("useRandomHostname")
399+
}
400+
if(options.hasKey("useFloat")){
401+
temporaryProfile.mUseFloat = options.getBoolean("useFloat")
402+
}
403+
404+
if(options.hasKey("useCustomConfig")){
405+
temporaryProfile.mUseCustomConfig = options.getBoolean("useCustomConfig")
406+
}
407+
if(options.hasKey("customOptions")){
408+
temporaryProfile.mCustomConfigOptions = options.getString("customOptions")
409+
}
410+
411+
if(options.hasKey("connectRetryMax")){
412+
temporaryProfile.mConnectRetryMax = options.getString("connectRetryMax")
413+
}
414+
if(options.hasKey("connectRetryMaxTime")){
415+
temporaryProfile.mConnectRetryMaxTime = options.getString("connectRetryMaxTime")
416+
}
417+
if(options.hasKey("connectRetry")){
418+
temporaryProfile.mConnectRetry = options.getString("connectRetry")
419+
}
420+
421+
422+
423+
return temporaryProfile
424+
}
425+
163426
}

example/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export default function App() {
99
openVPNConfig: '',
1010
openVPNConfigLocalFile: '',
1111
androidOptions: {
12-
useLzoCompression: false,
12+
useLZOCompression: false,
1313
allowedVPNApps: [],
1414
},
1515
iOSOptions: {

0 commit comments

Comments
 (0)