CharonVpnService reacts on Intents and properly inits/deinits charon
Charon is initialized with every new connection attempt and deinitialized when the service is terminated or it receives an empty Intent (or before starting a new connection). A separate thread is used to handle the connection attempts, this thread acts as main thread for charon.
This commit is contained in:
@@ -1,34 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012 Tobias Brunner
|
||||||
|
* Copyright (C) 2012 Giuliano Grassi
|
||||||
|
* Copyright (C) 2012 Ralf Sager
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
package org.strongswan.android.logic;
|
package org.strongswan.android.logic;
|
||||||
|
|
||||||
|
import org.strongswan.android.data.VpnProfile;
|
||||||
|
import org.strongswan.android.data.VpnProfileDataSource;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.VpnService;
|
import android.net.VpnService;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
public class CharonVpnService extends VpnService
|
public class CharonVpnService extends VpnService implements Runnable
|
||||||
{
|
{
|
||||||
|
private static final String TAG = CharonVpnService.class.getSimpleName();
|
||||||
|
private VpnProfileDataSource mDataSource;
|
||||||
|
private Thread mConnectionHandler;
|
||||||
|
private VpnProfile mCurrentProfile;
|
||||||
|
private VpnProfile mNextProfile;
|
||||||
|
private volatile boolean mProfileUpdated;
|
||||||
|
private volatile boolean mTerminate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId)
|
public int onStartCommand(Intent intent, int flags, int startId)
|
||||||
{
|
{
|
||||||
// called whenever the service is started with startService
|
if (intent != null)
|
||||||
// create our own thread because we are running in the calling processes
|
{
|
||||||
// main thread
|
Bundle bundle = intent.getExtras();
|
||||||
return super.onStartCommand(intent, flags, startId);
|
VpnProfile profile = null;
|
||||||
|
if (bundle != null)
|
||||||
|
{
|
||||||
|
profile = mDataSource.getVpnProfile(bundle.getLong(VpnProfileDataSource.KEY_ID));
|
||||||
|
if (profile != null)
|
||||||
|
{
|
||||||
|
String password = bundle.getString(VpnProfileDataSource.KEY_PASSWORD);
|
||||||
|
profile.setPassword(password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setNextProfile(profile);
|
||||||
|
}
|
||||||
|
return START_NOT_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate()
|
public void onCreate()
|
||||||
{
|
{
|
||||||
// onCreate is only called once
|
mDataSource = new VpnProfileDataSource(this);
|
||||||
initializeCharon();
|
mDataSource.open();
|
||||||
super.onCreate();
|
/* use a separate thread as main thread for charon */
|
||||||
|
mConnectionHandler = new Thread(this);
|
||||||
|
mConnectionHandler.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRevoke()
|
||||||
|
{ /* the system revoked the rights grated with the initial prepare() call.
|
||||||
|
* called when the user clicks disconnect in the system's VPN dialog */
|
||||||
|
setNextProfile(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy()
|
public void onDestroy()
|
||||||
{
|
{
|
||||||
// called once the service is to be destroyed
|
mTerminate = true;
|
||||||
deinitializeCharon();
|
setNextProfile(null);
|
||||||
super.onDestroy();
|
try
|
||||||
|
{
|
||||||
|
mConnectionHandler.join();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
mDataSource.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the profile that is to be initiated next. Notify the handler thread.
|
||||||
|
*
|
||||||
|
* @param profile the profile to initiate
|
||||||
|
*/
|
||||||
|
private void setNextProfile(VpnProfile profile)
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
this.mNextProfile = profile;
|
||||||
|
mProfileUpdated = true;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!mProfileUpdated)
|
||||||
|
{
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
mProfileUpdated = false;
|
||||||
|
stopCurrentConnection();
|
||||||
|
if (mNextProfile == null)
|
||||||
|
{
|
||||||
|
if (mTerminate)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mCurrentProfile = mNextProfile;
|
||||||
|
mNextProfile = null;
|
||||||
|
|
||||||
|
initializeCharon();
|
||||||
|
Log.i(TAG, "charon started");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InterruptedException ex)
|
||||||
|
{
|
||||||
|
stopCurrentConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop any existing connection by deinitializing charon.
|
||||||
|
*/
|
||||||
|
private void stopCurrentConnection()
|
||||||
|
{
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
if (mCurrentProfile != null)
|
||||||
|
{
|
||||||
|
deinitializeCharon();
|
||||||
|
Log.i(TAG, "charon stopped");
|
||||||
|
mCurrentProfile = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user