mirror of
https://github.com/Cateners/tiny_computer.git
synced 2026-05-20 16:35:47 +08:00
223 lines
8.2 KiB
C
223 lines
8.2 KiB
C
// getifaddrs_bridge_server.c -- This file is part of tiny_computer.
|
||
|
||
// Copyright (C) 2023 Caten Hu
|
||
|
||
// Tiny Computer is free software: you can redistribute it and/or modify
|
||
// it under the terms of the GNU General Public License as published
|
||
// by the Free Software Foundation, either version 3 of the License,
|
||
// or any later version.
|
||
|
||
// Tiny Computer is distributed in the hope that it will be useful,
|
||
// but WITHOUT ANY WARRANTY; without even the implied warranty
|
||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
// See the GNU General Public License for more details.
|
||
|
||
// You should have received a copy of the GNU General Public License
|
||
// along with this program. If not, see http://www.gnu.org/licenses/.
|
||
|
||
/* this file is mainly generated by Bing */
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
#include <sys/socket.h>
|
||
#include <netinet/in.h>
|
||
#include <arpa/inet.h>
|
||
#include <ifaddrs.h>
|
||
#include <sys/ioctl.h>
|
||
#include <net/if.h>
|
||
#include <sys/un.h>
|
||
|
||
#define BUFSIZE 1024 // 定义缓冲区大小
|
||
|
||
// 定义一个序列化函数,将ifaddrs结构体转换为字节数组
|
||
int serialize_ifaddrs(struct ifaddrs *ifa, char *buf, int size) {
|
||
int len = 0; // 记录已经写入的字节数
|
||
while (ifa != NULL && len < size) {
|
||
// 写入接口名称
|
||
int namelen = strlen(ifa->ifa_name) + 1; // 包括结束符
|
||
if (len + namelen > size) break; // 缓冲区不足
|
||
memcpy(buf + len, ifa->ifa_name, namelen);
|
||
len += namelen;
|
||
// 写入接口标志
|
||
if (len + sizeof(unsigned int) > size) break; // 缓冲区不足
|
||
memcpy(buf + len, &ifa->ifa_flags, sizeof(unsigned int));
|
||
len += sizeof(unsigned int);
|
||
// 写入接口地址
|
||
if (ifa->ifa_addr != NULL) {
|
||
int addrlen = sizeof(struct sockaddr); // 地址结构体长度
|
||
if (len + addrlen > size) break; // 缓冲区不足
|
||
memcpy(buf + len, ifa->ifa_addr, addrlen);
|
||
len += addrlen;
|
||
} else {
|
||
// 如果没有地址,写入一个空字节
|
||
if (len + 1 > size) break; // 缓冲区不足
|
||
buf[len] = '\0';
|
||
len += 1;
|
||
}
|
||
// 写入接口掩码
|
||
if (ifa->ifa_netmask != NULL) {
|
||
int masklen = sizeof(struct sockaddr); // 掩码结构体长度
|
||
if (len + masklen > size) break; // 缓冲区不足
|
||
memcpy(buf + len, ifa->ifa_netmask, masklen);
|
||
len += masklen;
|
||
} else {
|
||
// 如果没有掩码,写入一个空字节
|
||
if (len + 1 > size) break; // 缓冲区不足
|
||
buf[len] = '\0';
|
||
len += 1;
|
||
}
|
||
// 写入接口广播地址或点对点地址
|
||
if (ifa->ifa_flags & IFF_BROADCAST) {
|
||
// 如果有广播地址
|
||
if (ifa->ifa_broadaddr != NULL) {
|
||
int broadlen = sizeof(struct sockaddr); // 广播地址结构体长度
|
||
if (len + broadlen > size) break; // 缓冲区不足
|
||
memcpy(buf + len, ifa->ifa_broadaddr, broadlen);
|
||
len += broadlen;
|
||
} else {
|
||
// 如果没有广播地址,写入一个空字节
|
||
if (len + 1 > size) break; // 缓冲区不足
|
||
buf[len] = '\0';
|
||
len += 1;
|
||
}
|
||
} else if (ifa->ifa_flags & IFF_POINTOPOINT) {
|
||
// 如果有点对点地址
|
||
if (ifa->ifa_dstaddr != NULL) {
|
||
int dstlen = sizeof(struct sockaddr); // 点对点地址结构体长度
|
||
if (len + dstlen > size) break; // 缓冲区不足
|
||
memcpy(buf + len, ifa->ifa_dstaddr, dstlen);
|
||
len += dstlen;
|
||
} else {
|
||
// 如果没有点对点地址,写入一个空字节
|
||
if (len + 1 > size) break; // 缓冲区不足
|
||
buf[len] = '\0';
|
||
len += 1;
|
||
}
|
||
} else {
|
||
// 如果没有广播地址或点对点地址,写入两个空字节
|
||
if (len + 2 > size) break; // 缓冲区不足
|
||
buf[len] = '\0';
|
||
buf[len + 1] = '\0';
|
||
len += 2;
|
||
}
|
||
// 写入接口数据
|
||
if (ifa->ifa_data != NULL) {
|
||
// TODO: 根据不同的地址族,写入不同的数据
|
||
// 这里暂时省略,只写入一个空字节
|
||
if (len + 1 > size) break; // 缓冲区不足
|
||
buf[len] = '\0';
|
||
len += 1;
|
||
} else {
|
||
// 如果没有数据,写入一个空字节
|
||
if (len + 1 > size) break; // 缓冲区不足
|
||
buf[len] = '\0';
|
||
len += 1;
|
||
}
|
||
// 跳到下一个接口
|
||
ifa = ifa->ifa_next;
|
||
}
|
||
return len; // 返回写入的总字节数
|
||
}
|
||
|
||
// 定义一个接收信号的函数,从客户端接收一个信号
|
||
int receive_signal(int sockfd) {
|
||
char sig; // 定义信号变量
|
||
int n = read(sockfd, &sig, 1); // 从套接字读取一个字节
|
||
if (n < 0) {
|
||
perror("read");
|
||
return -1; // 返回错误
|
||
}
|
||
if (sig == 'S') {
|
||
// 如果收到信号S,表示客户端需要数据
|
||
return 0; // 返回成功
|
||
} else {
|
||
// 如果收到其他信号,表示无效信号
|
||
fprintf(stderr, "invalid signal: %c\n", sig);
|
||
return -1; // 返回错误
|
||
}
|
||
}
|
||
|
||
// 定义一个发送数据的函数,向客户端发送数据并序列化
|
||
int send_data(int sockfd) {
|
||
struct ifaddrs *ifap = NULL; // 定义ifaddrs结构体指针
|
||
// 调用getifaddrs函数,获取本地接口信息
|
||
if (getifaddrs(&ifap) < 0) {
|
||
perror("getifaddrs");
|
||
return -1; // 返回错误
|
||
}
|
||
char buf[BUFSIZE]; // 定义缓冲区
|
||
// 调用序列化函数,将ifaddrs结构体转换为字节数组
|
||
int len = serialize_ifaddrs(ifap, buf, BUFSIZE);
|
||
if (len < 0) {
|
||
fprintf(stderr, "serialize_ifaddrs failed\n");
|
||
return -1; // 返回错误
|
||
}
|
||
// 向套接字写入数据
|
||
int n = write(sockfd, buf, len);
|
||
if (n < 0) {
|
||
perror("write");
|
||
return -1; // 返回错误
|
||
}
|
||
// 释放ifaddrs结构体
|
||
freeifaddrs(ifap);
|
||
return 0; // 返回成功
|
||
}
|
||
|
||
// 主函数
|
||
int main(int argc, char *argv[]) {
|
||
if (argc != 2) {
|
||
printf("usage: %s <socket_path>\n", argv[0]);
|
||
return 0;
|
||
}
|
||
// 创建一个套接字
|
||
int sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||
if (sockfd < 0) {
|
||
perror("socket");
|
||
exit(1);
|
||
}
|
||
// 定义服务器地址结构体
|
||
struct sockaddr_un un;
|
||
memset(&un, 0, sizeof(un));
|
||
un.sun_family = AF_UNIX;
|
||
snprintf(un.sun_path, sizeof(un.sun_path), "%s", argv[1]);
|
||
unlink(un.sun_path);
|
||
// 绑定套接字到服务器地址
|
||
if (bind(sockfd, (struct sockaddr *)&un, sizeof(un)) < 0) {
|
||
perror("bind");
|
||
exit(1);
|
||
}
|
||
// 监听套接字
|
||
if (listen(sockfd, 5) < 0) {
|
||
perror("listen");
|
||
exit(1);
|
||
}
|
||
// 循环接受客户端连接
|
||
while (1) {
|
||
int connfd = accept(sockfd, NULL, NULL);
|
||
if (connfd < 0) {
|
||
perror("accept");
|
||
continue; // 如果接受失败,继续循环
|
||
}
|
||
// 循环接收和发送数据
|
||
while (1) {
|
||
// 接收信号
|
||
if (receive_signal(connfd) < 0) {
|
||
fprintf(stderr, "receive_signal failed\n");
|
||
close(connfd); // 如果接收失败,关闭连接套接字
|
||
break; // 跳出循环
|
||
}
|
||
// 发送数据
|
||
if (send_data(connfd) < 0) {
|
||
fprintf(stderr, "send_data failed\n");
|
||
close(connfd); // 如果发送失败,关闭连接套接字
|
||
break; // 跳出循环
|
||
}
|
||
}
|
||
}
|
||
// 关闭监听套接字
|
||
close(sockfd);
|
||
return 0;
|
||
}
|