diff options
author | Isaac Chen <isaacchen@isaacchen.cn> | 2018-12-31 10:55:08 +0100 |
---|---|---|
committer | TingyiChen <tingyi364@gmail.com> | 2019-08-13 11:54:40 +0200 |
commit | e5c53750f06e9d9739b45ec108260ead7ff80941 (patch) | |
tree | fe1d84884caefc481e994ae9c59c84b11fddd408 /gps/utils/LocIpc.cpp | |
parent | 3ac2a0309619515c9ac27a5b6ec7c212b86dc355 (diff) |
wayne-common: Synchorize gps to P
* QC Tag: LA.UM.7.2.r1-04900-sdm660.0
Signed-off-by: Isaac Chen <isaacchen@isaacchen.cn>
Change-Id: I34383e8fbf394b774f83f8d662873e8786ff1bbf
Diffstat (limited to 'gps/utils/LocIpc.cpp')
-rw-r--r-- | gps/utils/LocIpc.cpp | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/gps/utils/LocIpc.cpp b/gps/utils/LocIpc.cpp new file mode 100644 index 0000000..675664a --- /dev/null +++ b/gps/utils/LocIpc.cpp @@ -0,0 +1,237 @@ +/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <log_util.h> +#include "LocIpc.h" + +namespace loc_util { + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "LocSvc_LocIpc" + +#define LOC_MSG_BUF_LEN 8192 +#define LOC_MSG_HEAD "$MSGLEN$" +#define LOC_MSG_ABORT "LocIpcMsg::ABORT" + +class LocIpcRunnable : public LocRunnable { +friend LocIpc; +public: + LocIpcRunnable(LocIpc& locIpc, const std::string& ipcName) + : mLocIpc(locIpc), mIpcName(ipcName) {} + bool run() override { + if (!mLocIpc.startListeningBlocking(mIpcName)) { + LOC_LOGe("listen to socket failed"); + } + + return false; + } +private: + LocIpc& mLocIpc; + const std::string mIpcName; +}; + +bool LocIpc::startListeningNonBlocking(const std::string& name) { + mRunnable = new LocIpcRunnable(*this, name); + std::string threadName("LocIpc-"); + threadName.append(name); + return mThread.start(threadName.c_str(), mRunnable); +} + +bool LocIpc::startListeningBlocking(const std::string& name) { + + int fd = socket(AF_UNIX, SOCK_DGRAM, 0); + if (fd < 0) { + LOC_LOGe("create socket error. reason:%s", strerror(errno)); + return false; + } + + if ((unlink(name.c_str()) < 0) && (errno != ENOENT)) { + LOC_LOGw("unlink socket error. reason:%s", strerror(errno)); + } + + struct sockaddr_un addr = { .sun_family = AF_UNIX }; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", name.c_str()); + + umask(0157); + + if (::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + LOC_LOGe("bind socket error. reason:%s", strerror(errno)); + ::close(fd); + fd = -1; + return false; + } + + mIpcFd = fd; + + // inform that the socket is ready to receive message + onListenerReady(); + + ssize_t nBytes = 0; + std::string msg = ""; + std::string abort = LOC_MSG_ABORT; + while (1) { + msg.resize(LOC_MSG_BUF_LEN); + nBytes = ::recvfrom(mIpcFd, (void*)(msg.data()), msg.size(), 0, NULL, NULL); + if (nBytes < 0) { + break; + } else if (nBytes == 0) { + continue; + } + + if (strncmp(msg.data(), abort.c_str(), abort.length()) == 0) { + LOC_LOGi("recvd abort msg.data %s", msg.data()); + break; + } + + if (strncmp(msg.data(), LOC_MSG_HEAD, sizeof(LOC_MSG_HEAD) - 1)) { + // short message + msg.resize(nBytes); + onReceive(msg); + } else { + // long message + size_t msgLen = 0; + sscanf(msg.data(), LOC_MSG_HEAD"%zu", &msgLen); + msg.resize(msgLen); + size_t msgLenReceived = 0; + while ((msgLenReceived < msgLen) && (nBytes > 0)) { + nBytes = recvfrom(mIpcFd, (void*)&(msg[msgLenReceived]), + msg.size() - msgLenReceived, 0, NULL, NULL); + msgLenReceived += nBytes; + } + if (nBytes > 0) { + onReceive(msg); + } else { + break; + } + } + } + + if (mStopRequested) { + mStopRequested = false; + return true; + } else { + LOC_LOGe("cannot read socket. reason:%s", strerror(errno)); + (void)::close(mIpcFd); + mIpcFd = -1; + return false; + } +} + +void LocIpc::stopListening() { + + const char *socketName = nullptr; + mStopRequested = true; + + if (mRunnable) { + std::string abort = LOC_MSG_ABORT; + socketName = (reinterpret_cast<LocIpcRunnable *>(mRunnable))->mIpcName.c_str(); + send(socketName, abort); + mRunnable = nullptr; + } + + if (mIpcFd >= 0) { + if (::close(mIpcFd)) { + LOC_LOGe("cannot close socket:%s", strerror(errno)); + } + mIpcFd = -1; + } + + //delete from the file system at the end + if (socketName) { + unlink(socketName); + } +} + +bool LocIpc::send(const char name[], const std::string& data) { + return send(name, (const uint8_t*)data.c_str(), data.length()); +} + +bool LocIpc::send(const char name[], const uint8_t data[], uint32_t length) { + + bool result = true; + int fd = ::socket(AF_UNIX, SOCK_DGRAM, 0); + if (fd < 0) { + LOC_LOGe("create socket error. reason:%s", strerror(errno)); + return false; + } + + struct sockaddr_un addr = { .sun_family = AF_UNIX }; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", name); + + result = sendData(fd, addr, data, length); + + (void)::close(fd); + return result; +} + + +bool LocIpc::sendData(int fd, const sockaddr_un &addr, const uint8_t data[], uint32_t length) { + + bool result = true; + + if (length <= LOC_MSG_BUF_LEN) { + if (::sendto(fd, data, length, 0, + (struct sockaddr*)&addr, sizeof(addr)) < 0) { + LOC_LOGe("cannot send to socket. reason:%s", strerror(errno)); + result = false; + } + } else { + std::string head = LOC_MSG_HEAD; + head.append(std::to_string(length)); + if (::sendto(fd, head.c_str(), head.length(), 0, + (struct sockaddr*)&addr, sizeof(addr)) < 0) { + LOC_LOGe("cannot send to socket. reason:%s", strerror(errno)); + result = false; + } else { + size_t sentBytes = 0; + while(sentBytes < length) { + size_t partLen = length - sentBytes; + if (partLen > LOC_MSG_BUF_LEN) { + partLen = LOC_MSG_BUF_LEN; + } + ssize_t rv = ::sendto(fd, data + sentBytes, partLen, 0, + (struct sockaddr*)&addr, sizeof(addr)); + if (rv < 0) { + LOC_LOGe("cannot send to socket. reason:%s", strerror(errno)); + result = false; + break; + } + sentBytes += rv; + } + } + } + return result; +} + +} |