Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prepare release #395

Merged
merged 10 commits into from
Aug 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ android {
applicationId "org.bepass.oblivion"
minSdk 21
targetSdk 34
versionCode 14
versionName "4"
versionCode 15
versionName "5"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
Expand Down Expand Up @@ -61,7 +61,6 @@ dependencies {
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'com.github.bumptech.glide:glide:4.16.0'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.vdurmont:emoji-java:5.1.1'
implementation 'com.github.erfansn:locale-config-x:1.0.1'
implementation 'com.tencent:mmkv:1.3.7'
implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'])
Expand Down
159 changes: 86 additions & 73 deletions app/src/main/java/org/bepass/oblivion/service/OblivionVpnService.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import androidx.core.app.NotificationChannelCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;

import org.bepass.oblivion.enums.ConnectionState;
import org.bepass.oblivion.interfaces.ConnectionStateChangeListener;
import org.bepass.oblivion.R;
Expand All @@ -43,8 +45,8 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
Expand Down Expand Up @@ -86,19 +88,15 @@ public void run() {
}
};
// For JNI Calling in a new threa
private static final Executor executorService = Executors.newSingleThreadExecutor();
private static final ExecutorService executorService = Executors.newFixedThreadPool(1);
// For PingHTTPTestConnection to don't busy-waiting
private static ScheduledExecutorService scheduler;
private Notification notification;
private static ParcelFileDescriptor mInterface;
private String bindAddress;
private static PowerManager.WakeLock wLock;
private static ConnectionState lastKnownState = ConnectionState.DISCONNECTED;
public static synchronized void startVpnService(Context context) {
Intent intent = new Intent(context, OblivionVpnService.class);
intent.setAction(OblivionVpnService.FLAG_VPN_START);
context.startService(intent);
}
private Intent serviceIntent;

public static synchronized void stopVpnService(Context context) {
Intent intent = new Intent(context, OblivionVpnService.class);
Expand Down Expand Up @@ -258,29 +256,26 @@ private void performConnectionTest(String bindAddress, ConnectionStateChangeList
return;
}

scheduler = Executors.newScheduledThreadPool(1);

final long startTime = System.currentTimeMillis();
final long timeout = 60 * 1000; // 1 minute

Runnable pingTask = () -> {
if (System.currentTimeMillis() - startTime >= timeout) {
changeListener.onChange(ConnectionState.DISCONNECTED);
stopForegroundService();
scheduler.shutdown();
scheduler.shutdown(); // Shutdown scheduler after test completion
return;
}

boolean result = pingOverHTTP(bindAddress);
if (result) {
changeListener.onChange(ConnectionState.CONNECTED);
scheduler.shutdown();
scheduler.shutdown(); // Shutdown scheduler after successful connection
}
};


// Schedule the ping task to run with a fixed delay of 1 second
scheduler.scheduleWithFixedDelay(pingTask, 0, 1, TimeUnit.SECONDS);
// Schedule the ping task to run with a fixed delay of 5 seconds using shared scheduler
scheduler.scheduleWithFixedDelay(pingTask, 0, 5, TimeUnit.SECONDS);
}

private void stopForegroundService() {
Expand All @@ -295,8 +290,8 @@ private void stopForegroundService() {
}

private String getBindAddress() {
String port = FileManager.getString("USERSETTING_port");
boolean enableLan = FileManager.getBoolean("USERSETTING_lan");
String port = serviceIntent.getStringExtra("USERSETTING_port");
boolean enableLan = serviceIntent.getBooleanExtra("USERSETTING_lan",false);
String bindAddress = "127.0.0.1:" + port;

if (isLocalPortInUse(bindAddress).equals("true")) {
Expand Down Expand Up @@ -347,6 +342,7 @@ private void start() {
}

executorService.execute(() -> {
Log.d("OblivionVpnService", "Starting VPN service");
bindAddress = getBindAddress();
Log.i(TAG, "Configuring VPN service");
try {
Expand Down Expand Up @@ -378,7 +374,7 @@ private void start() {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String action = intent != null ? intent.getAction() : null;

this.serviceIntent = intent;
if (FLAG_VPN_START.equals(action)) {
// Start VPN
if (lastKnownState == ConnectionState.DISCONNECTED) {
Expand All @@ -396,12 +392,18 @@ public int onStartCommand(Intent intent, int flags, int startId) {
public void onCreate() {
super.onCreate();
handler.post(logRunnable);
if (scheduler == null) {
scheduler = Executors.newScheduledThreadPool(1);
}
}

@Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(logRunnable);
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdown();
}
if (wLock != null && wLock.isHeld()) {
wLock.release();
wLock = null;
Expand All @@ -424,10 +426,9 @@ public void onRevoke() {
} else {
Log.w(TAG, "No wake lock to release");
}

// Close the VPN interface
try {
if (!FileManager.getBoolean("USERSETTING_proxymode")) {
if (!serviceIntent.getBooleanExtra("USERSETTING_proxymode",false)) {
if (mInterface != null) {
mInterface.close();
mInterface = null; // Set to null to ensure it's not reused
Expand All @@ -452,7 +453,7 @@ public void onRevoke() {
stopForegroundService();
stopSelf();
// Shutdown executor service
if (executorService instanceof ExecutorService) {
if (executorService != null) {
ExecutorService service = (ExecutorService) executorService;
try {
service.shutdownNow(); // Attempt to forcibly shutdown
Expand Down Expand Up @@ -501,10 +502,10 @@ private void setLastKnownState(ConnectionState lastKnownState) {
}

private String getNotificationText() {
boolean usePsiphon = FileManager.getBoolean("USERSETTING_psiphon");
boolean useWarp = FileManager.getBoolean("USERSETTING_gool");
boolean proxyMode = FileManager.getBoolean("USERSETTING_proxymode");
String portInUse = FileManager.getString("USERSETTING_port");
boolean usePsiphon = serviceIntent.getBooleanExtra("USERSETTING_psiphon",false);
boolean useWarp = serviceIntent.getBooleanExtra("USERSETTING_gool",false);
boolean proxyMode = serviceIntent.getBooleanExtra("USERSETTING_proxymode",false);
String portInUse = serviceIntent.getStringExtra("USERSETTING_port");
String notificationText;
String proxyText = proxyMode ? String.format(Locale.getDefault(), " on socks5 proxy at 127.0.0.1:%s", portInUse) : "";

Expand Down Expand Up @@ -555,58 +556,70 @@ public void removeConnectionStateObserver(String key) {
connectionStateObservers.remove(key);
}

private void configure() throws Exception {
boolean proxyModeEnabled = FileManager.getBoolean("USERSETTING_proxymode");
if (proxyModeEnabled) {
// Proxy mode logic
StartOptions so = new StartOptions();
so.setPath(getApplicationContext().getFilesDir().getAbsolutePath());
so.setVerbose(true);
so.setEndpoint(getEndpoint());
so.setBindAddress(bindAddress);
so.setLicense(FileManager.getString("USERSETTING_license", "").trim());
so.setDNS("1.1.1.1");
so.setEndpointType(FileManager.getInt("USERSETTING_endpoint_type"));

if (FileManager.getBoolean("USERSETTING_psiphon", false)) {
so.setPsiphonEnabled(true);
so.setCountry(FileManager.getString("USERSETTING_country", "AT").trim());
} else if (FileManager.getBoolean("USERSETTING_gool", false)) {
so.setGool(true);
}
private void configure() {
Runnable configureTask = () -> {
try {
if(serviceIntent != null) {
boolean proxyModeEnabled = serviceIntent.getBooleanExtra("USERSETTING_proxymode",false);
if (proxyModeEnabled) {
// Proxy mode logic
StartOptions so = new StartOptions();
so.setPath(getApplicationContext().getFilesDir().getAbsolutePath());
so.setVerbose(true);
so.setEndpoint(getEndpoint());
so.setBindAddress(bindAddress);
so.setLicense(Objects.requireNonNull(serviceIntent.getStringExtra("USERSETTING_license")).trim());
so.setDNS("1.1.1.1");
so.setEndpointType(serviceIntent.getIntExtra("USERSETTING_endpoint_type",0));

if (serviceIntent.getBooleanExtra("USERSETTING_psiphon", false)) {
so.setPsiphonEnabled(true);
so.setCountry(Objects.requireNonNull(serviceIntent.getStringExtra("USERSETTING_country")).trim());
} else if (serviceIntent.getBooleanExtra("USERSETTING_gool", false)) {
so.setGool(true);
}

// Start tun2socks in proxy mode
Tun2socks.start(so);
// Start tun2socks in proxy mode
Tun2socks.start(so);

} else {
// VPN mode logic
Builder builder = new Builder();
configureVpnBuilder(builder);

mInterface = builder.establish();
if (mInterface == null)
throw new RuntimeException("failed to establish VPN interface");
Log.i(TAG, "Interface created");

StartOptions so = new StartOptions();
so.setPath(getApplicationContext().getFilesDir().getAbsolutePath());
so.setVerbose(true);
so.setEndpoint(getEndpoint());
so.setBindAddress(bindAddress);
so.setLicense(Objects.requireNonNull(serviceIntent.getStringExtra("USERSETTING_license")).trim());
so.setDNS("1.1.1.1");
so.setEndpointType(serviceIntent.getIntExtra("USERSETTING_endpoint_type",0));
so.setTunFd(mInterface.getFd());

if (serviceIntent.getBooleanExtra("USERSETTING_psiphon", false)) {
so.setPsiphonEnabled(true);
so.setCountry(Objects.requireNonNull(serviceIntent.getStringExtra("USERSETTING_country")).trim());
} else if (serviceIntent.getBooleanExtra("USERSETTING_gool", false)) {
so.setGool(true);
}

} else {
// VPN mode logic
VpnService.Builder builder = new VpnService.Builder();
configureVpnBuilder(builder);

mInterface = builder.establish();
if (mInterface == null) throw new RuntimeException("failed to establish VPN interface");
Log.i(TAG, "Interface created");

StartOptions so = new StartOptions();
so.setPath(getApplicationContext().getFilesDir().getAbsolutePath());
so.setVerbose(true);
so.setEndpoint(getEndpoint());
so.setBindAddress(bindAddress);
so.setLicense(FileManager.getString("USERSETTING_license", "").trim());
so.setDNS("1.1.1.1");
so.setEndpointType(FileManager.getInt("USERSETTING_endpoint_type"));
so.setTunFd(mInterface.getFd());

if (FileManager.getBoolean("USERSETTING_psiphon", false)) {
so.setPsiphonEnabled(true);
so.setCountry(FileManager.getString("USERSETTING_country", "AT").trim());
} else if (FileManager.getBoolean("USERSETTING_gool", false)) {
so.setGool(true);
// Start tun2socks with VPN
Tun2socks.start(so);
}
}
} catch (Exception e) {
Log.e(TAG, "Configuration failed", e);
}
};

// Start tun2socks with VPN
Tun2socks.start(so);
}
// Run the task on a separate thread if needed
new Thread(configureTask).start();
}

private void configureVpnBuilder(VpnService.Builder builder) throws Exception {
Expand Down Expand Up @@ -634,7 +647,7 @@ private void configureVpnBuilder(VpnService.Builder builder) throws Exception {
}

private String getEndpoint() {
String endpoint = FileManager.getString("USERSETTING_endpoint", "engage.cloudflareclient.com:2408").trim();
String endpoint = Objects.requireNonNull(serviceIntent.getStringExtra("USERSETTING_endpoint")).trim();
return endpoint.equals("engage.cloudflareclient.com:2408") ? "" : endpoint;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.bepass.oblivion.service;

import static org.bepass.oblivion.ui.MainActivity.startVpnService;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
Expand Down Expand Up @@ -75,8 +77,8 @@ public void onClick() {
Toast.makeText(this, "لطفا یک‌بار از درون اپلیکیشن متصل شوید", Toast.LENGTH_LONG).show();
return;
}

OblivionVpnService.startVpnService(this);
Intent vpnIntent = new Intent(this, OblivionVpnService.class);
startVpnService(this, vpnIntent);
}

private void subscribe() {
Expand Down
Loading