socket_client.h revision f972651484105181854f604e4709e32c8bf30375
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_CLIENT_H_
18#define CHRE_HOST_SOCKET_CLIENT_H_
19
20#include <atomic>
21#include <condition_variable>
22#include <mutex>
23#include <thread>
24
25#include <cutils/sockets.h>
26#include <utils/RefBase.h>
27#include <utils/StrongPointer.h>
28
29namespace android {
30namespace chre {
31
32class SocketClient {
33 public:
34  SocketClient();
35  ~SocketClient();
36
37  /**
38   * Represents the callback interface used for handling events that occur on
39   * the receive thread. Note that it is *not* safe to call connect() or
40   * disconnect() from the context of these callbacks.
41   */
42  class ICallbacks : public VirtualLightRefBase {
43   public:
44    /**
45     * Invoked from within the context of the read thread when a message is
46     * received on the socket.
47     *
48     * @param data Buffer containing received message data
49     * @param length Size of the message in bytes
50     */
51    virtual void onMessageReceived(const void *data, size_t length) = 0;
52
53    /**
54     * Invoked when the remote side disconnects the socket. It is not safe to
55     * call connect() or disconnect() from the context of this callback.
56     */
57    virtual void onSocketDisconnectedByRemote() {};
58
59    /**
60     * Invoked if reconnectAutomatically was true in connect() and we've
61     * successfully reconnected the socket.
62     */
63    virtual void onSocketReconnected() {};
64
65    /**
66     * Invoked if reconnectAutomatically was true in connect(), and we've tried
67     * to reconnect the socket too many times and are giving up. After this, the
68     */
69    virtual void onReconnectAborted() {};
70  };
71
72  /**
73   * Connects to the Android reserved namespace socket with the given name,
74   * and starts a receive thread to handle messages received on the socket.
75   * Returns
76   *
77   * @param socketName
78   * @param reconnectAutomatically If true, automatically attempt to re-connect
79   *        to the socket if disconnected by the remote end. This does not
80   *        influence the initial connection attempt, which happens
81   *        synchronously within this function call.
82   * @param callbacks
83   *
84   * @return true if the connection was successful
85   */
86  bool connect(const char *socketName, bool reconnectAutomatically,
87               ::android::sp<ICallbacks> callbacks);
88
89  /**
90   * Performs graceful teardown of the socket. After this function returns, this
91   * object will no longer invoke any callbacks or hold a reference to the
92   * callbacks object provided to connect().
93   */
94  void disconnect();
95
96  /**
97   * Send a message on the connected socket. Safe to call from any thread.
98   *
99   * @param data Buffer containing message data
100   * @param length Size of the message to send in bytes
101   *
102   * @return true if the message was successfully sent
103   */
104  bool sendMessage(const void *data, size_t length);
105
106 private:
107  static constexpr size_t kMaxSocketNameLen = 64;
108  char mSocketName[kMaxSocketNameLen];
109  bool mReconnectAutomatically;
110  sp<ICallbacks> mCallbacks;
111
112  std::atomic<int> mSockFd;
113  std::thread mRxThread;
114
115  //! Set to true when we initiate the graceful socket shutdown procedure, so we
116  //! know not to invoke onSocketDisconnectedByRemote()
117  std::atomic<bool> mGracefulShutdown;
118
119  //! Condition variable used as the method to wake the RX thread when we want
120  //! to disconnect, but it's trying to reconnect automatically
121  std::condition_variable mShutdownCond;
122  std::mutex mShutdownMutex;
123
124  bool inReceiveThread() const;
125  void receiveThread();
126  bool receiveThreadRunning() const;
127  bool reconnect();
128  bool tryConnect();
129};
130
131}  // namespace chre
132}  // namespace android
133
134#endif  // CHRE_HOST_SOCKET_CLIENT_H_
135