158 lines
6.0 KiB
C
158 lines
6.0 KiB
C
/*
|
||
* 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);
|
||
}
|