mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
983 lines
22 KiB
C
983 lines
22 KiB
C
/*
|
|
* Copyright (c) 1990-92 Regents of the University of Michigan.
|
|
* All rights reserved.
|
|
*
|
|
* tcp.c -- TCP communication related routines
|
|
*/
|
|
#include "lber.h"
|
|
#include "ldap.h"
|
|
#include "tcp.h"
|
|
|
|
#include <Devices.h>
|
|
#include <Desk.h> /* to get SystemTask() */
|
|
#include <Memory.h>
|
|
#include <Errors.h>
|
|
#include <Gestalt.h>
|
|
|
|
/*
|
|
* local prototypes
|
|
*/
|
|
#ifdef NEEDPROTOS
|
|
void bzero( char *buf, unsigned long count );
|
|
pascal void setdoneflag( struct hostInfo *hip, char *donep );
|
|
pascal void tcp_asynchnotify( StreamPtr tstream, unsigned short event, Ptr userdatap,
|
|
unsigned short term_reason, struct ICMPReport *icmpmsg );
|
|
OSErr kick_mactcp( short *drefnump );
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
pascal void EventHandler(tcpstream *tsp, OTEventCode event, OTResult result, void * /* cookie */);
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
#else /* NEEDPROTOS */
|
|
void bzero();
|
|
pascal void setdoneflag();
|
|
pascal void tcp_asynchnotify();
|
|
OSErr kick_mactcp();
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
pascal void EventHandler();
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
#endif /* NEEDPROTOS */
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
static Boolean gHaveOT = false;
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
/*
|
|
* Initialize the tcp module. This mainly consists of seeing if we have
|
|
* Open Transport and initializing it and setting our global saying so.
|
|
*/
|
|
OSStatus
|
|
tcp_init( void )
|
|
{
|
|
long result;
|
|
OSStatus err;
|
|
|
|
gHaveOT = (( err = Gestalt( gestaltOpenTpt, &result )) == noErr &&
|
|
( result & gestaltOpenTptPresent ) != 0 &&
|
|
( result & gestaltOpenTptTCPPresent ) != 0 );
|
|
|
|
if ( gHaveOT ) {
|
|
return( InitOpenTransport());
|
|
} else {
|
|
return( kOTNoError ); /* assume we have MacTCP */
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
tcp_shutdown( void )
|
|
{
|
|
if ( gHaveOT ) {
|
|
CloseOpenTransport();
|
|
}
|
|
}
|
|
|
|
Boolean
|
|
tcp_have_opentransport( void )
|
|
{
|
|
return( gHaveOT );
|
|
}
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
|
|
/*
|
|
* open and return an pointer to a TCP stream (return NULL if error)
|
|
* "buf" is a buffer for receives of length "buflen."
|
|
*/
|
|
tcpstream *
|
|
tcpopen( unsigned char * buf, long buflen ) {
|
|
TCPiopb pb;
|
|
OSStatus err;
|
|
tcpstream * tsp;
|
|
short drefnum;
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
TEndpointInfo info;
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
if (nil == (tsp = (tcpstream *)NewPtrClear(sizeof(tcpstream)))) {
|
|
return( nil );
|
|
}
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
if ( gHaveOT ) {
|
|
|
|
//
|
|
// Now create a TCP
|
|
//
|
|
tsp->tcps_ep = OTOpenEndpoint( OTCreateConfiguration( kTCPName ), 0, &info, &err );
|
|
|
|
if ( !tsp->tcps_ep ) {
|
|
if ( err == kOTNoError ) {
|
|
err = -1;
|
|
}
|
|
}
|
|
|
|
if ( !err ) {
|
|
err = OTSetSynchronous( tsp->tcps_ep );
|
|
}
|
|
|
|
tsp->tcps_data = 0;
|
|
tsp->tcps_terminated = tsp->tcps_connected = false;
|
|
|
|
//
|
|
// Install notifier we're going to use
|
|
//
|
|
if ( !err ) {
|
|
err = OTInstallNotifier( tsp->tcps_ep, (OTNotifyProcPtr) EventHandler, 0 );
|
|
}
|
|
|
|
if ( err != kOTNoError ) {
|
|
if ( tsp->tcps_ep ) {
|
|
OTCloseProvider( tsp->tcps_ep );
|
|
}
|
|
DisposePtr( (Ptr)tsp );
|
|
tsp = nil;
|
|
}
|
|
} else {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
if ( kick_mactcp( &drefnum ) != noErr ) {
|
|
return ( nil );
|
|
}
|
|
|
|
if (( tsp->tcps_notifyupp = NewTCPNotifyProc( tcp_asynchnotify )) == NULL ) {
|
|
DisposePtr( (Ptr)tsp );
|
|
return( nil );
|
|
}
|
|
|
|
tsp->drefnum = drefnum;
|
|
|
|
if ( buflen == 0 ) {
|
|
buflen = TCP_BUFSIZ;
|
|
}
|
|
|
|
if ( buf == NULL &&
|
|
(nil == ( buf = tsp->tcps_buffer = (unsigned char *)NewPtr( buflen )))) {
|
|
DisposeRoutineDescriptor( tsp->tcps_notifyupp );
|
|
DisposePtr( (Ptr)tsp );
|
|
return( nil );
|
|
}
|
|
bzero( (char *)&pb, sizeof( pb ));
|
|
pb.csCode = TCPCreate;
|
|
pb.ioCRefNum = tsp->drefnum;
|
|
pb.csParam.create.rcvBuff = (Ptr) buf;
|
|
pb.csParam.create.rcvBuffLen = buflen;
|
|
pb.csParam.create.notifyProc = tsp->tcps_notifyupp;
|
|
pb.csParam.create.userDataPtr = (Ptr)tsp;
|
|
|
|
if (( err = PBControlSync( (ParmBlkPtr)&pb )) != noErr || pb.ioResult != noErr ) {
|
|
DisposeRoutineDescriptor( tsp->tcps_notifyupp );
|
|
DisposePtr( (Ptr)tsp->tcps_buffer );
|
|
DisposePtr( (Ptr)tsp );
|
|
return( nil );
|
|
}
|
|
|
|
tsp->tcps_data = 0;
|
|
tsp->tcps_terminated = tsp->tcps_connected = false;
|
|
tsp->tcps_sptr = pb.tcpStream;
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
}
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
return( tsp );
|
|
}
|
|
|
|
/*
|
|
* connect to remote host at IP address "addr", TCP port "port"
|
|
* return local port assigned, 0 if error
|
|
*/
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
InetPort
|
|
tcpconnect( tcpstream * tsp, InetHost addr, InetPort port ) {
|
|
#else /* SUPPORT_OPENTRANSPORT */
|
|
ip_port
|
|
tcpconnect( tcpstream * tsp, ip_addr addr, ip_port port ) {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
TCPiopb pb;
|
|
OSStatus err;
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
struct InetAddress sndsin, rcvsin, retsin;
|
|
TCall sndcall, rcvcall;
|
|
TBind ret;
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
if ( gHaveOT ) {
|
|
|
|
if ( tsp->tcps_ep == NULL ) {
|
|
return( 0 );
|
|
}
|
|
|
|
bzero( (char *)&sndsin, sizeof( struct InetAddress ));
|
|
bzero( (char *)&rcvsin, sizeof( struct InetAddress ));
|
|
bzero( (char *)&retsin, sizeof( struct InetAddress ));
|
|
bzero( (char *)&sndcall, sizeof( TCall ));
|
|
bzero( (char *)&rcvcall, sizeof( TCall));
|
|
bzero( (char *)&ret, sizeof( TBind ));
|
|
|
|
// Bind TCP to an address and port. We don't care which one, so we pass null for
|
|
// the requested address.
|
|
ret.addr.maxlen = sizeof( struct InetAddress );
|
|
ret.addr.buf = (unsigned char *)&retsin;
|
|
err = OTBind( tsp->tcps_ep, NULL, &ret );
|
|
if ( err != kOTNoError ) {
|
|
return( 0 );
|
|
}
|
|
|
|
OTInitInetAddress( &sndsin, port, addr );
|
|
sndcall.addr.len = sizeof( struct InetAddress );
|
|
sndcall.addr.buf = (UInt8 *)&sndsin;
|
|
|
|
rcvcall.addr.maxlen = sizeof( struct InetAddress );
|
|
rcvcall.addr.buf = (unsigned char *)&rcvsin;
|
|
|
|
err = OTConnect( tsp->tcps_ep, &sndcall, &rcvcall );
|
|
if ( err != kOTNoError ) {
|
|
return 0;
|
|
}
|
|
|
|
tsp->tcps_connected = true;
|
|
tsp->tcps_remoteport = rcvsin.fPort;
|
|
tsp->tcps_remoteaddr = rcvsin.fHost;
|
|
return( retsin.fPort );
|
|
|
|
} else {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
if ( tsp->tcps_sptr == (StreamPtr)NULL ) {
|
|
return( 0 );
|
|
}
|
|
|
|
bzero( (char *)&pb, sizeof( pb ));
|
|
pb.csCode = TCPActiveOpen;
|
|
pb.ioCRefNum = tsp->drefnum;
|
|
pb.tcpStream = tsp->tcps_sptr;
|
|
pb.csParam.open.remoteHost = addr;
|
|
pb.csParam.open.remotePort = port;
|
|
pb.csParam.open.ulpTimeoutValue = 15;
|
|
pb.csParam.open.validityFlags = timeoutValue;
|
|
|
|
if (( err = PBControlSync( (ParmBlkPtr)&pb )) != noErr || pb.ioResult != noErr ) {
|
|
return( 0 );
|
|
}
|
|
|
|
tsp->tcps_connected = true;
|
|
return( pb.csParam.open.localPort );
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
}
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* close and release a TCP stream
|
|
* returns 0 if no error, -1 if any error occurs
|
|
*/
|
|
short
|
|
tcpclose( tcpstream * tsp ) {
|
|
TCPiopb pb;
|
|
OSStatus rc;
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
if ( gHaveOT ) {
|
|
|
|
|
|
if ( tsp->tcps_ep == NULL ) {
|
|
return( -1 );
|
|
}
|
|
|
|
#ifdef notdef
|
|
/*
|
|
* if connected execute a close
|
|
*/
|
|
if ( tcp->tcps_connected ) {
|
|
Call OTSndOrderlyDisconnect and wait for the other end to respond. This requires
|
|
waiting for and reading any data that comes in in the meantime. This code was ifdefed
|
|
out in the MacTCP so it is here too.
|
|
}
|
|
#endif /* notdef */
|
|
|
|
rc = OTSndDisconnect( tsp->tcps_ep, NULL );
|
|
|
|
OTCloseProvider( tsp->tcps_ep );
|
|
DisposePtr( (Ptr)tsp );
|
|
|
|
if ( rc != 0 ) {
|
|
rc = -1;
|
|
}
|
|
|
|
} else {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
if ( tsp->tcps_sptr == (StreamPtr)NULL ) {
|
|
return( -1 );
|
|
}
|
|
|
|
#ifdef notdef
|
|
/*
|
|
* if connected execute a close
|
|
*/
|
|
if ( tcp->tcps_connected ) {
|
|
bzero( (char *)&pb, sizeof( pb ));
|
|
pb.csCode = TCPClose;
|
|
pb.ioCRefNum = tsp->drefnum;
|
|
pb.tcpStream = sp;
|
|
pb.csParam.close.validityFlags = 0;
|
|
PBControlSync( (ParmBlkPtr)&pb );
|
|
}
|
|
#endif /* notdef */
|
|
|
|
bzero( (char *)&pb, sizeof( pb ));
|
|
pb.csCode = TCPRelease;
|
|
pb.ioCRefNum = tsp->drefnum;
|
|
pb.tcpStream = tsp->tcps_sptr;
|
|
pb.csParam.close.validityFlags = 0;
|
|
rc = 0;
|
|
|
|
if ( PBControlSync( (ParmBlkPtr)&pb ) != noErr || pb.ioResult != noErr ) {
|
|
rc = -1;
|
|
}
|
|
|
|
DisposeRoutineDescriptor( tsp->tcps_notifyupp );
|
|
DisposePtr( (Ptr)tsp->tcps_buffer );
|
|
DisposePtr( (Ptr)tsp );
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
}
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
return( rc );
|
|
}
|
|
|
|
|
|
/*
|
|
* wait for new data to arrive
|
|
*
|
|
* if "timeout" is NULL, wait until data arrives or connection goes away
|
|
* if "timeout" is a pointer to a zero'ed struct, poll
|
|
* else wait for "timeout->tv_sec + timeout->tv_usec" seconds
|
|
*/
|
|
short
|
|
tcpselect( tcpstream * tsp, struct timeval * timeout )
|
|
{
|
|
long ticks, endticks;
|
|
short rc;
|
|
|
|
if ( timeout != NULL ) {
|
|
endticks = 60 * timeout->tv_sec + ( 60 * timeout->tv_usec ) / 1000000 + TickCount();
|
|
}
|
|
ticks = 0;
|
|
|
|
while (( rc = tcpreadready( tsp )) == 0 && ( timeout == NULL || ticks < endticks )) {
|
|
Delay( 2L, &ticks );
|
|
SystemTask();
|
|
}
|
|
|
|
return ( rc );
|
|
}
|
|
|
|
|
|
short
|
|
tcpreadready( tcpstream *tsp )
|
|
{
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
size_t dataAvail;
|
|
|
|
if (gHaveOT) {
|
|
if ( tsp->tcps_ep == NULL ) {
|
|
return( -1 );
|
|
}
|
|
|
|
OTCountDataBytes( tsp->tcps_ep, &dataAvail );
|
|
tsp->tcps_data = ( dataAvail != 0 );
|
|
} else {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
if ( tsp->tcps_sptr == (StreamPtr)NULL ) {
|
|
return( -1 );
|
|
}
|
|
|
|
/* tsp->tcps_data is set in async. notify proc, so nothing for us to do here */
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
}
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
return ( tsp->tcps_terminated ? -1 : ( tsp->tcps_data < 1 ) ? 0 : 1 );
|
|
}
|
|
|
|
|
|
/*
|
|
* read up to "rbuflen" bytes into "rbuf" from a connected TCP stream
|
|
* wait up to "timeout" seconds for data (if timeout == 0, wait "forever")
|
|
*/
|
|
long
|
|
tcpread( tcpstream * tsp, byte timeout, unsigned char * rbuf,
|
|
unsigned short rbuflen, DialogPtr dlp ) {
|
|
TCPiopb pb;
|
|
unsigned long time, end_time;
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
OTFlags flags;
|
|
OTResult result;
|
|
size_t dataAvail;
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
if ( gHaveOT ) {
|
|
|
|
if ( tsp->tcps_ep == NULL ) {
|
|
return( -1 );
|
|
}
|
|
|
|
// Try to read data. Since we're in non-blocking mode, this will fail with kOTNoDataErr
|
|
// if no data is available.
|
|
result = OTRcv( tsp->tcps_ep, rbuf, rbuflen, &flags );
|
|
if ( result == kOTNoDataErr ) {
|
|
// Nothing available, wait for some. The ugly spin loop below is the way the old
|
|
// MacTCP code worked. I should fix it, but I don't have time right now.
|
|
tsp->tcps_data = 0;
|
|
GetDateTime( &time );
|
|
end_time = time + timeout;
|
|
|
|
while (( timeout <= 0 || end_time > time ) && tsp->tcps_data < 1 && !tsp->tcps_terminated ) {
|
|
OTCountDataBytes( tsp->tcps_ep, &dataAvail );
|
|
if ( dataAvail > 0 ) {
|
|
tsp->tcps_data = 1;
|
|
}
|
|
GetDateTime( &time );
|
|
SystemTask();
|
|
}
|
|
|
|
if ( tsp->tcps_data < 1 ) {
|
|
return( tsp->tcps_terminated ? -3 : -1 );
|
|
}
|
|
|
|
// Should have data available now, try again.
|
|
result = OTRcv( tsp->tcps_ep, rbuf, rbuflen, &flags );
|
|
}
|
|
|
|
if ( result < 0 ) {
|
|
return( -1 );
|
|
}
|
|
|
|
OTCountDataBytes( tsp->tcps_ep, &dataAvail );
|
|
if ( dataAvail == 0 ) {
|
|
tsp->tcps_data = 0;
|
|
}
|
|
|
|
return( result );
|
|
|
|
} else {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
if ( tsp->tcps_sptr == (StreamPtr)NULL ) {
|
|
return( -1 );
|
|
}
|
|
|
|
GetDateTime( &time );
|
|
end_time = time + timeout;
|
|
|
|
while(( timeout <= 0 || end_time > time ) && tsp->tcps_data < 1 &&
|
|
!tsp->tcps_terminated ) {
|
|
GetDateTime( &time );
|
|
SystemTask();
|
|
}
|
|
|
|
if ( tsp->tcps_data < 1 ) {
|
|
return( tsp->tcps_terminated ? -3 : -1 );
|
|
}
|
|
|
|
bzero( (char *)&pb, sizeof( pb ));
|
|
pb.csCode = TCPRcv;
|
|
pb.ioCRefNum = tsp->drefnum;
|
|
pb.tcpStream = tsp->tcps_sptr;
|
|
pb.csParam.receive.commandTimeoutValue = timeout;
|
|
pb.csParam.receive.rcvBuff = (char *)rbuf;
|
|
pb.csParam.receive.rcvBuffLen = rbuflen;
|
|
|
|
if ( PBControlSync( (ParmBlkPtr)&pb ) != noErr || pb.ioResult != noErr ) {
|
|
return( -1 );
|
|
}
|
|
|
|
if ( --(tsp->tcps_data) < 0 ) {
|
|
tsp->tcps_data = 0;
|
|
}
|
|
|
|
return( pb.csParam.receive.rcvBuffLen );
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
}
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
#pragma unused (dlp)
|
|
}
|
|
|
|
/*
|
|
* send TCP data
|
|
* "sp" is the stream to write to
|
|
* "wbuf" is "wbuflen" bytes of data to send
|
|
* returns < 0 if error, number of bytes written if no error
|
|
*/
|
|
long
|
|
tcpwrite( tcpstream * tsp, unsigned char * wbuf, unsigned short wbuflen ) {
|
|
TCPiopb pb;
|
|
wdsEntry wds[ 2 ];
|
|
OSErr err;
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
OTResult result;
|
|
unsigned short nwritten;
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
if ( gHaveOT ) {
|
|
|
|
if ( tsp->tcps_ep == NULL ) {
|
|
return( -1 );
|
|
}
|
|
|
|
/*
|
|
* We used to do a single call to OTSnd() here, framed with OTSetBlocking() and OTSetNonBlocking()
|
|
* this caused crashes deep inside OpenTransport when writes were large or done in
|
|
* rapid succession, so now we never turn on blocking mode
|
|
*/
|
|
nwritten = 0;
|
|
while ( wbuflen > 0 ) {
|
|
if (( result = OTSnd( tsp->tcps_ep, wbuf, wbuflen, 0 )) < 0 ) {
|
|
if ( result != kOTFlowErr ) {
|
|
break;
|
|
}
|
|
} else {
|
|
nwritten += result;
|
|
if (( wbuflen -= result ) > 0 ) {
|
|
SystemTask();
|
|
wbuf += result;
|
|
}
|
|
}
|
|
}
|
|
return(( wbuflen == 0 ) ? nwritten : result );
|
|
|
|
} else {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
if ( tsp->tcps_sptr == (StreamPtr)NULL ) {
|
|
return( -1 );
|
|
}
|
|
|
|
wds[ 0 ].length = wbuflen;
|
|
wds[ 0 ].ptr = (char *)wbuf;
|
|
wds[ 1 ].length = 0;
|
|
|
|
bzero( (char *)&pb, sizeof( pb ));
|
|
pb.csCode = TCPSend;
|
|
pb.ioCRefNum = tsp->drefnum;
|
|
pb.tcpStream = tsp->tcps_sptr;
|
|
pb.csParam.send.wdsPtr = (Ptr)wds;
|
|
pb.csParam.send.validityFlags = 0;
|
|
|
|
if (( err = PBControlSync( (ParmBlkPtr)&pb )) != noErr || pb.ioResult != noErr ) {
|
|
return( -1 );
|
|
}
|
|
|
|
return( wbuflen );
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
}
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
}
|
|
|
|
static pascal void
|
|
tcp_asynchnotify(
|
|
StreamPtr tstream,
|
|
unsigned short event,
|
|
Ptr userdatap,
|
|
unsigned short term_reason,
|
|
struct ICMPReport *icmpmsg
|
|
)
|
|
{
|
|
tcpstream *tsp;
|
|
|
|
tsp = (tcpstream *)userdatap;
|
|
switch( event ) {
|
|
case TCPDataArrival:
|
|
++(tsp->tcps_data);
|
|
break;
|
|
case TCPClosing:
|
|
case TCPTerminate:
|
|
case TCPULPTimeout:
|
|
tsp->tcps_terminated = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#pragma unused (tstream, term_reason, icmpmsg)
|
|
}
|
|
|
|
|
|
short
|
|
tcpgetpeername( tcpstream *tsp, ip_addr *addrp, tcp_port *portp ) {
|
|
TCPiopb pb;
|
|
OSErr err;
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
if ( gHaveOT ) {
|
|
|
|
if ( tsp->tcps_ep == NULL ) {
|
|
return( -1 );
|
|
}
|
|
|
|
if ( addrp != NULL ) {
|
|
*addrp = tsp->tcps_remoteaddr;
|
|
}
|
|
|
|
if ( portp != NULL ) {
|
|
*portp = tsp->tcps_remoteport;
|
|
}
|
|
|
|
} else {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
if ( tsp->tcps_sptr == (StreamPtr)NULL ) {
|
|
return( -1 );
|
|
}
|
|
|
|
bzero( (char *)&pb, sizeof( pb ));
|
|
pb.csCode = TCPStatus;
|
|
pb.ioCRefNum = tsp->drefnum;
|
|
pb.tcpStream = tsp->tcps_sptr;
|
|
|
|
if (( err = PBControlSync( (ParmBlkPtr)&pb )) != noErr || pb.ioResult != noErr ) {
|
|
return( err );
|
|
}
|
|
|
|
if ( addrp != NULL ) {
|
|
*addrp = pb.csParam.status.remoteHost;
|
|
}
|
|
|
|
if ( portp != NULL ) {
|
|
*portp = pb.csParam.status.remotePort;
|
|
}
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
}
|
|
|
|
return( kOTNoError );
|
|
#else /* SUPPORT_OPENTRANSPORT */
|
|
return( noErr );
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
}
|
|
|
|
|
|
/*
|
|
* bzero -- set "len" bytes starting at "p" to zero
|
|
*/
|
|
static void
|
|
bzero( char *p, unsigned long len )
|
|
{
|
|
unsigned long i;
|
|
|
|
for ( i = 0; i < len; ++i ) {
|
|
*p++ = '\0';
|
|
}
|
|
}
|
|
|
|
|
|
pascal void
|
|
setdoneflag( struct hostInfo *hip, char *donep )
|
|
{
|
|
++(*donep);
|
|
#pragma unused (hip)
|
|
}
|
|
|
|
|
|
/*
|
|
* return a hostInfo structure for "host" (return != noErr if error)
|
|
*/
|
|
short
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
gethostinfobyname( char *host, InetHostInfo *hip ) {
|
|
#else /* SUPPORT_OPENTRANSPORT */
|
|
gethostinfobyname( char *host, struct hostInfo *hip ) {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
char done = 0;
|
|
OSStatus err;
|
|
long time;
|
|
ResultUPP rupp;
|
|
#ifdef notdef
|
|
struct dnr_struct dnr_global = {nil, 0};
|
|
#endif /* notdef */
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
hostInfo hi; /* Old MacTCP version of hostinfo */
|
|
InetSvcRef inetsvc; /* Internet services reference */
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
if ( gHaveOT ) {
|
|
|
|
// Get an Internet Services reference
|
|
inetsvc = OTOpenInternetServices( kDefaultInternetServicesPath, 0, &err );
|
|
if ( !inetsvc || err != kOTNoError ) {
|
|
if ( err == kOTNoError ) {
|
|
err = -1;
|
|
}
|
|
inetsvc = nil;
|
|
}
|
|
|
|
if ( !err ) {
|
|
err = OTInetStringToAddress( inetsvc, host, hip );
|
|
}
|
|
|
|
if ( inetsvc ) {
|
|
OTCloseProvider(inetsvc);
|
|
}
|
|
|
|
} else {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
if (( err = kick_mactcp( NULL )) != noErr
|
|
|| ( err = OpenResolver( /* &dnr_global, */ NULL )) != noErr ) {
|
|
return( err );
|
|
}
|
|
|
|
if (( rupp = NewResultProc( setdoneflag )) == NULL ) {
|
|
err = memFullErr;
|
|
} else {
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
bzero( (char *)&hi, sizeof( hostInfo ));
|
|
if (( err = StrToAddr( /* &dnr_global, */ host, &hi, rupp, &done )) == cacheFault ) {
|
|
#else /* SUPPORT_OPENTRANSPORT */
|
|
bzero((char *) hip, sizeof( hostInfo ));
|
|
if (( err = StrToAddr( /* &dnr_global, */ host, hip, rupp, &done )) == cacheFault ) {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
while( !done ) {
|
|
Delay( 2L, &time ); // querying DN servers; wait for reply
|
|
SystemTask();
|
|
}
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
err = hi.rtnCode;
|
|
#else /* SUPPORT_OPENTRANSPORT */
|
|
err = hip->rtnCode;
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
}
|
|
DisposeRoutineDescriptor( rupp );
|
|
}
|
|
|
|
CloseResolver( /* &dnr_global */ );
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
/* Copy the results to the InetHostInfo area passed in by caller */
|
|
BlockMove(hi.cname, hip->name, kMaxHostNameLen);
|
|
BlockMove(hi.addr, hip->addrs, 4*NUM_ALT_ADDRS);
|
|
hip->addrs[NUM_ALT_ADDRS] = 0;
|
|
|
|
/* Convert the return code to an OT style return code */
|
|
if ( err == nameSyntaxErr ) {
|
|
err = kOTBadNameErr;
|
|
} else if ( err == noNameServer || err == authNameErr || err == noAnsErr ) {
|
|
err = kOTBadNameErr;
|
|
} else if (err != noErr) {
|
|
err = kOTSysErrorErr;
|
|
}
|
|
|
|
}
|
|
|
|
if (( err == kOTNoError ) && ( hip->addrs[ 0 ] == 0 )) {
|
|
err = kOTBadNameErr;
|
|
}
|
|
return( err );
|
|
|
|
#else /* SUPPORT_OPENTRANSPORT */
|
|
if ( err != noErr || (( err == noErr ) && ( hip->addr[ 0 ] == 0 ))) {
|
|
return( err == noErr ? noAnsErr : err );
|
|
}
|
|
return( noErr );
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
}
|
|
|
|
/*
|
|
* return a hostInfo structure for "addr" (return != noErr if error)
|
|
*/
|
|
short
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
gethostinfobyaddr( InetHost addr, InetHostInfo *hip )
|
|
#else /* SUPPORT_OPENTRANSPORT */
|
|
gethostinfobyaddr( ip_addr addr, struct hostInfo *hip )
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
{
|
|
|
|
char done = 0;
|
|
OSStatus err;
|
|
long time;
|
|
ResultUPP rupp;
|
|
#ifdef notdef
|
|
struct dnr_struct dnr_global = {nil, 0};
|
|
#endif /* notdef */
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
hostInfo hi; /* Old MacTCP version of hostinfo */
|
|
InetSvcRef inetsvc; /* Internet services reference */
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
if ( gHaveOT ) {
|
|
// Get an Internet Services reference
|
|
inetsvc = OTOpenInternetServices( kDefaultInternetServicesPath, 0, &err );
|
|
if ( !inetsvc || err != kOTNoError ) {
|
|
if ( err == kOTNoError ) {
|
|
err = -1;
|
|
}
|
|
inetsvc = nil;
|
|
}
|
|
|
|
if ( !err ) {
|
|
err = OTInetAddressToName( inetsvc, addr, hip->name );
|
|
}
|
|
|
|
if ( inetsvc ) {
|
|
OTCloseProvider( inetsvc );
|
|
}
|
|
|
|
} else {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
if (( err = kick_mactcp( NULL )) != noErr ||
|
|
( err = OpenResolver( /* &dnr_global, */ NULL )) != noErr )
|
|
return( err );
|
|
|
|
if (( rupp = NewResultProc( setdoneflag )) == NULL ) {
|
|
err = memFullErr;
|
|
} else {
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
bzero( (char *) &hi, sizeof( hostInfo ));
|
|
if (( err = AddrToName( /* &dnr_global, */ addr, &hi, rupp, &done )) == cacheFault ) {
|
|
#else /* SUPPORT_OPENTRANSPORT */
|
|
bzero( (char *)hip, sizeof( hostInfo ));
|
|
if (( err = AddrToName( /* &dnr_global, */ addr, hip, rupp, &done )) == cacheFault ) {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
while( !done ) {
|
|
Delay( 2L, &time ); // querying DN servers; wait for reply
|
|
SystemTask();
|
|
}
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
err = hi.rtnCode;
|
|
#else /* SUPPORT_OPENTRANSPORT */
|
|
err = hip->rtnCode;
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
}
|
|
DisposeRoutineDescriptor( rupp );
|
|
}
|
|
|
|
CloseResolver( /* &dnr_global */ );
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
/* Copy the results to the InetHostInfo area passed in by caller */
|
|
BlockMove(hi.cname, hip->name, kMaxHostNameLen);
|
|
BlockMove(hi.addr, hip->addrs, 4*NUM_ALT_ADDRS);
|
|
hip->addrs[NUM_ALT_ADDRS] = 0;
|
|
|
|
/* Convert the return code to an OT style return code */
|
|
if (err == nameSyntaxErr) {
|
|
err = kOTBadNameErr;
|
|
} else if (err == noNameServer || err == authNameErr || err == noAnsErr) {
|
|
err = kOTBadNameErr;
|
|
} else if (err != noErr) {
|
|
err = kOTSysErrorErr;
|
|
}
|
|
|
|
}
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
return( err );
|
|
}
|
|
|
|
/*
|
|
* return a ASCII equivalent of ipaddr. addrstr must be at large enough to hold the
|
|
* result which is of the form "AAA.BBB.CCC.DDD" and can be a maximum of 16 bytes in size
|
|
*/
|
|
short
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
ipaddr2str( InetHost ipaddr, char *addrstr )
|
|
#else /* SUPPORT_OPENTRANSPORT */
|
|
ipaddr2str( ip_addr ipaddr, char *addrstr )
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
{
|
|
OSStatus err;
|
|
#ifdef notdef
|
|
struct dnr_struct dnr_global = {nil, 0};
|
|
#endif /* notdef */
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
if ( gHaveOT ) {
|
|
|
|
OTInetHostToString( ipaddr, addrstr );
|
|
err = kOTNoError;
|
|
|
|
} else {
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
if (( err = kick_mactcp( NULL )) != noErr ||
|
|
( err = OpenResolver( /* &dnr_global, */ NULL )) != noErr )
|
|
return( err );
|
|
|
|
err = AddrToStr( ipaddr, addrstr );
|
|
|
|
CloseResolver( /* &dnr_global */ );
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
}
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
return( err );
|
|
}
|
|
|
|
|
|
#ifdef SUPPORT_OPENTRANSPORT
|
|
/*******************************************************************************
|
|
** EventHandler
|
|
********************************************************************************/
|
|
pascal void EventHandler(tcpstream *tsp, OTEventCode event, OTResult result, void * /* cookie */)
|
|
{
|
|
|
|
switch(event)
|
|
{
|
|
case T_ORDREL:
|
|
case T_DISCONNECT:
|
|
tsp->tcps_terminated = true;
|
|
break;
|
|
case T_DATA:
|
|
case T_EXDATA:
|
|
tsp->tcps_data += 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
#endif /* SUPPORT_OPENTRANSPORT */
|
|
|
|
|
|
static OSErr
|
|
kick_mactcp( short *drefnump )
|
|
{
|
|
short dref;
|
|
OSErr err;
|
|
struct GetAddrParamBlock gapb;
|
|
|
|
/*
|
|
* we make sure the MacTCP driver is open and issue a "Get My Address" call
|
|
* so that adevs like MacPPP are initialized (MacTCP is dumb)
|
|
*/
|
|
if (( err = OpenDriver( "\p.IPP", &dref )) != noErr ) {
|
|
return( err );
|
|
}
|
|
|
|
if ( drefnump != NULL ) {
|
|
*drefnump = dref;
|
|
}
|
|
|
|
bzero( (char *)&gapb, sizeof( gapb ));
|
|
gapb.csCode = ipctlGetAddr;
|
|
gapb.ioCRefNum = dref;
|
|
|
|
err = PBControlSync( (ParmBlkPtr)&gapb );
|
|
|
|
return( noErr );
|
|
}
|