// Copyright 2016 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

#pragma once

#include "android/base/async/Looper.h"
#include "android/base/async/ScopedSocketWatch.h"
#include "android/base/StringView.h"
#include "android/emulation/AndroidPipe.h"
#include "android/emulation/AdbTypes.h"

#include <vector>

namespace android {
namespace emulation {

// AdbGuestPipe implements an AndroidPipe instance corresponding to the guest
// connections from the adbd daemon to the 'qemud:adb' service. Each instance
// is used to implement a single 'transport' between adbd and the host ADB
// server.
//
// The emulator implements two classes to support this: AdbGuestPipe and
// AdbHostListener and everything is linked at runtime like this:
//
//       guest side            |            emulator                   |     host
//
//   adbd <--> /dev/qemu_pipe <--> AdbGuestPipe <--> AdbHostListener <--> ADB Server
//
// There is a little protocol between adbd and the emulator which looks like:
//
//   1) Guest opens /dev/qemu_pipe and writes 'pipe:qemud:adb:<port>\0' to
//      connect to the ADB pipe service, where <port> is a decimal port
//      number (5555 by default). The port number is guest-specific and
//      should be ignored (it is assumed to be here for obsolete reasons).
//
//      -> This ends up calling AdbGuestPipe::Service::create() to create a new
//         instance.
//
//   2) Guest writes 'accept' to tell the emulator to start accepting
//      connections from the ADB server.
//
//   3) Once a connection from the ADB server is established, the emulator
//      should send back 'ok' (or 'ko' / closing the connection to indicate
//      an error).
//
//   4) The guest will write 'start' to indicate it is ready to exchange
//      data with the host ADB server (all data on the pipe should be
//      proxied between the two at this point).
//
// IMPORTANT NOTE: The adbd daemon will typically create a new AdbGuestPipe
//                 instance just after that, but it will only 'accept'
//                 one at a time. For more details see qemu_socket_thread()
//                 in $AOSP/system/core/adb/transport_local.cpp
//
// Usage is the following:
//
//   1) Create a new AdbGuestPipe::Service instance, passing a valid
//      AdbHostAgent instance to it (in practice an AdbHostListener one).
//      Then call AndroidPipe::Service::add() to register it.
//
// NOTE: This must be done at emulation setup time from the QEMU main loop!
//
class AdbGuestPipe : public AndroidPipe {
public:
    using StringView = ::android::base::StringView;
    using ScopedSocket = ::android::base::ScopedSocket;

    // AndroidPipe::Service class
    class Service : public AndroidPipe::Service, public AdbGuestAgent {
    public:
        Service(AdbHostAgent* hostAgent)
            : AndroidPipe::Service("qemud:adb"), mHostAgent(hostAgent) {}

        // Create a new AdbGuestPipe instance.
        virtual AndroidPipe* create(void* mHwPipe, const char* args) override;

        // Can't save their state to disk.
        virtual bool canLoad() const override { return false; }

        // Overridden AdbGuestAgent method.
        virtual void onHostConnection(ScopedSocket&& socket) override;

        // Called when a new adb pipe connection is opened by
        // the guest. Note that this does *not* transfer ownership of |pipe|.
        // Technically, AndroidPipe instances are owned by the virtual device.
        // except when onGuestClose() is called (which should destroy it).
        void onPipeOpen(AdbGuestPipe* pipe);

        // Called when the guest closes a pipe. This must delete the instance.
        void onPipeClose(AdbGuestPipe* pipe);

        // If there is no active pipe, search for an item in |mPipes| that
        // is in the WaitingForHostAdbConnection state, when found record
        // it as the active pipe and tell the host agent to start listening
        // for host connections.
        void searchForActivePipe();

    private:
        AdbHostAgent* mHostAgent;
        AdbGuestPipe* mActivePipe = nullptr;
        std::vector<AdbGuestPipe*> mPipes;
    };

    virtual ~AdbGuestPipe();

    // Overridden AndroidPipe methods. Called from the device context.
    virtual void onGuestClose() override;
    virtual unsigned onGuestPoll() const override;
    virtual int onGuestRecv(AndroidPipeBuffer* buffers, int count) override;
    virtual int onGuestSend(const AndroidPipeBuffer* buffers,
                            int count) override;
    virtual void onGuestWantWakeOn(int flags) override;

    // Called when a host connection occurs. Transfers ownership of
    // |socket| to the pipe. On success, return true, on error return
    // false and closes the socket.
    void onHostConnection(ScopedSocket&& socket);

private:
    AdbGuestPipe(void* mHwPipe, Service* service, AdbHostAgent* hostAgent)
        : AndroidPipe(mHwPipe, service), mHostAgent(hostAgent) {
        setExpectedGuestCommand("accept", State::WaitingForGuestAcceptCommand);
    }

    // Return current service with the right type.
    Service* service() const {
        return static_cast<AdbGuestPipe::Service*>(mService);
    }

    // Each pipe instance can be in one of these states:
    enum class State {
        WaitingForGuestAcceptCommand,
        WaitingForHostAdbConnection,
        SendingAcceptReplyOk,
        WaitingForGuestStartCommand,
        ProxyingData,
        ClosedByGuest,
        ClosedByHost,
    };

    // Used for debugging.
    static const char* toString(State);

    // Called when an i/o event occurs on the host socket.
    // |events| is a mask of FdWatch::kEventXXX flags.
    void onHostSocketEvent(unsigned events);

    // Implement onGuestRecv() and onGuestSend() while proxying the data
    // between the guest and the host.
    int onGuestRecvData(AndroidPipeBuffer* buffers, int count);
    int onGuestSendData(const AndroidPipeBuffer* buffers, int count);

    // Implement onGuestRecv() when sending a reply to the guest.
    int onGuestRecvReply(AndroidPipeBuffer* buffers, int count);

    // Implement onGuestSend() when receiving a command from the guest.
    int onGuestSendCommand(const AndroidPipeBuffer* buffers, int count);

    // Set the reply to send to the guest as |reply|, and change the state
    // to |newState|.
    void setReply(StringView reply, State newState);

    // Set the expected |command| to wait from the guest, and change the
    // state to |newState|.
    void setExpectedGuestCommand(StringView command, State newState);

    // Try to wait for a new host connection. Change the state according to
    // whether one already occured or not.
    void waitForHostConnection();

    // Command/reply buffer and cursor.
    char mBuffer[16];        // the command being accepted or reply being sent.
    size_t mBufferSize = 0;  // size of valid bytes in mBuffer.
    size_t mBufferPos = 0;   // number of matched command bytes on input/output.

    State mState = State::WaitingForGuestAcceptCommand;  // current pipe state.
    android::base::ScopedSocketWatch
            mHostSocket;  // current host socket, if connected.
    AdbHostAgent* mHostAgent = nullptr;
};

}  // namespace emulation
}  // namespace android
