mirror of
https://github.com/DrBeef/DVR.git
synced 2024-12-21 10:01:47 +00:00
430 lines
9.4 KiB
Text
430 lines
9.4 KiB
Text
/*
|
|
SDL_net: An example cross-platform network library for use with SDL
|
|
Copyright (C) 1997-2004 Sam Lantinga
|
|
|
|
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 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.
|
|
|
|
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
|
|
*/
|
|
|
|
/* $Id: SDLnet.c 2207 2006-04-20 16:48:25Z slouken $ */
|
|
|
|
#include <string.h>
|
|
|
|
#include "SDL_endian.h"
|
|
|
|
#include "SDLnetsys.h"
|
|
#include "SDL_net.h"
|
|
|
|
|
|
const SDL_version *SDLNet_Linked_Version(void)
|
|
{
|
|
static SDL_version linked_version;
|
|
SDL_NET_VERSION(&linked_version);
|
|
return(&linked_version);
|
|
}
|
|
|
|
/* Since the UNIX/Win32/BeOS code is so different from MacOS,
|
|
we'll just have two completely different sections here.
|
|
*/
|
|
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
|
|
|
|
/* Initialize/Cleanup the network API */
|
|
int SDLNet_Init(void)
|
|
{
|
|
if ( !SDLNet_started ) {
|
|
#ifdef __USE_W32_SOCKETS
|
|
/* Start up the windows networking */
|
|
WORD version_wanted = MAKEWORD(1,1);
|
|
WSADATA wsaData;
|
|
|
|
if ( WSAStartup(version_wanted, &wsaData) != 0 ) {
|
|
SDLNet_SetError("Couldn't initialize Winsock 1.1\n");
|
|
return(-1);
|
|
}
|
|
#else
|
|
/* SIGPIPE is generated when a remote socket is closed */
|
|
void (*handler)(int);
|
|
handler = signal(SIGPIPE, SIG_IGN);
|
|
if ( handler != SIG_DFL ) {
|
|
signal(SIGPIPE, handler);
|
|
}
|
|
#endif
|
|
}
|
|
++SDLNet_started;
|
|
return(0);
|
|
}
|
|
void SDLNet_Quit(void)
|
|
{
|
|
if ( SDLNet_started == 0 ) {
|
|
return;
|
|
}
|
|
if ( --SDLNet_started == 0 ) {
|
|
#ifdef __USE_W32_SOCKETS
|
|
/* Clean up windows networking */
|
|
if ( WSACleanup() == SOCKET_ERROR ) {
|
|
if ( WSAGetLastError() == WSAEINPROGRESS ) {
|
|
WSACancelBlockingCall();
|
|
WSACleanup();
|
|
}
|
|
}
|
|
#else
|
|
/* Restore the SIGPIPE handler */
|
|
void (*handler)(int);
|
|
handler = signal(SIGPIPE, SIG_DFL);
|
|
if ( handler != SIG_IGN ) {
|
|
signal(SIGPIPE, handler);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* 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 {
|
|
address->host = inet_addr(host);
|
|
if ( address->host == INADDR_NONE ) {
|
|
struct hostent *hp;
|
|
|
|
hp = gethostbyname(host);
|
|
if ( hp ) {
|
|
memcpy(&address->host,hp->h_addr,hp->h_length);
|
|
} else {
|
|
retval = -1;
|
|
}
|
|
}
|
|
}
|
|
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.
|
|
*/
|
|
/* Written by Miguel Angel Blanch.
|
|
* Main Programmer of Arianne RPG.
|
|
* http://come.to/arianne_rpg
|
|
*/
|
|
const char *SDLNet_ResolveIP(IPaddress *ip)
|
|
{
|
|
struct hostent *hp;
|
|
|
|
hp = gethostbyaddr((char *)&ip->host, 4, AF_INET);
|
|
if ( hp != NULL ) {
|
|
return hp->h_name;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#endif /* MACOS_OPENTRANSPORT */
|
|
|
|
#if !SDL_DATA_ALIGNED /* function versions for binary compatibility */
|
|
|
|
/* Write a 16 bit value to network packet buffer */
|
|
#undef SDLNet_Write16
|
|
void SDLNet_Write16(Uint16 value, void *areap)
|
|
{
|
|
(*(Uint16 *)(areap) = SDL_SwapBE16(value));
|
|
}
|
|
|
|
/* Write a 32 bit value to network packet buffer */
|
|
#undef SDLNet_Write32
|
|
void SDLNet_Write32(Uint32 value, void *areap)
|
|
{
|
|
*(Uint32 *)(areap) = SDL_SwapBE32(value);
|
|
}
|
|
|
|
/* Read a 16 bit value from network packet buffer */
|
|
#undef SDLNet_Read16
|
|
Uint16 SDLNet_Read16(void *areap)
|
|
{
|
|
return (SDL_SwapBE16(*(Uint16 *)(areap)));
|
|
}
|
|
|
|
/* Read a 32 bit value from network packet buffer */
|
|
#undef SDLNet_Read32
|
|
Uint32 SDLNet_Read32(void *areap)
|
|
{
|
|
return (SDL_SwapBE32(*(Uint32 *)(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 */
|