| /* |
| * 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 <Memory.h> |
| # include <Files.h> |
| # include <Errors.h> |
| |
| #include "tcpglue.h" |
| #include <Devices.h> |
| |
| 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; |
| TCPNotifyUPP 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, TCPIOCompletionUPP 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, |
| TCPIOCompletionUPP 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; |
| TCPIOCompletionUPP 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,TCPIOCompletionUPP 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, TCPIOCompletionUPP 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,TCPIOCompletionUPP 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, UDPNotifyUPP 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, UDPIOCompletionUPP 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, (TCPIOCompletionUPP)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,(TCPIOCompletionUPP)-1 ) ); |
| } |
| |
| /* |
| * send data |
| */ |
| OSErr xUDPWrite(UDPiopb *pb,ip_addr host,ip_port port,miniwds *wds, |
| UDPIOCompletionUPP 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, (TCPIOCompletionUPP)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; |
| TCPIOCompletionUPP 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,TCPIOCompletionUPP completion) |
| { |
| #ifndef __MWERKS__ |
| pb->ioNamePtr = ReturnA5(); |
| #endif |
| |
| if (completion == 0L) |
| { |
| (pb)->ioCompletion = 0L; |
| return(PBControl((ParmBlkPtr)(pb),false)); /* sync */ |
| } |
| else if (completion == (TCPIOCompletionUPP)-1L) |
| { |
| (pb)->ioCompletion = 0L; |
| return(PBControl((ParmBlkPtr)(pb),true)); /* async */ |
| } |
| else |
| { |
| (pb)->ioCompletion = completion; |
| return(PBControl((ParmBlkPtr)(pb),true)); /* async */ |
| } |
| } |
| |