/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes. * Copyright (C) 2010-2012 - Hans-Kristian Arntzen * * Some code herein may be based on code found in BSNES. * * SSNES is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. * * SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with SSNES. * If not, see . */ #include "netplay_compat.h" #undef getaddrinfo #undef freeaddrinfo #undef sockaddr_storage #undef addrinfo #if defined(_WIN32) && !defined(_XBOX) #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 #endif #define WIN32_LEAN_AND_MEAN #include #include #include #elif defined(_XBOX) #include #else #include #include #include #include #include #endif #include #include #include #define addrinfo addrinfo_ssnes__ // Yes, we love shitty implementations, don't we? :( #ifdef _XBOX struct hostent { char **h_addr_list; // Just do the minimal needed ... }; static struct hostent *gethostbyname(const char *name) { static struct hostent he; static struct in_addr addr; static char *addr_ptr; he.h_addr_list = &addr_ptr; addr_ptr = (char*)&addr; if (!name) return NULL; XNDNS *dns = NULL; WSAEVENT event = WSACreateEvent(); XNetDnsLookup(name, event, &dns); if (!dns) goto error; WaitForSingleObject((HANDLE)event, INFINITE); if (dns->iStatus) goto error; memcpy(&addr, dns->aina, sizeof(addr)); WSACloseEvent(event); XNetDnsRelease(dns); return &he; error: if (event) WSACloseEvent(event); return NULL; } #endif int getaddrinfo_ssnes__(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { struct addrinfo *info = (struct addrinfo*)calloc(1, sizeof(*info)); if (!info) return -1; info->ai_family = AF_INET; info->ai_socktype = hints->ai_socktype; struct sockaddr_in *in_addr = (struct sockaddr_in*)calloc(1, sizeof(*in_addr)); if (!in_addr) { free(info); return -1; } info->ai_addrlen = sizeof(*in_addr); in_addr->sin_family = AF_INET; in_addr->sin_port = htons(strtoul(service, NULL, 0)); if (!node && (hints->ai_flags & AI_PASSIVE)) in_addr->sin_addr.s_addr = INADDR_ANY; else if (node && isdigit(*node)) in_addr->sin_addr.s_addr = inet_addr(node); else if (node && !isdigit(*node)) { struct hostent *host = gethostbyname(node); if (!host || !host->h_addr_list[0]) goto error; in_addr->sin_addr.s_addr = inet_addr(host->h_addr_list[0]); } else goto error; info->ai_addr = (struct sockaddr*)in_addr; *res = info; return 0; error: free(in_addr); free(info); return -1; } void freeaddrinfo_ssnes__(struct addrinfo *res) { free(res->ai_addr); free(res); }