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:
Tobias Brunner
2012-08-13 11:00:27 +02:00
parent d1220566ef
commit a4f9028e08
@@ -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;
}
}
}
/**