Files
BPI-CM9-Linux/aml-comp/vendor/amlogic/aml_subtitleserver/client/AmSocketClient.cpp
T
2026-08-24 10:03:24 +08:00

244 lines
7.1 KiB
C++

/*
* Copyright (C) 2014-2019 Amlogic, Inc. All rights reserved.
*
* All information contained herein is Amlogic confidential.
*
* This software is provided to you pursuant to Software License Agreement
* (SLA) with Amlogic Inc ("Amlogic"). This software may be used
* only in accordance with the terms of this agreement.
*
* Redistribution and use in source and binary forms, with or without
* modification is strictly prohibited without prior written permission from
* Amlogic.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE 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.
*/
/************************************************
* name : AmSocket.cpp
* function : transfer data by socket
* data : 2017.03.02
* author : wxl
* version : 1.0.0
*************************************************/
#define LOG_NDEBUG 0
#define LOG_TAG "AmSocket"
#include <arpa/inet.h>
#include <errno.h>
#include "SubtitleLog.h"
// #include <media/stagefright/foundation/ALooper.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <chrono>
#include <cstddef>
#include <string>
#include "AmSocketClient.h"
#include "cutils/properties.h"
// #include "utils/AmlMpLog.h"
#define USE_UN true
#if USE_UN
#define UN_BASE_PATH "/tmp/subtitlesocketserver.sock"
#endif
static const char *mName = "AmSocketClient";
static double now(int clockId = CLOCK_MONOTONIC) {
struct timespec spec;
clock_gettime(clockId, &spec);
return spec.tv_sec;
}
// namespace aml_mp {
AmSocketClient::AmSocketClient() {
mSockFd = -1;
}
AmSocketClient::~AmSocketClient() {
mSockFd = -1;
}
int64_t AmSocketClient::GetNowUs() {
// Return systemTime(SYSTEM_TIME_MONOTONIC) / 1000LL;
return std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
}
int AmSocketClient::socketConnect() {
SUBTITLE_LOGI("socketConnect");
#if USE_UN
mSockFd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
if (mSockFd < 0) {
SUBTITLE_LOGE("%s, create socket failed!mSockFd:%d, error=%d, err:%m", __FILE__, mSockFd,
errno);
return -1;
}
std::string unPath = std::string(UN_BASE_PATH);
struct sockaddr_un un{};
bzero(&un, sizeof(un));
un.sun_family = AF_UNIX;
strcpy(un.sun_path, UN_BASE_PATH);
size_t sockLen = offsetof(struct sockaddr_un, sun_path) + unPath.size();
int ret = ::connect(mSockFd, (struct sockaddr *)&un, (socklen_t)sockLen);
if (ret < 0 && errno != EINPROGRESS) {
SUBTITLE_LOGE("%s, connect socket failed!mSockFd:%d, error=%d, err:%m", __FILE__, mSockFd,
errno);
close(mSockFd);
mSockFd = -1;
return -1;
}
// Poll waits for the socket to be writable, indicating that the connection is complete
struct pollfd pfd;
pfd.fd = mSockFd;
pfd.events = POLLOUT;
int pollRet = poll(&pfd, 1, 120);
if (pollRet < 0) {
SUBTITLE_LOGE("%s, poll socket failed!mSockFd:%d, error=%d, err:%m", __FILE__, mSockFd,
errno);
close(mSockFd);
mSockFd = -1;
return -1;
} else if (pollRet == 0) {
SUBTITLE_LOGE("%s, connect socket timeout!mSockFd:%d\n", __FILE__, mSockFd);
close(mSockFd);
mSockFd = -1;
return -1;
}
// Check the connection status
int err = 0;
socklen_t len = sizeof(err);
if (getsockopt(mSockFd, SOL_SOCKET, SO_ERROR, &err, &len) < 0 || err != 0) {
SUBTITLE_LOGE("connect failed after poll: %m");
close(mSockFd);
mSockFd = -1;
return -1;
}
#else
mSockFd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr{};
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (mSockFd < 0) {
SUBTITLE_LOGE("%s, create socket failed!mSockFd:%d, error=%d, err:%s\n", __FILE__, mSockFd,
errno, strerror(errno));
return false;
}
int64_t startTime = now();
while (true) {
if (::connect(mSockFd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
// load dvb so need time since add close caption subtitle, add to 120ms.
// only has subtitle to connect socket
if (now() - startTime > 120000ll) {
SUBTITLE_LOGE("%s, connect socket failed!, error=%d, err:%s\n", __FILE__, errno,
strerror(errno));
close(mSockFd);
mSockFd = -1;
return false;
}
} else {
break;
}
}
#endif
SUBTITLE_LOGI("%s, connect socket success!mSockFd:%d\n", __FILE__, mSockFd);
return 0;
}
void AmSocketClient::socketSend(const char *buf, int size) {
android::AutoMutex _l(mSockLock);
char value[PROPERTY_VALUE_MAX] = {0};
if (property_get("sys.amsocket.disable", value, "false") > 0) {
if (!strncmp(value, "true", 4)) {
return;
}
}
int sendLen = 0;
int retLen = 0;
int leftLen = size;
const char *sendBuf = buf;
char recvBuf[32] = {0};
if (mSockFd >= 0) {
do {
// prepare send length
if (leftLen > SEND_LEN) {
sendLen = SEND_LEN;
} else {
sendLen = leftLen;
}
// start to send
retLen = send(mSockFd, sendBuf, sendLen, 0);
if (retLen < 0) {
if (errno == EINTR) {
retLen = 0;
}
// SUBTITLE_LOGI("%s, send socket failed!retLen:%d\n", __FILE__, retLen);
return;
}
// prepare left buffer pointer
sendBuf += retLen;
leftLen -= retLen;
} while (leftLen > 0);
}
}
int AmSocketClient::socketRecv(char *buf, int size) {
android::AutoMutex _l(mSockLock);
int retlen = 0;
if (mSockFd >= 0) {
retlen = recv(mSockFd, buf, size, 0);
if (retlen < 0) {
if (errno == EINTR)
retlen = 0;
else {
SUBTITLE_LOGE("%s, receive socket failed!", __FILE__);
return -1;
}
}
}
return retlen;
}
void AmSocketClient::socketDisconnect() {
if (mSockFd >= 0) {
close(mSockFd);
mSockFd = -1;
}
}
//}