/* * Glue routines for mactcp module. * Jack Jansen, CWI, 1994. * * Adapted from mactcp socket library, which was in turn * adapted from ncsa telnet code. * * Original authors: Tom Milligan, Charlie Reiman */ # include # include # include #include "tcpglue.h" #include #ifndef __MWERKS__ #define TCPIOCompletionUPP TCPIOCompletionProc #define NewTCPIOCompletionProc(x) (x) #endif /* __MWERKS__ */ static short driver = 0; #ifndef __powerc /* * Hack fix for MacTCP 1.0.X bug * * This hack doesn't work on the PPC. But then, people with new machines * shouldn't run ancient buggy software. -- Jack. */ pascal char *ReturnA5(void) = {0x2E8D}; #endif /* !__powerc */ OSErr xOpenDriver() { if (driver == 0) { ParamBlockRec pb; OSErr io; pb.ioParam.ioCompletion = 0L; pb.ioParam.ioNamePtr = "\p.IPP"; pb.ioParam.ioPermssn = fsCurPerm; io = PBOpen(&pb,false); if (io != noErr) return(io); driver = pb.ioParam.ioRefNum; } return noErr; } /* * create a TCP stream */ OSErr xTCPCreate(buflen,notify,udp, pb) int buflen; TCPNotifyProc notify; void *udp; TCPiopb *pb; { pb->ioCRefNum = driver; pb->csCode = TCPCreate; pb->csParam.create.rcvBuff = (char *)NewPtr(buflen); pb->csParam.create.rcvBuffLen = buflen; pb->csParam.create.notifyProc = notify; pb->csParam.create.userDataPtr = udp; return (xPBControlSync(pb)); } /* * start listening for a TCP connection */ OSErr xTCPPassiveOpen(TCPiopb *pb, short port, TCPIOCompletionProc completion, void *udp) { if (driver == 0) return(invalidStreamPtr); pb->ioCRefNum = driver; pb->csCode = TCPPassiveOpen; pb->csParam.open.validityFlags = timeoutValue | timeoutAction; pb->csParam.open.ulpTimeoutValue = 255 /* seconds */; pb->csParam.open.ulpTimeoutAction = 0 /* 1:abort 0:report */; pb->csParam.open.commandTimeoutValue = 0 /* infinity */; pb->csParam.open.remoteHost = 0; pb->csParam.open.remotePort = 0; pb->csParam.open.localHost = 0; pb->csParam.open.localPort = port; pb->csParam.open.dontFrag = 0; pb->csParam.open.timeToLive = 0; pb->csParam.open.security = 0; pb->csParam.open.optionCnt = 0; pb->csParam.open.userDataPtr = udp; return (xPBControl(pb,completion)); } /* * connect to a remote TCP */ OSErr xTCPActiveOpen(TCPiopb *pb, short port, long rhost, short rport, TCPIOCompletionProc completion) { if (driver == 0) return(invalidStreamPtr); pb->ioCRefNum = driver; pb->csCode = TCPActiveOpen; pb->csParam.open.validityFlags = timeoutValue | timeoutAction; pb->csParam.open.ulpTimeoutValue = 60 /* seconds */; pb->csParam.open.ulpTimeoutAction = 1 /* 1:abort 0:report */; pb->csParam.open.commandTimeoutValue = 0; pb->csParam.open.remoteHost = rhost; pb->csParam.open.remotePort = rport; pb->csParam.open.localHost = 0; pb->csParam.open.localPort = port; pb->csParam.open.dontFrag = 0; pb->csParam.open.timeToLive = 0; pb->csParam.open.security = 0; pb->csParam.open.optionCnt = 0; return (xPBControl(pb,completion)); } OSErr xTCPNoCopyRcv(pb,rds,rdslen,timeout,completion) TCPiopb *pb; rdsEntry *rds; int rdslen; int timeout; TCPIOCompletionProc completion; { if (driver == 0) return(invalidStreamPtr); pb->ioCRefNum = driver; pb->csCode = TCPNoCopyRcv; pb->csParam.receive.commandTimeoutValue = timeout; /* seconds, 0 = blocking */ pb->csParam.receive.rdsPtr = (Ptr)rds; pb->csParam.receive.rdsLength = rdslen; return (xPBControl(pb,completion)); } OSErr xTCPBufReturn(TCPiopb *pb,rdsEntry *rds,TCPIOCompletionProc completion) { pb->ioCRefNum = driver; pb->csCode = TCPRcvBfrReturn; pb->csParam.receive.rdsPtr = (Ptr)rds; return (xPBControl(pb,completion)); } /* * send data */ OSErr xTCPSend(TCPiopb *pb, wdsEntry *wds, Boolean push, Boolean urgent, TCPIOCompletionProc completion) { if (driver == 0) return invalidStreamPtr; pb->ioCRefNum = driver; pb->csCode = TCPSend; pb->csParam.send.validityFlags = timeoutValue | timeoutAction; pb->csParam.send.ulpTimeoutValue = 60 /* seconds */; pb->csParam.send.ulpTimeoutAction = 0 /* 0:abort 1:report */; pb->csParam.send.pushFlag = push; pb->csParam.send.urgentFlag = urgent; pb->csParam.send.wdsPtr = (Ptr)wds; return (xPBControl(pb,completion)); } /* * close a connection */ OSErr xTCPClose(TCPiopb *pb,TCPIOCompletionProc completion) { if (driver == 0) return(invalidStreamPtr); pb->ioCRefNum = driver; pb->csCode = TCPClose; pb->csParam.close.validityFlags = timeoutValue | timeoutAction; pb->csParam.close.ulpTimeoutValue = 60 /* seconds */; pb->csParam.close.ulpTimeoutAction = 1 /* 1:abort 0:report */; return (xPBControl(pb,completion)); } /* * abort a connection */ OSErr xTCPAbort(TCPiopb *pb) { if (driver == 0) return(invalidStreamPtr); pb->ioCRefNum = driver; pb->csCode = TCPAbort; return (xPBControlSync(pb)); } /* * close down a TCP stream (aborting a connection, if necessary) */ OSErr xTCPRelease(pb) TCPiopb *pb; { OSErr io; if (driver == 0) return(invalidStreamPtr); pb->ioCRefNum = driver; pb->csCode = TCPRelease; io = xPBControlSync(pb); if (io == noErr) DisposPtr(pb->csParam.create.rcvBuff); /* there is no release pb */ return(io); } #if 0 int xTCPBytesUnread(sp) SocketPtr sp; { TCPiopb *pb; OSErr io; if (!(pb = sock_fetch_pb(sp))) return -1; /* panic */ if (driver == 0) return(-1); pb->ioCRefNum = driver; pb->csCode = TCPStatus; io = xPBControlSync(pb); if (io != noErr) return(-1); return(pb->csParam.status.amtUnreadData); } int xTCPBytesWriteable(sp) SocketPtr sp; { TCPiopb *pb; OSErr io; long amount; if (!(pb = sock_fetch_pb(sp))) return -1; /* panic */ if (driver == 0) return(-1); pb->ioCRefNum = driver; pb->csCode = TCPStatus; io = xPBControlSync(pb); if (io != noErr) return(-1); amount = pb->csParam.status.sendWindow-pb->csParam.status.amtUnackedData; if (amount < 0) amount = 0; return amount; } int xTCPWriteBytesLeft(SocketPtr sp) { TCPiopb *pb; OSErr io; if (!(pb = sock_fetch_pb(sp))) return -1; /* panic */ if (driver == 0) return(-1); pb->ioCRefNum = driver; pb->csCode = TCPStatus; io = xPBControlSync(pb); if (io != noErr) return(-1); return (pb->csParam.status.amtUnackedData); } #endif OSErr xTCPStatus(TCPiopb *pb, TCPStatusPB **spb) { OSErr io; if (driver == 0) return(-1); pb->ioCRefNum = driver; pb->csCode = TCPStatus; io = xPBControlSync(pb); if (io == noErr) *spb = &pb->csParam.status; return(io); } /* * create a UDP stream, hook it to a socket. */ OSErr xUDPCreate(UDPiopb *pb,int buflen,ip_port *port, UDPNotifyProc asr, void *udp) { OSErr io; pb->ioCRefNum = driver; pb->csCode = UDPCreate; pb->csParam.create.rcvBuff = (char *)NewPtr(buflen); pb->csParam.create.rcvBuffLen = buflen; pb->csParam.create.notifyProc = asr; pb->csParam.create.userDataPtr = udp; pb->csParam.create.localPort = *port; if ( (io = xPBControlSync( (TCPiopb *)pb ) ) != noErr) return io; *port = pb->csParam.create.localPort; return noErr; } /* * ask for incoming data */ OSErr xUDPRead(UDPiopb *pb, int timeout, UDPIOCompletionProc completion) { if (driver == 0) return(invalidStreamPtr); pb->ioCRefNum = driver; pb->csCode = UDPRead; pb->csParam.receive.timeOut = timeout; pb->csParam.receive.secondTimeStamp = 0/* must be zero */; return (xPBControl ( (TCPiopb *)pb, (TCPIOCompletionProc)completion )); } OSErr xUDPBfrReturn(UDPiopb *pb, char *buff) { if (driver == 0) return(invalidStreamPtr); pb->ioCRefNum = driver; pb->csCode = UDPBfrReturn; pb->csParam.receive.rcvBuff = buff; return ( xPBControl( (TCPiopb *)pb,(TCPIOCompletionProc)-1 ) ); } /* * send data */ OSErr xUDPWrite(UDPiopb *pb,ip_addr host,ip_port port,miniwds *wds, UDPIOCompletionProc completion) { if (driver == 0) return(invalidStreamPtr); pb->ioCRefNum = driver; pb->csCode = UDPWrite; pb->csParam.send.remoteHost = host; pb->csParam.send.remotePort = port; pb->csParam.send.wdsPtr = (Ptr)wds; pb->csParam.send.checkSum = true; pb->csParam.send.sendLength = 0/* must be zero */; return (xPBControl( (TCPiopb *)pb, (TCPIOCompletionProc)completion)); } /* * close down a UDP stream (aborting a read, if necessary) */ OSErr xUDPRelease(UDPiopb *pb) { OSErr io; if (driver == 0) return(invalidStreamPtr); pb->ioCRefNum = driver; pb->csCode = UDPRelease; io = xPBControlSync( (TCPiopb *)pb ); if (io == noErr) { DisposPtr(pb->csParam.create.rcvBuff); } return(io); } ip_addr xIPAddr(void) { struct GetAddrParamBlock pbr; OSErr io; pbr.ioCRefNum = driver; pbr.csCode = ipctlGetAddr; io = xPBControlSync( (TCPiopb *)&pbr ); if (io != noErr) return(0); return(pbr.ourAddress); } long xNetMask() { struct GetAddrParamBlock pbr; OSErr io; pbr.ioCRefNum = driver; pbr.csCode = ipctlGetAddr; io = xPBControlSync( (TCPiopb *)&pbr); if (io != noErr) return(0); return(pbr.ourNetMask); } unsigned short xMaxMTU() { struct UDPiopb pbr; OSErr io; pbr.ioCRefNum = driver; pbr.csCode = UDPMaxMTUSize; pbr.csParam.mtu.remoteHost = xIPAddr(); io = xPBControlSync( (TCPiopb *)&pbr ); if (io != noErr) return(0); return(pbr.csParam.mtu.mtuSize); } OSErr xPBControlSync(TCPiopb *pb) { (pb)->ioCompletion = 0L; return PBControl((ParmBlkPtr)(pb),false); } #pragma segment SOCK_RESIDENT OSErr xTCPRcv(pb,buf,buflen,timeout,completion) TCPiopb *pb; Ptr buf; int buflen; int timeout; TCPIOCompletionProc completion; { if (driver == 0) return(invalidStreamPtr); pb->ioCRefNum = driver; pb->csCode = TCPRcv; pb->csParam.receive.commandTimeoutValue = timeout; /* seconds, 0 = blocking */ pb->csParam.receive.rcvBuff = buf; pb->csParam.receive.rcvBuffLen = buflen; return (xPBControl(pb,completion)); } OSErr xPBControl(TCPiopb *pb,TCPIOCompletionProc completion) { #ifndef __MWERKS__ pb->ioNamePtr = ReturnA5(); #endif if (completion == 0L) { (pb)->ioCompletion = 0L; return(PBControl((ParmBlkPtr)(pb),false)); /* sync */ } else if (completion == (TCPIOCompletionProc)-1L) { (pb)->ioCompletion = 0L; return(PBControl((ParmBlkPtr)(pb),true)); /* async */ } else { #if 0 /* If I understand the PowerPC calling correctly this is the right ** code, but the MetroWerks headers seem to disagree. We'll see... -- Jack */ TCPIOCompletionUPP comp_upp = NewTCPIOCompletionProc(completion); (pb)->ioCompletion = comp_upp; #else (pb)->ioCompletion = completion; #endif return(PBControl((ParmBlkPtr)(pb),true)); /* async */ } }