project_files/Android-build/SDL-android-project/jni/sdl_net/SDLnet.c
branchhedgeroid
changeset 5317 86984c1034a5
equal deleted inserted replaced
5314:09bcdcd78379 5317:86984c1034a5
       
     1 /*
       
     2     SDL_net:  An example cross-platform network library for use with SDL
       
     3     Copyright (C) 1997-2004 Sam Lantinga
       
     4 
       
     5     This library is free software; you can redistribute it and/or
       
     6     modify it under the terms of the GNU Library General Public
       
     7     License as published by the Free Software Foundation; either
       
     8     version 2 of the License, or (at your option) any later version.
       
     9 
       
    10     This library is distributed in the hope that it will be useful,
       
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13     Library General Public License for more details.
       
    14 
       
    15     You should have received a copy of the GNU Library General Public
       
    16     License along with this library; if not, write to the Free
       
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    18 
       
    19     Sam Lantinga
       
    20     slouken@libsdl.org
       
    21 */
       
    22 
       
    23 /* $Id: SDLnet.c 2207 2006-04-20 16:48:25Z slouken $ */
       
    24 
       
    25 #include <string.h>
       
    26 
       
    27 #include "SDL_endian.h"
       
    28 
       
    29 #include "SDLnetsys.h"
       
    30 #include "SDL_net.h"
       
    31 
       
    32 
       
    33 const SDL_version *SDLNet_Linked_Version(void)
       
    34 {
       
    35 	static SDL_version linked_version;
       
    36 	SDL_NET_VERSION(&linked_version);
       
    37 	return(&linked_version);
       
    38 }
       
    39 
       
    40 /* Since the UNIX/Win32/BeOS code is so different from MacOS,
       
    41    we'll just have two completely different sections here.
       
    42 */
       
    43 static int SDLNet_started = 0;
       
    44 
       
    45 #ifdef MACOS_OPENTRANSPORT
       
    46 
       
    47 #include <Events.h>
       
    48 
       
    49 typedef struct
       
    50 {
       
    51 	Uint8	stat;
       
    52 	InetSvcRef dns;
       
    53 }DNSStatus, *DNSStatusRef;
       
    54 
       
    55 enum
       
    56 {
       
    57 	dnsNotReady = 0,
       
    58 	dnsReady = 1,
       
    59 	dnsResolved = 2,
       
    60 	dnsError = 255
       
    61 };
       
    62 
       
    63 //static InetSvcRef dns = 0;
       
    64 static DNSStatus dnsStatus;
       
    65 Uint32 OTlocalhost = 0;
       
    66 
       
    67 /* We need a notifier for opening DNS.*/
       
    68 /* ( 010311 masahiro minami<elsur@aaa.letter.co.jp>) */
       
    69 static pascal void OpenDNSNotifier(
       
    70 	void* context, OTEventCode code, OTResult result, void* cookie )
       
    71 {
       
    72 	switch( code )
       
    73 	{
       
    74 		case T_OPENCOMPLETE:
       
    75 			// DNS is ready now.
       
    76 			if( result == kOTNoError )
       
    77 			{
       
    78 				dnsStatus.dns = (InetSvcRef)cookie;
       
    79 				dnsStatus.stat = dnsReady;
       
    80 			}
       
    81 			else
       
    82 			{
       
    83 				SDLNet_SetError("T_DNRSTRINGTOADDRCOMPLETE event returned an error");
       
    84 				dnsStatus.dns = NULL;
       
    85 				dnsStatus.stat = dnsError;
       
    86 			}
       
    87 			break;
       
    88 		case T_DNRSTRINGTOADDRCOMPLETE:
       
    89 			// DNR resolved the name to address
       
    90 			// WORK IN PROGRESS (TODO )
       
    91 			dnsStatus.stat = dnsResolved;
       
    92 			break;
       
    93 		default:
       
    94 			if( result != kOTNoError )
       
    95 				dnsStatus.stat = dnsError;
       
    96 	}
       
    97 	// Is there anything else to be done here ???
       
    98 	// ( 010311 masahiro minami<elsur@aaa.letter.co.jp> )
       
    99 	// (TODO)
       
   100 }
       
   101 
       
   102 /* Local functions for initializing and cleaning up the DNS resolver */
       
   103 static int OpenDNS(void)
       
   104 {
       
   105 	int retval;
       
   106 	OSStatus status;
       
   107 
       
   108 	retval = 0;
       
   109 	status = OTAsyncOpenInternetServices(
       
   110 		kDefaultInternetServicesPath, 0, OpenDNSNotifier, NULL);
       
   111 	if ( status == noErr ) {
       
   112 		InetInterfaceInfo	info;
       
   113 		
       
   114 		dnsStatus.stat = dnsNotReady;
       
   115 		
       
   116 		while( dnsStatus.stat != dnsError && dnsStatus.dns == NULL)
       
   117 		{
       
   118 			// what's to be done ? Yield ? WaitNextEvent ? or what ?
       
   119 			// ( 010311 masahiro minami<elsur@aaa.letter.co.jp> )
       
   120 			//YieldToAnyThread();
       
   121 		}
       
   122 		/* Get the address of the local system -
       
   123 		   What should it be if ethernet is off?
       
   124 		 */
       
   125 		OTInetGetInterfaceInfo(&info, kDefaultInetInterface);
       
   126 		OTlocalhost = info.fAddress;
       
   127 	} else {
       
   128 		SDLNet_SetError("Unable to open DNS handle");
       
   129 		retval = status;
       
   130 	}
       
   131 	
       
   132 	return(retval);
       
   133 }
       
   134 
       
   135 static void CloseDNS(void)
       
   136 {
       
   137 	if ( dnsStatus.dns ) {
       
   138 		OTCloseProvider(dnsStatus.dns);
       
   139 		dnsStatus.dns = 0;
       
   140 		dnsStatus.stat = dnsNotReady;
       
   141 	}
       
   142 	
       
   143 	OTlocalhost = 0;
       
   144 }
       
   145 
       
   146 /* Initialize/Cleanup the network API */
       
   147 int  SDLNet_Init(void)
       
   148 {
       
   149 	OSStatus status;
       
   150 	int retval;
       
   151 
       
   152 	dnsStatus.stat = dnsNotReady;
       
   153 	dnsStatus.dns = 0;
       
   154 
       
   155 
       
   156 	retval = 0;
       
   157 	if ( ! SDLNet_started ) {
       
   158 		status = InitOpenTransport();
       
   159 		if ( status == noErr ) {
       
   160 			retval = OpenDNS();
       
   161 			if ( retval < 0 ) {
       
   162 				SDLNet_Quit();
       
   163 			}
       
   164 		} else {
       
   165 			SDLNet_SetError("Unable to initialize Open Transport");
       
   166 			retval = status;
       
   167 		}
       
   168 	}
       
   169 	if ( retval == 0 ) {
       
   170 		++SDLNet_started;
       
   171 	}
       
   172 	return(retval);
       
   173 }
       
   174 
       
   175 void SDLNet_Quit(void)
       
   176 {
       
   177 	if ( SDLNet_started == 0 ) {
       
   178 		return;
       
   179 	}
       
   180 	if ( --SDLNet_started == 0 ) {
       
   181 		CloseDNS();
       
   182 		CloseOpenTransport();
       
   183 	}
       
   184 }
       
   185 
       
   186 /* Resolve a host name and port to an IP address in network form */
       
   187 int SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port)
       
   188 {
       
   189 	int retval = 0;
       
   190 
       
   191 	/* Perform the actual host resolution */
       
   192 	if ( host == NULL ) {
       
   193 		address->host = INADDR_ANY;
       
   194 	} else {
       
   195 /*		int a[4];
       
   196 
       
   197 		address->host = INADDR_NONE;
       
   198 		
       
   199 		if ( sscanf(host, "%d.%d.%d.%d", a, a+1, a+2, a+3) == 4 ) {
       
   200 			if ( !(a[0] & 0xFFFFFF00) && !(a[1] & 0xFFFFFF00) &&
       
   201 			     !(a[2] & 0xFFFFFF00) && !(a[3] & 0xFFFFFF00) ) {
       
   202 				address->host = ((a[0] << 24) |
       
   203 				                 (a[1] << 16) |
       
   204 				                 (a[2] <<  8) | a[3]);
       
   205 				if ( address->host == 0x7F000001 ) {
       
   206 					address->host = OTlocalhost;
       
   207 				}
       
   208 			}
       
   209 		}
       
   210 		
       
   211 		if ( address->host == INADDR_NONE ) {*/
       
   212 			InetHostInfo hinfo;
       
   213 			
       
   214 			/* Check for special case - localhost */
       
   215 			if ( strcmp(host, "localhost") == 0 )
       
   216 				return(SDLNet_ResolveHost(address, "127.0.0.1", port));
       
   217 
       
   218 			/* Have OpenTransport resolve the hostname for us */
       
   219 			retval = OTInetStringToAddress(dnsStatus.dns, (char *)host, &hinfo);
       
   220 			if (retval == noErr) {
       
   221 				while( dnsStatus.stat != dnsResolved )
       
   222 					{WaitNextEvent(everyEvent, 0, 1, NULL );}
       
   223 				address->host = hinfo.addrs[0];
       
   224 			}
       
   225 		//}
       
   226 	}
       
   227 	
       
   228 	address->port = SDL_SwapBE16(port);
       
   229 
       
   230 	/* Return the status */
       
   231 	return(retval);
       
   232 }
       
   233 
       
   234 /* Resolve an ip address to a host name in canonical form.
       
   235    If the ip couldn't be resolved, this function returns NULL,
       
   236    otherwise a pointer to a static buffer containing the hostname
       
   237    is returned.  Note that this function is not thread-safe.
       
   238 */
       
   239 /* MacOS implementation by Roy Wood
       
   240  */
       
   241 const char *SDLNet_ResolveIP(IPaddress *ip)
       
   242 {
       
   243 	if (ip != nil)
       
   244 	{
       
   245 	InetHost				theIP;
       
   246 	static InetDomainName	theInetDomainName;
       
   247 	OSStatus				theOSStatus;
       
   248 	
       
   249 		
       
   250 		/*	Default result will be null string */
       
   251 		
       
   252 		theInetDomainName[0] = '\0';	
       
   253 		
       
   254 		
       
   255 		/*	Do a reverse DNS lookup */
       
   256 		
       
   257 		theIP = ip->host;
       
   258 		
       
   259 		theOSStatus = OTInetAddressToName(dnsStatus.dns,theIP,theInetDomainName);
       
   260 		
       
   261 		/*	If successful, return the result */
       
   262 			
       
   263 		if (theOSStatus == kOTNoError)
       
   264 		{
       
   265 			while( dnsStatus.stat != dnsResolved )
       
   266 				{ /*should we yield or what ? */ }
       
   267 			return(theInetDomainName);
       
   268 		}
       
   269 	}
       
   270 	
       
   271 	SDLNet_SetError("Can't perform reverse DNS lookup");
       
   272 	
       
   273 	return(NULL);
       
   274 }
       
   275 
       
   276 #else /* !MACOS_OPENTRANSPORT */
       
   277 
       
   278 #ifndef __USE_W32_SOCKETS
       
   279 #include <signal.h>
       
   280 #endif
       
   281 
       
   282 /* Initialize/Cleanup the network API */
       
   283 int  SDLNet_Init(void)
       
   284 {
       
   285 	if ( !SDLNet_started ) {
       
   286 #ifdef __USE_W32_SOCKETS
       
   287 		/* Start up the windows networking */
       
   288 		WORD version_wanted = MAKEWORD(1,1);
       
   289 		WSADATA wsaData;
       
   290 
       
   291 		if ( WSAStartup(version_wanted, &wsaData) != 0 ) {
       
   292 			SDLNet_SetError("Couldn't initialize Winsock 1.1\n");
       
   293 			return(-1);
       
   294 		}
       
   295 #else
       
   296 		/* SIGPIPE is generated when a remote socket is closed */
       
   297 		void (*handler)(int);
       
   298 		handler = signal(SIGPIPE, SIG_IGN);
       
   299 		if ( handler != SIG_DFL ) {
       
   300 			signal(SIGPIPE, handler);
       
   301 		}
       
   302 #endif
       
   303 	}
       
   304 	++SDLNet_started;
       
   305 	return(0);
       
   306 }
       
   307 void SDLNet_Quit(void)
       
   308 {
       
   309 	if ( SDLNet_started == 0 ) {
       
   310 		return;
       
   311 	}
       
   312 	if ( --SDLNet_started == 0 ) {
       
   313 #ifdef __USE_W32_SOCKETS
       
   314 		/* Clean up windows networking */
       
   315 		if ( WSACleanup() == SOCKET_ERROR ) {
       
   316 			if ( WSAGetLastError() == WSAEINPROGRESS ) {
       
   317 				WSACancelBlockingCall();
       
   318 				WSACleanup();
       
   319 			}
       
   320 		}
       
   321 #else
       
   322 		/* Restore the SIGPIPE handler */
       
   323 		void (*handler)(int);
       
   324 		handler = signal(SIGPIPE, SIG_DFL);
       
   325 		if ( handler != SIG_IGN ) {
       
   326 			signal(SIGPIPE, handler);
       
   327 		}
       
   328 #endif
       
   329 	}
       
   330 }
       
   331 
       
   332 /* Resolve a host name and port to an IP address in network form */
       
   333 int SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port)
       
   334 {
       
   335 	int retval = 0;
       
   336 
       
   337 	/* Perform the actual host resolution */
       
   338 	if ( host == NULL ) {
       
   339 		address->host = INADDR_ANY;
       
   340 	} else {
       
   341 		address->host = inet_addr(host);
       
   342 		if ( address->host == INADDR_NONE ) {
       
   343 			struct hostent *hp;
       
   344 
       
   345 			hp = gethostbyname(host);
       
   346 			if ( hp ) {
       
   347 				memcpy(&address->host,hp->h_addr,hp->h_length);
       
   348 			} else {
       
   349 				retval = -1;
       
   350 			}
       
   351 		}
       
   352 	}
       
   353 	address->port = SDL_SwapBE16(port);
       
   354 
       
   355 	/* Return the status */
       
   356 	return(retval);
       
   357 }
       
   358 
       
   359 /* Resolve an ip address to a host name in canonical form.
       
   360    If the ip couldn't be resolved, this function returns NULL,
       
   361    otherwise a pointer to a static buffer containing the hostname
       
   362    is returned.  Note that this function is not thread-safe.
       
   363 */
       
   364 /* Written by Miguel Angel Blanch.
       
   365  * Main Programmer of Arianne RPG.
       
   366  * http://come.to/arianne_rpg
       
   367  */
       
   368 const char *SDLNet_ResolveIP(IPaddress *ip)
       
   369 {
       
   370 	struct hostent *hp;
       
   371 
       
   372 	hp = gethostbyaddr((char *)&ip->host, 4, AF_INET);
       
   373 	if ( hp != NULL ) {
       
   374 		return hp->h_name;
       
   375 	}
       
   376   	return NULL;
       
   377 }
       
   378 
       
   379 #endif /* MACOS_OPENTRANSPORT */
       
   380 
       
   381 #if !SDL_DATA_ALIGNED /* function versions for binary compatibility */
       
   382 
       
   383 /* Write a 16 bit value to network packet buffer */
       
   384 #undef SDLNet_Write16
       
   385 void   SDLNet_Write16(Uint16 value, void *areap)
       
   386 {
       
   387 	(*(Uint16 *)(areap) = SDL_SwapBE16(value));
       
   388 }
       
   389 
       
   390 /* Write a 32 bit value to network packet buffer */
       
   391 #undef SDLNet_Write32
       
   392 void   SDLNet_Write32(Uint32 value, void *areap)
       
   393 {
       
   394 	*(Uint32 *)(areap) = SDL_SwapBE32(value);
       
   395 }
       
   396 
       
   397 /* Read a 16 bit value from network packet buffer */
       
   398 #undef SDLNet_Read16
       
   399 Uint16 SDLNet_Read16(void *areap)
       
   400 {
       
   401 	return (SDL_SwapBE16(*(Uint16 *)(areap)));
       
   402 }
       
   403 
       
   404 /* Read a 32 bit value from network packet buffer */
       
   405 #undef SDLNet_Read32
       
   406 Uint32 SDLNet_Read32(void *areap)
       
   407 {
       
   408 	return (SDL_SwapBE32(*(Uint32 *)(areap)));
       
   409 }
       
   410 
       
   411 #endif /* !SDL_DATA_ALIGNED */
       
   412 
       
   413 
       
   414 #ifdef USE_GUSI_SOCKETS
       
   415 
       
   416 /* Configure Socket Factories */
       
   417 
       
   418 void GUSISetupFactories()
       
   419 {
       
   420 	GUSIwithInetSockets();
       
   421 }
       
   422 
       
   423 /* Configure File Devices */
       
   424 
       
   425 void GUSISetupDevices()
       
   426 {
       
   427 	return;
       
   428 }
       
   429 
       
   430 #endif /* USE_GUSI_SOCKETS */