lokinet-flutter-app/lokinet_lib/android/src/main/java/network/loki/lokinet/LokinetDaemon.java

167 lines
3.7 KiB
Java

package network.loki.lokinet;
import java.lang.Thread;
import java.nio.ByteBuffer;
import android.net.VpnService;
import android.util.Log;
import android.content.Intent;
import android.os.ParcelFileDescriptor;
public class LokinetDaemon extends VpnService
{
static {
System.loadLibrary("lokinet-android");
}
private static native ByteBuffer Obtain();
private static native void Free(ByteBuffer buf);
public native boolean Configure(LokinetConfig config);
public native int Mainloop();
public native boolean IsRunning();
public native boolean Stop();
public native void InjectVPNFD();
public native int GetUDPSocket();
private static native String DetectFreeRange();
public static final String LOG_TAG = "LokinetDaemon";
ByteBuffer impl = null;
ParcelFileDescriptor iface;
int m_FD = -1;
int m_UDPSocket = -1;
@Override
public void onCreate()
{
super.onCreate();
}
@Override
public void onDestroy()
{
super.onDestroy();
if (IsRunning())
{
Stop();
}
if (impl != null)
{
Free(impl);
impl = null;
}
}
public int onStartCommand(Intent intent, int flags, int startID)
{
Log.d(LOG_TAG, "onStartCommand()");
if (!IsRunning())
{
if (impl != null)
{
Free(impl);
impl = null;
}
impl = Obtain();
if (impl == null)
{
Log.e(LOG_TAG, "got nullptr when creating llarp::Context in jni");
return START_NOT_STICKY;
}
String dataDir = getFilesDir().toString();
LokinetConfig config;
try
{
config = new LokinetConfig(dataDir);
}
catch(RuntimeException ex)
{
Log.e(LOG_TAG, ex.toString());
return START_NOT_STICKY;
}
// FIXME: make these configurable
String exitNode = "exit.loki";
String upstreamDNS = "1.1.1.1";
String ourRange = DetectFreeRange();
if(ourRange.isEmpty())
{
Log.e(LOG_TAG, "cannot detect free range");
return START_NOT_STICKY;
}
// set up config values
config.AddDefaultValue("network", "exit-node", exitNode);
config.AddDefaultValue("network", "ifaddr", ourRange);
config.AddDefaultValue("dns", "upstream", upstreamDNS);
if (!config.Load())
{
Log.e(LOG_TAG, "failed to load (or create) config file at: " + dataDir + "/loki.network.loki.lokinet.ini");
return START_NOT_STICKY;
}
VpnService.Builder builder = new VpnService.Builder();
builder.setMtu(1500);
String[] parts = ourRange.split("/");
String ourIP = parts[0];
int ourMask = Integer.parseInt(parts[1]);
builder.addAddress(ourIP, ourMask);
builder.addRoute("0.0.0.0", 0);
builder.addDnsServer(upstreamDNS);
builder.setSession("Lokinet");
builder.setConfigureIntent(null);
iface = builder.establish();
if (iface == null)
{
Log.e(LOG_TAG, "VPN Interface from builder.establish() came back null");
return START_NOT_STICKY;
}
m_FD = iface.detachFd();
InjectVPNFD();
if (!Configure(config))
{
//TODO: close vpn FD if this fails, either on native side, or here if possible
Log.e(LOG_TAG, "failed to configure daemon");
return START_NOT_STICKY;
}
m_UDPSocket = GetUDPSocket();
if (m_UDPSocket <= 0)
{
Log.e(LOG_TAG, "failed to get proper UDP handle from daemon, aborting.");
return START_NOT_STICKY;
}
protect(m_UDPSocket);
new Thread(() -> {
Mainloop();
}).start();
Log.d(LOG_TAG, "started successfully!");
}
else
{
Log.d(LOG_TAG, "already running");
}
return START_STICKY;
}
}