You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.2 KiB
117 lines
3.2 KiB
#include "utun_test_socket_api.h" |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <errno.h> |
|
|
|
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; |
|
} |