Updated SDL_net
This commit is contained in:
@@ -1,30 +1,29 @@
|
||||
/*
|
||||
SDL_net: An example cross-platform network library for use with SDL
|
||||
Copyright (C) 1997-2004 Sam Lantinga
|
||||
SDL_net: An example cross-platform network library for use with SDL
|
||||
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* $Id: SDLnet.c 2207 2006-04-20 16:48:25Z slouken $ */
|
||||
/* $Id$ */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_byteorder.h"
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#include "SDLnetsys.h"
|
||||
#include "SDL_net.h"
|
||||
@@ -42,243 +41,24 @@ const SDL_version *SDLNet_Linked_Version(void)
|
||||
*/
|
||||
static int SDLNet_started = 0;
|
||||
|
||||
#ifdef MACOS_OPENTRANSPORT
|
||||
|
||||
#include <Events.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Uint8 stat;
|
||||
InetSvcRef dns;
|
||||
}DNSStatus, *DNSStatusRef;
|
||||
|
||||
enum
|
||||
{
|
||||
dnsNotReady = 0,
|
||||
dnsReady = 1,
|
||||
dnsResolved = 2,
|
||||
dnsError = 255
|
||||
};
|
||||
|
||||
//static InetSvcRef dns = 0;
|
||||
static DNSStatus dnsStatus;
|
||||
Uint32 OTlocalhost = 0;
|
||||
|
||||
/* We need a notifier for opening DNS.*/
|
||||
/* ( 010311 masahiro minami<elsur@aaa.letter.co.jp>) */
|
||||
static pascal void OpenDNSNotifier(
|
||||
void* context, OTEventCode code, OTResult result, void* cookie )
|
||||
{
|
||||
switch( code )
|
||||
{
|
||||
case T_OPENCOMPLETE:
|
||||
// DNS is ready now.
|
||||
if( result == kOTNoError )
|
||||
{
|
||||
dnsStatus.dns = (InetSvcRef)cookie;
|
||||
dnsStatus.stat = dnsReady;
|
||||
}
|
||||
else
|
||||
{
|
||||
SDLNet_SetError("T_DNRSTRINGTOADDRCOMPLETE event returned an error");
|
||||
dnsStatus.dns = NULL;
|
||||
dnsStatus.stat = dnsError;
|
||||
}
|
||||
break;
|
||||
case T_DNRSTRINGTOADDRCOMPLETE:
|
||||
// DNR resolved the name to address
|
||||
// WORK IN PROGRESS (TODO )
|
||||
dnsStatus.stat = dnsResolved;
|
||||
break;
|
||||
default:
|
||||
if( result != kOTNoError )
|
||||
dnsStatus.stat = dnsError;
|
||||
}
|
||||
// Is there anything else to be done here ???
|
||||
// ( 010311 masahiro minami<elsur@aaa.letter.co.jp> )
|
||||
// (TODO)
|
||||
}
|
||||
|
||||
/* Local functions for initializing and cleaning up the DNS resolver */
|
||||
static int OpenDNS(void)
|
||||
{
|
||||
int retval;
|
||||
OSStatus status;
|
||||
|
||||
retval = 0;
|
||||
status = OTAsyncOpenInternetServices(
|
||||
kDefaultInternetServicesPath, 0, OpenDNSNotifier, NULL);
|
||||
if ( status == noErr ) {
|
||||
InetInterfaceInfo info;
|
||||
|
||||
dnsStatus.stat = dnsNotReady;
|
||||
|
||||
while( dnsStatus.stat != dnsError && dnsStatus.dns == NULL)
|
||||
{
|
||||
// what's to be done ? Yield ? WaitNextEvent ? or what ?
|
||||
// ( 010311 masahiro minami<elsur@aaa.letter.co.jp> )
|
||||
//YieldToAnyThread();
|
||||
}
|
||||
/* Get the address of the local system -
|
||||
What should it be if ethernet is off?
|
||||
*/
|
||||
OTInetGetInterfaceInfo(&info, kDefaultInetInterface);
|
||||
OTlocalhost = info.fAddress;
|
||||
} else {
|
||||
SDLNet_SetError("Unable to open DNS handle");
|
||||
retval = status;
|
||||
}
|
||||
|
||||
return(retval);
|
||||
}
|
||||
|
||||
static void CloseDNS(void)
|
||||
{
|
||||
if ( dnsStatus.dns ) {
|
||||
OTCloseProvider(dnsStatus.dns);
|
||||
dnsStatus.dns = 0;
|
||||
dnsStatus.stat = dnsNotReady;
|
||||
}
|
||||
|
||||
OTlocalhost = 0;
|
||||
}
|
||||
|
||||
/* Initialize/Cleanup the network API */
|
||||
int SDLNet_Init(void)
|
||||
{
|
||||
OSStatus status;
|
||||
int retval;
|
||||
|
||||
dnsStatus.stat = dnsNotReady;
|
||||
dnsStatus.dns = 0;
|
||||
|
||||
|
||||
retval = 0;
|
||||
if ( ! SDLNet_started ) {
|
||||
status = InitOpenTransport();
|
||||
if ( status == noErr ) {
|
||||
retval = OpenDNS();
|
||||
if ( retval < 0 ) {
|
||||
SDLNet_Quit();
|
||||
}
|
||||
} else {
|
||||
SDLNet_SetError("Unable to initialize Open Transport");
|
||||
retval = status;
|
||||
}
|
||||
}
|
||||
if ( retval == 0 ) {
|
||||
++SDLNet_started;
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
|
||||
void SDLNet_Quit(void)
|
||||
{
|
||||
if ( SDLNet_started == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( --SDLNet_started == 0 ) {
|
||||
CloseDNS();
|
||||
CloseOpenTransport();
|
||||
}
|
||||
}
|
||||
|
||||
/* Resolve a host name and port to an IP address in network form */
|
||||
int SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
/* Perform the actual host resolution */
|
||||
if ( host == NULL ) {
|
||||
address->host = INADDR_ANY;
|
||||
} else {
|
||||
/* int a[4];
|
||||
|
||||
address->host = INADDR_NONE;
|
||||
|
||||
if ( sscanf(host, "%d.%d.%d.%d", a, a+1, a+2, a+3) == 4 ) {
|
||||
if ( !(a[0] & 0xFFFFFF00) && !(a[1] & 0xFFFFFF00) &&
|
||||
!(a[2] & 0xFFFFFF00) && !(a[3] & 0xFFFFFF00) ) {
|
||||
address->host = ((a[0] << 24) |
|
||||
(a[1] << 16) |
|
||||
(a[2] << 8) | a[3]);
|
||||
if ( address->host == 0x7F000001 ) {
|
||||
address->host = OTlocalhost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( address->host == INADDR_NONE ) {*/
|
||||
InetHostInfo hinfo;
|
||||
|
||||
/* Check for special case - localhost */
|
||||
if ( strcmp(host, "localhost") == 0 )
|
||||
return(SDLNet_ResolveHost(address, "127.0.0.1", port));
|
||||
|
||||
/* Have OpenTransport resolve the hostname for us */
|
||||
retval = OTInetStringToAddress(dnsStatus.dns, (char *)host, &hinfo);
|
||||
if (retval == noErr) {
|
||||
while( dnsStatus.stat != dnsResolved )
|
||||
{WaitNextEvent(everyEvent, 0, 1, NULL );}
|
||||
address->host = hinfo.addrs[0];
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
address->port = SDL_SwapBE16(port);
|
||||
|
||||
/* Return the status */
|
||||
return(retval);
|
||||
}
|
||||
|
||||
/* Resolve an ip address to a host name in canonical form.
|
||||
If the ip couldn't be resolved, this function returns NULL,
|
||||
otherwise a pointer to a static buffer containing the hostname
|
||||
is returned. Note that this function is not thread-safe.
|
||||
*/
|
||||
/* MacOS implementation by Roy Wood
|
||||
*/
|
||||
const char *SDLNet_ResolveIP(IPaddress *ip)
|
||||
{
|
||||
if (ip != nil)
|
||||
{
|
||||
InetHost theIP;
|
||||
static InetDomainName theInetDomainName;
|
||||
OSStatus theOSStatus;
|
||||
|
||||
|
||||
/* Default result will be null string */
|
||||
|
||||
theInetDomainName[0] = '\0';
|
||||
|
||||
|
||||
/* Do a reverse DNS lookup */
|
||||
|
||||
theIP = ip->host;
|
||||
|
||||
theOSStatus = OTInetAddressToName(dnsStatus.dns,theIP,theInetDomainName);
|
||||
|
||||
/* If successful, return the result */
|
||||
|
||||
if (theOSStatus == kOTNoError)
|
||||
{
|
||||
while( dnsStatus.stat != dnsResolved )
|
||||
{ /*should we yield or what ? */ }
|
||||
return(theInetDomainName);
|
||||
}
|
||||
}
|
||||
|
||||
SDLNet_SetError("Can't perform reverse DNS lookup");
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#else /* !MACOS_OPENTRANSPORT */
|
||||
|
||||
#ifndef __USE_W32_SOCKETS
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#ifndef __USE_W32_SOCKETS
|
||||
|
||||
int SDLNet_GetLastError(void)
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
void SDLNet_SetLastError(int err)
|
||||
{
|
||||
errno = err;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Initialize/Cleanup the network API */
|
||||
int SDLNet_Init(void)
|
||||
{
|
||||
@@ -314,7 +94,9 @@ void SDLNet_Quit(void)
|
||||
/* Clean up windows networking */
|
||||
if ( WSACleanup() == SOCKET_ERROR ) {
|
||||
if ( WSAGetLastError() == WSAEINPROGRESS ) {
|
||||
#ifndef _WIN32_WCE
|
||||
WSACancelBlockingCall();
|
||||
#endif
|
||||
WSACleanup();
|
||||
}
|
||||
}
|
||||
@@ -365,18 +147,94 @@ int SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port)
|
||||
* Main Programmer of Arianne RPG.
|
||||
* http://come.to/arianne_rpg
|
||||
*/
|
||||
const char *SDLNet_ResolveIP(IPaddress *ip)
|
||||
const char *SDLNet_ResolveIP(const IPaddress *ip)
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct in_addr in;
|
||||
|
||||
hp = gethostbyaddr((char *)&ip->host, 4, AF_INET);
|
||||
hp = gethostbyaddr((const char *)&ip->host, sizeof(ip->host), AF_INET);
|
||||
if ( hp != NULL ) {
|
||||
return hp->h_name;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
in.s_addr = ip->host;
|
||||
return inet_ntoa(in);
|
||||
}
|
||||
|
||||
#endif /* MACOS_OPENTRANSPORT */
|
||||
int SDLNet_GetLocalAddresses(IPaddress *addresses, int maxcount)
|
||||
{
|
||||
int count = 0;
|
||||
#ifdef SIOCGIFCONF
|
||||
/* Defined on Mac OS X */
|
||||
#ifndef _SIZEOF_ADDR_IFREQ
|
||||
#define _SIZEOF_ADDR_IFREQ sizeof
|
||||
#endif
|
||||
SOCKET sock;
|
||||
struct ifconf conf;
|
||||
char data[4096];
|
||||
struct ifreq *ifr;
|
||||
struct sockaddr_in *sock_addr;
|
||||
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if ( sock == INVALID_SOCKET ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
conf.ifc_len = sizeof(data);
|
||||
conf.ifc_buf = (caddr_t) data;
|
||||
if ( ioctl(sock, SIOCGIFCONF, &conf) < 0 ) {
|
||||
closesocket(sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ifr = (struct ifreq*)data;
|
||||
while ((char*)ifr < data+conf.ifc_len) {
|
||||
if (ifr->ifr_addr.sa_family == AF_INET) {
|
||||
if (count < maxcount) {
|
||||
sock_addr = (struct sockaddr_in*)&ifr->ifr_addr;
|
||||
addresses[count].host = sock_addr->sin_addr.s_addr;
|
||||
addresses[count].port = sock_addr->sin_port;
|
||||
}
|
||||
++count;
|
||||
}
|
||||
ifr = (struct ifreq*)((char*)ifr + _SIZEOF_ADDR_IFREQ(*ifr));
|
||||
}
|
||||
closesocket(sock);
|
||||
#elif defined(__WIN32__)
|
||||
PIP_ADAPTER_INFO pAdapterInfo;
|
||||
PIP_ADAPTER_INFO pAdapter;
|
||||
PIP_ADDR_STRING pAddress;
|
||||
DWORD dwRetVal = 0;
|
||||
ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO);
|
||||
|
||||
pAdapterInfo = (IP_ADAPTER_INFO *) SDL_malloc(sizeof (IP_ADAPTER_INFO));
|
||||
if (pAdapterInfo == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == ERROR_BUFFER_OVERFLOW) {
|
||||
pAdapterInfo = (IP_ADAPTER_INFO *) SDL_realloc(pAdapterInfo, ulOutBufLen);
|
||||
if (pAdapterInfo == NULL) {
|
||||
return 0;
|
||||
}
|
||||
dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
|
||||
}
|
||||
|
||||
if (dwRetVal == NO_ERROR) {
|
||||
for (pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next) {
|
||||
for (pAddress = &pAdapterInfo->IpAddressList; pAddress; pAddress = pAddress->Next) {
|
||||
if (count < maxcount) {
|
||||
addresses[count].host = inet_addr(pAddress->IpAddress.String);
|
||||
addresses[count].port = 0;
|
||||
}
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_free(pAdapterInfo);
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
||||
#if !SDL_DATA_ALIGNED /* function versions for binary compatibility */
|
||||
|
||||
@@ -409,22 +267,3 @@ Uint32 SDLNet_Read32(void *areap)
|
||||
}
|
||||
|
||||
#endif /* !SDL_DATA_ALIGNED */
|
||||
|
||||
|
||||
#ifdef USE_GUSI_SOCKETS
|
||||
|
||||
/* Configure Socket Factories */
|
||||
|
||||
void GUSISetupFactories()
|
||||
{
|
||||
GUSIwithInetSockets();
|
||||
}
|
||||
|
||||
/* Configure File Devices */
|
||||
|
||||
void GUSISetupDevices()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* USE_GUSI_SOCKETS */
|
||||
|
||||
Reference in New Issue
Block a user