summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHung-ying Tyan <tyanh@google.com>2009-09-30 16:57:51 +0800
committerHung-ying Tyan <tyanh@google.com>2009-10-01 15:18:28 +0800
commitc8217638be7e39161fa31bfe240a64a563690dbf (patch)
treea6f5e9f6b160d751bc28dfc79156ff1a0f11fd36
parentc868acf442a69429056a574c67a5e0187e2b9536 (diff)
downloadframeworks_base-c8217638be7e39161fa31bfe240a64a563690dbf.zip
frameworks_base-c8217638be7e39161fa31bfe240a64a563690dbf.tar.gz
frameworks_base-c8217638be7e39161fa31bfe240a64a563690dbf.tar.bz2
Fix stopping all vpn daemons before connect and more.
* move DaemonHelper out from VpnService to VpnDaemons for better managing native daemons. * check connectivity and dns less frequently to save battery.
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java15
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java14
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/L2tpService.java10
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java69
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/PptpService.java12
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/VpnDaemons.java147
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/VpnService.java125
7 files changed, 195 insertions, 197 deletions
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
index 7910f4a..50e0de1 100644
--- a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
@@ -31,24 +31,17 @@ class L2tpIpsecPskService extends VpnService<L2tpIpsecPskProfile> {
protected void connect(String serverIp, String username, String password)
throws IOException {
L2tpIpsecPskProfile p = getProfile();
+ VpnDaemons daemons = getDaemons();
// IPSEC
- DaemonProxy ipsec = startDaemon(IPSEC);
- ipsec.sendCommand(serverIp, L2tpService.L2TP_PORT, p.getPresharedKey());
- ipsec.closeControlSocket();
+ daemons.startIpsecForL2tp(serverIp, p.getPresharedKey())
+ .closeControlSocket();
sleep(2000); // 2 seconds
// L2TP
- MtpdHelper.sendCommand(this, L2tpService.L2TP_DAEMON, serverIp,
- L2tpService.L2TP_PORT,
+ daemons.startL2tp(serverIp,
(p.isSecretEnabled() ? p.getSecretString() : null),
username, password);
}
-
- @Override
- protected void stopPreviouslyRunDaemons() {
- stopDaemon(IPSEC);
- stopDaemon(MtpdHelper.MTPD);
- }
}
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
index 9909905..663b0e8 100644
--- a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
@@ -31,9 +31,10 @@ class L2tpIpsecService extends VpnService<L2tpIpsecProfile> {
protected void connect(String serverIp, String username, String password)
throws IOException {
L2tpIpsecProfile p = getProfile();
+ VpnDaemons daemons = getDaemons();
+
// IPSEC
- DaemonProxy ipsec = startDaemon(IPSEC);
- ipsec.sendCommand(serverIp, L2tpService.L2TP_PORT,
+ DaemonProxy ipsec = daemons.startIpsecForL2tp(serverIp,
Credentials.USER_PRIVATE_KEY + p.getUserCertificate(),
Credentials.USER_CERTIFICATE + p.getUserCertificate(),
Credentials.CA_CERTIFICATE + p.getCaCertificate());
@@ -42,15 +43,8 @@ class L2tpIpsecService extends VpnService<L2tpIpsecProfile> {
sleep(2000); // 2 seconds
// L2TP
- MtpdHelper.sendCommand(this, L2tpService.L2TP_DAEMON, serverIp,
- L2tpService.L2TP_PORT,
+ daemons.startL2tp(serverIp,
(p.isSecretEnabled() ? p.getSecretString() : null),
username, password);
}
-
- @Override
- protected void stopPreviouslyRunDaemons() {
- stopDaemon(IPSEC);
- stopDaemon(MtpdHelper.MTPD);
- }
}
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpService.java
index d658a36..784a366 100644
--- a/packages/VpnServices/src/com/android/server/vpn/L2tpService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/L2tpService.java
@@ -24,20 +24,12 @@ import java.io.IOException;
* The service that manages the L2TP VPN connection.
*/
class L2tpService extends VpnService<L2tpProfile> {
- static final String L2TP_DAEMON = "l2tp";
- static final String L2TP_PORT = "1701";
-
@Override
protected void connect(String serverIp, String username, String password)
throws IOException {
L2tpProfile p = getProfile();
- MtpdHelper.sendCommand(this, L2TP_DAEMON, serverIp, L2TP_PORT,
+ getDaemons().startL2tp(serverIp,
(p.isSecretEnabled() ? p.getSecretString() : null),
username, password);
}
-
- @Override
- protected void stopPreviouslyRunDaemons() {
- stopDaemon(MtpdHelper.MTPD);
- }
}
diff --git a/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java b/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java
deleted file mode 100644
index 9078d9b..0000000
--- a/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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 java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * A helper class for sending commands to the MTP daemon (mtpd).
- */
-class MtpdHelper {
- static final String MTPD = "mtpd";
- private static final String VPN_LINKNAME = "vpn";
- private static final String PPP_ARGS_SEPARATOR = "";
-
- static void sendCommand(VpnService<?> vpnService, String protocol,
- String serverIp, String port, String secret, String username,
- String password) throws IOException {
- sendCommand(vpnService, protocol, serverIp, port, secret, username,
- password, false);
- }
-
- static void sendCommand(VpnService<?> vpnService, String protocol,
- String serverIp, String port, String secret, String username,
- String password, boolean encryption) throws IOException {
- ArrayList<String> args = new ArrayList<String>();
- args.addAll(Arrays.asList(protocol, serverIp, port));
- if (secret != null) args.add(secret);
- args.add(PPP_ARGS_SEPARATOR);
- addPppArguments(args, serverIp, username, password, encryption);
-
- DaemonProxy mtpd = vpnService.startDaemon(MTPD);
- mtpd.sendCommand(args.toArray(new String[args.size()]));
- }
-
- private static void addPppArguments(ArrayList<String> args, String serverIp,
- String username, String password, boolean encryption)
- throws IOException {
- args.addAll(Arrays.asList(
- "linkname", VPN_LINKNAME,
- "name", username,
- "password", password,
- "refuse-eap", "nodefaultroute", "usepeerdns",
- "idle", "1800",
- "mtu", "1400",
- "mru", "1400"));
- if (encryption) {
- args.add("+mppe");
- }
- }
-
- private MtpdHelper() {
- }
-}
diff --git a/packages/VpnServices/src/com/android/server/vpn/PptpService.java b/packages/VpnServices/src/com/android/server/vpn/PptpService.java
index d903d1b..de12710 100644
--- a/packages/VpnServices/src/com/android/server/vpn/PptpService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/PptpService.java
@@ -24,19 +24,11 @@ import java.io.IOException;
* The service that manages the PPTP VPN connection.
*/
class PptpService extends VpnService<PptpProfile> {
- static final String PPTP_DAEMON = "pptp";
- static final String PPTP_PORT = "1723";
-
@Override
protected void connect(String serverIp, String username, String password)
throws IOException {
PptpProfile p = getProfile();
- MtpdHelper.sendCommand(this, PPTP_DAEMON, serverIp, PPTP_PORT, null,
- username, password, p.isEncryptionEnabled());
- }
-
- @Override
- protected void stopPreviouslyRunDaemons() {
- stopDaemon(MtpdHelper.MTPD);
+ getDaemons().startPptp(serverIp, username, password,
+ p.isEncryptionEnabled());
}
}
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnDaemons.java b/packages/VpnServices/src/com/android/server/vpn/VpnDaemons.java
new file mode 100644
index 0000000..499195f
--- /dev/null
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnDaemons.java
@@ -0,0 +1,147 @@
+/*
+ * 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.util.Log;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A helper class for managing native VPN daemons.
+ */
+class VpnDaemons implements Serializable {
+ static final long serialVersionUID = 1L;
+ private final String TAG = VpnDaemons.class.getSimpleName();
+
+ private static final String MTPD = "mtpd";
+ private static final String IPSEC = "racoon";
+
+ private static final String L2TP = "l2tp";
+ private static final String L2TP_PORT = "1701";
+
+ private static final String PPTP = "pptp";
+ private static final String PPTP_PORT = "1723";
+
+ private static final String VPN_LINKNAME = "vpn";
+ private static final String PPP_ARGS_SEPARATOR = "";
+
+ private List<DaemonProxy> mDaemonList = new ArrayList<DaemonProxy>();
+
+ public DaemonProxy startL2tp(String serverIp, String secret,
+ String username, String password) throws IOException {
+ return startMtpd(L2TP, serverIp, L2TP_PORT, secret, username, password,
+ false);
+ }
+
+ public DaemonProxy startPptp(String serverIp, String username,
+ String password, boolean encryption) throws IOException {
+ return startMtpd(PPTP, serverIp, PPTP_PORT, null, username, password,
+ encryption);
+ }
+
+ public DaemonProxy startIpsecForL2tp(String serverIp, String pskKey)
+ throws IOException {
+ DaemonProxy ipsec = startDaemon(IPSEC);
+ ipsec.sendCommand(serverIp, L2TP_PORT, pskKey);
+ return ipsec;
+ }
+
+ public DaemonProxy startIpsecForL2tp(String serverIp, String userKeyKey,
+ String userCertKey, String caCertKey) throws IOException {
+ DaemonProxy ipsec = startDaemon(IPSEC);
+ ipsec.sendCommand(serverIp, L2TP_PORT, userKeyKey, userCertKey,
+ caCertKey);
+ return ipsec;
+ }
+
+ public synchronized void stopAll() {
+ new DaemonProxy(MTPD).stop();
+ new DaemonProxy(IPSEC).stop();
+ }
+
+ public synchronized void closeSockets() {
+ for (DaemonProxy s : mDaemonList) s.closeControlSocket();
+ }
+
+ public synchronized boolean anyDaemonStopped() {
+ for (DaemonProxy s : mDaemonList) {
+ if (s.isStopped()) {
+ Log.w(TAG, " VPN daemon gone: " + s.getName());
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public synchronized int getSocketError() {
+ for (DaemonProxy s : mDaemonList) {
+ int errCode = getResultFromSocket(s);
+ if (errCode != 0) return errCode;
+ }
+ return 0;
+ }
+
+ private synchronized DaemonProxy startDaemon(String daemonName)
+ throws IOException {
+ DaemonProxy daemon = new DaemonProxy(daemonName);
+ mDaemonList.add(daemon);
+ daemon.start();
+ return daemon;
+ }
+
+ private int getResultFromSocket(DaemonProxy s) {
+ try {
+ return s.getResultFromSocket();
+ } catch (IOException e) {
+ return -1;
+ }
+ }
+
+ private DaemonProxy startMtpd(String protocol,
+ String serverIp, String port, String secret, String username,
+ String password, boolean encryption) throws IOException {
+ ArrayList<String> args = new ArrayList<String>();
+ args.addAll(Arrays.asList(protocol, serverIp, port));
+ if (secret != null) args.add(secret);
+ args.add(PPP_ARGS_SEPARATOR);
+ addPppArguments(args, serverIp, username, password, encryption);
+
+ DaemonProxy mtpd = startDaemon(MTPD);
+ mtpd.sendCommand(args.toArray(new String[args.size()]));
+ return mtpd;
+ }
+
+ private static void addPppArguments(ArrayList<String> args, String serverIp,
+ String username, String password, boolean encryption)
+ throws IOException {
+ args.addAll(Arrays.asList(
+ "linkname", VPN_LINKNAME,
+ "name", username,
+ "password", password,
+ "refuse-eap", "nodefaultroute", "usepeerdns",
+ "idle", "1800",
+ "mtu", "1400",
+ "mru", "1400"));
+ if (encryption) {
+ args.add("+mppe");
+ }
+ }
+}
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
index 53167f6..63b87b1 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
@@ -30,18 +30,15 @@ import android.util.Log;
import java.io.IOException;
import java.io.Serializable;
import java.net.DatagramSocket;
-import java.net.Socket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.List;
/**
* The service base class for managing a type of VPN connection.
*/
abstract class VpnService<E extends VpnProfile> implements Serializable {
- protected static final long serialVersionUID = 1L;
+ static final long serialVersionUID = 1L;
private static final boolean DBG = true;
private static final int NOTIFICATION_ID = 1;
@@ -75,8 +72,8 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
private long mStartTime; // VPN connection start time
- // for helping managing multiple daemons
- private DaemonHelper mDaemonHelper = new DaemonHelper();
+ // for helping managing daemons
+ private VpnDaemons mDaemons = new VpnDaemons();
// for helping showing, updating notification
private transient NotificationHelper mNotification;
@@ -87,21 +84,11 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
protected abstract void connect(String serverIp, String username,
String password) throws IOException;
- protected abstract void stopPreviouslyRunDaemons();
-
/**
- * Starts a VPN daemon.
+ * Returns the daemons management class for this service object.
*/
- protected DaemonProxy startDaemon(String daemonName)
- throws IOException {
- return mDaemonHelper.startDaemon(daemonName);
- }
-
- /**
- * Stops a VPN daemon.
- */
- protected void stopDaemon(String daemonName) {
- new DaemonProxy(daemonName).stop();
+ protected VpnDaemons getDaemons() {
+ return mDaemons;
}
/**
@@ -141,7 +128,7 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
try {
setState(VpnState.CONNECTING);
- stopPreviouslyRunDaemons();
+ mDaemons.stopAll();
String serverIp = getIp(getProfile().getServerName());
saveLocalIpAndInterface(serverIp);
onBeforeConnect();
@@ -160,7 +147,7 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
setState(VpnState.DISCONNECTING);
mNotification.showDisconnect();
- mDaemonHelper.stopAll();
+ mDaemons.stopAll();
} catch (Throwable e) {
Log.e(TAG, "onDisconnect()", e);
} finally {
@@ -206,7 +193,7 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
onConnected();
return;
} else {
- int err = mDaemonHelper.getSocketError();
+ int err = mDaemons.getSocketError();
if (err != 0) {
onError(err);
return;
@@ -223,7 +210,7 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
private synchronized void onConnected() throws IOException {
if (DBG) Log.d(TAG, "onConnected()");
- mDaemonHelper.closeSockets();
+ mDaemons.closeSockets();
saveOriginalDns();
saveAndSetDomainSuffices();
@@ -341,15 +328,20 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
public void run() {
Log.i(TAG, "VPN connectivity monitor running");
try {
- for (;;) {
+ for (int i = 10; ; i--) {
+ long now = System.currentTimeMillis();
+
+ boolean heavyCheck = i == 0;
synchronized (VpnService.this) {
- if ((mState != VpnState.CONNECTED)
- || !checkConnectivity()) {
- break;
+ if (mState != VpnState.CONNECTED) break;
+ mNotification.update(now);
+
+ if (heavyCheck) {
+ i = 10;
+ if (checkConnectivity()) checkDns();
}
- mNotification.update();
- checkDns();
- VpnService.this.wait(1000); // 1 second
+ long t = 1000L - System.currentTimeMillis() + now;
+ if (t > 100L) VpnService.this.wait(t);
}
}
} catch (InterruptedException e) {
@@ -378,7 +370,7 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
// returns false if vpn connectivity is broken
private boolean checkConnectivity() {
- if (mDaemonHelper.anyDaemonStopped() || isLocalIpChanged()) {
+ if (mDaemons.anyDaemonStopped() || isLocalIpChanged()) {
onError(new IOException("Connectivity lost"));
return false;
} else {
@@ -421,60 +413,17 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
}
private class DaemonHelper implements Serializable {
- private List<DaemonProxy> mDaemonList =
- new ArrayList<DaemonProxy>();
-
- synchronized DaemonProxy startDaemon(String daemonName)
- throws IOException {
- DaemonProxy daemon = new DaemonProxy(daemonName);
- mDaemonList.add(daemon);
- daemon.start();
- return daemon;
- }
-
- synchronized void stopAll() {
- for (DaemonProxy s : mDaemonList) s.stop();
- }
-
- synchronized void closeSockets() {
- for (DaemonProxy s : mDaemonList) s.closeControlSocket();
- }
-
- synchronized boolean anyDaemonStopped() {
- for (DaemonProxy s : mDaemonList) {
- if (s.isStopped()) {
- Log.w(TAG, " VPN daemon gone: " + s.getName());
- return true;
- }
- }
- return false;
- }
-
- private int getResultFromSocket(DaemonProxy s) {
- try {
- return s.getResultFromSocket();
- } catch (IOException e) {
- return -1;
- }
- }
-
- synchronized int getSocketError() {
- for (DaemonProxy s : mDaemonList) {
- int errCode = getResultFromSocket(s);
- if (errCode != 0) return errCode;
- }
- return 0;
- }
}
// Helper class for showing, updating notification.
private class NotificationHelper {
- void update() {
+ void update(long now) {
String title = getNotificationTitle(true);
Notification n = new Notification(R.drawable.vpn_connected, title,
mStartTime);
n.setLatestEventInfo(mContext, title,
- getNotificationMessage(true), prepareNotificationIntent());
+ getConnectedNotificationMessage(now),
+ prepareNotificationIntent());
n.flags |= Notification.FLAG_NO_CLEAR;
n.flags |= Notification.FLAG_ONGOING_EVENT;
enableNotification(n);
@@ -485,7 +434,8 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
Notification n = new Notification(R.drawable.vpn_disconnected,
title, System.currentTimeMillis());
n.setLatestEventInfo(mContext, title,
- getNotificationMessage(false), prepareNotificationIntent());
+ getDisconnectedNotificationMessage(),
+ prepareNotificationIntent());
n.flags |= Notification.FLAG_AUTO_CANCEL;
disableNotification();
enableNotification(n);
@@ -515,8 +465,8 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
return String.format(formatString, mProfile.getName());
}
- private String getFormattedTime(long duration) {
- long hours = duration / 3600;
+ private String getFormattedTime(int duration) {
+ int hours = duration / 3600;
StringBuilder sb = new StringBuilder();
if (hours > 0) sb.append(hours).append(':');
sb.append(String.format("%02d:%02d", (duration % 3600 / 60),
@@ -524,14 +474,13 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
return sb.toString();
}
- private String getNotificationMessage(boolean connected) {
- if (connected) {
- long time = (System.currentTimeMillis() - mStartTime) / 1000;
- return getFormattedTime(time);
- } else {
- return mContext.getString(
- R.string.vpn_notification_hint_disconnected);
- }
+ private String getConnectedNotificationMessage(long now) {
+ return getFormattedTime((int) (now - mStartTime) / 1000);
+ }
+
+ private String getDisconnectedNotificationMessage() {
+ return mContext.getString(
+ R.string.vpn_notification_hint_disconnected);
}
}
}