vmnet-proxy/pkg/vmnet/vmnet.m

107 lines
3.1 KiB
Mathematica
Raw Permalink Normal View History

2024-11-15 04:45:55 +00:00
#import "vmnet.h"
void _vmnet_start(interface_ref *interface, char *host_interface, uint64_t *max_packet_size) {
xpc_object_t interface_desc = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_uint64(interface_desc, vmnet_operation_mode_key,
VMNET_BRIDGED_MODE);
xpc_dictionary_set_string(interface_desc, vmnet_shared_interface_name_key, host_interface);
dispatch_queue_t interface_start_queue =
dispatch_queue_create("vmnet-start", DISPATCH_QUEUE_SERIAL);
dispatch_semaphore_t interface_start_semaphore = dispatch_semaphore_create(0);
__block interface_ref _interface;
__block vmnet_return_t interface_status;
__block uint64_t _max_packet_size = 0;
_interface = vmnet_start_interface(
interface_desc, interface_start_queue,
^(vmnet_return_t status, xpc_object_t interface_param) {
interface_status = status;
if (status == VMNET_SUCCESS) {
_max_packet_size = xpc_dictionary_get_uint64(
interface_param, vmnet_max_packet_size_key);
}
dispatch_semaphore_signal(interface_start_semaphore);
});
dispatch_semaphore_wait(interface_start_semaphore, DISPATCH_TIME_FOREVER);
dispatch_release(interface_start_queue);
xpc_release(interface_desc);
if (interface_status != VMNET_SUCCESS) {
return;
}
*interface = _interface;
*max_packet_size = _max_packet_size;
}
void _vmnet_stop(interface_ref interface) {
if (interface == NULL) {
return;
}
dispatch_queue_t interface_stop_queue =
dispatch_queue_create("vmnet-stop", DISPATCH_QUEUE_SERIAL);
dispatch_semaphore_t interface_stop_semaphore = dispatch_semaphore_create(0);
vmnet_stop_interface(interface, interface_stop_queue,
^(vmnet_return_t status) {
dispatch_semaphore_signal(interface_stop_semaphore);
});
dispatch_semaphore_wait(interface_stop_semaphore, DISPATCH_TIME_FOREVER);
dispatch_release(interface_stop_queue);
}
void _vmnet_write(interface_ref interface, void *bytes, size_t bytes_size) {
if (interface == NULL) {
return;
}
struct iovec packets_iovec = {
.iov_base = bytes,
.iov_len = bytes_size,
};
struct vmpktdesc packets = {
.vm_pkt_size = bytes_size,
.vm_pkt_iov = &packets_iovec,
.vm_pkt_iovcnt = 1,
.vm_flags = 0,
};
int packets_count = packets.vm_pkt_iovcnt;
vmnet_write(interface, &packets, &packets_count);
}
void _vmnet_read(interface_ref interface, uint64_t max_packet_size,
void **bytes, size_t *bytes_size) {
struct iovec packets_iovec = {
.iov_base = malloc(max_packet_size),
.iov_len = max_packet_size,
};
struct vmpktdesc packets = {
.vm_pkt_size = max_packet_size,
.vm_pkt_iov = &packets_iovec,
.vm_pkt_iovcnt = 1,
.vm_flags = 0,
};
int packets_count = 1;
vmnet_return_t status = vmnet_read(interface, &packets, &packets_count);
if (status != VMNET_SUCCESS || packets_count == 0) {
return;
}
*bytes = packets.vm_pkt_iov->iov_base;
*bytes_size = packets.vm_pkt_size;
}