/*
 * 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.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.net.vpn.VpnManager;
import android.os.SystemProperties;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Proxy to start, stop and interact with a VPN daemon.
 * The daemon is expected to accept connection through Unix domain socket.
 * When the proxy successfully starts the daemon, it will establish a socket
 * connection with the daemon, to both send commands to the daemon and receive
 * response and connecting error code from the daemon.
 */
class DaemonProxy {
    private static final int WAITING_TIME = 15; // sec

    private static final String SVC_STATE_CMD_PREFIX = "init.svc.";
    private static final String SVC_START_CMD = "ctl.start";
    private static final String SVC_STOP_CMD = "ctl.stop";
    private static final String SVC_STATE_RUNNING = "running";
    private static final String SVC_STATE_STOPPED = "stopped";

    private static final int END_OF_ARGUMENTS = 255;

    private String mName;
    private LocalSocket mControlSocket;
    private String mTag;

    /**
     * Creates a proxy of the specified daemon.
     * @param daemonName name of the daemon
     */
    DaemonProxy(String daemonName) {
        mName = daemonName;
        mTag = "SProxy_" + daemonName;
    }

    String getName() {
        return mName;
    }

    void start() throws IOException {
        String svc = mName;
        Log.d(mTag, "-----  Stop the daemon just in case: " + mName);
        SystemProperties.set(SVC_STOP_CMD, mName);
        if (!blockUntil(SVC_STATE_STOPPED, 5)) {
            throw new IOException("cannot start service anew: " + svc
                    + ", it is still running");
        }

        Log.d(mTag, "+++++  Start: " + svc);
        SystemProperties.set(SVC_START_CMD, svc);

        if (!blockUntil(SVC_STATE_RUNNING, WAITING_TIME)) {
            throw new IOException("cannot start service: " + svc);
        } else {
            mControlSocket = createServiceSocket();
        }
    }

    void sendCommand(String ...args) throws IOException {
        OutputStream out = getControlSocketOutput();
        for (String arg : args) outputString(out, arg);
        out.write(END_OF_ARGUMENTS);
        out.flush();

        int result = getResultFromSocket(true);
        if (result != args.length) {
            throw new IOException("socket error, result from service: "
                    + result);
        }
    }

    // returns 0 if nothing is in the receive buffer
    int getResultFromSocket() throws IOException {
        return getResultFromSocket(false);
    }

    void closeControlSocket() {
        if (mControlSocket == null) return;
        try {
            mControlSocket.close();
        } catch (IOException e) {
            Log.e(mTag, "close control socket", e);
        } finally {
            mControlSocket = null;
        }
    }

    void stop() {
        String svc = mName;
        Log.d(mTag, "-----  Stop: " + svc);
        SystemProperties.set(SVC_STOP_CMD, svc);
        boolean success = blockUntil(SVC_STATE_STOPPED, 5);
        Log.d(mTag, "stopping " + svc + ", success? " + success);
    }

    boolean isStopped() {
        String cmd = SVC_STATE_CMD_PREFIX + mName;
        return SVC_STATE_STOPPED.equals(SystemProperties.get(cmd));
    }

    private int getResultFromSocket(boolean blocking) throws IOException {
        LocalSocket s = mControlSocket;
        if (s == null) return 0;
        InputStream in = s.getInputStream();
        if (!blocking && in.available() == 0) return 0;

        int data = in.read();
        Log.d(mTag, "got data from control socket: " + data);

        return data;
    }

    private LocalSocket createServiceSocket() throws IOException {
        LocalSocket s = new LocalSocket();
        LocalSocketAddress a = new LocalSocketAddress(mName,
                LocalSocketAddress.Namespace.RESERVED);

        // try a few times in case the service has not listen()ed
        IOException excp = null;
        for (int i = 0; i < 10; i++) {
            try {
                s.connect(a);
                return s;
            } catch (IOException e) {
                Log.d(mTag, "service not yet listen()ing; try again");
                excp = e;
                sleep(500);
            }
        }
        throw excp;
    }

    private OutputStream getControlSocketOutput() throws IOException {
        if (mControlSocket != null) {
            return mControlSocket.getOutputStream();
        } else {
            throw new IOException("no control socket available");
        }
    }

    /**
     * Waits for the process to be in the expected state. The method returns
     * false if after the specified duration (in seconds), the process is still
     * not in the expected state.
     */
    private boolean blockUntil(String expectedState, int waitTime) {
        String cmd = SVC_STATE_CMD_PREFIX + mName;
        int sleepTime = 200; // ms
        int n = waitTime * 1000 / sleepTime;
        for (int i = 0; i < n; i++) {
            if (expectedState.equals(SystemProperties.get(cmd))) {
                Log.d(mTag, mName + " is " + expectedState + " after "
                        + (i * sleepTime) + " msec");
                break;
            }
            sleep(sleepTime);
        }
        return expectedState.equals(SystemProperties.get(cmd));
    }

    private void outputString(OutputStream out, String s) throws IOException {
        byte[] bytes = s.getBytes();
        out.write(bytes.length);
        out.write(bytes);
        out.flush();
    }

    private void sleep(int msec) {
        try {
            Thread.currentThread().sleep(msec);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
