1 /* 2 * Copyright (C) 2009, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.vpn; 18 19 import android.app.Service; 20 import android.content.Intent; 21 import android.net.vpn.IVpnService; 22 import android.net.vpn.L2tpIpsecProfile; 23 import android.net.vpn.L2tpIpsecPskProfile; 24 import android.net.vpn.L2tpProfile; 25 import android.net.vpn.PptpProfile; 26 import android.net.vpn.VpnManager; 27 import android.net.vpn.VpnProfile; 28 import android.net.vpn.VpnState; 29 import android.os.IBinder; 30 import android.util.Log; 31 32 import java.io.File; 33 import java.io.FileInputStream; 34 import java.io.FileNotFoundException; 35 import java.io.FileOutputStream; 36 import java.io.IOException; 37 import java.io.ObjectInputStream; 38 import java.io.ObjectOutputStream; 39 40 /** 41 * The service class for managing a VPN connection. It implements the 42 * {@link IVpnService} binder interface. 43 */ 44 public class VpnServiceBinder extends Service { 45 private static final String TAG = VpnServiceBinder.class.getSimpleName(); 46 private static final boolean DBG = true; 47 48 private static final String STATES_FILE_PATH = "/data/misc/vpn/.states"; 49 50 // The actual implementation is delegated to the VpnService class. 51 private VpnService<? extends VpnProfile> mService; 52 53 private final IBinder mBinder = new IVpnService.Stub() { 54 public boolean connect(VpnProfile p, String username, String password) { 55 return VpnServiceBinder.this.connect(p, username, password); 56 } 57 58 public void disconnect() { 59 VpnServiceBinder.this.disconnect(); 60 } 61 62 public void checkStatus(VpnProfile p) { 63 VpnServiceBinder.this.checkStatus(p); 64 } 65 }; 66 67 @Override onCreate()68 public void onCreate() { 69 super.onCreate(); 70 checkSavedStates(); 71 } 72 73 74 @Override onStart(Intent intent, int startId)75 public void onStart(Intent intent, int startId) { 76 super.onStart(intent, startId); 77 } 78 79 @Override onBind(Intent intent)80 public IBinder onBind(Intent intent) { 81 return mBinder; 82 } 83 saveStates()84 void saveStates() throws IOException { 85 if (DBG) Log.d("VpnServiceBinder", " saving states"); 86 ObjectOutputStream oos = 87 new ObjectOutputStream(new FileOutputStream(STATES_FILE_PATH)); 88 oos.writeObject(mService); 89 oos.close(); 90 } 91 removeStates()92 void removeStates() { 93 try { 94 File f = new File(STATES_FILE_PATH); 95 if (f.exists()) f.delete(); 96 } catch (Throwable e) { 97 if (DBG) Log.d("VpnServiceBinder", " remove states: " + e); 98 } 99 } 100 connect(final VpnProfile p, final String username, final String password)101 private synchronized boolean connect(final VpnProfile p, 102 final String username, final String password) { 103 if (mService != null) return false; 104 final VpnService s = mService = createService(p); 105 106 new Thread(new Runnable() { 107 public void run() { 108 s.onConnect(username, password); 109 } 110 }).start(); 111 return true; 112 } 113 disconnect()114 private synchronized void disconnect() { 115 if (mService == null) return; 116 final VpnService s = mService; 117 118 new Thread(new Runnable() { 119 public void run() { 120 s.onDisconnect(); 121 } 122 }).start(); 123 } 124 checkStatus(VpnProfile p)125 private synchronized void checkStatus(VpnProfile p) { 126 if ((mService == null) 127 || (!p.getName().equals(mService.mProfile.getName()))) { 128 broadcastConnectivity(p.getName(), VpnState.IDLE); 129 } else { 130 broadcastConnectivity(p.getName(), mService.getState()); 131 } 132 } 133 checkSavedStates()134 private void checkSavedStates() { 135 try { 136 ObjectInputStream ois = new ObjectInputStream(new FileInputStream( 137 STATES_FILE_PATH)); 138 mService = (VpnService<? extends VpnProfile>) ois.readObject(); 139 mService.recover(this); 140 ois.close(); 141 } catch (FileNotFoundException e) { 142 // do nothing 143 } catch (Throwable e) { 144 Log.i("VpnServiceBinder", "recovery error, remove states: " + e); 145 removeStates(); 146 } 147 } 148 createService(VpnProfile p)149 private VpnService<? extends VpnProfile> createService(VpnProfile p) { 150 switch (p.getType()) { 151 case L2TP: 152 L2tpService l2tp = new L2tpService(); 153 l2tp.setContext(this, (L2tpProfile) p); 154 return l2tp; 155 156 case PPTP: 157 PptpService pptp = new PptpService(); 158 pptp.setContext(this, (PptpProfile) p); 159 return pptp; 160 161 case L2TP_IPSEC_PSK: 162 L2tpIpsecPskService psk = new L2tpIpsecPskService(); 163 psk.setContext(this, (L2tpIpsecPskProfile) p); 164 return psk; 165 166 case L2TP_IPSEC: 167 L2tpIpsecService l2tpIpsec = new L2tpIpsecService(); 168 l2tpIpsec.setContext(this, (L2tpIpsecProfile) p); 169 return l2tpIpsec; 170 171 default: 172 return null; 173 } 174 } 175 broadcastConnectivity(String name, VpnState s)176 private void broadcastConnectivity(String name, VpnState s) { 177 new VpnManager(this).broadcastConnectivity(name, s); 178 } 179 } 180