| // 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 |