Browse Source

[Feat] [1.0.0] vmnet 使用 vmprocess 通信

xcbosa mbp16 2 months ago
parent
commit
3d505f312c
1 changed files with 108 additions and 240 deletions
  1. 108 240
      post_sbin/getty.c

+ 108 - 240
post_sbin/getty.c

@@ -17,6 +17,8 @@
 #include <sys/ioctl.h>
 #include <fcntl.h>
 
+#define MAX_BUFFER_SIZE 4096        // 最大缓冲区大小
+
 #define POSIX_SPAWN_SETSID              0x0400
 #define DEBUG 0
 #define VMP_DEVICE_RX "/etc/.vmpdrvfna_rx"
@@ -24,9 +26,64 @@
 #define VMP_TID_MAX 64
 #define VMP_TX_POOL_SIZE 64
 #define VMP_STRBUF_LEN 256
-#define VMNET_PROXY_FLAG (O_RDWR | O_DIRECT | O_SYNC)
 
 extern int vmnetproxy_main(void);
+extern void tx_push(tx_command cmd);
+
+typedef struct vmnet_queue_elem {
+    char buffer[MAX_BUFFER_SIZE];
+    int length;
+    struct vmnet_queue_elem *next;
+} vmnet_queue_elem;
+
+vmnet_queue_elem *vmnet_queue_front;
+vmnet_queue_elem *vmnet_queue_waiting_buffer;
+pthread_mutex_t vmnet_queue_lock;
+
+void vmnet_queue_setup(void) {
+    vmnet_queue_front = NULL;
+    vmnet_queue_waiting_buffer = NULL;
+    pthread_mutex_init(&vmnet_queue_lock, NULL);
+}
+
+int vmnet_write_message(const char *buffer, int length) {
+    int packetOffset = 0;
+    const int maximumSplitPacketSize = VMP_STRBUF_LEN - 1;
+    do {
+        int currentSplitSize = MIN(length - packetOffset, maximumSplitPacketSize);
+        bool hasNext = packetOffset + currentSplitSize >= length;
+        tx_command tx = {
+            .type = tx_command_type_vmnet,
+            .tid = hasNext ? 21 : 22,
+            .error = 0,
+            .magic = 0,
+            .sstdout_len = currentSplitSize
+        };
+        memcpy(&tx.sstdout[0], &buffer[packetOffset], currentSplitSize);
+        tx_push(tx);
+        packetOffset += currentSplitSize;
+    }
+    while (packetOffset < length);
+}
+
+int vmnet_read_message(char *buffer, int length) {
+    vmnet_queue_elem *elem;
+    pthread_mutex_lock(&vmnet_queue_lock);
+    elem = vmnet_queue_front;
+    if (elem) {
+        vmnet_queue_front = elem->next;
+    }
+    pthread_mutex_unlock(&vmnet_queue_lock);
+
+    if (!elem) {
+        return 0;
+    }
+
+    int write_len = MIN(elem->length, length);
+    memcpy(buffer, &elem->buffer[0], write_len);
+    free(elem);
+    return write_len;
+}
 
 typedef struct {
     short width;
@@ -42,7 +99,8 @@ typedef enum {
     rx_command_type_lsproc,
     rx_command_type_sstdin,
     rx_command_type_winsize,
-    rx_command_type_ping
+    rx_command_type_ping,
+    rx_command_type_vmnet
 } rx_command_type;
 
 typedef struct {
@@ -59,7 +117,8 @@ typedef enum {
     tx_command_type_online,
     tx_command_type_stdout,
     tx_command_type_cb,
-    tx_command_type_stoped
+    tx_command_type_stoped,
+    tx_command_type_vmnet
 } tx_command_type;
 
 typedef struct {
@@ -90,6 +149,41 @@ typedef struct {
     FD stdout_fd;
 } management_process;
 
+void vmnet_push_data(rx_command command) {
+    if (command.type != rx_command_type_vmnet) {
+        return;
+    }
+    bool has_next = command.tid == 21;
+
+    pthread_mutex_lock(&vmnet_queue_lock);
+
+    if (vmnet_queue_waiting_buffer == NULL) {
+        vmnet_queue_waiting_buffer = (vmnet_queue_elem *)calloc(1, sizeof(vmnet_queue_elem));
+    }
+
+    const int size = command.sstdin_len;
+    int approve_size = MIN(size, MAX_BUFFER_SIZE - vmnet_queue_waiting_buffer->length);
+    if (approve_size >= 0) {
+        memcpy(&vmnet_queue_waiting_buffer->buffer[vmnet_queue_waiting_buffer->length], command.sstdin, approve_size);
+        vmnet_queue_waiting_buffer->length += approve_size;
+    }
+
+    if (!has_next) {
+        if (vmnet_queue_front == NULL) {
+            vmnet_queue_front = vmnet_queue_waiting_buffer;
+        }
+        else {
+            vmnet_queue_elem *elem;
+            for (elem = vmnet_queue_front; elem != NULL; elem = elem->next) ;
+            elem->next = vmnet_queue_waiting_buffer;
+        }
+        vmnet_queue_waiting_buffer->next = NULL;
+        vmnet_queue_waiting_buffer = NULL;
+    }
+
+    pthread_mutex_unlock(&vmnet_queue_lock);
+}
+
 void debug_print_rx(rx_command rx) {
 #if DEBUG
     printf("RX: (type=%d tid=%d signal=%d magic=%ld sstdin=%s)\n", rx.type, rx.tid, rx.signal, rx.magic, rx.sstdin);
@@ -493,6 +587,10 @@ void rx_process(rx_command cmd) {
             CB_PUSH(cmd.magic, 0, "PONG");
             break;
         }
+        case rx_command_type_vmnet: {
+            vmnet_push_data(cmd);
+            break;
+        }
     }
 }
 
@@ -503,6 +601,7 @@ void *vmnetproxy_program(void *param) {
 }
 
 int main() {
+    vmnet_queue_setup();
     printf("Boot Success\n");
     printf("Welcome to XCVMKit-OS!\n");
     RX = open(VMP_DEVICE_RX, 1101824);
@@ -561,8 +660,6 @@ int main() {
 #include <pthread.h>
 
 /* 常量定义 */
-#define PROXY_FILE "/etc/.vmpdrvfna"  // 共享文件路径
-#define MAX_BUFFER_SIZE 4096        // 最大缓冲区大小
 #define MAX_PORTS 16                // 最大端口数量
 #define MAX_CONNECTIONS 64          // 最大连接数
 
@@ -659,12 +756,7 @@ static void __file_lock_initiator(void) {
  * @return 文件描述符
  */
 int open_proxy_file(int flags) {
-    int fd = open(PROXY_FILE, flags, 0644);
-    if (fd < 0) {
-        log_message("无法打开代理文件: %s", strerror(errno));
-        return -1;
-    }
-    return fd;
+    return 0;
 }
 
 /**
@@ -673,15 +765,6 @@ int open_proxy_file(int flags) {
  */
 void lock_file(int fd) {
     pthread_mutex_lock(&file_lock);
-    close(fd);
-    fd = open_proxy_file(VMNET_PROXY_FLAG);
-    if (fd < 0) {
-        return;
-    }
-    if (flock(fd, LOCK_EX) < 0) {
-        log_message("无法锁定文件: %s", strerror(errno));
-    }
-    posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
 }
 
 /**
@@ -689,10 +772,6 @@ void lock_file(int fd) {
  * @param fd 文件描述符
  */
 void unlock_file(int fd) {
-    fsync(fd);
-    if (flock(fd, LOCK_UN) < 0) {
-        log_message("无法解锁文件: %s", strerror(errno));
-    }
     pthread_mutex_unlock(&file_lock);
 }
 
@@ -707,44 +786,9 @@ void unlock_file(int fd) {
  */
 int write_message(int fd, void *message, int size) {
     lock_file(fd);
-
-    // 将文件指针移动到文件开头
-    if (lseek(fd, 0, SEEK_SET) < 0) {
-        log_message("无法定位文件指针: %s", strerror(errno));
-        unlock_file(fd);
-        return -1;
-    }
-
-    long total_message_size = 0;
-    while (1) {
-        int message_size;
-        if (read(fd, &message_size, sizeof(int)) != sizeof(int)) {
-            ftruncate(fd, total_message_size);
-            break;
-        }
-        total_message_size += message_size;
-        lseek(fd, total_message_size, SEEK_SET);
-    }
-    
-    // 写入消息大小(用于读取时分隔消息)
-    int total_size = size + sizeof(int);
-    if (write(fd, &total_size, sizeof(int)) < 0) {
-        log_message("写入消息大小失败: %s", strerror(errno));
-        unlock_file(fd);
-        return -1;
-    }
-    
-    // 写入消息内容
-    int bytes_written = write(fd, message, size);
-    if (bytes_written < 0) {
-        log_message("写入消息失败: %s", strerror(errno));
-    }
-    
-    // 刷新文件缓冲区
-    fsync(fd);
-    
+    int ret = vmnet_write_message(message, size);
     unlock_file(fd);
-    return bytes_written;
+    return ret;
 }
 
 /**
@@ -757,170 +801,9 @@ int write_message(int fd, void *message, int size) {
  */
 int read_message(int fd, void *buffer, int size, int target) {
     lock_file(fd);
-    
-    // 将文件指针移动到文件开头
-    if (lseek(fd, 0, SEEK_SET) < 0) {
-        log_message("无法定位文件指针: %s", strerror(errno));
-        unlock_file(fd);
-        return -1;
-    }
-    
-    // 读取文件大小
-    off_t file_size = lseek(fd, 0, SEEK_END);
-    if (file_size < 0) {
-        log_message("无法获取文件大小: %s", strerror(errno));
-        unlock_file(fd);
-        return -1;
-    }
-    
-    // 如果文件为空,则没有消息
-    if (file_size == 0) {
-        unlock_file(fd);
-        return 0;
-    }
-    
-    // 重新定位到文件开头
-    if (lseek(fd, 0, SEEK_SET) < 0) {
-        log_message("无法重新定位文件指针: %s", strerror(errno));
-        unlock_file(fd);
-        return -1;
-    }
-
-    int message_size;
-    int content_size;
-    long total_message_size = 0;
-    while (1)
-    {
-        // 读取第一条消息的大小
-        if (read(fd, &message_size, sizeof(int)) != sizeof(int)) {
-            log_message("读取消息大小失败: %s", strerror(errno));
-            ftruncate(fd, total_message_size);
-            unlock_file(fd);
-            return -1;
-        }
-    
-        // 检查消息大小是否合理
-        content_size = message_size - sizeof(int);
-        if (content_size <= 0 || content_size > size) {
-            log_message("消息大小不合理: %d", content_size);
-            ftruncate(fd, total_message_size);
-            unlock_file(fd);
-            return -1;
-        }
-
-        total_message_size += message_size;
-    
-        // 先读取消息头部以检查target
-        MessageHeader header;
-        int header_size = sizeof(MessageHeader) < content_size ? sizeof(MessageHeader) : content_size;
-        int peek_bytes = read(fd, &header, header_size);
-        if (peek_bytes < 0) {
-            log_message("读取消息头部失败: %s", strerror(errno));
-            unlock_file(fd);
-            return -1;
-        }
-    
-        // 将文件指针移回消息内容开始位置
-        if (lseek(fd, -peek_bytes, SEEK_CUR) < 0) {
-            log_message("无法重新定位文件指针: %s", strerror(errno));
-            unlock_file(fd);
-            return -1;
-        }
-    
-        // 检查消息target是否匹配
-        if (header.target == target) {
-            // 是发给当前接收方的消息,跳过当前消息,继续查找后续消息
-            break;
-        }
-        else {
-            // 不是发给当前接收方的消息,跳过当前消息,继续查找后续消息
-            
-            // 跳过当前消息内容
-            if (lseek(fd, content_size, SEEK_CUR) < 0) {
-                log_message("无法跳过当前消息: %s", strerror(errno));
-                unlock_file(fd);
-                return -1;
-            }
-        
-            // 计算剩余数据大小
-            off_t current_position = lseek(fd, 0, SEEK_CUR);
-            if (current_position < 0) {
-                log_message("无法获取当前位置: %s", strerror(errno));
-                unlock_file(fd);
-                return -1;
-            }
-        
-            // 如果还有剩余数据,继续查找
-            if (current_position < file_size) {
-                continue;
-            } else {
-                // 没有更多消息了
-                unlock_file(fd);
-                return 0;
-            }
-        }
-    }
-    
-    // 读取完整消息内容
-    int bytes_read = read(fd, buffer, content_size);
-    if (bytes_read < 0) {
-        log_message("读取消息内容失败: %s", strerror(errno));
-        unlock_file(fd);
-        return -1;
-    }
-    
-    // 计算剩余数据大小
-    off_t remaining_size = file_size - total_message_size;
-    off_t before_size = total_message_size - content_size - sizeof(int);
-    
-    // 如果还有剩余数据,将其移动到文件开头
-    if (remaining_size > 0) {
-        char *temp_buffer = malloc(remaining_size);
-        if (temp_buffer == NULL) {
-            log_message("内存分配失败");
-            unlock_file(fd);
-            return bytes_read;
-        }
-        
-        // 读取剩余数据
-        if (read(fd, temp_buffer, remaining_size) != remaining_size) {
-            log_message("读取剩余数据失败: %s", strerror(errno));
-            free(temp_buffer);
-            unlock_file(fd);
-            return bytes_read;
-        }
-        
-        // 将文件截断为0
-        if (ftruncate(fd, before_size) < 0) {
-            log_message("截断文件失败: %s", strerror(errno));
-            free(temp_buffer);
-            unlock_file(fd);
-            return bytes_read;
-        }
-        
-        // 将文件指针移回开头
-        if (lseek(fd, before_size, SEEK_SET) < 0) {
-            log_message("无法重新定位文件指针: %s", strerror(errno));
-            free(temp_buffer);
-            unlock_file(fd);
-            return bytes_read;
-        }
-        
-        // 写回剩余数据
-        if (write(fd, temp_buffer, remaining_size) != remaining_size) {
-            log_message("写回剩余数据失败: %s", strerror(errno));
-        }
-        
-        free(temp_buffer);
-    } else {
-        // 如果没有剩余数据,将文件截断为0
-        if (ftruncate(fd, before_size) < 0) {
-            log_message("截断文件失败: %s", strerror(errno));
-        }
-    }
-    
+    int ret = vmnet_read_message(buffer, size);
     unlock_file(fd);
-    return bytes_read;
+    return ret;
 }
 
 /* 网络操作函数 */
@@ -1108,19 +991,7 @@ void log_message(const char *format, ...) {
  */
 int clear_message_queue(int fd) {
     lock_file(fd);
-    
-    // 将文件截断为0字节,清空所有内容
-    if (ftruncate(fd, 0) < 0) {
-        log_message("清空消息队列失败: %s", strerror(errno));
-        unlock_file(fd);
-        return -1;
-    }
-    
-    // 刷新文件缓冲区
-    fsync(fd);
-    
     unlock_file(fd);
-    log_message("消息队列已清空");
     return 0;
 }
 
@@ -1480,7 +1351,7 @@ int vmnetproxy_main() {
     init_connection_map();
     
     // 打开代理文件
-    proxy_fd = open_proxy_file(VMNET_PROXY_FLAG);
+    proxy_fd = open_proxy_file(0);
     if (proxy_fd < 0) {
         log_message("无法打开代理文件,退出");
         return 1;
@@ -1500,7 +1371,6 @@ int vmnetproxy_main() {
     pthread_t port_thread;
     if (pthread_create(&port_thread, NULL, port_monitor_thread, NULL) != 0) {
         log_message("创建端口监控线程失败: %s", strerror(errno));
-        close(proxy_fd);
         return 1;
     }
     
@@ -1508,7 +1378,6 @@ int vmnetproxy_main() {
     pthread_t message_thread;
     if (pthread_create(&message_thread, NULL, message_handler_thread, NULL) != 0) {
         log_message("创建消息处理线程失败: %s", strerror(errno));
-        close(proxy_fd);
         return 1;
     }
     
@@ -1516,6 +1385,5 @@ int vmnetproxy_main() {
     pthread_join(port_thread, NULL);
     pthread_join(message_thread, NULL);
     
-    close(proxy_fd);
     return 0;
 }