/* * 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 #include /* to get SystemTask() */ #include #include #include /* * 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 ); }