#include "utun_test_socket_api.h" #include #include #include void utun_test_packet_queue_init(struct utun_test_packet_queue* queue) { if (!queue) return; queue->head = NULL; queue->tail = NULL; queue->count = 0; } void utun_test_packet_queue_cleanup(struct utun_test_packet_queue* queue) { if (!queue) return; struct utun_test_packet* pkt = queue->head; while (pkt) { struct utun_test_packet* next = pkt->next; free(pkt->data); free(pkt); pkt = next; } queue->head = NULL; queue->tail = NULL; queue->count = 0; } void utun_test_packet_queue_push(struct utun_test_packet_queue* queue, const uint8_t* data, size_t len, const struct sockaddr* addr, socklen_t addrlen) { if (!queue || !data) return; struct utun_test_packet* pkt = calloc(1, sizeof(*pkt)); if (!pkt) return; pkt->data = malloc(len); if (!pkt->data) { free(pkt); return; } memcpy(pkt->data, data, len); pkt->len = len; if (addr && addrlen > 0 && addrlen <= sizeof(pkt->addr)) { memcpy(&pkt->addr, addr, addrlen); pkt->addrlen = addrlen; } pkt->next = NULL; if (queue->tail) { queue->tail->next = pkt; } else { queue->head = pkt; } queue->tail = pkt; queue->count++; } struct utun_test_packet* utun_test_packet_queue_pop(struct utun_test_packet_queue* queue) { if (!queue || !queue->head) return NULL; struct utun_test_packet* pkt = queue->head; queue->head = pkt->next; if (!queue->head) { queue->tail = NULL; } queue->count--; pkt->next = NULL; return pkt; } size_t utun_test_packet_queue_count(struct utun_test_packet_queue* queue) { return queue ? queue->count : 0; } ssize_t utun_test_default_on_send(const uint8_t* data, size_t len, const struct sockaddr* dest_addr, socklen_t dest_addrlen, void* user_data) { struct utun_test_socket_api* api = (struct utun_test_socket_api*)user_data; if (!api || !data || len == 0) return -1; utun_test_packet_queue_push(&api->send_queue, data, len, dest_addr, dest_addrlen); return len; } ssize_t utun_test_default_on_recv(uint8_t* buffer, size_t buffer_size, struct sockaddr* src_addr, socklen_t* src_addrlen, void* user_data) { struct utun_test_socket_api* api = (struct utun_test_socket_api*)user_data; if (!api || !buffer || buffer_size == 0) return -1; struct utun_test_packet* pkt = utun_test_packet_queue_pop(&api->recv_queue); if (!pkt) { errno = EAGAIN; return -1; } size_t to_copy = (pkt->len < buffer_size) ? pkt->len : buffer_size; memcpy(buffer, pkt->data, to_copy); if (src_addr && src_addrlen && *src_addrlen > 0) { socklen_t copy_len = (pkt->addrlen < *src_addrlen) ? pkt->addrlen : *src_addrlen; memcpy(src_addr, &pkt->addr, copy_len); *src_addrlen = copy_len; } free(pkt->data); free(pkt); return to_copy; }