blob: 99012efab194a8f7bf9137e35d14d1b127ca3fbf [file] [log] [blame] [edit]
// Copyright 2019 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.
#include "fake_trace_manager.h"
#include <fuchsia/tracing/provider/c/fidl.h>
#include <lib/fidl/coding.h>
#include <stdio.h>
#include <zircon/assert.h>
#include <zircon/status.h>
#include <utility>
namespace trace {
namespace test {
void FakeTraceManager::Create(async_dispatcher_t* dispatcher,
std::unique_ptr<FakeTraceManager>* out_manager,
zx::channel* out_channel) {
zx::channel server, client;
zx_status_t status = zx::channel::create(0, &server, &client);
ZX_DEBUG_ASSERT(status == ZX_OK);
auto manager = new FakeTraceManager(dispatcher, std::move(server));
out_manager->reset(manager);
*out_channel = std::move(client);
}
FakeTraceManager::FakeTraceManager(async_dispatcher_t* dispatcher, zx::channel channel)
: channel_(std::move(channel)),
wait_(this, channel_.get(), ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED) {
zx_status_t status = wait_.Begin(dispatcher);
ZX_DEBUG_ASSERT(status == ZX_OK);
}
void FakeTraceManager::Close() { channel_.reset(); }
void FakeTraceManager::Handle(async_dispatcher_t* dispatcher, async::WaitBase* wait,
zx_status_t status, const zx_packet_signal_t* signal) {
if (status == ZX_ERR_CANCELED) {
// The wait could be canceled if we're shutting down, e.g., the
// program is exiting.
return;
}
if (status != ZX_OK) {
fprintf(stderr, "FakeTraceManager: wait failed: %d(%s)\n", status,
zx_status_get_string(status));
} else if (signal->observed & ZX_CHANNEL_READABLE) {
if (ReadMessage()) {
zx_status_t status = wait_.Begin(dispatcher);
if (status == ZX_OK) {
return;
}
fprintf(stderr, "FakeTraceManager: Error re-registering channel wait: %d(%s)\n", status,
zx_status_get_string(status));
} else {
fprintf(stderr, "FakeTraceManager: received invalid FIDL message or failed to send reply\n");
}
} else {
ZX_DEBUG_ASSERT(signal->observed & ZX_CHANNEL_PEER_CLOSED);
}
Close();
}
bool FakeTraceManager::ReadMessage() {
FIDL_ALIGNDECL uint8_t buffer[16 * 1024];
uint32_t num_bytes = 0u;
constexpr uint32_t kNumHandles = 2;
zx_handle_t handles[kNumHandles];
uint32_t num_handles = 0u;
zx_status_t status =
channel_.read(0u, buffer, handles, sizeof(buffer), kNumHandles, &num_bytes, &num_handles);
if (status != ZX_OK) {
fprintf(stderr, "FakeTraceManager: channel read failed: status=%d(%s)\n", status,
zx_status_get_string(status));
return false;
}
if (!DecodeAndDispatch(buffer, num_bytes, handles, num_handles)) {
fprintf(stderr, "FakeTraceManager: DecodeAndDispatch failed\n");
zx_handle_close_many(handles, num_handles);
return false;
}
return true;
}
bool FakeTraceManager::DecodeAndDispatch(uint8_t* buffer, uint32_t num_bytes, zx_handle_t* handles,
uint32_t num_handles) {
printf("FakeTraceManager: Got request\n");
if (num_bytes < sizeof(fidl_message_header_t)) {
return false;
}
auto hdr = reinterpret_cast<fidl_message_header_t*>(buffer);
uint64_t ordinal = hdr->ordinal;
switch (ordinal) {
case fuchsia_tracing_provider_RegistryRegisterProviderOrdinal:
printf("FakeTraceManager: Got RegisterProvider request\n");
// We currently don't need to do anything more here.
return true;
default:
return false;
}
}
} // namespace test
} // namespace trace