Files
Android11/external/rkaiq_tool_server/netserver/domain_tcp_client.cpp
2023-10-13 14:01:41 +00:00

182 lines
4.3 KiB
C++

#include "domain_tcp_client.h"
#include <errno.h>
#ifdef __ANDROID__
#include <android-base/file.h>
#include <cutils/sockets.h>
#endif
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "aiqtool"
extern struct ucred* g_aiqCred;
#ifdef __ANDROID__
#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
// Connects to /dev/socket/<name> and returns the associated fd or returns -1 on error.
// O_CLOEXEC is always set.
static int socket_local_client(const std::string& name, int type)
{
sockaddr_un addr = {.sun_family = AF_LOCAL};
std::string path = "/dev/socket/" + name;
if (path.size() + 1 > sizeof(addr.sun_path)) {
return -1;
}
strlcpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path));
int fd = socket(AF_LOCAL, type | SOCK_CLOEXEC, 0);
if (fd == -1) {
return -1;
}
if (connect(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
close(fd);
return -1;
}
return fd;
}
#endif
DomainTCPClient::DomainTCPClient()
{
sock = -1;
}
DomainTCPClient::~DomainTCPClient()
{
Close();
}
void DomainTCPClient::Close()
{
if (g_aiqCred) {
delete g_aiqCred;
g_aiqCred = nullptr;
}
if (sock > 0) {
close(sock);
sock = -1;
}
}
bool DomainTCPClient::Setup(string domainPath)
{
#ifdef __ANDROID__
if (sock > 0) {
// close(sock);
return true;
}
sock = socket_local_client(android::base::Basename(domainPath), SOCK_STREAM);
if (sock < 0) {
LOG_ERROR("Could not create domain socket %s\n", strerror(errno));
return false;
} else {
LOG_DEBUG("Android,Create domain socket success.\n");
}
#else
if (sock == -1) {
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1) {
LOG_ERROR("Could not create domain socket\n");
return false;
} else {
LOG_DEBUG("Linux,Create domain socket success.\n");
}
}
server.sun_family = AF_UNIX;
strcpy(server.sun_path, domainPath.c_str());
struct timeval timeout = {1, 0}; // 1 sec
int ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
LOG_ERROR("connect domain server failed. Error\n");
close(sock);
sock = -1;
return false;
}
#endif
if (g_aiqCred == nullptr) {
g_aiqCred = new ucred();
}
socklen_t len = sizeof(struct ucred);
if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, (void*)g_aiqCred, &len) == -1) {
// close(sock);
// sock = -1;
LOG_ERROR("getsockopt peer credentials not supported");
} else {
LOG_DEBUG("Credentials from SO_PEERCRED: pid=%ld, euid=%ld, egid=%ld\n", (long)g_aiqCred->pid,
(long)g_aiqCred->uid, (long)g_aiqCred->gid);
}
return true;
}
bool DomainTCPClient::Send(string data)
{
if (sock != -1) {
if (send(sock, data.c_str(), strlen(data.c_str()), 0) < 0) {
LOG_ERROR("Send failed : %s\n", data.c_str());
Close();
return false;
}
} else {
return false;
}
return true;
}
int DomainTCPClient::Send(char* buff, int size)
{
int ret = -1;
if (sock != -1) {
ret = send(sock, buff, size, 0);
if (ret < 0 && (errno != EAGAIN && errno != EINTR)) {
LOG_ERROR("Send buff size %d failed\n", size);
Close();
return ret;
}
}
return ret;
}
string DomainTCPClient::Receive(int size)
{
char buffer[size];
memset(&buffer[0], 0, sizeof(buffer));
string reply;
if (sock < 0) {
return "\0";
}
ssize_t ret = recv(sock, buffer, size, 0);
if (ret < 0 && (errno != EAGAIN && errno != EINTR)) {
LOG_ERROR("domain receive 1 failed %s!\n", strerror(errno));
Close();
return "\0";
}
buffer[size - 1] = '\0';
reply = buffer;
return reply;
}
int DomainTCPClient::Receive(char* buff, int size)
{
ssize_t ret = -1;
if (sock < 0) {
return -1;
}
memset(buff, 0, size);
ret = recv(sock, buff, size, 0);
if (ret < 0 && (errno != EAGAIN && errno != EINTR)) {
LOG_ERROR("domain receive 2 failed %s!\n", strerror(errno));
Close();
return -1;
}
return ret;
}