1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <fbl/unique_fd.h>
8 #include <map>
9 #include <poll.h>
10 #include <set>
11 #include <vector>
12 
13 #include "usb-handler.h"
14 
15 namespace xdc {
16 
17 class Client {
18 public:
Client(int fd)19     explicit Client(int fd)
20         : fd_(fd) {}
21 
22     void SetStreamId(uint32_t stream_id);
23     void SetConnected(bool connected);
24     // Returns whether the set of client events we are polling for has changed.
25     bool UpdatePollState(bool usb_writable);
26 
27     // Queues a completed read transfer to be written to the client.
28     void AddCompletedRead(std::unique_ptr<UsbHandler::Transfer> transfer);
29     // Writes data from completed read transfers to the client until there are
30     // no transfers left, or the client is currently unavailable to accept data.
31     void ProcessCompletedReads(const std::unique_ptr<UsbHandler>& usb_handler);
32     // Writes data read from the client to the usb handler.
33     zx_status_t ProcessWrites(const std::unique_ptr<UsbHandler>& usb_handler);
34     // Returns any unused transfers to the usb handler.
35     void ReturnTransfers(const std::unique_ptr<UsbHandler>& usb_handler);
36 
fd()37     int fd() const { return fd_.get(); }
38     // Returns the set of client events we should poll for.
events()39     short events() const { return events_; }
registered()40     bool registered() const { return registered_; }
stream_id()41     uint32_t stream_id() const { return stream_id_; }
connected()42     bool connected() const { return connected_; }
43     // Returns true if we have read data from the client not yet sent to the usb handler.
has_write_data()44     bool has_write_data() const { return pending_write_ && pending_write_->request_length() > 0; }
45 
46 private:
47     fbl::unique_fd fd_;
48 
49     short events_ = 0;
50 
51     // Whether the client has registered a stream id.
52     bool registered_ = false;
53     uint32_t stream_id_ = 0;
54     // True if the client has registered a stream id,
55     // and that stream id is also registered on the xdc device side.
56     bool connected_ = false;
57 
58     std::vector<std::unique_ptr<UsbHandler::Transfer>> completed_reads_;
59     // Data read from the client, to be sent to the usb handler.
60     std::unique_ptr<UsbHandler::Transfer> pending_write_;
61 };
62 
63 class XdcServer {
64     // This is required by the XdcServer constructor, to stop clients calling it directly.
65     struct ConstructorTag {
66         explicit ConstructorTag() = default;
67     };
68 
69 public:
70     // Create should be called instead. This is public for make_unique.
XdcServer(ConstructorTag tag)71     XdcServer(ConstructorTag tag) {}
72 
73     static std::unique_ptr<XdcServer> Create();
74     void Run();
75 
76 private:
77     bool Init();
78 
79     void UpdateClientPollEvents();
80 
81     // Updates poll_fds_ with any newly added or removed usb handler fds.
82     void UpdateUsbHandlerFds();
83 
84     // Processes new client connections on the server socket.
85     void ClientConnect();
86 
87     // Returns whether registration succeeded.
88     bool RegisterStream(std::shared_ptr<Client> client);
89 
90     // Returns the client registered to the given stream id, or nullptr if none was found.
91     std::shared_ptr<Client> GetClient(uint32_t stream_id);
92 
93     void UsbReadComplete(std::unique_ptr<UsbHandler::Transfer> transfer);
94     // Parses the control message from the given transfer buffer.
95     void HandleCtrlMsg(unsigned char* transfer_buf, int transfer_len);
96 
97     // Sends a control message the to the xdc device with whether a stream has gone on / offline.
98     // If the message cannot currently be sent, it is queued to be retried later.
99     void NotifyStreamState(uint32_t stream_id, bool online);
100     bool SendCtrlMsg(xdc_msg_t& msg);
101     void SendQueuedCtrlMsgs();
102 
103     std::unique_ptr<UsbHandler> usb_handler_;
104 
105     // Server socket we receive client connections on.
106     fbl::unique_fd socket_fd_;
107     // File lock acquired to ensure we don't unlink the socket of a running xdc server instance.
108     fbl::unique_fd socket_lock_fd_;
109 
110     // Maps from client socket file descriptor to client.
111     std::map<int, std::shared_ptr<Client>> clients_;
112 
113     // File descriptors we are currently polling on.
114     std::vector<pollfd> poll_fds_;
115 
116     // Stream ids registered on the xdc device side.
117     std::set<uint32_t> dev_stream_ids_;
118 
119     std::vector<xdc_msg_t> queued_ctrl_msgs_;
120 
121     xdc_packet_state_t read_packet_state_;
122 };
123 
124 } // namespace xdc
125