• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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