| // Copyright 2018 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 <fbl/unique_fd.h> |
| #include <map> |
| #include <poll.h> |
| #include <set> |
| #include <vector> |
| |
| #include "usb-handler.h" |
| |
| namespace xdc { |
| |
| class Client { |
| public: |
| explicit Client(int fd) |
| : fd_(fd) {} |
| |
| void SetStreamId(uint32_t stream_id); |
| void SetConnected(bool connected); |
| // Returns whether the set of client events we are polling for has changed. |
| bool UpdatePollState(bool usb_writable); |
| |
| // Queues a completed read transfer to be written to the client. |
| void AddCompletedRead(std::unique_ptr<UsbHandler::Transfer> transfer); |
| // Writes data from completed read transfers to the client until there are |
| // no transfers left, or the client is currently unavailable to accept data. |
| void ProcessCompletedReads(const std::unique_ptr<UsbHandler>& usb_handler); |
| // Writes data read from the client to the usb handler. |
| zx_status_t ProcessWrites(const std::unique_ptr<UsbHandler>& usb_handler); |
| // Returns any unused transfers to the usb handler. |
| void ReturnTransfers(const std::unique_ptr<UsbHandler>& usb_handler); |
| |
| int fd() const { return fd_.get(); } |
| // Returns the set of client events we should poll for. |
| short events() const { return events_; } |
| bool registered() const { return registered_; } |
| uint32_t stream_id() const { return stream_id_; } |
| bool connected() const { return connected_; } |
| // Returns true if we have read data from the client not yet sent to the usb handler. |
| bool has_write_data() const { return pending_write_ && pending_write_->request_length() > 0; } |
| |
| private: |
| fbl::unique_fd fd_; |
| |
| short events_ = 0; |
| |
| // Whether the client has registered a stream id. |
| bool registered_ = false; |
| uint32_t stream_id_ = 0; |
| // True if the client has registered a stream id, |
| // and that stream id is also registered on the xdc device side. |
| bool connected_ = false; |
| |
| std::vector<std::unique_ptr<UsbHandler::Transfer>> completed_reads_; |
| // Data read from the client, to be sent to the usb handler. |
| std::unique_ptr<UsbHandler::Transfer> pending_write_; |
| }; |
| |
| class XdcServer { |
| // This is required by the XdcServer constructor, to stop clients calling it directly. |
| struct ConstructorTag { |
| explicit ConstructorTag() = default; |
| }; |
| |
| public: |
| // Create should be called instead. This is public for make_unique. |
| XdcServer(ConstructorTag tag) {} |
| |
| static std::unique_ptr<XdcServer> Create(); |
| void Run(); |
| |
| private: |
| bool Init(); |
| |
| void UpdateClientPollEvents(); |
| |
| // Updates poll_fds_ with any newly added or removed usb handler fds. |
| void UpdateUsbHandlerFds(); |
| |
| // Processes new client connections on the server socket. |
| void ClientConnect(); |
| |
| // Returns whether registration succeeded. |
| bool RegisterStream(std::shared_ptr<Client> client); |
| |
| // Returns the client registered to the given stream id, or nullptr if none was found. |
| std::shared_ptr<Client> GetClient(uint32_t stream_id); |
| |
| void UsbReadComplete(std::unique_ptr<UsbHandler::Transfer> transfer); |
| // Parses the control message from the given transfer buffer. |
| void HandleCtrlMsg(unsigned char* transfer_buf, int transfer_len); |
| |
| // Sends a control message the to the xdc device with whether a stream has gone on / offline. |
| // If the message cannot currently be sent, it is queued to be retried later. |
| void NotifyStreamState(uint32_t stream_id, bool online); |
| bool SendCtrlMsg(xdc_msg_t& msg); |
| void SendQueuedCtrlMsgs(); |
| |
| std::unique_ptr<UsbHandler> usb_handler_; |
| |
| // Server socket we receive client connections on. |
| fbl::unique_fd socket_fd_; |
| // File lock acquired to ensure we don't unlink the socket of a running xdc server instance. |
| fbl::unique_fd socket_lock_fd_; |
| |
| // Maps from client socket file descriptor to client. |
| std::map<int, std::shared_ptr<Client>> clients_; |
| |
| // File descriptors we are currently polling on. |
| std::vector<pollfd> poll_fds_; |
| |
| // Stream ids registered on the xdc device side. |
| std::set<uint32_t> dev_stream_ids_; |
| |
| std::vector<xdc_msg_t> queued_ctrl_msgs_; |
| |
| xdc_packet_state_t read_packet_state_; |
| }; |
| |
| } // namespace xdc |