Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4005648e authored by Android (Google) Code Review's avatar Android (Google) Code Review Committed by The Android Open Source Project
Browse files

am 575eb928: Merge change 6883 into donut

Merge commit '575eb928'

* commit '575eb928':
  Add error code in vpn connectivity broadcast.
parents a62e3e4d 575eb928
Loading
Loading
Loading
Loading
+32 −22
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.vpn;

import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.net.vpn.VpnManager;
import android.os.SystemProperties;
import android.util.Log;

@@ -48,6 +49,9 @@ public class AndroidServiceProxy extends ProcessProxy {

    private static final int END_OF_ARGUMENTS = 255;

    private static final int STOP_SERVICE = -1;
    private static final int AUTH_ERROR_CODE = 51;

    private String mServiceName;
    private String mSocketName;
    private LocalSocket mKeepaliveSocket;
@@ -72,14 +76,21 @@ public class AndroidServiceProxy extends ProcessProxy {

    @Override
    public synchronized void stop() {
        if (isRunning()) setResultAndCloseControlSocket(-1);
        if (isRunning()) {
            try {
                setResultAndCloseControlSocket(STOP_SERVICE);
            } catch (IOException e) {
                // should not occur
                throw new RuntimeException(e);
            }
        }
        SystemProperties.set(SVC_STOP_CMD, mServiceName);
    }

    /**
     * Sends a command with arguments to the service through the control socket.
     */
    public void sendCommand(String ...args) throws IOException {
    public synchronized void sendCommand(String ...args) throws IOException {
        OutputStream out = getControlSocketOutput();
        for (String arg : args) outputString(out, arg);
        out.write(END_OF_ARGUMENTS);
@@ -114,30 +125,22 @@ public class AndroidServiceProxy extends ProcessProxy {
                    InputStream in = s.getInputStream();
                    int data = in.read();
                    if (data >= 0) {
                        Log.d(mTag, "got data from keepalive socket: " + data);
                        Log.d(mTag, "got data from control socket: " + data);

                        if (data == 0) {
                            // re-establish the connection:
                            // synchronized here so that checkSocketResult()
                            // returns when new mKeepaliveSocket is available for
                            // next cmd
                            synchronized (this) {
                                setResultAndCloseControlSocket((byte) data);
                                s = mKeepaliveSocket = createServiceSocket();
                            }
                        } else {
                            // keep the socket
                        setSocketResult(data);
                        }
                    } else {
                        // service is gone
                        if (mControlSocketInUse) setSocketResult(-1);
                        break;
                    }
                }
                Log.d(mTag, "keepalive connection closed");
                Log.d(mTag, "control connection closed");
            } catch (IOException e) {
                Log.d(mTag, "keepalive socket broken: " + e.getMessage());
                if (e instanceof VpnConnectingError) {
                    throw e;
                } else {
                    Log.d(mTag, "control socket broken: " + e.getMessage());
                }
            }

            // Wait 5 seconds for the service to exit
@@ -179,7 +182,7 @@ public class AndroidServiceProxy extends ProcessProxy {
        }
    }

    private synchronized void checkSocketResult() throws IOException {
    private void checkSocketResult() throws IOException {
        try {
            // will be notified when the result comes back from service
            if (mSocketResult == null) wait();
@@ -194,14 +197,21 @@ public class AndroidServiceProxy extends ProcessProxy {
        }
    }

    private synchronized void setSocketResult(int result) {
    private synchronized void setSocketResult(int result)
            throws VpnConnectingError {
        if (mControlSocketInUse) {
            mSocketResult = result;
            notifyAll();
        } else if (result > 0) {
            // error from daemon
            throw new VpnConnectingError((result == AUTH_ERROR_CODE)
                    ? VpnManager.VPN_ERROR_AUTH
                    : VpnManager.VPN_ERROR_CONNECTION_FAILED);
        }
    }

    private void setResultAndCloseControlSocket(int result) {
    private void setResultAndCloseControlSocket(int result)
            throws VpnConnectingError {
        setSocketResult(result);
        try {
            mKeepaliveSocket.shutdownInput();
+35 −0
Original line number Diff line number Diff line
/*
 * 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;

/**
 * Exception thrown when a connecting attempt fails.
 */
class VpnConnectingError extends IOException {
    private int mErrorCode;

    VpnConnectingError(int errorCode) {
        super("Connecting error: " + errorCode);
        mErrorCode = errorCode;
    }

    int getErrorCode() {
        return mErrorCode;
    }
}
+40 −15
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
@@ -46,9 +47,9 @@ abstract class VpnService<E extends VpnProfile> {
    private static final String DNS2 = "net.dns2";
    private static final String VPN_DNS1 = "vpn.dns1";
    private static final String VPN_DNS2 = "vpn.dns2";
    private static final String VPN_UP = "vpn.up";
    private static final String VPN_IS_UP = "1";
    private static final String VPN_IS_DOWN = "0";
    private static final String VPN_STATUS = "vpn.status";
    private static final String VPN_IS_UP = "ok";
    private static final String VPN_IS_DOWN = "down";

    private static final String REMOTE_IP = "net.ipremote";
    private static final String DNS_DOMAIN_SUFFICES = "net.dns.search";
@@ -60,6 +61,7 @@ abstract class VpnService<E extends VpnProfile> {

    private VpnState mState = VpnState.IDLE;
    private boolean mInError;
    private VpnConnectingError mError;

    // connection settings
    private String mOriginalDns1;
@@ -166,8 +168,8 @@ abstract class VpnService<E extends VpnProfile> {
        return mState;
    }

    synchronized void onConnect(String username, String password)
            throws IOException {
    synchronized boolean onConnect(String username, String password) {
        try {
            mState = VpnState.CONNECTING;
            broadcastConnectivity(VpnState.CONNECTING);

@@ -176,6 +178,13 @@ abstract class VpnService<E extends VpnProfile> {
            onBeforeConnect();
            connect(serverIp, username, password);
            waitUntilConnectedOrTimedout();
            return true;
        } catch (Throwable e) {
            Log.e(TAG, "onConnect()", e);
            mError = newConnectingError(e);
            onError();
            return false;
        }
    }

    synchronized void onDisconnect(boolean cleanUpServices) {
@@ -214,8 +223,8 @@ abstract class VpnService<E extends VpnProfile> {

        SystemProperties.set(VPN_DNS1, "-");
        SystemProperties.set(VPN_DNS2, "-");
        SystemProperties.set(VPN_UP, VPN_IS_DOWN);
        Log.d(TAG, "       VPN UP: " + SystemProperties.get(VPN_UP));
        SystemProperties.set(VPN_STATUS, VPN_IS_DOWN);
        Log.d(TAG, "       VPN UP: " + SystemProperties.get(VPN_STATUS));
    }

    private void waitUntilConnectedOrTimedout() {
@@ -224,7 +233,7 @@ abstract class VpnService<E extends VpnProfile> {
            public void run() {
                sleep(2000); // 2 seconds
                for (int i = 0; i < 60; i++) {
                    if (VPN_IS_UP.equals(SystemProperties.get(VPN_UP))) {
                    if (VPN_IS_UP.equals(SystemProperties.get(VPN_STATUS))) {
                        onConnected();
                        return;
                    } else if (mState != VpnState.CONNECTING) {
@@ -271,6 +280,13 @@ abstract class VpnService<E extends VpnProfile> {
        mContext.stopSelf();
    }

    private VpnConnectingError newConnectingError(Throwable e) {
        return new VpnConnectingError(
                (e instanceof UnknownHostException)
                ? VpnManager.VPN_ERROR_UNKNOWN_SERVER
                : VpnManager.VPN_ERROR_CONNECTION_FAILED);
    }

    private synchronized void onOneServiceGone() {
        switch (mState) {
        case IDLE:
@@ -347,7 +363,13 @@ abstract class VpnService<E extends VpnProfile> {
    }

    private void broadcastConnectivity(VpnState s) {
        new VpnManager(mContext).broadcastConnectivity(mProfile.getName(), s);
        VpnManager m = new VpnManager(mContext);
        if ((s == VpnState.IDLE) && (mError != null)) {
            m.broadcastConnectivity(mProfile.getName(), s,
                    mError.getErrorCode());
        } else {
            m.broadcastConnectivity(mProfile.getName(), s);
        }
    }

    private void startConnectivityMonitor() {
@@ -447,6 +469,9 @@ abstract class VpnService<E extends VpnProfile> {
        //@Override
        public void error(ProcessProxy p, Throwable e) {
            Log.e(TAG, "service error: " + p.getName(), e);
            if (e instanceof VpnConnectingError) {
                mError = (VpnConnectingError) e;
            }
            commonCallback((AndroidServiceProxy) p);
        }

+7 −10
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.net.vpn.VpnManager;
import android.net.vpn.VpnProfile;
import android.net.vpn.VpnState;
import android.os.IBinder;
import android.util.Log;

import java.io.IOException;

@@ -55,6 +54,11 @@ public class VpnServiceBinder extends Service {
        }
    };

    public void onStart (Intent intent, int startId) {
        super.onStart(intent, startId);
        setForeground(true);
    }

    public IBinder onBind(Intent intent) {
        return mBinder;
    }
@@ -62,15 +66,8 @@ public class VpnServiceBinder extends Service {
    private synchronized boolean connect(
            VpnProfile p, String username, String password) {
        if (mService != null) return false;
        try {
        mService = createService(p);
            mService.onConnect(username, password);
            return true;
        } catch (Throwable e) {
            Log.e(TAG, "connect()", e);
            if (mService != null) mService.onError();
            return false;
        }
        return mService.onConnect(username, password);
    }

    private synchronized void checkStatus(VpnProfile p) {
+20 −1
Original line number Diff line number Diff line
@@ -42,6 +42,15 @@ public class VpnManager {
    public static final String BROADCAST_PROFILE_NAME = "profile_name";
    /** Key to the connectivity state of a connectivity broadcast event. */
    public static final String BROADCAST_CONNECTION_STATE = "connection_state";
    /** Key to the error code of a connectivity broadcast event. */
    public static final String BROADCAST_ERROR_CODE = "err";
    /** Error code to indicate an error from authentication. */
    public static final int VPN_ERROR_AUTH = 1;
    /** Error code to indicate the connection attempt failed. */
    public static final int VPN_ERROR_CONNECTION_FAILED = 2;
    /** Error code to indicate the server is not known. */
    public static final int VPN_ERROR_UNKNOWN_SERVER = 3;
    private static final int VPN_ERROR_NO_ERROR = 0;

    public static final String PROFILES_PATH = "/data/misc/vpn/profiles";

@@ -52,7 +61,8 @@ public class VpnManager {
    private static final String ACTION_VPN_SERVICE = PACKAGE_PREFIX + "SERVICE";

    // Action to start VPN settings
    private static final String ACTION_VPN_SETTINGS = PACKAGE_PREFIX + "SETTINGS";
    private static final String ACTION_VPN_SETTINGS =
            PACKAGE_PREFIX + "SETTINGS";

    private static final String TAG = VpnManager.class.getSimpleName();

@@ -130,9 +140,18 @@ public class VpnManager {

    /** Broadcasts the connectivity state of the specified profile. */
    public void broadcastConnectivity(String profileName, VpnState s) {
        broadcastConnectivity(profileName, s, VPN_ERROR_NO_ERROR);
    }

    /** Broadcasts the connectivity state with an error code. */
    public void broadcastConnectivity(String profileName, VpnState s,
            int error) {
        Intent intent = new Intent(ACTION_VPN_CONNECTIVITY);
        intent.putExtra(BROADCAST_PROFILE_NAME, profileName);
        intent.putExtra(BROADCAST_CONNECTION_STATE, s);
        if (error != VPN_ERROR_NO_ERROR) {
            intent.putExtra(BROADCAST_ERROR_CODE, error);
        }
        mContext.sendBroadcast(intent);
    }