summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcyberta <cyberta@riseup.net>2021-11-25 13:00:01 +0000
committercyberta <cyberta@riseup.net>2021-11-25 13:00:01 +0000
commit976843d09cc7455945bf42a3817445649fec7c05 (patch)
tree4a05965b62cdecae5e0630267adb09d51a13f667
parentdcee5f2fa1dc67e5b08223db3441da8bd38e8b20 (diff)
parentd939fc28aaa8f9992d296ddf596fa703ffd5ccb0 (diff)
Merge branch 'UDP_ui' into 'master'
UDP UI See merge request leap/bitmask_android!147
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java23
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java8
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java3
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java46
-rw-r--r--app/src/main/res/drawable-hdpi/ic_multiple_stop.pngbin0 -> 472 bytes
-rw-r--r--app/src/main/res/drawable-ldpi/ic_multiple_stop.pngbin0 -> 311 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_multiple_stop.pngbin0 -> 311 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_multiple_stop.pngbin0 -> 455 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_multiple_stop.pngbin0 -> 663 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_multiple_stop.pngbin0 -> 837 bytes
-rw-r--r--app/src/main/res/layout/f_settings.xml178
-rw-r--r--app/src/main/res/values/strings.xml3
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java12
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java182
-rw-r--r--app/src/test/resources/v4/multiport_tcpudp_eip-service.json67
16 files changed, 401 insertions, 123 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
index ed1e8b6d..7157d1cc 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
@@ -34,10 +34,12 @@ import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT;
import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES;
import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES;
import static se.leap.bitmaskclient.base.models.Constants.USE_IPv6_FIREWALL;
+import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferUDP;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getShowAlwaysOnDialog;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseBridges;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseSnowflake;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.hasSnowflakePrefs;
+import static se.leap.bitmaskclient.base.utils.PreferenceHelper.preferUDP;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useBridges;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useSnowflake;
@@ -63,10 +65,11 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh
View view = inflater.inflate(R.layout.f_settings, container, false);
initAlwaysOnVpnEntry(view);
initExcludeAppsEntry(view);
- initFirewallEntry(view);
- initTetheringEntry(view);
+ initPreferUDPEntry(view);
initUseBridgesEntry(view);
initUseSnowflakeEntry(view);
+ initFirewallEntry(view);
+ initTetheringEntry(view);
return view;
}
@@ -126,6 +129,22 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh
}
}
+ private void initPreferUDPEntry(View rootView) {
+ IconSwitchEntry useSnowflake = rootView.findViewById(R.id.prefer_udp);
+ useSnowflake.setVisibility(VISIBLE);
+ useSnowflake.setChecked(getPreferUDP(getContext()));
+ useSnowflake.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ if (!buttonView.isPressed()) {
+ return;
+ }
+ preferUDP(getContext(), isChecked);
+ if (VpnStatus.isVPNActive()) {
+ EipCommand.startVPN(getContext(), false);
+ showVPNFragment();
+ }
+ });
+ }
+
private void initExcludeAppsEntry(View rootView) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
IconTextEntry excludeApps = rootView.findViewById(R.id.exclude_apps);
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java
index 016a8563..468b1b01 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java
@@ -42,6 +42,7 @@ public interface Constants {
String LAST_UPDATE_CHECK = "last_update_check";
String PREFERRED_CITY = "preferred_city";
String USE_SNOWFLAKE = "use_snowflake";
+ String PREFER_UDP = "prefer_UDP";
//////////////////////////////////////////////
@@ -163,6 +164,7 @@ public interface Constants {
String REMOTE = "remote";
String PORTS = "ports";
String PROTOCOLS = "protocols";
+ String UDP = "udp";
String CAPABILITIES = "capabilities";
String TRANSPORT = "transport";
String TYPE = "type";
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java
index 515ec282..fe9100cb 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java
@@ -29,6 +29,7 @@ import static se.leap.bitmaskclient.base.models.Constants.EXCLUDED_APPS;
import static se.leap.bitmaskclient.base.models.Constants.LAST_UPDATE_CHECK;
import static se.leap.bitmaskclient.base.models.Constants.LAST_USED_PROFILE;
import static se.leap.bitmaskclient.base.models.Constants.PREFERRED_CITY;
+import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_CONFIGURED;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY;
@@ -145,6 +146,13 @@ public class PreferenceHelper {
return getBoolean(context, RESTART_ON_UPDATE, false);
}
+ public static boolean getPreferUDP(Context context) {
+ return getBoolean(context, PREFER_UDP, false);
+ }
+
+ public static void preferUDP(Context context, boolean prefer) {
+ putBoolean(context, PREFER_UDP, prefer);
+ }
public static boolean getUseBridges(SharedPreferences preferences) {
return preferences.getBoolean(USE_BRIDGES, false);
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
index a3d3abbc..60507363 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
@@ -174,7 +174,8 @@ public class Gateway {
*/
private @NonNull HashMap<Connection.TransportType, VpnProfile> createVPNProfiles(Context context)
throws ConfigParser.ConfigParseError, IOException, JSONException {
- VpnConfigGenerator vpnConfigurationGenerator = new VpnConfigGenerator(generalConfiguration, secrets, gateway, apiVersion);
+ boolean preferUDP = PreferenceHelper.getPreferUDP(context);
+ VpnConfigGenerator vpnConfigurationGenerator = new VpnConfigGenerator(generalConfiguration, secrets, gateway, apiVersion, preferUDP);
HashMap<Connection.TransportType, VpnProfile> profiles = vpnConfigurationGenerator.generateVpnProfiles();
addProfileInfos(context, profiles);
return profiles;
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
index d72f0936..303959d0 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
@@ -48,6 +48,7 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICA
import static se.leap.bitmaskclient.base.models.Constants.REMOTE;
import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT;
import static se.leap.bitmaskclient.base.models.Constants.TYPE;
+import static se.leap.bitmaskclient.base.models.Constants.UDP;
import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_IP;
import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_PORT;
@@ -57,16 +58,18 @@ public class VpnConfigGenerator {
private JSONObject secrets;
private JSONObject obfs4Transport;
private int apiVersion;
+ private boolean preferUDP;
public final static String TAG = VpnConfigGenerator.class.getSimpleName();
private final String newLine = System.getProperty("line.separator"); // Platform new line
- public VpnConfigGenerator(JSONObject generalConfiguration, JSONObject secrets, JSONObject gateway, int apiVersion) throws ConfigParser.ConfigParseError {
+ public VpnConfigGenerator(JSONObject generalConfiguration, JSONObject secrets, JSONObject gateway, int apiVersion, boolean preferUDP) throws ConfigParser.ConfigParseError {
this.generalConfiguration = generalConfiguration;
this.gateway = gateway;
this.secrets = secrets;
this.apiVersion = apiVersion;
+ this.preferUDP = preferUDP;
checkCapabilities();
}
@@ -174,7 +177,7 @@ public class VpnConfigGenerator {
default:
case 1:
case 2:
- ipAddress = gateway.getString(IP_ADDRESS);
+ ipAddress = gateway.getString(IP_ADDRESS);
gatewayConfigApiv1(stringBuilder, ipAddress, capabilities);
break;
case 3:
@@ -213,9 +216,9 @@ public class VpnConfigGenerator {
int port;
String protocol;
JSONArray ports = capabilities.getJSONArray(PORTS);
+ JSONArray protocols = capabilities.getJSONArray(PROTOCOLS);
for (int i = 0; i < ports.length(); i++) {
port = ports.getInt(i);
- JSONArray protocols = capabilities.getJSONArray(PROTOCOLS);
for (int j = 0; j < protocols.length(); j++) {
protocol = protocols.optString(j);
String newRemote = REMOTE + " " + ipAddress + " " + port + " " + protocol + newLine;
@@ -229,14 +232,35 @@ public class VpnConfigGenerator {
String protocol;
JSONObject openvpnTransport = getTransport(transports, OPENVPN);
JSONArray ports = openvpnTransport.getJSONArray(PORTS);
- for (int j = 0; j < ports.length(); j++) {
- port = ports.getString(j);
- JSONArray protocols = openvpnTransport.getJSONArray(PROTOCOLS);
- for (int k = 0; k < protocols.length(); k++) {
- protocol = protocols.optString(k);
- for (String ipAddress : ipAddresses) {
- String newRemote = REMOTE + " " + ipAddress + " " + port + " " + protocol + newLine;
- stringBuilder.append(newRemote);
+ JSONArray protocols = openvpnTransport.getJSONArray(PROTOCOLS);
+ if (preferUDP) {
+ StringBuilder udpRemotes = new StringBuilder();
+ StringBuilder tcpRemotes = new StringBuilder();
+ for (int i = 0; i < protocols.length(); i++) {
+ protocol = protocols.optString(i);
+ for (int j = 0; j < ports.length(); j++) {
+ port = ports.optString(j);
+ for (String ipAddress : ipAddresses) {
+ String newRemote = REMOTE + " " + ipAddress + " " + port + " " + protocol + newLine;
+ if (UDP.equals(protocol)) {
+ udpRemotes.append(newRemote);
+ } else {
+ tcpRemotes.append(newRemote);
+ }
+ }
+ }
+ }
+ stringBuilder.append(udpRemotes.toString());
+ stringBuilder.append(tcpRemotes.toString());
+ } else {
+ for (int j = 0; j < ports.length(); j++) {
+ port = ports.getString(j);
+ for (int k = 0; k < protocols.length(); k++) {
+ protocol = protocols.optString(k);
+ for (String ipAddress : ipAddresses) {
+ String newRemote = REMOTE + " " + ipAddress + " " + port + " " + protocol + newLine;
+ stringBuilder.append(newRemote);
+ }
}
}
}
diff --git a/app/src/main/res/drawable-hdpi/ic_multiple_stop.png b/app/src/main/res/drawable-hdpi/ic_multiple_stop.png
new file mode 100644
index 00000000..cd67c160
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_multiple_stop.png
Binary files differ
diff --git a/app/src/main/res/drawable-ldpi/ic_multiple_stop.png b/app/src/main/res/drawable-ldpi/ic_multiple_stop.png
new file mode 100644
index 00000000..fc0a47e1
--- /dev/null
+++ b/app/src/main/res/drawable-ldpi/ic_multiple_stop.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_multiple_stop.png b/app/src/main/res/drawable-mdpi/ic_multiple_stop.png
new file mode 100644
index 00000000..fc0a47e1
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_multiple_stop.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_multiple_stop.png b/app/src/main/res/drawable-xhdpi/ic_multiple_stop.png
new file mode 100644
index 00000000..c16a18c1
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_multiple_stop.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_multiple_stop.png b/app/src/main/res/drawable-xxhdpi/ic_multiple_stop.png
new file mode 100644
index 00000000..b6fe22a8
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_multiple_stop.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_multiple_stop.png b/app/src/main/res/drawable-xxxhdpi/ic_multiple_stop.png
new file mode 100644
index 00000000..6cf3f58b
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_multiple_stop.png
Binary files differ
diff --git a/app/src/main/res/layout/f_settings.xml b/app/src/main/res/layout/f_settings.xml
index b625d548..a4d86fa6 100644
--- a/app/src/main/res/layout/f_settings.xml
+++ b/app/src/main/res/layout/f_settings.xml
@@ -1,105 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/stdpadding"
>
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/general_header"
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.AppCompat.Title"
- android:text="@string/vpn_settings"
- android:paddingTop="@dimen/activity_margin"
- />
+ android:orientation="vertical">
- <se.leap.bitmaskclient.base.views.IconTextEntry
- android:id="@+id/always_on_vpn"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:text="@string/always_on_vpn"
- app:subtitle="@string/subtitle_always_on_vpn"
- app:icon="@drawable/ic_always_on_36"
- android:visibility="visible"
- />
+ <androidx.appcompat.widget.AppCompatTextView
+ android:id="@+id/general_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.AppCompat.Title"
+ android:text="@string/vpn_settings"
+ android:paddingTop="@dimen/activity_margin"
+ />
- <se.leap.bitmaskclient.base.views.IconTextEntry
- android:id="@+id/exclude_apps"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:text="@string/exclude_apps_fragment_title"
- app:icon="@drawable/ic_shield_remove_grey600_36dp"
- android:visibility="visible"
- />
+ <se.leap.bitmaskclient.base.views.IconTextEntry
+ android:id="@+id/always_on_vpn"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:text="@string/always_on_vpn"
+ app:subtitle="@string/subtitle_always_on_vpn"
+ app:icon="@drawable/ic_always_on_36"
+ android:visibility="visible"
+ />
- <!-- <se.leap.bitmaskclient.base.views.IconSwitchEntry
- android:id="@+id/prefer_udp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:text="@string/prefer_udp"
- app:subtitle="@string/prefer_udp_subtitle"
- app:icon="@drawable/ic_multiple_stop"
- app:singleLine="false"
- />
- -->
+ <se.leap.bitmaskclient.base.views.IconTextEntry
+ android:id="@+id/exclude_apps"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:text="@string/exclude_apps_fragment_title"
+ app:icon="@drawable/ic_shield_remove_grey600_36dp"
+ android:visibility="visible"
+ />
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/circumvention_header"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.AppCompat.Title"
- android:text="@string/censorship_circumvention"
- android:paddingTop="@dimen/activity_margin"
- />
- <se.leap.bitmaskclient.base.views.IconSwitchEntry
- android:id="@+id/bridges_switch"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:text="@string/nav_drawer_obfuscated_connection"
- app:subtitle="@string/nav_drawer_subtitle_obfuscated_connection"
- app:icon="@drawable/ic_bridge_36"
- app:singleLine="false"
- />
+ <se.leap.bitmaskclient.base.views.IconSwitchEntry
+ android:id="@+id/prefer_udp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:text="@string/prefer_udp"
+ app:subtitle="@string/prefer_udp_subtitle"
+ app:icon="@drawable/ic_multiple_stop"
+ app:singleLine="false"
+ />
- <se.leap.bitmaskclient.base.views.IconSwitchEntry
- android:id="@+id/snowflake_switch"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:icon="@drawable/ic_snowflake"
- app:text="@string/use_snowflake"
- app:subtitle="@string/snowflake_description"
- app:singleLine="false"
- />
+ <androidx.appcompat.widget.AppCompatTextView
+ android:id="@+id/circumvention_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.AppCompat.Title"
+ android:text="@string/censorship_circumvention"
+ android:paddingTop="@dimen/activity_margin"
+ />
+ <se.leap.bitmaskclient.base.views.IconSwitchEntry
+ android:id="@+id/bridges_switch"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:text="@string/nav_drawer_obfuscated_connection"
+ app:subtitle="@string/nav_drawer_subtitle_obfuscated_connection"
+ app:icon="@drawable/ic_bridge_36"
+ app:singleLine="false"
+ />
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/experimental_header"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textAppearance="@style/TextAppearance.AppCompat.Title"
- android:text="@string/experimental_features"
- android:paddingTop="@dimen/activity_margin"
- />
+ <se.leap.bitmaskclient.base.views.IconSwitchEntry
+ android:id="@+id/snowflake_switch"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:icon="@drawable/ic_snowflake"
+ app:text="@string/use_snowflake"
+ app:subtitle="@string/snowflake_description"
+ app:singleLine="false"
+ />
+ <androidx.appcompat.widget.AppCompatTextView
+ android:id="@+id/experimental_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.AppCompat.Title"
+ android:text="@string/experimental_features"
+ android:paddingTop="@dimen/activity_margin"
+ />
- <se.leap.bitmaskclient.base.views.IconSwitchEntry
- android:id="@+id/enableIPv6Firewall"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:text="@string/ipv6Firewall"
- app:subtitle="@string/require_root"
- app:icon="@drawable/ic_cancel"
- />
- <se.leap.bitmaskclient.base.views.IconTextEntry
- android:id="@+id/tethering"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:text="@string/tethering"
- app:subtitle="@string/require_root"
- app:icon="@drawable/ic_access_point_36"
- />
+ <se.leap.bitmaskclient.base.views.IconSwitchEntry
+ android:id="@+id/enableIPv6Firewall"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:text="@string/ipv6Firewall"
+ app:subtitle="@string/require_root"
+ app:icon="@drawable/ic_cancel"
+ />
+
+ <se.leap.bitmaskclient.base.views.IconTextEntry
+ android:id="@+id/tethering"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:text="@string/tethering"
+ app:subtitle="@string/require_root"
+ app:icon="@drawable/ic_access_point_36"
+ />
-</LinearLayout> \ No newline at end of file
+ </LinearLayout>
+</ScrollView> \ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c49a456e..9ef0b9a5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -188,5 +188,8 @@
<string name="use_snowflake">Use Snowflake</string>
<string name="snowflake_description">Circumvent blocking of the provider\'s configuration server.</string>
<string name="vpn_settings">VPN settings</string>
+ <string name="prefer_udp">Use UDP if available</string>
+ <string name="prefer_udp_subtitle">UDP can be faster and better for streaming, but does not work for all networks.</string>
+
</resources>
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java
index 43a6a496..a3cde58b 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java
@@ -114,7 +114,7 @@ public class GatewaysManagerTest {
MockHelper.mockProviderObservable(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
- VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3);
+ VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false);
VpnProfile profile = configGenerator.createProfile(OBFS4);
profile.mGatewayIp = "37.218.247.60";
@@ -129,7 +129,7 @@ public class GatewaysManagerTest {
MockHelper.mockProviderObservable(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
- VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3);
+ VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false);
VpnProfile profile = configGenerator.createProfile(OPENVPN);
profile.mGatewayIp = "37.218.247.60";
@@ -144,7 +144,7 @@ public class GatewaysManagerTest {
MockHelper.mockProviderObservable(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
- VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3);
+ VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false);
VpnProfile profile = configGenerator.createProfile(OBFS4);
profile.mGatewayIp = "37.218.247.60";
@@ -159,7 +159,7 @@ public class GatewaysManagerTest {
MockHelper.mockProviderObservable(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
- VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3);
+ VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false);
VpnProfile profile = configGenerator.createProfile(OPENVPN);
profile.mGatewayIp = "37.218.247.60";
@@ -174,7 +174,7 @@ public class GatewaysManagerTest {
MockHelper.mockProviderObservable(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
- VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3);
+ VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false);
VpnProfile profile = configGenerator.createProfile(OBFS4);
profile.mGatewayIp = "37.218.247.61";
@@ -189,7 +189,7 @@ public class GatewaysManagerTest {
MockHelper.mockProviderObservable(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
- VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3);
+ VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false);
VpnProfile profile = configGenerator.createProfile(OBFS4);
profile.mGatewayIp = "3.21.247.89";
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
index 56575556..4bacd81a 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
@@ -12,7 +12,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
-import org.mockito.internal.util.StringUtil;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@@ -1016,6 +1015,138 @@ public class VpnConfigGeneratorTest {
"sndbuf 0 \n" +
"rcvbuf 0 \n";
+ String expectedVPNConfig_v4_ovpn_multiport_tcpudp = "# Config for OpenVPN 2.x\n" +
+ "# Enables connection to GUI\n" +
+ "management /data/data/se.leap.bitmask/mgmtsocket unix\n" +
+ "management-client\n" +
+ "management-query-passwords\n" +
+ "management-hold\n" +
+ "\n" +
+ "setenv IV_GUI_VER \"se.leap.bitmaskclient 0.9.10\" \n" +
+ "setenv IV_PLAT_VER \"0 null JUNIT null null null\"\n" +
+ "machine-readable-output\n" +
+ "allow-recursive-routing\n" +
+ "ifconfig-nowarn\n" +
+ "client\n" +
+ "verb 4\n" +
+ "connect-retry 2 300\n" +
+ "resolv-retry 60\n" +
+ "dev tun\n" +
+ "remote 2001:db8:123::1056 53 udp\n" +
+ "remote 37.218.247.60 53 udp\n" +
+ "remote 2001:db8:123::1056 80 udp\n" +
+ "remote 37.218.247.60 80 udp\n" +
+ "remote 2001:db8:123::1056 1194 udp\n" +
+ "remote 37.218.247.60 1194 udp\n" +
+ "remote 2001:db8:123::1056 53 tcp-client\n" +
+ "remote 37.218.247.60 53 tcp-client\n" +
+ "remote 2001:db8:123::1056 80 tcp-client\n" +
+ "remote 37.218.247.60 80 tcp-client\n" +
+ "remote 2001:db8:123::1056 1194 tcp-client\n" +
+ "remote 37.218.247.60 1194 tcp-client\n" +
+ "<ca>\n" +
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\n" +
+ "YXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNVBAsME2h0dHBzOi8v\n" +
+ "Yml0bWFzay5uZXQwHhcNMTIxMTA2MDAwMDAwWhcNMjIxMTA2MDAwMDAwWjBKMRgw\n" +
+ "FgYDVQQDDA9CaXRtYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNV\n" +
+ "BAsME2h0dHBzOi8vYml0bWFzay5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\n" +
+ "ggIKAoICAQC1eV4YvayaU+maJbWrD4OHo3d7S1BtDlcvkIRS1Fw3iYDjsyDkZxai\n" +
+ "dHp4EUasfNQ+EVtXUvtk6170EmLco6Elg8SJBQ27trE6nielPRPCfX3fQzETRfvB\n" +
+ "7tNvGw4Jn2YKiYoMD79kkjgyZjkJ2r/bEHUSevmR09BRp86syHZerdNGpXYhcQ84\n" +
+ "CA1+V+603GFIHnrP+uQDdssW93rgDNYu+exT+Wj6STfnUkugyjmPRPjL7wh0tzy+\n" +
+ "znCeLl4xiV3g9sjPnc7r2EQKd5uaTe3j71sDPF92KRk0SSUndREz+B1+Dbe/RGk4\n" +
+ "MEqGFuOzrtsgEhPIX0hplhb0Tgz/rtug+yTT7oJjBa3u20AAOQ38/M99EfdeJvc4\n" +
+ "lPFF1XBBLh6X9UKF72an2NuANiX6XPySnJgZ7nZ09RiYZqVwu/qt3DfvLfhboq+0\n" +
+ "bQvLUPXrVDr70onv5UDjpmEA/cLmaIqqrduuTkFZOym65/PfAPvpGnt7crQj/Ibl\n" +
+ "DEDYZQmP7AS+6zBjoOzNjUGE5r40zWAR1RSi7zliXTu+yfsjXUIhUAWmYR6J3KxB\n" +
+ "lfsiHBQ+8dn9kC3YrUexWoOqBiqJOAJzZh5Y1tqgzfh+2nmHSB2dsQRs7rDRRlyy\n" +
+ "YMbkpzL9ZsOUO2eTP1mmar6YjCN+rggYjRrX71K2SpBG6b1zZxOG+wIDAQABo2Aw\n" +
+ "XjAdBgNVHQ4EFgQUuYGDLL2sswnYpHHvProt1JU+D48wDgYDVR0PAQH/BAQDAgIE\n" +
+ "MAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUuYGDLL2sswnYpHHvProt1JU+D48w\n" +
+ "DQYJKoZIhvcNAQENBQADggIBADeG67vaFcbITGpi51264kHPYPEWaXUa5XYbtmBl\n" +
+ "cXYyB6hY5hv/YNuVGJ1gWsDmdeXEyj0j2icGQjYdHRfwhrbEri+h1EZOm1cSBDuY\n" +
+ "k/P5+ctHyOXx8IE79DBsZ6IL61UKIaKhqZBfLGYcWu17DVV6+LT+AKtHhOrv3TSj\n" +
+ "RnAcKnCbKqXLhUPXpK0eTjPYS2zQGQGIhIy9sQXVXJJJsGrPgMxna1Xw2JikBOCG\n" +
+ "htD/JKwt6xBmNwktH0GI/LVtVgSp82Clbn9C4eZN9E5YbVYjLkIEDhpByeC71QhX\n" +
+ "EIQ0ZR56bFuJA/CwValBqV/G9gscTPQqd+iETp8yrFpAVHOW+YzSFbxjTEkBte1J\n" +
+ "aF0vmbqdMAWLk+LEFPQRptZh0B88igtx6tV5oVd+p5IVRM49poLhuPNJGPvMj99l\n" +
+ "mlZ4+AeRUnbOOeAEuvpLJbel4rhwFzmUiGoeTVoPZyMevWcVFq6BMkS+jRR2w0jK\n" +
+ "G6b0v5XDHlcFYPOgUrtsOBFJVwbutLvxdk6q37kIFnWCd8L3kmES5q4wjyFK47Co\n" +
+ "Ja8zlx64jmMZPg/t3wWqkZgXZ14qnbyG5/lGsj5CwVtfDljrhN0oCWK1FZaUmW3d\n" +
+ "69db12/g4f6phldhxiWuGC/W6fCW5kre7nmhshcltqAJJuU47iX+DarBFiIj816e\n" +
+ "yV8e\n" +
+ "-----END CERTIFICATE-----\n" +
+ "\n" +
+ "</ca>\n" +
+ "<key>\n" +
+ "-----BEGIN RSA PRIVATE KEY-----\n" +
+ "MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDUTYWeGgsHS+fjijmziniNqw6h\n" +
+ "MBpyK4S/cM6PxV28C33VuOWPTMcIYesctjZANWFCggfFTQSjV5Qaxq9UK4i27tayLbCdlVS6hpbl\n" +
+ "Vf4DuI3Gj1Pv1rtITBShtvCf3T7yBnjW4wVpOpsUAAOViKUSvUU3kPPMFWhiGQw8yHYr82ts6XMo\n" +
+ "jwMoonW5Ml4e7C7Cr22QesC63q7emNcpUd0pZGT9C33RgDAHZDMrlyjo4HEp1JbUfB0gbmXElJbE\n" +
+ "1TNdZ62HhgmMjzTUN1GGrQ1t91AEoEQwaK65o4YSj+yFv6KXZZz5OWaz94tKiN9v26EXtBFmRlyb\n" +
+ "6+D9ynSd9LghAgMBAAECggEBANPHLRXkhsHVj1EkzqBx7gXr8CEMmiTvknFh9zvltrZhhDoRQjWr\n" +
+ "chPDkcRHY2Cznvy4N0YyqQDD2ULIlZdSAgPxxothFoBruWSD47yMBmLx08ORsDpcqt/YvPAATJI8\n" +
+ "IpFNsXcyaXBp/M57oRemgnxp/8UJPJmFdWX99H4hvffh/jdj7POgYiWUaAl37XTYZKZ4nzKU2wpL\n" +
+ "EDLj9RKPz9gG7CYp2zrLC9LaAsrXVrKwPBw6g+XwbClaqFj97db3mrY4lr6mTo89qmus1AU+fBDH\n" +
+ "3Xlpmc8JwB+30TvhRNKrpLx9cEjuEj7K1gm8Y4dWCjPi+lNbtAyUBcgPJFa/81ECgYEA7pLoBU/Y\n" +
+ "ZYjyHFca8FvDBcBh6haHfqJr9doXWtgjDrbi3o2n5wHqfKhFWOH6vPEQozkOVeX1ze6HOiRmGBpW\n" +
+ "r+r7x8TD25L7I6HJw3M351RWOAfkF0w/RTVdetcTgduQtfN1u6BDhYSVceXMjyQYx7MhfETWI8Gh\n" +
+ "KSYm8OEDYiUCgYEA489fmbrCcUnXzpTsbswJ5NmSoEXbcX8cLxnQuzE0z9GHhQdrMjOpXR76reTW\n" +
+ "6jcuudarNcwRUYSWWhjCDKHhpx4HhasWPaHgr7jIzcRw8yZSJRSxKr8sl1qh6g7s47JcmfXOMWLt\n" +
+ "yuyE933XrT19Th4ODZHY40Uv35mPjMi9d00CgYEAyRNAQtndBRa7GG/B4Ls2T+6pl+aNJIo4e+no\n" +
+ "rURlp800wWabEPRocdBRQmyULBLxduBr2LIMzhgwGSz8b2wji/l9ZA3PFY135bxClVzSzUIjuO3N\n" +
+ "rGUzHl2wAAyuAFDSUshzfkPBJRNt8aVBF5PQ3t93ZYmPAmv8LPZe875yX5ECgYEAsUEcwK/ZNW7g\n" +
+ "dQPZR4iJNkC4Xu6cBZ6Cnn92swBheEYvLSoNlX0vDZ7aLE3/jzQqrjzC8NP8sbH5jtbuvgeDXZX3\n" +
+ "AmGRp5j6C6A61ihAPmEVz3ZfN8SSfJ3vl//PAIg6lyz0J+cy4Q7RkwSeuVQ72Hl4M8TEvmmKC3Af\n" +
+ "ispy6Y0CgYEAgl1o2lo+ACyk+oVQPaaPqK3d7WOBFp4eR2nXFor/vsx9igQOlZUgzRDQsR8jo1o9\n" +
+ "efOSBf87igrZGgssys89pWa2dnXnz5PMmzkKr6bw4D9Ez6u6Puc9UZhGw/8wDYg6fSosdB9utspm\n" +
+ "M698ycef7jBNMDgmhpSvfw5GctoNQ4s=\n" +
+ "-----END RSA PRIVATE KEY-----\n" +
+ "</key>\n" +
+ "<cert>\n" +
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIEjDCCAnSgAwIBAgIQG6MBp/cd9DlY+7cdvp3R3jANBgkqhkiG9w0BAQsFADBmMRAwDgYDVQQK\n" +
+ "DAdCaXRtYXNrMRwwGgYDVQQLDBNodHRwczovL2JpdG1hc2submV0MTQwMgYDVQQDDCtCaXRtYXNr\n" +
+ "IFJvb3QgQ0EgKGNsaWVudCBjZXJ0aWZpY2F0ZXMgb25seSEpMB4XDTE0MTIwNTAwMDAwMFoXDTE1\n" +
+ "MDMwNTAwMDAwMFowLTErMCkGA1UEAwwiVU5MSU1JVEVEZDBwZDdkMzE4eTNtOHNkeXllaTFqYmZl\n" +
+ "eDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANRNhZ4aCwdL5+OKObOKeI2rDqEwGnIr\n" +
+ "hL9wzo/FXbwLfdW45Y9Mxwhh6xy2NkA1YUKCB8VNBKNXlBrGr1QriLbu1rItsJ2VVLqGluVV/gO4\n" +
+ "jcaPU+/Wu0hMFKG28J/dPvIGeNbjBWk6mxQAA5WIpRK9RTeQ88wVaGIZDDzIdivza2zpcyiPAyii\n" +
+ "dbkyXh7sLsKvbZB6wLrert6Y1ylR3SlkZP0LfdGAMAdkMyuXKOjgcSnUltR8HSBuZcSUlsTVM11n\n" +
+ "rYeGCYyPNNQ3UYatDW33UASgRDBorrmjhhKP7IW/opdlnPk5ZrP3i0qI32/boRe0EWZGXJvr4P3K\n" +
+ "dJ30uCECAwEAAaNvMG0wHQYDVR0OBBYEFK8bMVAM4GBB5sHptoIOAaIvlYueMAsGA1UdDwQEAwIH\n" +
+ "gDATBgNVHSUEDDAKBggrBgEFBQcDAjAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFId+E7bsWFsUWah9\n" +
+ "vZuPvZ7O+aJsMA0GCSqGSIb3DQEBCwUAA4ICAQAQOX81csVhvP422NKkZH7+g3npBpl+sEHedaGR\n" +
+ "xYPOu4HrA4TVF9h44sljRoRJyenGNdBZCXcLKHg889eePTf8Z5K3lTojp6hvwyA6tgxOMHT1kESW\n" +
+ "PfqnRw8mHfHJuE3g+4YNUMwggzwc/VZATdV/7M33sarVN9AUOHou9n9BizgCC+UnYlS+F2POumE3\n" +
+ "FbOhKo5uubI02MwBYlN2JVO2TBt1Q20w8wc6cU07Xi5Epp+1mkgFiOShkNtPcJmEyBWJhxDtSDOW\n" +
+ "2doqWYNqH2kq7B5R/kyyfcpFJqAnBTV7xs+C5rTS1mW7LpxfdCUMbYuLCpyxpO3A/DhAm8n47tUH\n" +
+ "lBtmo8Avdb8VdFpYiGBpB0o9kTFcsWFb2GkWFBduGfSEB8jUI7QtqhgZqocAKK/cweSRV8FwyUcn\n" +
+ "R0prRm3QEi9fbXqEddzjSY9y/lqWYzT7u+IOAQpKroeZ4wzgYperDNOUFuYk1rP7yuvjP2pV5rcN\n" +
+ "yPoBP60TPVWMRM4WJm6nTogAz2qBrFsf/XwT/ajzbsjT6HNB7QbRE+wkFkqspoXG5Agp7KQ8lW3L\n" +
+ "SKCDGOQJz7VIE85pD0tg7QEXBEw8oaRZtMjQ0Gvs25mxXAKka4wGasaWfYH6d0E+iKYcWn86V1rH\n" +
+ "K2ZoknT+Nno5jgjFuUR3fZseNizEfx7BteooKQ==\n" +
+ "-----END CERTIFICATE-----\n" +
+ "</cert>\n" +
+ "crl-verify file missing in config profile\n" +
+ "comp-lzo\n" +
+ "nobind\n"+
+ "remote-cert-tls server\n" +
+ "data-ciphers AES-256-GCM:AES-128-GCM:AES-256-CBC\n" +
+ "cipher AES-256-CBC\n" +
+ "auth SHA1\n" +
+ "persist-tun\n" +
+ "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" +
+ "preresolve\n" +
+ "# Custom configuration options\n" +
+ "# You are on your on own here :)\n" +
+ "# These options found in the config file do not map to config settings:\n" +
+ "keepalive 10 30 \n" +
+ "tls-cipher DHE-RSA-AES128-SHA \n" +
+ "sndbuf 0 \n" +
+ "rcvbuf 0 \n";
@Before
@@ -1035,7 +1166,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_v1_tcp_udp() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_tcp_udp.json")));
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertFalse(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_tcp_udp.trim()));
@@ -1044,7 +1175,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_v1_udp_tcp() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_udp_tcp.json")));
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertFalse(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_udp_tcp.trim()));
@@ -1053,7 +1184,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_v2_tcp_udp() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_tcp_udp.json")));
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertFalse(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_tcp_udp.trim()));
@@ -1062,7 +1193,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_v2_udp_tcp() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_udp_tcp.json")));
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertFalse(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_udp_tcp.trim()));
@@ -1072,7 +1203,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_v3_obfs4() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0);
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.containsKey(OPENVPN));
@@ -1083,7 +1214,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_v3_ovpn_tcp_udp() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_pt_tcp_udp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0);
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.containsKey(OPENVPN));
@@ -1094,7 +1225,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_v3_ovpn_udp_tcp() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_pt_udp_tcp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0);
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.containsKey(OPENVPN));
@@ -1107,7 +1238,7 @@ public class VpnConfigGeneratorTest {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_pt_udp_tcp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0);
//delete "data-ciphers" from config to test if the resulting openvpn config file will contain the default value taken from "cipher" flag
generalConfig.put("data-ciphers", null);
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.containsKey(OPENVPN));
@@ -1119,7 +1250,7 @@ public class VpnConfigGeneratorTest {
public void testGenerateVpnProfile_v4_ovpn_tcp_udp() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/ptdemo_pt_tcp_udp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/ptdemo_pt_tcp_udp.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION);
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 4);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 4, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.containsKey(OPENVPN));
@@ -1131,7 +1262,7 @@ public class VpnConfigGeneratorTest {
public void testGenerateVpnProfile_v4_ovpn_udp_tcp() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/ptdemo_pt_udp_tcp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/ptdemo_pt_udp_tcp.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION);
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 4);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 4, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.containsKey(OPENVPN));
@@ -1144,7 +1275,7 @@ public class VpnConfigGeneratorTest {
public void testGenerateVpnProfile_v3_ipv6only_allowOpenvpnIPv6Only() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_ipv6.json"))).getJSONArray("gateways").getJSONObject(0);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_ipv6.json"))).getJSONObject(OPENVPN_CONFIGURATION);
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OPENVPN));
}
@@ -1153,16 +1284,19 @@ public class VpnConfigGeneratorTest {
public void testGenerateVpnProfile_v3_obfs4IPv6_skip() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_ipv6.json"))).getJSONArray("gateways").getJSONObject(0);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_ipv6.json"))).getJSONObject(OPENVPN_CONFIGURATION);
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertFalse(vpnProfiles.containsKey(OBFS4));
}
+ /**
+ * obfs4 cannot be used with ipv6 addresses currently
+ */
@Test
public void testGenerateVpnProfile_v3_obfs4IPv4AndIPv6_skipIPv6() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_ipv4ipv6.json"))).getJSONArray("gateways").getJSONObject(0);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_ipv4ipv6.json"))).getJSONObject(OPENVPN_CONFIGURATION);
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.containsKey(OPENVPN));
@@ -1170,11 +1304,14 @@ public class VpnConfigGeneratorTest {
assertEquals("37.218.247.60/32", vpnProfiles.get(OBFS4).mExcludedRoutes.trim());
}
+ /**
+ * obfs4 cannot be used with UDP
+ */
@Test
public void testGenerateVpnProfile_v3_obfs4udp_skip() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_udp.json"))).getJSONArray("gateways").getJSONObject(0);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_udp.json"))).getJSONObject(OPENVPN_CONFIGURATION);
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertFalse(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.containsKey(OPENVPN));
@@ -1184,7 +1321,7 @@ public class VpnConfigGeneratorTest {
public void testGenerateVpnProfile_v3_obfs4UDPAndTCP_skipUDP() throws Exception {
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_udptcp.json"))).getJSONArray("gateways").getJSONObject(0);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_udptcp.json"))).getJSONObject(OPENVPN_CONFIGURATION);
- vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OBFS4));
assertTrue(vpnProfiles.containsKey(OPENVPN));
@@ -1192,4 +1329,17 @@ public class VpnConfigGeneratorTest {
assertFalse(vpnProfiles.get(OBFS4).mConnections[0].isUseUdp());
}
+ @Test
+ public void testGenerateVpnProfile_preferUDP_firstRemotesUDP() throws Exception {
+ gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/multiport_tcpudp_eip-service.json"))).getJSONArray("gateways").getJSONObject(0);
+ generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/multiport_tcpudp_eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION);
+ vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, true);
+ HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
+ assertTrue(vpnProfiles.containsKey(OBFS4));
+ assertTrue(vpnProfiles.containsKey(OPENVPN));
+ System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false));
+ System.out.println(expectedVPNConfig_v4_ovpn_multiport_tcpudp.trim());
+ assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v4_ovpn_multiport_tcpudp.trim()));
+ }
+
} \ No newline at end of file
diff --git a/app/src/test/resources/v4/multiport_tcpudp_eip-service.json b/app/src/test/resources/v4/multiport_tcpudp_eip-service.json
new file mode 100644
index 00000000..c713e632
--- /dev/null
+++ b/app/src/test/resources/v4/multiport_tcpudp_eip-service.json
@@ -0,0 +1,67 @@
+{
+ "gateways":[
+ {
+ "capabilities":{
+ "adblock":false,
+ "filter_dns":false,
+ "limited":false,
+ "transport":[
+ {
+ "ports":[
+ "53",
+ "80",
+ "1194"
+ ],
+ "protocols":[
+ "tcp",
+ "udp"
+ ],
+ "type":"openvpn"
+ },
+ {
+ "options":{
+ "cert":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+ "iatMode":"0"
+ },
+ "ports":[
+ "443"
+ ],
+ "protocols":[
+ "tcp"
+ ],
+ "type":"obfs4"
+ }
+ ]
+ },
+ "host":"pt.demo.bitmask.net",
+ "ip_address":"37.218.247.60",
+ "ip_address6":"2001:db8:123::1056",
+ "location":"Amsterdam"
+ }
+ ],
+ "locations":{
+ "Amsterdam":{
+ "country_code":"NL",
+ "hemisphere":"N",
+ "name":"Amsterdam",
+ "timezone":"-1"
+ }
+ },
+ "openvpn_configuration":{
+ "auth":"SHA1",
+ "cipher":"AES-256-CBC",
+ "keepalive":"10 30",
+ "tls-cipher":"DHE-RSA-AES128-SHA",
+ "tun-ipv6":true,
+ "dev" : "tun",
+ "sndbuf" : "0",
+ "rcvbuf" : "0",
+ "nobind" : true,
+ "persist-key" : true,
+ "comp-lzo" : true,
+ "key-direction" : "1",
+ "verb" : "3"
+ },
+ "serial":3,
+ "version":3
+} \ No newline at end of file