// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef GARNET_LIB_MACHINA_VIRTIO_VSOCK_H_
#define GARNET_LIB_MACHINA_VIRTIO_VSOCK_H_

#include <unordered_map>
#include <unordered_set>

#include <fuchsia/guest/cpp/fidl.h>
#include <virtio/virtio_ids.h>
#include <virtio/vsock.h>
#include <zx/socket.h>

#include "garnet/lib/machina/virtio_device.h"
#include "garnet/lib/machina/virtio_queue_waiter.h"
#include "lib/app/cpp/startup_context.h"
#include "lib/fidl/cpp/binding_set.h"

namespace machina {

static constexpr uint16_t kVirtioVsockNumQueues = 3;

class VirtioVsock
    : public VirtioDeviceBase<VIRTIO_ID_VSOCK, kVirtioVsockNumQueues,
                              virtio_vsock_config_t>,
      public fuchsia::guest::SocketEndpoint,
      public fuchsia::guest::SocketAcceptor {
 public:
  VirtioVsock(fuchsia::sys::StartupContext* context, const PhysMem&,
              async_t* async);

  uint32_t guest_cid() const;

  // Check whether a connection exists. The connection is identified by a local
  // tuple, local_cid/local_port, and a remote tuple, guest_cid/remote_port. The
  // local tuple identifies the host-side of the connection, and the remote
  // tuple identifies the guest-side of the connection.
  bool HasConnection(uint32_t local_cid, uint32_t local_port,
                     uint32_t remote_port) const;

  VirtioQueue* rx_queue() { return queue(0); }
  VirtioQueue* tx_queue() { return queue(1); }

 private:
  // |fuchsia::guest::SocketEndpoint|
  void SetContextId(
      uint32_t cid,
      fidl::InterfaceHandle<fuchsia::guest::SocketConnector> connector,
      fidl::InterfaceRequest<fuchsia::guest::SocketAcceptor> acceptor) override;
  // |fuchsia::guest::SocketAcceptor|
  void Accept(uint32_t src_cid, uint32_t src_port, uint32_t port,
              AcceptCallback callback) override;

  struct ConnectionKey {
    // The host-side of the connection is represented by local_cid and
    // local_port.
    uint32_t local_cid;
    uint32_t local_port;
    // The guest-side of the connection is represented by guest_cid and
    // remote_port.
    uint32_t remote_port;
    bool operator==(const ConnectionKey& key) const {
      return local_cid == key.local_cid && local_port == key.local_port &&
             remote_port == key.remote_port;
    }
  };
  struct ConnectionHash {
    size_t operator()(const ConnectionKey& key) const {
      return ((static_cast<size_t>(key.local_cid) << 32) | key.local_port) ^
             (key.remote_port << 16);
    }
  };
  class Connection {
   public:
    ~Connection();

    // The number of bytes the guest expects us to have in our socket buffer.
    // This is the last credit_update sent minus any bytes we've received since
    // that update was sent.
    //
    // When this is 0 we'll need to send a CREDIT_UPDATE once buffer space has
    // been free'd so that the guest knows it can resume transmitting.
    size_t reported_buf_avail = 0;

    uint32_t flags = 0;
    uint32_t rx_cnt = 0;
    uint32_t tx_cnt = 0;
    uint32_t peer_buf_alloc = 0;
    uint32_t peer_fwd_cnt = 0;
    zx::socket socket;
    zx::socket remote_socket;
    async::Wait rx_wait;
    async::Wait tx_wait;
    fuchsia::guest::SocketAcceptor::AcceptCallback acceptor;

    uint16_t op() const { return op_; }
    void UpdateOp(uint16_t op);

    uint32_t peer_free() const {
      return peer_buf_alloc - (tx_cnt - peer_fwd_cnt);
    }

   private:
    uint16_t op_ = VIRTIO_VSOCK_OP_REQUEST;
  };
  using ConnectionMap =
      std::unordered_map<ConnectionKey, fbl::unique_ptr<Connection>,
                         ConnectionHash>;
  using ConnectionSet = std::unordered_set<ConnectionKey, ConnectionHash>;

  using StreamFunc = void (VirtioVsock::*)(zx_status_t, uint16_t);
  template <StreamFunc F>
  class Stream {
   public:
    Stream(async_t* async, VirtioQueue* queue, VirtioVsock* device);

    zx_status_t WaitOnQueue();

   private:
    VirtioQueueWaiter waiter_;
  };

  void ConnectCallback(ConnectionKey key, zx_status_t status,
                       zx::socket socket);
  zx_status_t SetupConnection(ConnectionKey key, Connection* conn);
  zx_status_t AddConnectionLocked(ConnectionKey key,
                                  fbl::unique_ptr<Connection> conn)
      __TA_REQUIRES(mutex_);
  Connection* GetConnectionLocked(ConnectionKey key) __TA_REQUIRES(mutex_);
  virtio_vsock_hdr_t* GetHeaderLocked(VirtioQueue* queue, uint16_t index,
                                      virtio_desc_t* desc, bool writable)
      __TA_REQUIRES(mutex_);

  template <StreamFunc F>
  zx_status_t WaitOnQueueLocked(ConnectionKey key, ConnectionSet* keys,
                                Stream<F>* stream) __TA_REQUIRES(mutex_);
  void WaitOnSocketLocked(zx_status_t status, ConnectionKey key,
                          async::Wait* wait) __TA_REQUIRES(mutex_);

  void OnSocketReady(async_t* async, async::Wait* wait, zx_status_t status,
                     const zx_packet_signal_t* signal, ConnectionKey key);

  void Mux(zx_status_t status, uint16_t index);
  zx_status_t SendMessageForConnectionLocked(const ConnectionKey& key,
                                             Connection* conn, uint16_t desc,
                                             uint32_t* used)
      __TA_REQUIRES(mutex_);
  void Demux(zx_status_t status, uint16_t index);

  async_t* const async_;
  Stream<&VirtioVsock::Mux> rx_stream_;
  Stream<&VirtioVsock::Demux> tx_stream_;

  // TODO(PD-117): Evaluate granularity of locking.
  mutable fbl::Mutex mutex_;
  ConnectionMap connections_ __TA_GUARDED(mutex_);
  ConnectionSet readable_ __TA_GUARDED(mutex_);
  // NOTE(abdulla): We ignore the event queue, as we don't support VM migration.

  fidl::BindingSet<fuchsia::guest::SocketAcceptor> acceptor_bindings_;
  fidl::BindingSet<fuchsia::guest::SocketEndpoint> endpoint_bindings_;
  fuchsia::guest::SocketConnectorPtr connector_;
};

}  // namespace machina

#endif  // GARNET_LIB_MACHINA_VIRTIO_VSOCK_H_
