• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 
17 #ifndef CHRE_HOST_SOCKET_SERVER_H_
18 #define CHRE_HOST_SOCKET_SERVER_H_
19 
20 #include <poll.h>
21 
22 #include <atomic>
23 #include <functional>
24 #include <map>
25 #include <mutex>
26 #include <vector>
27 
28 #include <android-base/macros.h>
29 #include <cutils/sockets.h>
30 
31 namespace android {
32 namespace chre {
33 
34 class SocketServer {
35  public:
36   SocketServer();
37 
38   /**
39    * Defines the function signature of the callback given to run() which
40    * receives message data sent in by a client.
41    *
42    * @param clientId A unique identifier for the client that sent this request
43    *        (assigned locally)
44    * @param data Pointer to buffer containing the raw message data
45    * @param len Number of bytes of data received
46    */
47   typedef std::function<void(uint16_t clientId, void *data, size_t len)>
48       ClientMessageCallback;
49 
50   /**
51    * Opens the socket, and runs the receive loop until an error is encountered,
52    * or SIGINT/SIGTERM is received. Masks off all other signals.
53    *
54    * @param socketName Android socket name to use when listening
55    * @param allowSocketCreation If true, allow creation of the socket rather
56    *        than strictly inheriting it from init (used primarily for
57    *        development purposes)
58    * @param clientMessageCallback Callback to be invoked when a message is
59    *        received from a client
60    */
61   void run(const char *socketName, bool allowSocketCreation,
62            ClientMessageCallback clientMessageCallback);
63 
64   /**
65    * Delivers data to all connected clients. This method is thread-safe.
66    *
67    * @param data Pointer to buffer containing message data
68    * @param length Number of bytes of data to send
69    */
70   void sendToAllClients(const void *data, size_t length);
71 
72   /**
73    * Sends a message to one client, specified via its unique client ID. This
74    * method is thread-safe.
75    *
76    * @param data
77    * @param length
78    * @param clientId
79    *
80    * @return true if the message was successfully sent to the specified client
81    */
82   bool sendToClientById(const void *data, size_t length, uint16_t clientId);
83 
shutdownServer()84   void shutdownServer() {
85     sSignalReceived = true;
86   }
87 
88  private:
89   DISALLOW_COPY_AND_ASSIGN(SocketServer);
90 
91   static constexpr size_t kMaxActiveClients = 8;
92   static constexpr int kMaxPendingConnectionRequests =
93       static_cast<int>(kMaxActiveClients);
94   static constexpr size_t kMaxPacketSize = 1024 * 1024;
95 
96   int mSockFd = INVALID_SOCKET;
97   uint16_t mNextClientId = 1;
98   // TODO: std::vector-ify this
99   struct pollfd mPollFds[1 + kMaxActiveClients] = {};
100 
101   struct ClientData {
102     uint16_t clientId;
103   };
104 
105   // Maps from socket FD to ClientData
106   std::map<int, ClientData> mClients;
107 
108   // A buffer to read packets into. Allocated here to prevent a large object on
109   // the stack.
110   std::vector<uint8_t> mRecvBuffer = std::vector<uint8_t>(kMaxPacketSize);
111 
112   // Ensures that mClients can be safely iterated over from other threads
113   // without worrying about potential modification from the RX thread
114   std::mutex mClientsMutex;
115 
116   ClientMessageCallback mClientMessageCallback;
117 
118   void acceptClientConnection();
119   void disconnectClient(int clientSocket);
120   void handleClientData(int clientSocket);
121   bool sendToClientSocket(const void *data, size_t length, int clientSocket,
122                           uint16_t clientId);
123   void serviceSocket();
124 
125   static std::atomic<bool> sSignalReceived;
126 };
127 
128 }  // namespace chre
129 }  // namespace android
130 
131 #endif  // CHRE_HOST_SOCKET_SERVER_H_
132