home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-02 | 24.1 KB | 915 lines | [TEXT/MMCC] |
- // tcpstuff.cpp
- // most copyright John Norstad
-
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdio.h>
-
- #include "mytypes.h"
- #include "MyMacTCP.h"
-
- #include "error.h"
- #include "util.h"
- #include "tcpstuff.h"
- #include "globals.h"
- #include "preffile.h"
-
- /* Types. */
-
- typedef struct TStream { /* Stream info */
-
- TCPiopb pBlock; /* MacTCP parameter block (must be first, unused with
- Open Transport) */
-
- unsigned long serverAddr; /* IP address of server */
- unsigned short serverPort; /* port number on server */
- unsigned short localPort; /* local port number */
- // CStr255 command; /* last command sent on stream */
- // CStr255 response; /* last response received on stream */
- long responseCode; /* last response code received on stream */
- Boolean closing; /* true when closing stream */
- Boolean otherSideHasClosed; /* true when other side has closed its end of
- the stream */
- Boolean weHaveClosed; /* true when we have closed our end of the stream */
- Boolean release; /* true when stream should be released */
- long bytesIn; /* number of bytes received on stream */
- long bytesOut; /* number of bytes sent on stream */
-
- short myID;
-
- /* Fields used only with MacTCP. */
-
- long myA5; /* our A5 register */
- StreamPtr tcpStream; /* MacTCP stream pointer */
- struct wdsEntry wds[2]; /* MacTCP write data structure */
- char mactcpBuf[1]; /* MacTCP buffer - size depends on MTU (must be last) */
-
- } TStream, *TStreamPtr;
-
- // defines for sending data
- enum {
- kNumSmallOut = 8,
- kNumMidOut = 2,
- kNumLargeOut = 2,
- kNumOutChunks = kNumSmallOut + kNumMidOut + kNumLargeOut,
-
- kSmallOutSize = 24,
- kMidOutSize = 128,
- kLargeOutSize = 2048
- };
-
- typedef struct {
- TCPiopb pBlock;
- struct wdsEntry wds[2]; /* MacTCP write data structure */
- short bufSize;
- uchar buf[2]; // variable size
- } OutChunk;
-
- OutChunk *outChunk[kNumOutChunks];
-
- static short gRefNum; /* MacTCP driver reference number */
- static long gStreamBufSize; /* stream buffer size */
- static long gTCPBufSize; /* TCP buffer size for MacTCP */
- static UniversalProcPtr gOldExitToShellUPP;
- static UniversalProcPtr gMyExitToShellUPP;
- static ResultUPP gMacTCPDNRResultProcUPP = nil;
- static TCPIOCompletionUPP gMacTCPCloseStreamCompletionRoutineUPP = nil;
- static Boolean gMacTCPDNROperationInProgress = false;
-
- unsigned long gMyAddress;
-
- unsigned char buf[kMaxStreams][kBufferLength];
- long bufdata[kMaxStreams];
- TStream *myStream[kMaxStreams];
- short nexStatus[kMaxStreams];
-
- /*----------------------------------------------------------------------------
- NewStreamBuffer
-
- Allocate a stream buffer.
-
- Exit: function result = error code.
- *s = pointer to new stream buffer.
- ----------------------------------------------------------------------------*/
-
- static TStreamPtr NewStreamBuffer (void)
- {
- OSErr err = noErr;
- TStreamPtr s;
-
- s = (TStreamPtr) NewPtr(gStreamBufSize);
- if (!s) return nil;
- memset(s, 0, sizeof(TStream));
- s->myA5 = SetCurrentA5();
- return s;
- }
-
-
- /*----------------------------------------------------------------------------
- InitMacTCPParamBlock
-
- Initialize a MacTCP parameter block.
-
- Entry: pBlock = pointer to parameter block.
- csCode = MacTCP control code (TCPCreate, etc.).
- ----------------------------------------------------------------------------*/
-
- static void InitMacTCPParamBlock (TCPiopb *pBlock, short csCode)
- {
- memset(pBlock, 0, sizeof(TCPiopb));
- pBlock->ioResult = 1;
- pBlock->ioCRefNum = gRefNum;
- pBlock->csCode = csCode;
- }
-
-
- /*----------------------------------------------------------------------------
- CallMacTCP
-
- Call MacTCP and wait for the call to complete.
-
- Entry: s = pointer to stream.
- returnImmediatelyOnError = true to return immediately if
- the GiveTime function returns an error.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr CallMacTCP (TStreamPtr s, Boolean returnImmediatelyOnError)
- {
- OSErr err = noErr, giveTimeErr = noErr;
-
- PBControlAsync((ParmBlkPtr)&s->pBlock);
- do {
- // giveTimeErr = (*gGiveTime)();
- // if (err == noErr) err = giveTimeErr;
- // if (err != noErr && returnImmediatelyOnError) return err;
- } while (s->pBlock.ioResult > 0);
- err = s->pBlock.ioResult;
- // if (err == connectionClosing || err == connectionDoesntExist ||
- // err == connectionTerminated) s->otherSideHasClosed = true;
- return err;
- }
-
- static inline void CallMacTCPAsynch(TCPiopb *pBlock)
- {
- PBControlAsync((ParmBlkPtr)pBlock);
- }
-
-
- /*----------------------------------------------------------------------------
- MacTCPDNRResultProc
-
- MacTCP domain name resolver completion routine.
-
- Entry: hInfoPtr = pointer to hostInfo struct.
- userDataPtr = pointer to user data.
- ----------------------------------------------------------------------------*/
-
- static pascal void MacTCPDNRResultProc (struct hostInfo *hInfoPtr, char *userDataPtr)
- {
- *(Boolean*)userDataPtr = true;
- }
-
- /*----------------------------------------------------------------------------
- MacTCPCloseStreamCompletionRoutine
-
- This is the asynchronous MacTCP completion routine used to close streams.
-
- This completion routine chains to itself to do the following tasks
- involved in gracefully tearing down a stream in the background:
-
- Wait for QUIT command send to complete (the send is initiated by the
- NetClose function below).
- Read incoming data until an error occurs (signalling that the
- server has closed its end of the connection).
- Close our end of the connection.
-
- Entry: pBlock = pointer to MacTCP parameter block.
- ----------------------------------------------------------------------------*/
-
- static void MacTCPCloseStreamCompletionRoutine (TCPiopb *pBlock)
- {
- TStreamPtr s;
- OSErr err = noErr;
- long savedA5;
-
- s = (TStreamPtr)pBlock;
-
- savedA5 = SetA5(s->myA5);
-
- if (s->pBlock.csCode == TCPSend) {
-
- /* The QUIT command has been sent. Start the first receive. */
-
- err = s->pBlock.ioResult;
- if (err != noErr) {
- s->release = true;
- SetA5(savedA5);
- return;
- }
- InitMacTCPParamBlock(&s->pBlock, TCPRcv);
- s->pBlock.csParam.receive.rcvBuff = (Ptr) buf[s->myID];
- s->pBlock.csParam.receive.rcvBuffLen = kBufferLength;
-
- } else if (s->pBlock.csCode == TCPRcv) {
-
- /* A receive operation has finished. If there was no error, start another
- receive. If an error occurred, it was because the server has closed
- its side of the connection. In this case, if we have already closed
- our side of the connection, set the "release" flag to signal that
- we can now release the stream and dispose of the queue element. If
- we have not yet closed our side, we start the TCPClose. */
-
- err = s->pBlock.ioResult;
- if (err == noErr) {
- InitMacTCPParamBlock(&s->pBlock, TCPRcv);
- s->pBlock.csParam.receive.rcvBuff = (Ptr) buf[s->myID];
- s->pBlock.csParam.receive.rcvBuffLen = kBufferLength;
- } else {
- s->otherSideHasClosed = true;
- if (s->weHaveClosed) {
- s->release = true;
- SetA5(savedA5);
- return;
- } else {
- InitMacTCPParamBlock(&s->pBlock, TCPClose);
- }
- }
-
- } else if (s->pBlock.csCode == TCPClose) {
-
- /* Our close has finished. If the other side has also closed,
- set the "release" flag to signal that we can now release
- the stream and dispose of the queue element. If the other
- side has not yet closed, issue a receive operation and wait
- for the other side to close. */
-
- s->weHaveClosed = true;
- if (s->otherSideHasClosed) {
- s->release = true;
- SetA5(savedA5);
- return;
- } else {
- InitMacTCPParamBlock(&s->pBlock, TCPRcv);
- s->pBlock.csParam.receive.rcvBuff = (Ptr) buf[s->myID];
- s->pBlock.csParam.receive.rcvBuffLen = kBufferLength;
- }
-
- }
-
- /* Issue the next PBControl call in the chain. */
-
- s->pBlock.ioCompletion = gMacTCPCloseStreamCompletionRoutineUPP;
- s->pBlock.tcpStream = s->tcpStream;
- s->pBlock.ioResult = 1;
- err = PBControlAsync((ParmBlkPtr)&s->pBlock);
- if (err != noErr) s->release = true;
- SetA5(savedA5);
-
- }
-
-
- /*----------------------------------------------------------------------------
- NetGetMyAddr
-
- Get this Mac's IP address.
-
- Exit: function result = error code.
- *addr = the IP address of this Mac.
-
- With Open Transport, if the Mac has more than one IP interface, the
- IP address of the default interface is returned.
- ----------------------------------------------------------------------------*/
-
- static OSErr NetGetMyAddr (unsigned long *addr)
- {
- struct GetAddrParamBlock pBlock;
- OSErr err = noErr, giveTimeErr = noErr;
- static Boolean gotIt = false;
- static unsigned long myAddr;
-
- if (!gotIt) {
-
- memset(&pBlock, 0, sizeof(pBlock));
- pBlock.ioResult = 1;
- pBlock.csCode = ipctlGetAddr;
- pBlock.ioCRefNum = gRefNum;
- PBControlAsync((ParmBlkPtr)&pBlock);
- while (pBlock.ioResult > 0) {
- // giveTimeErr = (*gGiveTime)();
- if (err == noErr) err = giveTimeErr;
- }
- if (err != noErr) return err;
- err = pBlock.ioResult;
- if (err != noErr) return err;
- myAddr = pBlock.ourAddress;
-
-
- gotIt = true;
- }
-
- *addr = myAddr;
- return noErr;
- }
-
- /*----------------------------------------------------------------------------
- GetMaxTCPMTU
-
- Get the max MTU size.
-
- Exit: function result = max MTU, or 0 if error.
- ----------------------------------------------------------------------------*/
-
- static long GetMaxTCPMTU (void)
- {
- UDPiopb iopb;
- OSErr err = noErr;
-
- memset(&iopb, 0, sizeof(iopb));
- err = NetGetMyAddr(&iopb.csParam.mtu.remoteHost);
- if (err != noErr) return 0;
- iopb.ioCRefNum = gRefNum;
- iopb.csCode = UDPMaxMTUSize;
- err = PBControlSync((ParmBlkPtr)&iopb);
- if (err != noErr) return 0;
- return iopb.csParam.mtu.mtuSize;
- }
-
-
- /*----------------------------------------------------------------------------
- DoTCPCreate
-
- Create a stream.
-
- Entry: s = pointer to stream.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr DoTCPCreate (TStreamPtr s)
- {
- OSErr err = noErr;
-
- InitMacTCPParamBlock(&s->pBlock, TCPCreate);
- s->pBlock.csParam.create.rcvBuff = s->mactcpBuf;
- s->pBlock.csParam.create.rcvBuffLen = gTCPBufSize;
- err = CallMacTCP(s, false);
- if (err != noErr) return err;
- s->tcpStream = s->pBlock.tcpStream;
- return noErr;
- }
-
- /*----------------------------------------------------------------------------
- DoTCPRelease
-
- Release a stream.
-
- Entry: s = pointer to stream.
-
- Exit: function result = error code.
-
- Any active connection is also aborted, if necessary, before releasing
- the stream.
-
- With MacTCP, the function uses its own TCPiopb parameter block instead
- of the one inside the stream block, because the one inside the stream block
- may already be in use by some other asynchronous operation.
- ----------------------------------------------------------------------------*/
-
- static OSErr DoTCPRelease (short stream)
- {
- TCPiopb pBlock;
- OSErr err = noErr, giveTimeErr = noErr;
- Boolean abort;
- TStreamPtr s;
-
- s = myStream[stream];
- if (!s || !s->tcpStream) return noErr;
- InitMacTCPParamBlock(&pBlock, TCPRelease);
- pBlock.tcpStream = s->tcpStream;
- PBControlAsync((ParmBlkPtr)&pBlock);
- while (pBlock.ioResult > 0) {
- // giveTimeErr = (*gGiveTime)();
- // if (err == noErr) err = giveTimeErr;
- }
- if (err == noErr) err = pBlock.ioResult;
- if (err == noErr) {
- s->tcpStream = 0; // we know we're done with it
- nexStatus[stream] = kStatClosed;
- }
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoTCPActiveOpen
-
- Open an active stream.
-
- Entry: s = pointer to stream.
- addr = IP address of server.
- port = port number of service.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr DoTCPActiveOpen (short stream, unsigned long addr,
- unsigned short port)
- {
- OSErr err = noErr;
- TStreamPtr s = myStream[stream];
-
- InitMacTCPParamBlock(&s->pBlock, TCPActiveOpen);
- s->pBlock.tcpStream = s->tcpStream;
- s->pBlock.csParam.open.remoteHost = addr;
- s->pBlock.csParam.open.remotePort = port;
- err = CallMacTCP(s, true);
- if (err == noErr)
- s->localPort = s->pBlock.csParam.open.localPort;
- return err;
- }
-
-
- /*----------------------------------------------------------------------------
- DoTCPPassiveOpen
-
- Open a passive stream.
-
- Entry: s = pointer to stream.
-
- Exit: function result = error code.
- *port = assigned unused local port number.
-
- Note: Unlike the other "DoTCPxxx" functions, DoTCPPassiveOpen is
- asynchronous. The passive stream is opened, but the function does not
- wait for another host to connect. The function is used by
- NetFTPDataPassiveOpen to open passive FTP data streams. The caller must
- call NetFTPDataWaitForConnection to wait for the FTP server to connect
- to the stream.
- ----------------------------------------------------------------------------*/
-
- OSErr DoTCPPassiveOpen (short stream, unsigned short *port)
- {
- OSErr err = noErr;
- TStreamPtr s = myStream[stream];
-
- InitMacTCPParamBlock(&s->pBlock, TCPPassiveOpen);
- s->pBlock.tcpStream = s->tcpStream;
- s->pBlock.csParam.open.localPort = *port;
- PBControlAsync((ParmBlkPtr)&s->pBlock);
- while (s->pBlock.csParam.open.localPort == 0) {
- // err = (*gGiveTime)();
- // if (err != noErr) return err;
- }
- *port = s->localPort = s->pBlock.csParam.open.localPort;
- return noErr;
- }
-
-
- /*----------------------------------------------------------------------------
- DoTCPSend
-
- Send data on a stream.
-
- Entry: s = pointer to stream.
- data = pointer to data to send.
- len = length of data to send.
- push = true to set push data flag. This flag should be set on
- the last buffer of data being sent on the stream before
- a response from the server is expected. This flag is need
- to keep IBM VM/CMS happy. (Note OT handles this internally,
- so this is needed only with MacTCP.)
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr OldDoTCPSend (TStreamPtr s, void *data, unsigned short len, Boolean push)
- {
- OSErr err = noErr;
- // TCPiopb pBlock;
-
- s->wds[0].ptr = (Ptr) data;
- s->wds[0].length = len;
- InitMacTCPParamBlock(&s->pBlock, TCPSend);
- s->pBlock.tcpStream = s->tcpStream;
- s->pBlock.csParam.send.wdsPtr = (Ptr)s->wds;
- s->pBlock.csParam.send.pushFlag = push;
- err = CallMacTCP(s, true);
- return err;
- }
-
- static OSErr DoTCPSend (TStreamPtr s, void *data, unsigned short len, Boolean push)
- {
- OSErr err = noErr;
- short nnn;
-
- for (nnn=0;nnn<kNumOutChunks;nnn++) {
- OutChunk *oc = outChunk[nnn];
- verify(oc);
- if (oc->bufSize < len)
- continue;
- if (oc->pBlock.ioResult > 0)
- continue; // already being used
-
- // okay, I think we're ready to use it and send
- oc->wds[0].ptr = (Ptr) oc->buf;
- oc->wds[0].length = len;
- memcpy(oc->buf, data, len);
- InitMacTCPParamBlock(&oc->pBlock, TCPSend);
- oc->pBlock.tcpStream = s->tcpStream;
- oc->pBlock.csParam.send.wdsPtr = (Ptr)oc->wds;
- oc->pBlock.csParam.send.pushFlag = push;
- CallMacTCPAsynch(&oc->pBlock);
- return noErr;
- }
- tprintf("Error writing data: no available buffers!\r");
- return -1;
- }
-
- OSErr
- SendData(short stream, void *data, long length)
- {
- OSErr err;
-
- if (length == 0)
- return noErr;
-
- if (nexStatus[stream] != kStatOpen)
- return -1;
-
- if (err = DoTCPSend(myStream[stream], data, length, true))
- VDebugStr("Error writing data!");
- return err;
- }
-
- /*----------------------------------------------------------------------------
- DoTCPRcv
-
- Reveive data on a stream.
-
- Entry: s = pointer to stream.
- data = pointer to data buffer.
- *len = length of data buffer.
-
- Exit: function result = error code.
- *len = number of bytes received.
- ----------------------------------------------------------------------------*/
-
- static OSErr DoTCPRcv (TStreamPtr s, Ptr data, unsigned short *len)
- {
- OSErr err = noErr;
-
- InitMacTCPParamBlock(&s->pBlock, TCPRcv);
- s->pBlock.tcpStream = s->tcpStream;
- s->pBlock.csParam.receive.rcvBuff = StripAddress(data);
- s->pBlock.csParam.receive.rcvBuffLen = *len;
- err = CallMacTCP(s, true);
- *len = s->pBlock.csParam.receive.rcvBuffLen;
- if (err == noErr) s->bytesIn += *len;
- return err;
- }
-
- void ReleaseStreams(void)
- {
- short nnn;
- for (nnn=0;nnn<kMaxStreams;nnn++)
- if (myStream[nnn] != nil && myStream[nnn]->tcpStream != nil)
- DoTCPRelease(nnn);
- }
-
- OSErr
- PrepareTheWay(short stream)
- {
- OSErr err;
-
- if (err = DoTCPCreate(myStream[stream]))
- VDebugStr("Error on create: stream %d", stream);
- return err;
- }
-
- /*----------------------------------------------------------------------------
- MyExitToShell
-
- ExitToShell trap patch (for MacTCP only).
-
- This patch makes sure that all open streams are closed when ExitToShell
- is called (e.g., if the program crashes and you type "es" in MacsBug, or
- if you use Command-Option-Escape to force quit the program). This keeps
- MacTCP happy. It doesn't always work, but it helps sometimes.
-
- Open Transport has its own mechanisms for doing this, so this patch
- is only installed if we are using MacTCP.
- ----------------------------------------------------------------------------*/
-
- static void MyExitToShell (void)
- {
- SetCurrentA5();
- SetToolTrapAddress(gOldExitToShellUPP, _ExitToShell);
- ReleaseStreams();
- ExitToShell();
- }
-
-
-
- /*----------------------------------------------------------------------------
- PatchExitToShell
-
- Install a patch on the ExitToShell trap (for MacTCP only).
- ----------------------------------------------------------------------------*/
-
- static void PatchExitToShell (void)
- {
- gOldExitToShellUPP = GetToolTrapAddress(_ExitToShell);
- gMyExitToShellUPP =
- NewRoutineDescriptor((ProcPtr)MyExitToShell, kPascalStackBased, GetCurrentISA());
- SetToolTrapAddress(gMyExitToShellUPP, _ExitToShell);
- }
-
- static void
- InitOutChunks(void)
- {
- short nnn, sz, bsize;
-
- for (nnn=0;nnn<kNumOutChunks;nnn++) {
- if (nnn<kNumSmallOut)
- bsize = kSmallOutSize;
- else if (nnn<kNumMidOut)
- bsize = kMidOutSize;
- else
- bsize = kLargeOutSize;
- sz = bsize + sizeof(OutChunk);
- sz -= 2; // important bytes
-
- outChunk[nnn] = (OutChunk *) NewPtr(sz);
- verify(outChunk[nnn]);
-
- memset(outChunk[nnn], 0, sz);
-
- outChunk[nnn]->bufSize = bsize;
- }
-
- }
-
-
- OSErr NetInit (void)
- {
- short i;
- OSErr err = noErr;
- long mtu;
-
-
- gMacTCPDNRResultProcUPP = NewResultProc(MacTCPDNRResultProc);
- gMacTCPCloseStreamCompletionRoutineUPP =
- NewTCPIOCompletionProc(MacTCPCloseStreamCompletionRoutine);
- err = OpenDriver("\p.IPP", &gRefNum);
- if (err != noErr) return err;
- mtu = GetMaxTCPMTU();
- gTCPBufSize = 8 * mtu;
- if (gTCPBufSize < kMinTCPBufSize) gTCPBufSize = kMinTCPBufSize;
- gStreamBufSize = sizeof(TStream) - 1 + gTCPBufSize;
- // PatchExitToShell();
-
- for (i = 0; i < kMaxStreams; i++) {
- myStream[i] = NewStreamBuffer();
- if (!myStream[i]) return -1;
- myStream[i]->myID = i;
- bufdata[i] = 0;
- }
-
- if (err = NetGetMyAddr(&gMyAddress)) {
- VDebugStr("Error getting my address.");
- return err;
- }
-
- InitOutChunks();
-
- return noErr;
- }
-
- static OSErr
- GetConnectionStatus(TStreamPtr s)
- {
- OSErr err = noErr;
-
- InitMacTCPParamBlock(&s->pBlock, TCPStatus);
- s->pBlock.tcpStream = s->tcpStream;
- err = CallMacTCP(s, true);
- return err;
- }
-
- #if TIMESTAMP
- long process_chars_from_server(char *buf, long len);
- #include "timeseal.h"
- #endif
-
- static void
- Upkeep(void)
- {
- short nnn;
- TStreamPtr s;
- unsigned long dat;
- unsigned short rd;
- short conn;
- static short lastcon = -1;
- unsigned char *dest;
-
- for (nnn=0;nnn<kMaxStreams;nnn++) {
- s = myStream[nnn];
- if (s->tcpStream)
- if (!GetConnectionStatus(s)) {
- // do reading in stuff
- dat = s->pBlock.csParam.status.amtUnreadData;
- conn = s->pBlock.csParam.status.connectionState;
- /* if (conn != lastcon) {
- lastcon = conn;
- tprintf("\r#####%d####\r", conn);
- }*/
- rd = dat;
- if (rd > 0) {
- // don't read too many bytes
- if (bufdata[nnn] + rd > kBufferLength)
- rd = kBufferLength - bufdata[nnn];
- dest = &buf[nnn][bufdata[nnn]];
- if (DoTCPRcv(s, (Ptr) dest, &rd))
- VDebugStr("Error reading data.");
- #if TIMESTAMP
- if (gPrefs.serverType == kIcc && gPrefs.timeseal) {
- bufdata[nnn] += process_chars_from_server((char *) dest, rd);
- }
- else if (gPrefs.serverType == kFics && gPrefs.timeseal) {
- bufdata[nnn] += SealFromServer((char *) dest, rd);
- }
- else
- #endif
- bufdata[nnn] += rd;
- // tprintf("Data: %u\r", rd);
- break;
- }
-
- // give rest of world some status on this connection
- // nice of Apple to provide these constants in the header
- switch (conn) {
- // next line handled better in Release
- // case 0: case 14: nexStatus[nnn] = kStatClosed; break;
- case 2: case 4: nexStatus[nnn] = kStatListening; break;
- case 8: nexStatus[nnn] = kStatOpen; break;
- default: nexStatus[nnn] = kStatOther; break;
- }
-
- // check for closed connection
- // it seems to hang on 14, so why not close it (???)
- if (conn == 0 || conn == 14) {
- if (!DoTCPRelease(nnn))
- tprintf("Connection terminated\r");
- }
- }
- else {
- // VDebugStr("Error getting connection status stream %d", nnn);
- // somehow this connection closed without us knowing
- nexStatus[nnn] = kStatClosed;
- DoTCPRelease(nnn); // ???
- }
- }
- }
-
- OSErr NetIdle (void)
- {
- TStreamPtr s, nextClose, prev = nil;
- OSErr err = noErr;
- short nnn;
-
- for (nnn=0;nnn<kMaxStreams;nnn++) {
- s = myStream[nnn];
- if (s->release) {
- err = DoTCPRelease(nnn);
- // DisposeStreamBuffer(s);
- }
- }
-
- Upkeep();
-
- return noErr;
- }
-
- /*----------------------------------------------------------------------------
- NetNameToAddr
-
- Translate a domain name to an IP address.
-
- Entry: name = C-format domain name string, optionally followed by a
- comma, space, or colon and then the port number.
- defaultPort = default port number.
-
- Exit: function result = error code.
- *addr = IP address.
- *port = port number.
- ----------------------------------------------------------------------------*/
-
- OSErr NetNameToAddr (char *name,
- unsigned long *addr, unsigned short *port)
- {
- OSErr err = noErr, giveTimeErr = noErr;
- short i;
- struct hostInfo hInfoMacTCP;
- Boolean done = false;
- char domainName[256];
- char *p, *q;
-
- p = name;
- q = domainName;
- while (*p != 0) *q++ = *p++;
- *q = 0;
- /* while (*p != 0 && *p != ',' && *p != ' ' && *p != ':') *q++ = *p++;
- *q = 0;
- q = p;
- while (*q == ' ') q++;
- if (*q == 0) {
- *port = defaultPort;
- } else {
- p++;
- if (!isdigit(*p)) return -1;
- q = p+1;
- while (isdigit(*q)) q++;
- while (*q == ' ') q++;
- if (*q != 0) return -1;
- *port = atoi(p);
- }
- */
-
- while (gMacTCPDNROperationInProgress) {
- /* Some other thread is using the DNR. Wait for it to finish. */
- // err = (*gGiveTime)();
- // if (err != noErr) return err;
- }
- err = OpenResolver(nil);
- if (err != noErr) return err;
- memset(&hInfoMacTCP, 0, sizeof(hInfoMacTCP));
- gMacTCPDNROperationInProgress = true;
- err = StrToAddr(domainName, &hInfoMacTCP, gMacTCPDNRResultProcUPP, (char*)&done);
- if (err == cacheFault) {
- err = noErr;
- while (!done) {
- // giveTimeErr = (*gGiveTime)();
- // if (err == noErr) err = giveTimeErr;
- }
- if (err == noErr) err = hInfoMacTCP.rtnCode;
- }
- gMacTCPDNROperationInProgress = false;
- // (*gGiveTime)();
- CloseResolver();
- if (err != noErr) return err;
- *addr = hInfoMacTCP.addr[0];
-
- return noErr;
- }
-
-
- /*----------------------------------------------------------------------------
- NetAddrToName
-
- Translate an IP address to a domain name.
-
- Entry: addr = IP address.
-
- Exit: function result = error code.
- name = domain name, as a C-format string.
- ----------------------------------------------------------------------------*/
-
- OSErr NetAddrToName (unsigned long addr, char *name)
- {
- struct hostInfo hInfoMacTCP;
- OSErr err = noErr, giveTimeErr = noErr;
- Boolean done=false;
-
- while (gMacTCPDNROperationInProgress) {
- /* Some other thread is using the DNR. Wait for it to finish. */
- // err = (*gGiveTime)();
- // if (err != noErr) return err;
- }
-
- err = OpenResolver(nil);
- if (err != noErr) return err;
- memset(&hInfoMacTCP, 0, sizeof(hInfoMacTCP));
-
- gMacTCPDNROperationInProgress = true;
- err = AddrToName(addr, &hInfoMacTCP, gMacTCPDNRResultProcUPP, (char*)&done);
- if (err == cacheFault) {
- err = noErr;
- while (!done) {
- // giveTimeErr = (*gGiveTime)();
- // if (err == noErr) err = giveTimeErr;
- }
- if (err == noErr) err = hInfoMacTCP.rtnCode;
- }
- gMacTCPDNROperationInProgress = false;
- // (*gGiveTime)();
- CloseResolver();
- if (err != noErr) return err;
- hInfoMacTCP.cname[254] = 0;
- strcpy(name, hInfoMacTCP.cname);
- return noErr;
- }
-