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;
|
||||
|
||||
import org.strongswan.android.data.VpnProfile;
|
||||
import org.strongswan.android.data.VpnProfileDataSource;
|
||||
|
||||
import android.content.Intent;
|
||||
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
|
||||
public int onStartCommand(Intent intent, int flags, int startId)
|
||||
{
|
||||
// called whenever the service is started with startService
|
||||
// create our own thread because we are running in the calling processes
|
||||
// main thread
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
if (intent != null)
|
||||
{
|
||||
Bundle bundle = intent.getExtras();
|
||||
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
|
||||
public void onCreate()
|
||||
{
|
||||
// onCreate is only called once
|
||||
initializeCharon();
|
||||
super.onCreate();
|
||||
mDataSource = new VpnProfileDataSource(this);
|
||||
mDataSource.open();
|
||||
/* 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
|
||||
public void onDestroy()
|
||||
{
|
||||
// called once the service is to be destroyed
|
||||
deinitializeCharon();
|
||||
super.onDestroy();
|
||||
mTerminate = true;
|
||||
setNextProfile(null);
|
||||
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