Files
MeowOS-SDK/sdk/meow_net_ipc.c
T

158 lines
6.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* meow_net_ipc.c — MeowOS SDK 网络自愿通道 → netmgrd IPC 桥(期4;追加式协议 0x00EE/0x00EF)。
*
* 与 meow_notify_ipc.c 同型:只做「一次性 connect + send + read」,不维护连接/订阅循环。
* - meow_net_policy_check(host):MSG_NET_SDK op=NET_SDK_CHECK(app_id=MEOW_LOG_APP + host);
* 读到 allow=1 → 返回 0(allow),allow=0 → 返回 1(block);任何失败(无 socket/超时/非法应答)
* → 返回 0(乐观放行,绝不因监控不可用误封业务——NETMGR_DESIGN §6.3 自愿性质)。
* - meow_net_report(rx,tx):MSG_NET_SDK op=NET_SDK_REPORT;send 后读一次应答头即关(不读文本),
* best-effort,失败静默(返回值 void)。
* 映射层(SDK 入参 ↔ IPC m_net_sdk_t 字段)集中在本文件;app_id 取 env MEOW_LOG_APP(与 meow_ui_log.c
* 口径一致),socket 路径取 env MEOW_NET_SOCK(宿主/qemu 覆盖)缺省 /usr/data/meow_net.sock。
*
* 线程安全:app_id pthread_once 缓存;本文件纯传输层不调 meow_log(与 meow_notify_ipc.c 同约定)。
*/
#include "meow_net_ipc.h"
#include "meow_ipc.h" /* 共享协议:帧头/m_net_sdk_t/m_net_sdk_result_t/MSG_NET_SDK* —— 防漂移 */
#include <stdio.h> /* snprintf */
#include <stdlib.h> /* getenv */
#include <string.h>
#include <errno.h> /* EINTR */
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#define MEOW_NET_IPC_TIMEOUT_MS 500 /* 应答读超时:netmgrd 单线程 poll,>500ms 视为降级 */
static pthread_once_t g_once = PTHREAD_ONCE_INIT;
static char g_app_id[MEOW_APP_ID_MAX] = "app";
static void ipc_init(void)
{
const char *s = getenv("MEOW_LOG_APP");
if (s && s[0]) snprintf(g_app_id, sizeof g_app_id, "%s", s);
}
const char *meow_net_ipc_app_id(void)
{
pthread_once(&g_once, ipc_init);
return g_app_id;
}
/* socket 路径:优先 env MEOW_NET_SOCK,缺省 /usr/data/meow_net.sock。 */
static const char *ipc_sock_path(void)
{
const char *s = getenv("MEOW_NET_SOCK");
return (s && s[0]) ? s : "/usr/data/meow_net.sock";
}
/* 连接 socket;失败 -1(调用方降级)。 */
static int conn_path(const char *path)
{
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) return -1;
struct sockaddr_un a;
memset(&a, 0, sizeof a);
a.sun_family = AF_UNIX;
strncpy(a.sun_path, path, sizeof a.sun_path - 1);
if (connect(fd, (struct sockaddr *)&a, sizeof a) < 0) { close(fd); return -1; }
return fd;
}
static int write_all(int fd, const uint8_t *p, size_t n)
{
size_t off = 0;
while (off < n) {
ssize_t w = write(fd, p + off, n - off);
if (w < 0) { if (errno == EINTR) continue; return 0; }
if (w == 0) return 0;
off += (size_t)w;
}
return 1;
}
static int read_all(int fd, uint8_t *p, size_t n)
{
size_t off = 0;
while (off < n) {
ssize_t r = read(fd, p + off, n - off);
if (r < 0) { if (errno == EINTR) continue; return 0; }
if (r == 0) return 0;
off += (size_t)r;
}
return 1;
}
static int send_frame(int fd, uint16_t type, uint32_t req_id, const void *payload, uint32_t len)
{
uint8_t hdr[MEOW_IPC_HDR_LEN];
uint32_t magic = MEOW_IPC_MAGIC, rl = len;
uint16_t ver = MEOW_IPC_VERSION, t = type;
memcpy(hdr + 0, &magic, 4); memcpy(hdr + 4, &ver, 2); memcpy(hdr + 6, &t, 2);
memcpy(hdr + 8, &req_id, 4); memcpy(hdr + 12, &rl, 4);
if (!write_all(fd, hdr, sizeof hdr)) return 0;
if (len && payload && !write_all(fd, payload, len)) return 0;
return 1;
}
static void set_timeout(int fd)
{
struct timeval tv;
tv.tv_sec = MEOW_NET_IPC_TIMEOUT_MS / 1000;
tv.tv_usec = (MEOW_NET_IPC_TIMEOUT_MS % 1000) * 1000;
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
}
int meow_net_policy_check(const char *host)
{
if (!host || !host[0]) return 0;
m_net_sdk_t q;
memset(&q, 0, sizeof q);
q.op = NET_SDK_CHECK;
snprintf(q.app_id, sizeof q.app_id, "%s", meow_net_ipc_app_id());
snprintf(q.host, sizeof q.host, "%s", host);
int fd = conn_path(ipc_sock_path());
if (fd < 0) return 0; /* java socket:乐观放行 */
set_timeout(fd);
int allow = 0; /* 默认放行 */
if (send_frame(fd, MSG_NET_SDK, 0x4E455443u /* "NETC" */, &q, (uint32_t)sizeof q)) {
uint8_t rhdr[MEOW_IPC_HDR_LEN];
if (read_all(fd, rhdr, sizeof rhdr)) {
uint16_t rtype; uint32_t rlen;
memcpy(&rtype, rhdr + 6, 2); memcpy(&rlen, rhdr + 12, 4);
if (rtype == MSG_NET_SDK_RESULT && rlen >= 10) {
uint8_t pay[12];
if (read_all(fd, pay, 12)) { /* code(4)+allow(4)+text_len(2)+pad(2) */
m_net_sdk_result_t res;
memset(&res, 0, sizeof res);
memcpy(&res.code, pay, 4);
memcpy(&res.allow, pay + 4, 4);
memcpy(&res.text_len, pay + 8, 2);
if (res.text_len < sizeof res.text)
read_all(fd, (uint8_t *)res.text, res.text_len);
if (res.code == MEOW_OK) allow = (res.allow != 0) ? 1 : 0;
}
}
}
}
close(fd);
return allow ? 0 : 1; /* allow=1 → 返回 0(放行);allow=0 → 返回 1(block) */
}
void meow_net_report(uint32_t rx, uint32_t tx)
{
m_net_sdk_t q;
memset(&q, 0, sizeof q);
q.op = NET_SDK_REPORT;
snprintf(q.app_id, sizeof q.app_id, "%s", meow_net_ipc_app_id());
q.rx = rx; q.tx = tx;
int fd = conn_path(ipc_sock_path());
if (fd < 0) return; /* 无 socket:静默 */
set_timeout(fd);
if (send_frame(fd, MSG_NET_SDK, 0x4E455452u /* "NETR" */, &q, (uint32_t)sizeof q)) {
uint8_t rhdr[MEOW_IPC_HDR_LEN];
read_all(fd, rhdr, sizeof rhdr); /* best-effort:读一次应答头即关,不解析 */
}
close(fd);
}