// retoor #include #include #include "dns.h" #include "scheduler.h" #include "wren.h" #include "vm.h" #include "uv.h" static void dnsCallback(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { WrenHandle* fiber = (WrenHandle*)req->data; WrenVM* vm = getVM(); wrenEnsureSlots(vm, 3); wrenSetSlotNewList(vm, 2); if (status == 0 && res != NULL) { struct addrinfo* addr = res; while (addr != NULL) { char ip[64]; if (addr->ai_family == AF_INET) { struct sockaddr_in* sa = (struct sockaddr_in*)addr->ai_addr; uv_ip4_name(sa, ip, sizeof(ip)); wrenSetSlotString(vm, 1, ip); wrenInsertInList(vm, 2, -1, 1); } else if (addr->ai_family == AF_INET6) { struct sockaddr_in6* sa = (struct sockaddr_in6*)addr->ai_addr; uv_ip6_name(sa, ip, sizeof(ip)); wrenSetSlotString(vm, 1, ip); wrenInsertInList(vm, 2, -1, 1); } addr = addr->ai_next; } uv_freeaddrinfo(res); } free(req); schedulerResume(fiber, true); schedulerFinishResume(); } void dnsLookup(WrenVM* vm) { const char* hostname = wrenGetSlotString(vm, 1); int family = (int)wrenGetSlotDouble(vm, 2); WrenHandle* fiber = wrenGetSlotHandle(vm, 3); if (hostname == NULL) { wrenSetSlotString(vm, 0, "Hostname required."); wrenAbortFiber(vm, 0); return; } uv_getaddrinfo_t* req = (uv_getaddrinfo_t*)malloc(sizeof(uv_getaddrinfo_t)); if (req == NULL) { wrenSetSlotString(vm, 0, "Memory allocation failed."); wrenAbortFiber(vm, 0); return; } req->data = fiber; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; if (family == 4) { hints.ai_family = AF_INET; } else if (family == 6) { hints.ai_family = AF_INET6; } else { hints.ai_family = AF_UNSPEC; } int result = uv_getaddrinfo(getLoop(), req, dnsCallback, hostname, NULL, &hints); if (result != 0) { free(req); wrenReleaseHandle(vm, fiber); wrenSetSlotString(vm, 0, uv_strerror(result)); wrenAbortFiber(vm, 0); return; } }