156 lines
4.9 KiB
C++
156 lines
4.9 KiB
C++
/*
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef CHRE_HOST_SOCKET_CLIENT_H_
|
|
#define CHRE_HOST_SOCKET_CLIENT_H_
|
|
|
|
#include <atomic>
|
|
#include <condition_variable>
|
|
#include <mutex>
|
|
#include <thread>
|
|
|
|
#include <cutils/sockets.h>
|
|
#include <utils/RefBase.h>
|
|
#include <utils/StrongPointer.h>
|
|
|
|
namespace android {
|
|
namespace chre {
|
|
|
|
class SocketClient {
|
|
public:
|
|
SocketClient();
|
|
~SocketClient();
|
|
|
|
/**
|
|
* Represents the callback interface used for handling events that occur on
|
|
* the receive thread. Note that it is *not* safe to call connect(),
|
|
* connectInBackground(), or disconnect() from the context of these callbacks.
|
|
*/
|
|
class ICallbacks : public VirtualLightRefBase {
|
|
public:
|
|
/**
|
|
* Invoked from within the context of the read thread when a message is
|
|
* received on the socket.
|
|
*
|
|
* @param data Buffer containing received message data
|
|
* @param length Size of the message in bytes
|
|
*/
|
|
virtual void onMessageReceived(const void *data, size_t length) = 0;
|
|
|
|
/**
|
|
* Called when the socket is successfully (re-)connected.
|
|
*/
|
|
virtual void onConnected(){};
|
|
|
|
/**
|
|
* Called when we have failed to (re-)connect the socket after many attempts
|
|
* and are giving up.
|
|
*/
|
|
virtual void onConnectionAborted(){};
|
|
|
|
/**
|
|
* Invoked when the socket is disconnected, and this connection loss was not
|
|
* the result of an explicit call to disconnect(), i.e. the connection was
|
|
* terminated on the remote end.
|
|
*/
|
|
virtual void onDisconnected(){};
|
|
};
|
|
|
|
/**
|
|
* Synchronously attempts to connect to the Android reserved namespace socket
|
|
* with the given name. If this connection attempt is successful, starts a
|
|
* receive thread to handle messages received on the socket, and uses this
|
|
* thread to automatically reconnect if disconnected by the remote end.
|
|
*
|
|
* @param socketName Name of the Android domain socket to connect to
|
|
* @param callbacks
|
|
*
|
|
* @return true if the connection was successful
|
|
*/
|
|
bool connect(const char *socketName,
|
|
const ::android::sp<ICallbacks> &callbacks);
|
|
|
|
/**
|
|
* Starts up the receive thread and attempts to connect to the socket in the
|
|
* background. The onConnected() callback will be invoked when the socket is
|
|
* connected successfully, or onConnectionAborted() will be invoked if the
|
|
* connection could not be made after many retries and the client is giving
|
|
* up.
|
|
*
|
|
* @param socketName Name of the Android domain socket to connect to
|
|
* @param callbacks
|
|
*
|
|
* @return true if the receive thread was started and will attempt to connect
|
|
* the socket asynchronously
|
|
*/
|
|
bool connectInBackground(const char *socketName,
|
|
const ::android::sp<ICallbacks> &callbacks);
|
|
|
|
/**
|
|
* Performs graceful teardown of the socket. After this function returns, this
|
|
* object will no longer invoke any callbacks or hold a reference to the
|
|
* callbacks object provided to connect().
|
|
*/
|
|
void disconnect();
|
|
|
|
/**
|
|
* @return true if the socket is currently connected
|
|
*/
|
|
bool isConnected() const;
|
|
|
|
/**
|
|
* Send a message on the connected socket. Safe to call from any thread.
|
|
*
|
|
* @param data Buffer containing message data
|
|
* @param length Size of the message to send in bytes
|
|
*
|
|
* @return true if the message was successfully sent
|
|
*/
|
|
bool sendMessage(const void *data, size_t length);
|
|
|
|
private:
|
|
static constexpr size_t kMaxSocketNameLen = 64;
|
|
char mSocketName[kMaxSocketNameLen];
|
|
sp<ICallbacks> mCallbacks;
|
|
|
|
std::atomic<int> mSockFd;
|
|
std::thread mRxThread;
|
|
|
|
//! Set to true when we initiate the graceful socket shutdown procedure, so we
|
|
//! know not to invoke onSocketDisconnectedByRemote()
|
|
std::atomic<bool> mGracefulShutdown;
|
|
|
|
//! Condition variable used as the method to wake the RX thread when we want
|
|
//! to disconnect, but it's trying to reconnect automatically
|
|
std::condition_variable mShutdownCond;
|
|
std::mutex mShutdownMutex;
|
|
|
|
bool doConnect(const char *socketName,
|
|
const ::android::sp<ICallbacks> &callbacks,
|
|
bool connectInBackground);
|
|
bool inReceiveThread() const;
|
|
void receiveThread();
|
|
bool receiveThreadRunning() const;
|
|
bool reconnect();
|
|
void startReceiveThread();
|
|
bool tryConnect(bool suppressErrorLogs = false);
|
|
};
|
|
|
|
} // namespace chre
|
|
} // namespace android
|
|
|
|
#endif // CHRE_HOST_SOCKET_CLIENT_H_
|