/*
 * Copyright (C) 2017 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.
 */

#ifndef INCLUDE_PERFETTO_EXT_IPC_CLIENT_H_
#define INCLUDE_PERFETTO_EXT_IPC_CLIENT_H_

#include <functional>
#include <memory>

#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/unix_socket.h"
#include "perfetto/ext/base/weak_ptr.h"
#include "perfetto/ext/ipc/basic_types.h"

namespace perfetto {

namespace base {
class TaskRunner;
}  // namespace base

namespace ipc {
class ServiceProxy;

// The client-side class that talks to the host over the socket and multiplexes
// requests coming from the various autogenerated ServiceProxy stubs.
// This is meant to be used by the user code as follows:
// auto client = Client::CreateInstance("socket_name", task_runner);
// std::unique_ptr<GreeterService> svc(new GreeterService());
// client.BindService(svc);
// svc.OnConnect([] () {
//    svc.SayHello(..., ...);
// });
class Client {
 public:
  // struct ConnArgs is used for creating a client in 2 connection modes:
  // 1. Connect using a socket name with the option to retry the connection on
  //    connection failure.
  // 2. Adopt a connected socket.
  struct ConnArgs {
    ConnArgs(const char* sock_name, bool sock_retry)
        : socket_name(sock_name), retry(sock_retry) {}
    explicit ConnArgs(base::ScopedSocketHandle sock_fd)
        : socket_fd(std::move(sock_fd)) {}

    // Disallow copy. Only supports move.
    ConnArgs(const ConnArgs& other) = delete;
    ConnArgs(ConnArgs&& other) = default;

    base::ScopedSocketHandle socket_fd;
    const char* socket_name = nullptr;
    bool retry = false;  // Only for connecting with |socket_name|.
    std::function<int(void)> receive_shmem_fd_cb_fuchsia;
  };

  static std::unique_ptr<Client> CreateInstance(ConnArgs, base::TaskRunner*);
  virtual ~Client();

  virtual void BindService(base::WeakPtr<ServiceProxy>) = 0;

  // There is no need to call this method explicitly. Destroying the
  // ServiceProxy instance is sufficient and will automatically unbind it. This
  // method is exposed only for the ServiceProxy destructor.
  virtual void UnbindService(ServiceID) = 0;

  // Returns (with move semantics) the last file descriptor received on the IPC
  // channel. No buffering is performed: if a service sends two file descriptors
  // and the caller doesn't read them immediately, the first one will be
  // automatically closed when the second is received (and will hit a DCHECK in
  // debug builds).
  virtual base::ScopedFile TakeReceivedFD() = 0;
};

}  // namespace ipc
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_EXT_IPC_CLIENT_H_
