1 //
2 // Copyright (C) 2020 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #pragma once
17 
18 #include <mutex>
19 #include <thread>
20 #include <vector>
21 
22 #include "common/libs/fs/shared_fd.h"
23 
24 class ModemServiceTest;
25 
26 namespace cuttlefish {
27 
28 class ModemSimulator;
29 
30 enum ModemSimulatorExitCodes : int {
31   kSuccess = 0,
32   kSelectError = 1,
33   kServerError = 2,
34 };
35 
36 class ClientId {
37  public:
38   ClientId();
39 
40   bool operator==(const ClientId&) const;
41 
42  private:
43   static size_t next_id_;
44   size_t id_;
45 };
46 
47 /**
48  * Client object managed by ChannelMonitor, contains two types, the RIL client
49  * and the remote client of other cuttlefish instance.
50  * Due to std::mutex does not implement its copy and operate= constructors, it
51  * can't be stored in standard contains (vector, map), so use the point instead.
52  */
53 class Client {
54  public:
55   enum ClientType { RIL, REMOTE };
56 
57   Client() = default;
58   ~Client() = default;
59   Client(SharedFD fd);
60   Client(SharedFD read, SharedFD write);
61   Client(SharedFD fd, ClientType client_type);
62   Client(SharedFD read, SharedFD write, ClientType client_type);
63   Client(const Client& client) = delete;
64   Client(Client&& client) = delete;
65 
66   Client& operator=(Client&& other) = delete;
67 
68   bool operator==(const Client& other) const;
69 
70   void SendCommandResponse(std::string response) const;
71   void SendCommandResponse(const std::vector<std::string>& responses) const;
72 
Id()73   ClientId Id() const { return id_; }
Type()74   ClientType Type() const { return type; }
75 
76  private:
77   friend class ChannelMonitor;
78   friend class ::ModemServiceTest;
79 
80   ClientId id_;
81   ClientType type = RIL;
82   SharedFD client_read_fd_;
83   SharedFD client_write_fd_;
84   std::string incomplete_command;
85   mutable std::mutex write_mutex;
86   bool first_read_command_;  // Only used when ClientType::REMOTE
87   bool is_valid = true;
88 };
89 
90 class ChannelMonitor {
91  public:
92   ChannelMonitor(ModemSimulator& modem, cuttlefish::SharedFD server);
93   ~ChannelMonitor();
94 
95   ChannelMonitor(const ChannelMonitor&) = delete;
96   ChannelMonitor& operator=(const ChannelMonitor&) = delete;
97 
98   ClientId SetRemoteClient(SharedFD client, bool is_accepted);
99   void SendRemoteCommand(ClientId client, std::string& response);
100   void CloseRemoteConnection(ClientId client);
101 
102   // For modem services to send unsolicited commands
103   void SendUnsolicitedCommand(std::string& response);
104 
105  private:
106   ModemSimulator& modem_;
107   std::thread monitor_thread_;
108   cuttlefish::SharedFD server_;
109   cuttlefish::SharedFD read_pipe_;
110   cuttlefish::SharedFD write_pipe_;
111   std::vector<std::unique_ptr<Client>> clients_;
112   std::vector<std::unique_ptr<Client>> remote_clients_;
113 
114   void AcceptIncomingConnection();
115   void OnClientSocketClosed(int sock);
116   void ReadCommand(Client& client);
117 
118   void MonitorLoop();
119   static void removeInvalidClients(
120       std::vector<std::unique_ptr<Client>>& clients);
121 };
122 
123 }  // namespace cuttlefish
124