Updated SDL_net

This commit is contained in:
pelya
2012-03-01 12:31:51 +02:00
parent c0482e36e2
commit 6d88235cf4
9 changed files with 410 additions and 1988 deletions

View File

@@ -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 */