blob: 5672a016ec9b0f915be209da4a4f5ab7c2ea98e3 [file] [log] [blame]
/*
* Copyright (C) 2009, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.vpn;
import android.app.Service;
import android.content.Intent;
import android.net.vpn.IVpnService;
import android.net.vpn.L2tpIpsecProfile;
import android.net.vpn.L2tpIpsecPskProfile;
import android.net.vpn.L2tpProfile;
import android.net.vpn.PptpProfile;
import android.net.vpn.VpnManager;
import android.net.vpn.VpnProfile;
import android.net.vpn.VpnState;
import android.os.Environment;
import android.os.IBinder;
import android.os.SystemProperties;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* The service class for managing a VPN connection. It implements the
* {@link IVpnService} binder interface.
*/
public class VpnServiceBinder extends Service {
private static final String TAG = VpnServiceBinder.class.getSimpleName();
private static final boolean DBG = true;
private static final String STATES_FILE_RELATIVE_PATH = "/misc/vpn/.states";
// The actual implementation is delegated to the VpnService class.
private VpnService<? extends VpnProfile> mService;
private static String getStateFilePath() {
return Environment.getDataDirectory().getPath() + STATES_FILE_RELATIVE_PATH;
}
private final IBinder mBinder = new IVpnService.Stub() {
public boolean connect(VpnProfile p, String username, String password) {
return VpnServiceBinder.this.connect(p, username, password);
}
public void disconnect() {
VpnServiceBinder.this.disconnect();
}
public void checkStatus(VpnProfile p) {
VpnServiceBinder.this.checkStatus(p);
}
};
@Override
public void onCreate() {
super.onCreate();
checkSavedStates();
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
void saveStates() throws IOException {
if (DBG) Log.d("VpnServiceBinder", " saving states");
ObjectOutputStream oos =
new ObjectOutputStream(new FileOutputStream(getStateFilePath()));
oos.writeObject(mService);
oos.close();
}
void removeStates() {
try {
File f = new File(getStateFilePath());
if (f.exists()) f.delete();
} catch (Throwable e) {
if (DBG) Log.d("VpnServiceBinder", " remove states: " + e);
}
}
private synchronized boolean connect(final VpnProfile p,
final String username, final String password) {
if (mService != null) return false;
final VpnService s = mService = createService(p);
new Thread(new Runnable() {
public void run() {
s.onConnect(username, password);
}
}).start();
return true;
}
private synchronized void disconnect() {
if (mService == null) return;
final VpnService s = mService;
new Thread(new Runnable() {
public void run() {
s.onDisconnect();
}
}).start();
}
private synchronized void checkStatus(VpnProfile p) {
if ((mService == null)
|| (!p.getName().equals(mService.mProfile.getName()))) {
broadcastConnectivity(p.getName(), VpnState.IDLE);
} else {
broadcastConnectivity(p.getName(), mService.getState());
}
}
private void checkSavedStates() {
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
getStateFilePath()));
mService = (VpnService<? extends VpnProfile>) ois.readObject();
mService.recover(this);
ois.close();
} catch (FileNotFoundException e) {
// do nothing
} catch (Throwable e) {
Log.i("VpnServiceBinder", "recovery error, remove states: " + e);
removeStates();
}
}
private VpnService<? extends VpnProfile> createService(VpnProfile p) {
switch (p.getType()) {
case L2TP:
L2tpService l2tp = new L2tpService();
l2tp.setContext(this, (L2tpProfile) p);
return l2tp;
case PPTP:
PptpService pptp = new PptpService();
pptp.setContext(this, (PptpProfile) p);
return pptp;
case L2TP_IPSEC_PSK:
L2tpIpsecPskService psk = new L2tpIpsecPskService();
psk.setContext(this, (L2tpIpsecPskProfile) p);
return psk;
case L2TP_IPSEC:
L2tpIpsecService l2tpIpsec = new L2tpIpsecService();
l2tpIpsec.setContext(this, (L2tpIpsecProfile) p);
return l2tpIpsec;
default:
return null;
}
}
private void broadcastConnectivity(String name, VpnState s) {
new VpnManager(this).broadcastConnectivity(name, s);
}
}