You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lokinet/jni/java/src/network/loki/lokinet/LokinetDaemon.java

163 lines
3.6 KiB
Java

package network.loki.lokinet;
import java.lang.Thread;
import java.nio.ByteBuffer;
import java.io.File;
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 native String DumpStatus();
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 + "/lokinet.ini");
return START_NOT_STICKY;
}
VpnService.Builder builder = new VpnService.Builder();
builder.setMtu(1500);
String[] parts = ourRange.split("/");
String ourIPv4 = parts[0];
int ourMask = Integer.parseInt(parts[1]);
// set ip4
builder.addAddress(ourIPv4, ourMask);
builder.addRoute("0.0.0.0", 0);
// set ip6
// TODO: convert ipv4 to fd00::/8 range for ipv6
// builder.addAddress(ourIPv6, ourMask + 96);
// builder.addRoute("::", 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();
new Thread(() -> {
Configure(config);
m_UDPSocket = GetUDPSocket();
protect(m_UDPSocket);
Mainloop();
}).start();
Log.d(LOG_TAG, "started successfully!");
}
else
{
Log.d(LOG_TAG, "already running");
}
return START_STICKY;
}
}