blob: 979d3bbcdde31217767dbe4a3ebd8173f2f0d46d [file] [log] [blame]
// 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.
#pragma once
#include <atomic>
#include <threads.h>
#include <limits.h>
#include <fuchsia/paver/c/fidl.h>
#include <lib/fzl/owned-vmo-mapper.h>
#include <lib/sync/completion.h>
#include <lib/zx/channel.h>
#include <lib/zx/time.h>
#include <tftp/tftp.h>
#include <zircon/types.h>
#include "tftp.h"
namespace netsvc {
class PaverInterface {
public:
virtual bool InProgress() = 0;
virtual zx_status_t exit_code() = 0;
virtual void reset_exit_code() = 0;
// TODO: Explore returning an object which implements write and when it goes
// out of scope, closes.
virtual tftp_status OpenWrite(const char* filename, size_t size) = 0;
virtual tftp_status Write(const void* data, size_t* length, off_t offset) = 0;
virtual void Close() = 0;
};
class Paver : public PaverInterface {
public:
// Get the singleton instance.
static Paver* Get();
bool InProgress() final;
zx_status_t exit_code() final;
void reset_exit_code() final;
tftp_status OpenWrite(const char* filename, size_t size) final;
tftp_status Write(const void* data, size_t* length, off_t offset) final;
void Close() final;
// Visible for testing.
explicit Paver(zx::channel svc_root)
: svc_root_(std::move(svc_root)) {}
void set_timeout(zx::duration timeout) { timeout_ = timeout; }
private:
// Refer to //zircon/system/fidl/fuchsia.paver/paver.fidl for a list of what
// these commands translate to.
enum class Command {
kAsset,
kBootloader,
kDataFile,
kFvm,
};
uint8_t* buffer() { return static_cast<uint8_t*>(buffer_mapper_.start()); }
// Pushes all data from the paver buffer (filled by netsvc) into the paver input VMO. When
// there's no data to copy, blocks on data_ready until more data is written into the buffer.
int StreamBuffer();
// Monitors the vmo progress, and calls into paver service once finished.
int MonitorBuffer();
std::atomic<bool> in_progress_ = false;
std::atomic<zx_status_t> exit_code_ = ZX_OK;
// Total size of file
size_t size_ = 0;
// Paver command to call into.
Command command_;
// Channel to svc.
zx::channel svc_root_;
// Channel to paver service.
zx::channel paver_svc_;
union {
// Only valid when command == Command::kAsset.
struct {
fuchsia_paver_Configuration configuration_;
fuchsia_paver_Asset asset_;
};
// Only valid when command == Command::kDataFile.
char path_[PATH_MAX];
};
// Buffer used for stashing data from tftp until it can be written out to the paver.
fzl::OwnedVmoMapper buffer_mapper_;
// Buffer write offset.
std::atomic<size_t> write_offset_ = 0;
std::atomic<unsigned int> buf_refcount_ = 0;
thrd_t buf_thrd_ = 0;
sync_completion_t data_ready_;
// Timeout monitor thread uses before timing out.
zx::duration timeout_ = zx::sec(5 * TFTP_TIMEOUT_SECS);
};
} // namespace netsvc