blob: 43e60451d199bbcb56c0f717231aef9154ac2d9c [file] [log] [blame]
/*
* 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 SRC_IPC_CLIENT_IMPL_H_
#define SRC_IPC_CLIENT_IMPL_H_
#include <list>
#include <map>
#include <memory>
#include "perfetto/base/task_runner.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/unix_socket.h"
#include "perfetto/ext/ipc/client.h"
#include "src/ipc/buffered_frame_deserializer.h"
namespace perfetto {
namespace protos {
namespace gen {
class IPCFrame_BindServiceReply;
class IPCFrame_InvokeMethodReply;
} // namespace gen
} // namespace protos
namespace base {
class TaskRunner;
} // namespace base
namespace ipc {
class ServiceDescriptor;
class ClientImpl : public Client, public base::UnixSocket::EventListener {
public:
ClientImpl(ConnArgs, base::TaskRunner*);
~ClientImpl() override;
// Client implementation.
void BindService(base::WeakPtr<ServiceProxy>) override;
void UnbindService(ServiceID) override;
base::ScopedFile TakeReceivedFD() override;
// base::UnixSocket::EventListener implementation.
void OnConnect(base::UnixSocket*, bool connected) override;
void OnDisconnect(base::UnixSocket*) override;
void OnDataAvailable(base::UnixSocket*) override;
RequestID BeginInvoke(ServiceID,
const std::string& method_name,
MethodID remote_method_id,
const ProtoMessage& method_args,
bool drop_reply,
base::WeakPtr<ServiceProxy>,
int fd = -1);
base::UnixSocket* GetUnixSocketForTesting() { return sock_.get(); }
private:
struct QueuedRequest {
QueuedRequest();
int type = 0; // From Frame::msg_case(), see wire_protocol.proto.
RequestID request_id = 0;
base::WeakPtr<ServiceProxy> service_proxy;
// Only for type == kMsgInvokeMethod.
std::string method_name;
};
ClientImpl(const ClientImpl&) = delete;
ClientImpl& operator=(const ClientImpl&) = delete;
void TryConnect();
bool SendFrame(const Frame&, int fd = -1);
void OnFrameReceived(const Frame&);
void OnBindServiceReply(QueuedRequest,
const protos::gen::IPCFrame_BindServiceReply&);
void OnInvokeMethodReply(QueuedRequest,
const protos::gen::IPCFrame_InvokeMethodReply&);
bool invoking_method_reply_ = false;
const char* socket_name_ = nullptr;
bool socket_retry_ = false;
uint32_t socket_backoff_ms_ = 0;
std::unique_ptr<base::UnixSocket> sock_;
base::TaskRunner* const task_runner_;
RequestID last_request_id_ = 0;
BufferedFrameDeserializer frame_deserializer_;
base::ScopedFile received_fd_;
std::map<RequestID, QueuedRequest> queued_requests_;
std::map<ServiceID, base::WeakPtr<ServiceProxy>> service_bindings_;
// Queue of calls to BindService() that happened before the socket connected.
std::list<base::WeakPtr<ServiceProxy>> queued_bindings_;
base::WeakPtrFactory<Client> weak_ptr_factory_; // Keep last.
};
} // namespace ipc
} // namespace perfetto
#endif // SRC_IPC_CLIENT_IMPL_H_