Initial commit.
This commit is contained in:
527
code/mac/mac_net.c
Normal file
527
code/mac/mac_net.c
Normal file
@@ -0,0 +1,527 @@
|
||||
#include "../client/client.h"
|
||||
#include "mac_local.h"
|
||||
#include <OpenTransport.h>
|
||||
#include <OpenTptInternet.h>
|
||||
|
||||
static qboolean gOTInited;
|
||||
static EndpointRef endpoint = kOTInvalidEndpointRef;
|
||||
static EndpointRef resolverEndpoint = kOTInvalidEndpointRef;
|
||||
|
||||
#define MAX_IPS 16
|
||||
static int numIP;
|
||||
static InetInterfaceInfo sys_inetInfo[MAX_IPS];
|
||||
|
||||
static TUDErr uderr;
|
||||
|
||||
void RcvUDErr( void ) {
|
||||
memset( &uderr, 0, sizeof( uderr ) );
|
||||
uderr.addr.maxlen = 0;
|
||||
uderr.opt.maxlen = 0;
|
||||
OTRcvUDErr( endpoint, &uderr );
|
||||
}
|
||||
|
||||
void HandleOTError( int err, const char *func ) {
|
||||
int r;
|
||||
static int lastErr;
|
||||
|
||||
if ( err != lastErr ) {
|
||||
Com_Printf( "%s: error %i\n", func, err );
|
||||
}
|
||||
|
||||
// if we don't call OTLook, things wedge
|
||||
r = OTLook( endpoint );
|
||||
if ( err != lastErr ) {
|
||||
Com_DPrintf( "%s: OTLook %i\n", func, r );
|
||||
}
|
||||
|
||||
switch( r ) {
|
||||
case T_UDERR:
|
||||
RcvUDErr();
|
||||
if ( err != lastErr ) {
|
||||
Com_DPrintf( "%s: OTRcvUDErr %i\n", func, uderr.error );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Com_Printf( "%s: Unknown OTLook error %i\n", func, r );
|
||||
break;
|
||||
}
|
||||
lastErr = err; // don't spew tons of messages
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
NotifyProc
|
||||
=================
|
||||
*/
|
||||
pascal void NotifyProc(void* contextPtr, OTEventCode code,
|
||||
OTResult result, void* cookie) {
|
||||
switch( code ) {
|
||||
case T_OPENCOMPLETE:
|
||||
endpoint = cookie;
|
||||
break;
|
||||
case T_UDERR:
|
||||
RcvUDErr();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
GetFourByteOption
|
||||
=================
|
||||
*/
|
||||
static OTResult GetFourByteOption(EndpointRef ep,
|
||||
OTXTILevel level,
|
||||
OTXTIName name,
|
||||
UInt32 *value)
|
||||
{
|
||||
OTResult err;
|
||||
TOption option;
|
||||
TOptMgmt request;
|
||||
TOptMgmt result;
|
||||
|
||||
/* Set up the option buffer */
|
||||
option.len = kOTFourByteOptionSize;
|
||||
option.level= level;
|
||||
option.name = name;
|
||||
option.status = 0;
|
||||
option.value[0] = 0;// Ignored because we're getting the value.
|
||||
|
||||
/* Set up the request parameter for OTOptionManagement to point
|
||||
to the option buffer we just filled out */
|
||||
|
||||
request.opt.buf= (UInt8 *) &option;
|
||||
request.opt.len= sizeof(option);
|
||||
request.flags= T_CURRENT;
|
||||
|
||||
/* Set up the reply parameter for OTOptionManagement. */
|
||||
result.opt.buf = (UInt8 *) &option;
|
||||
result.opt.maxlen = sizeof(option);
|
||||
|
||||
err = OTOptionManagement(ep, &request, &result);
|
||||
|
||||
if (err == noErr) {
|
||||
switch (option.status)
|
||||
{
|
||||
case T_SUCCESS:
|
||||
case T_READONLY:
|
||||
*value = option.value[0];
|
||||
break;
|
||||
default:
|
||||
err = option.status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
SetFourByteOption
|
||||
=================
|
||||
*/
|
||||
static OTResult SetFourByteOption(EndpointRef ep,
|
||||
OTXTILevel level,
|
||||
OTXTIName name,
|
||||
UInt32 value)
|
||||
{
|
||||
OTResult err;
|
||||
TOption option;
|
||||
TOptMgmt request;
|
||||
TOptMgmt result;
|
||||
|
||||
/* Set up the option buffer to specify the option and value to
|
||||
set. */
|
||||
option.len = kOTFourByteOptionSize;
|
||||
option.level= level;
|
||||
option.name = name;
|
||||
option.status = 0;
|
||||
option.value[0] = value;
|
||||
|
||||
/* Set up request parameter for OTOptionManagement */
|
||||
request.opt.buf= (UInt8 *) &option;
|
||||
request.opt.len= sizeof(option);
|
||||
request.flags = T_NEGOTIATE;
|
||||
|
||||
/* Set up reply parameter for OTOptionManagement. */
|
||||
result.opt.buf = (UInt8 *) &option;
|
||||
result.opt.maxlen = sizeof(option);
|
||||
|
||||
|
||||
err = OTOptionManagement(ep, &request, &result);
|
||||
|
||||
if (err == noErr) {
|
||||
if (option.status != T_SUCCESS)
|
||||
err = option.status;
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
NET_GetLocalAddress
|
||||
=====================
|
||||
*/
|
||||
void NET_GetLocalAddress( void ) {
|
||||
OSStatus err;
|
||||
|
||||
for ( numIP = 0 ; numIP < MAX_IPS ; numIP++ ) {
|
||||
err = OTInetGetInterfaceInfo( &sys_inetInfo[ numIP ], numIP );
|
||||
if ( err ) {
|
||||
break;
|
||||
}
|
||||
Com_Printf( "LocalAddress: %i.%i.%i.%i\n",
|
||||
((byte *)&sys_inetInfo[numIP].fAddress)[0],
|
||||
((byte *)&sys_inetInfo[numIP].fAddress)[1],
|
||||
((byte *)&sys_inetInfo[numIP].fAddress)[2],
|
||||
((byte *)&sys_inetInfo[numIP].fAddress)[3] );
|
||||
|
||||
Com_Printf( "Netmask: %i.%i.%i.%i\n",
|
||||
((byte *)&sys_inetInfo[numIP].fNetmask)[0],
|
||||
((byte *)&sys_inetInfo[numIP].fNetmask)[1],
|
||||
((byte *)&sys_inetInfo[numIP].fNetmask)[2],
|
||||
((byte *)&sys_inetInfo[numIP].fNetmask)[3] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_InitNetworking
|
||||
|
||||
|
||||
struct InetAddress
|
||||
{
|
||||
OTAddressType fAddressType; // always AF_INET
|
||||
InetPort fPort; // Port number
|
||||
InetHost fHost; // Host address in net byte order
|
||||
UInt8 fUnused[8]; // Traditional unused bytes
|
||||
};
|
||||
typedef struct InetAddress InetAddress;
|
||||
|
||||
==================
|
||||
*/
|
||||
void Sys_InitNetworking( void ) {
|
||||
OSStatus err;
|
||||
OTConfiguration *config;
|
||||
TBind bind, bindOut;
|
||||
InetAddress in, out;
|
||||
int i;
|
||||
|
||||
Com_Printf( "----- Sys_InitNetworking -----\n" );
|
||||
// init OpenTransport
|
||||
Com_Printf( "... InitOpenTransport()\n" );
|
||||
err = InitOpenTransport();
|
||||
if ( err != noErr ) {
|
||||
Com_Printf( "InitOpenTransport() failed\n" );
|
||||
Com_Printf( "------------------------------\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
gOTInited = true;
|
||||
|
||||
// get an endpoint
|
||||
Com_Printf( "... OTOpenEndpoint()\n" );
|
||||
config = OTCreateConfiguration( kUDPName );
|
||||
|
||||
#if 1
|
||||
endpoint = OTOpenEndpoint( config, 0, nil, &err);
|
||||
#else
|
||||
err = OTAsyncOpenEndpoint( config, 0, 0, NotifyProc, 0 );
|
||||
if ( !endpoint ) {
|
||||
err = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( err != noErr ) {
|
||||
endpoint = 0;
|
||||
Com_Printf( "OTOpenEndpoint() failed\n" );
|
||||
Com_Printf( "------------------------------\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// set non-blocking
|
||||
err = OTSetNonBlocking( endpoint );
|
||||
|
||||
// scan for a valid port in our range
|
||||
Com_Printf( "... OTBind()\n" );
|
||||
for ( i = 0 ; i < 10 ; i++ ) {
|
||||
in.fAddressType = AF_INET;
|
||||
in.fPort = PORT_SERVER + i;
|
||||
in.fHost = 0;
|
||||
|
||||
bind.addr.maxlen = sizeof( in );
|
||||
bind.addr.len = sizeof( in );
|
||||
bind.addr.buf = (unsigned char *)∈
|
||||
bind.qlen = 0;
|
||||
|
||||
bindOut.addr.maxlen = sizeof( out );
|
||||
bindOut.addr.len = sizeof( out );
|
||||
bindOut.addr.buf = (unsigned char *)&out;
|
||||
bindOut.qlen = 0;
|
||||
|
||||
err = OTBind( endpoint, &bind, &bindOut );
|
||||
if ( err == noErr ) {
|
||||
Com_Printf( "Opened UDP endpoint at port %i\n",
|
||||
out.fPort );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( err != noErr ) {
|
||||
Com_Printf( "Couldn't bind a local port\n" );
|
||||
}
|
||||
|
||||
// get the local address for LAN client detection
|
||||
NET_GetLocalAddress();
|
||||
|
||||
|
||||
// set to allow broadcasts
|
||||
err = SetFourByteOption( endpoint, INET_IP, IP_BROADCAST, T_YES );
|
||||
|
||||
if ( err != noErr ) {
|
||||
Com_Printf( "IP_BROADCAST failed\n" );
|
||||
}
|
||||
|
||||
// get an endpoint just for resolving addresses, because
|
||||
// I was having crashing problems doing it on the same endpoint
|
||||
config = OTCreateConfiguration( kUDPName );
|
||||
resolverEndpoint = OTOpenEndpoint( config, 0, nil, &err);
|
||||
if ( err != noErr ) {
|
||||
resolverEndpoint = 0;
|
||||
Com_Printf( "OTOpenEndpoint() for resolver failed\n" );
|
||||
Com_Printf( "------------------------------\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
in.fAddressType = AF_INET;
|
||||
in.fPort = 0;
|
||||
in.fHost = 0;
|
||||
|
||||
bind.addr.maxlen = sizeof( in );
|
||||
bind.addr.len = sizeof( in );
|
||||
bind.addr.buf = (unsigned char *)∈
|
||||
bind.qlen = 0;
|
||||
|
||||
bindOut.addr.maxlen = sizeof( out );
|
||||
bindOut.addr.len = sizeof( out );
|
||||
bindOut.addr.buf = (unsigned char *)&out;
|
||||
bindOut.qlen = 0;
|
||||
|
||||
err = OTBind( resolverEndpoint, &bind, &bindOut );
|
||||
|
||||
Com_Printf( "------------------------------\n" );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_ShutdownNetworking
|
||||
==================
|
||||
*/
|
||||
void Sys_ShutdownNetworking( void ) {
|
||||
Com_Printf( "Sys_ShutdownNetworking();\n" );
|
||||
|
||||
if ( endpoint != kOTInvalidEndpointRef ) {
|
||||
OTUnbind( endpoint );
|
||||
OTCloseProvider( endpoint );
|
||||
endpoint = kOTInvalidEndpointRef;
|
||||
}
|
||||
if ( resolverEndpoint != kOTInvalidEndpointRef ) {
|
||||
OTUnbind( resolverEndpoint );
|
||||
OTCloseProvider( resolverEndpoint );
|
||||
resolverEndpoint = kOTInvalidEndpointRef;
|
||||
}
|
||||
if (gOTInited) {
|
||||
CloseOpenTransport();
|
||||
gOTInited = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Sys_StringToAdr
|
||||
|
||||
|
||||
Does NOT parse port numbers
|
||||
|
||||
|
||||
idnewt
|
||||
192.246.40.70
|
||||
=============
|
||||
*/
|
||||
qboolean Sys_StringToAdr( const char *s, netadr_t *a ) {
|
||||
OSStatus err;
|
||||
TBind in, out;
|
||||
InetAddress inAddr;
|
||||
DNSAddress dnsAddr;
|
||||
|
||||
if ( !resolverEndpoint ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
memset( &in, 0, sizeof( in ) );
|
||||
in.addr.buf = (UInt8 *) &dnsAddr;
|
||||
in.addr.len = OTInitDNSAddress(&dnsAddr, (char *)s );
|
||||
in.qlen = 0;
|
||||
|
||||
memset( &out, 0, sizeof( out ) );
|
||||
out.addr.buf = (byte *)&inAddr;
|
||||
out.addr.maxlen = sizeof( inAddr );
|
||||
out.qlen = 0;
|
||||
|
||||
err = OTResolveAddress( resolverEndpoint, &in, &out, 10000 );
|
||||
if ( err ) {
|
||||
HandleOTError( err, "Sys_StringToAdr" );
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
a->type = NA_IP;
|
||||
*(int *)a->ip = inAddr.fHost;
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_SendPacket
|
||||
==================
|
||||
*/
|
||||
#define MAX_PACKETLEN 1400
|
||||
void Sys_SendPacket( int length, const void *data, netadr_t to ) {
|
||||
TUnitData d;
|
||||
InetAddress inAddr;
|
||||
OSStatus err;
|
||||
|
||||
if ( !endpoint ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( length > MAX_PACKETLEN ) {
|
||||
Com_Error( ERR_DROP, "Sys_SendPacket: length > MAX_PACKETLEN" );
|
||||
}
|
||||
|
||||
inAddr.fAddressType = AF_INET;
|
||||
inAddr.fPort = to.port;
|
||||
if ( to.type == NA_BROADCAST ) {
|
||||
inAddr.fHost = -1;
|
||||
} else {
|
||||
inAddr.fHost = *(int *)&to.ip;
|
||||
}
|
||||
|
||||
memset( &d, 0, sizeof( d ) );
|
||||
|
||||
d.addr.len = sizeof( inAddr );
|
||||
d.addr.maxlen = sizeof( inAddr );
|
||||
d.addr.buf = (unsigned char *)&inAddr;
|
||||
|
||||
d.opt.len = 0;
|
||||
d.opt.maxlen = 0;
|
||||
d.opt.buf = NULL;
|
||||
|
||||
d.udata.len = length;
|
||||
d.udata.maxlen = length;
|
||||
d.udata.buf = (unsigned char *)data;
|
||||
|
||||
err = OTSndUData( endpoint, &d );
|
||||
if ( err ) {
|
||||
HandleOTError( err, "Sys_SendPacket" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_GetPacket
|
||||
|
||||
Never called by the game logic, just the system event queing
|
||||
==================
|
||||
*/
|
||||
qboolean Sys_GetPacket ( netadr_t *net_from, msg_t *net_message ) {
|
||||
TUnitData d;
|
||||
InetAddress inAddr;
|
||||
OSStatus err;
|
||||
OTFlags flags;
|
||||
|
||||
if ( !endpoint ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
inAddr.fAddressType = AF_INET;
|
||||
inAddr.fPort = 0;
|
||||
inAddr.fHost = 0;
|
||||
|
||||
memset( &d, 0, sizeof( d ) );
|
||||
|
||||
d.addr.len = sizeof( inAddr );
|
||||
d.addr.maxlen = sizeof( inAddr );
|
||||
d.addr.buf = (unsigned char *)&inAddr;
|
||||
|
||||
d.opt.len = 0;
|
||||
d.opt.maxlen = 0;
|
||||
d.opt.buf = 0;
|
||||
|
||||
d.udata.len = net_message->maxsize;
|
||||
d.udata.maxlen = net_message->maxsize;
|
||||
d.udata.buf = net_message->data;
|
||||
|
||||
err = OTRcvUData( endpoint, &d, &flags );
|
||||
if ( err ) {
|
||||
if ( err == kOTNoDataErr ) {
|
||||
return false;
|
||||
}
|
||||
HandleOTError( err, "Sys_GetPacket" );
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
net_from->type = NA_IP;
|
||||
net_from->port = inAddr.fPort;
|
||||
*(int *)net_from->ip = inAddr.fHost;
|
||||
|
||||
net_message->cursize = d.udata.len;
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Sys_IsLANAddress
|
||||
|
||||
LAN clients will have their rate var ignored
|
||||
==================
|
||||
*/
|
||||
qboolean Sys_IsLANAddress (netadr_t adr) {
|
||||
int i;
|
||||
int ip;
|
||||
|
||||
if ( adr.type == NA_LOOPBACK ) {
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
if ( adr.type != NA_IP ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
for ( ip = 0 ; ip < numIP ; ip++ ) {
|
||||
for ( i = 0 ; i < 4 ; i++ ) {
|
||||
if ( ( adr.ip[i] & ((byte *)&sys_inetInfo[ip].fNetmask)[i] )
|
||||
!= ( ((byte *)&sys_inetInfo[ip].fAddress)[i] & ((byte *)&sys_inetInfo[ip].fNetmask)[i] ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i == 4 ) {
|
||||
return qtrue; // matches this subnet
|
||||
}
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
||||
void NET_Sleep( int i ) {
|
||||
}
|
||||
Reference in New Issue
Block a user