home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-12-10 | 16.8 KB | 797 lines | [TEXT/KAHL] |
- /*
- ** CTCPResolverCall.cp
- **
- ** TurboTCP support library
- ** TCP resolver call class
- **
- ** Copyright © 1993, FrostByte Design / Eric Scouten
- ** Some portions adapted from file “dnr.c” Copyright © 1988 by Apple Computer. All rights reserved.
- **
- */
-
-
- #include "CTCPResolverCall.h"
-
- #ifndef TurboTCPHeaders
- #include <Folders.h>
- #include <GestaltEqu.h>
- #include <Traps.h>
- #include <TCLUtilities.h>
- #include <OSChecks.h>
- #include "TurboTCP.const.h"
- #endif
- #include "CTCPDriver.h"
-
-
- // procedure code numbers for DNR code segment
-
- #define OPENRESOLVER 1L
- #define CLOSERESOLVER 2L
- #define STRTOADDR 3L
- #define ADDRTOSTR 4L
- #define ENUMCACHE 5L
- #define ADDRTONAME 6L
- #define HINFO 7L
- #define MXINFO 8L
-
-
- // declaration & initialization of class variables
-
- Handle CTCPResolverCall::macDNRcode = NULL;
- DNRProcPtr CTCPResolverCall::macDNRentry = NULL;
-
-
- // —— initialize/destroy resolver ——
-
- /*______________________________________________________________________
- **
- ** ITCPResolverCall
- **
- ** Initialize the resolver object. Must keep the object locked, since pointers are used
- ** frequently.
- **
- */
-
- void CTCPResolverCall::ITCPResolverCall (void)
-
- {
-
- // clear variables
-
- inUse = FALSE;
- disposeOnCompletion = FALSE;
- pendingNotify = notifNone;
- qEntry.qSelfLink = this;
- qEntry.qType = resolverCall;
-
-
- // initialize the collaborator object
-
- CCollaborator::ICollaborator();
-
-
- // prevent this from moving, since we use pointers
-
- MoveHHi((Handle) this);
- this->Lock(TRUE);
-
- }
-
-
- /*______________________________________________________________________
- **
- ** Dispose
- **
- ** Get rid of the resolver object. If a resolver operation is in progress, will dispose of
- ** itself when the current resolver operation is completed.
- **
- */
-
- void CTCPResolverCall::Dispose (void)
-
- {
- if (inUse)
- disposeOnCompletion = TRUE;
- else
- CCollaborator::Dispose();
- }
-
-
- // —— initiate resolver calls ——
-
- /*______________________________________________________________________
- **
- ** DoStrToAddr
- **
- ** Get the IP address of a host named by a DNS or dotted decimal string. Completion is
- ** handled by HandleStrToAddr.
- **
- ** theHostName (char *): whos IP address do we need?
- **
- */
-
- void CTCPResolverCall::DoStrToAddr (char *theHostName)
-
- {
- OSErr theResult;
-
- if (inUse)
- FailOSErr(resolverInUse);
- if (!gTCPDriver->CheckResolver())
- FailOSErr(noResolverErr);
-
- inUse = TRUE;
- gTCPDriver->RegisterActiveResolver(this);
- BlockMove(theHostName, &hostName, 255);
- theResult = (*macDNRentry)(STRTOADDR, (char *) &hostName, &theHostInfo,
- &PostponeStrToAddr, (char *) this);
-
-
- // if call was completed immediately (with error or not), process it immediately
-
- if (theResult != cacheFault) {
- inUse = FALSE;
- gTCPDriver->RemoveActiveResolver(this);
- HandleStrToAddr();
- }
- }
-
-
- /*______________________________________________________________________
- **
- ** DoAddrToStr
- **
- ** Convert an IP address to dotted decimal notation. This call can be used while the resolver
- ** object is otherwise in use, and is completed immediately.
- **
- ** theIPaddr (ip_addr): the address to convert
- ** theString (char *): where to send the completed string (min. 16 chars)
- **
- */
-
- void CTCPResolverCall::DoAddrToStr (ip_addr theIPaddr, char *theString)
-
- {
- OSErr theResult;
-
- if (!gTCPDriver->CheckResolver())
- FailOSErr(noResolverErr);
-
- (void) (*macDNRentry)(ADDRTOSTR, theIPaddr, theString);
-
- }
-
-
- /*______________________________________________________________________
- **
- ** DoAddrToName
- **
- ** Get the canonical name of a host as specified by IP address. Completion is handled by
- ** HandleAddrToName method.
- **
- ** theIPaddr (ip_addr): the IP address to query
- **
- */
-
-
- void CTCPResolverCall::DoAddrToName (ip_addr theIPaddr)
-
- {
- OSErr theResult;
-
- if (inUse)
- FailOSErr(resolverInUse);
- if (!gTCPDriver->CheckResolver())
- FailOSErr(noResolverErr);
-
- inUse = TRUE;
- gTCPDriver->RegisterActiveResolver(this);
- theResult = (*macDNRentry)(ADDRTONAME, theIPaddr, &theHostInfo,
- &PostponeAddrToName, (char *) this);
-
-
- // if call was completed immediately (with error or not), process it immediately
-
- if (theResult != cacheFault) {
- inUse = FALSE;
- gTCPDriver->RemoveActiveResolver(this);
- HandleAddrToName();
- }
- }
-
-
- /*______________________________________________________________________
- **
- ** DoHInfo
- **
- ** Get the CPU type and operating system type of a remote host. Completion is handled by
- ** HandleHInfo.
- **
- ** theHostName (char *): who we askin’ ‘bout anyway?
- **
- */
-
- void CTCPResolverCall::DoHInfo (char *theHostName)
-
- {
- OSErr theResult;
-
- if (inUse)
- FailOSErr(resolverInUse);
- if (!gTCPDriver->CheckResolver())
- FailOSErr(noResolverErr);
-
- inUse = TRUE;
- gTCPDriver->RegisterActiveResolver(this);
- BlockMove(theHostName, &hostName, 255);
- theResult = (*macDNRentry)(HINFO, (char *) &hostName, &theHMXInfo,
- &PostponeHInfo, (char *) this);
-
-
- // if call was completed immediately (with error or not), process it immediately
-
- if (theResult != cacheFault) {
- inUse = FALSE;
- gTCPDriver->RemoveActiveResolver(this);
- HandleHInfo();
- }
- }
-
-
- /*______________________________________________________________________
- **
- ** DoMXInfo
- **
- ** Get the mailbox exchange (MX) info of a remote host. Completion is handled by
- ** HandleMXInfo.
- **
- ** theHostName (char *): who we askin’ ‘bout anyway?
- **
- */
-
- void CTCPResolverCall::DoMXInfo (char *theHostName)
-
- {
- OSErr theResult;
-
- if (inUse)
- FailOSErr(resolverInUse);
- if (!gTCPDriver->CheckResolver())
- FailOSErr(noResolverErr);
-
- inUse = TRUE;
- gTCPDriver->RegisterActiveResolver(this);
- BlockMove(theHostName, &hostName, 255);
- theResult = (*macDNRentry)(MXINFO, (char *) &hostName, &theHMXInfo,
- &PostponeMXInfo, (char *) this);
-
-
- // if call was completed immediately (with error or not), process it immediately
-
- if (theResult != cacheFault) {
- inUse = FALSE;
- gTCPDriver->RemoveActiveResolver(this);
- HandleMXInfo();
- }
- }
-
-
- // —— respond to completion of resolver calls ——
-
- /*______________________________________________________________________
- **
- ** ProcessNotify
- **
- ** Handles any notifications passed to the resolver. This routine is free of interrupt-level
- ** constraints.
- **
- */
-
- void CTCPResolverCall::ProcessNotify (void)
-
- {
- // free this resolver object for future use
-
- gTCPDriver->RemoveActiveResolver(this);
- inUse = FALSE;
-
-
- // dispatch notification to appropriate routine
-
- switch (pendingNotify) {
- case notifStrToAddr:
- HandleStrToAddr();
- break;
-
- case notifAddrToName:
- HandleAddrToName();
- break;
-
- case notifHInfo:
- HandleHInfo();
- break;
-
- case notifMXInfo:
- HandleMXInfo();
- }
-
-
- // if someone attempted to dispose this earlier, do it now
-
- if (disposeOnCompletion)
- Dispose();
-
- }
-
-
- /*______________________________________________________________________
- **
- ** HandleStrToAddr (protected method)
- **
- ** Respond to completion of a StrToAddr call.
- **
- */
-
-
- void CTCPResolverCall::HandleStrToAddr (void)
-
- {
- BroadcastChange(tcpResolverStrToAddr, &theHostInfo);
- }
-
-
- /*______________________________________________________________________
- **
- ** HandleAddrToName (protected method)
- **
- ** Respond to completion of an AddrToName call.
- **
- */
-
- void CTCPResolverCall::HandleAddrToName (void)
-
- {
- BroadcastChange(tcpResolverAddrToName, &theHostInfo);
- }
-
-
- /*______________________________________________________________________
- **
- ** HandleHInfo (protected method)
- **
- ** Respond to completion of an HInfo call.
- **
- */
-
-
- void CTCPResolverCall::HandleHInfo (void)
-
- {
- BroadcastChange(tcpResolverHInfo, &theHMXInfo);
- }
-
-
- /*______________________________________________________________________
- **
- ** HandleMXInfo (protected method)
- **
- ** Respond to completion of an MXInfo call.
- **
- */
-
-
- void CTCPResolverCall::HandleMXInfo (void)
-
- {
- BroadcastChange(tcpResolverMXInfo, &theHMXInfo);
- }
-
-
- // —— open/close TCP resolver ——
-
- /*______________________________________________________________________
- **
- ** OpenResolver (static method)
- **
- ** Find the MacTCP DNR code resource and read it. Save the location of the resolver resource
- ** for later use.
- **
- */
-
- void CTCPResolverCall::OpenResolver (void)
-
- {
- short vRefNum;
- short refnum;
- long dirID;
- short fRef;
- OSErr rc;
-
-
- // is the resolver already there?
-
- if (macDNRentry)
- return;
-
-
- // open the MacTCP driver to get DNR resources
-
- TRY {
- refnum = OpenTheDNR();
- }
- CATCH {
- NO_PROPAGATE; // ignore failures since the resource may
- // have been installed in the System file
- // (if running on a Mac 512Ke)
- }
- ENDTRY;
-
-
- // load the DNR resource package
-
- macDNRcode = GetIndResource('dnrp', 1);
- FailNIL(macDNRcode);
- DetachResource(macDNRcode);
-
- if (refnum != -1)
- CloseResFile(refnum);
-
-
- // lock the DNR resource since it cannot be relocated while opened
-
- MoveHHi(macDNRcode);
- HLock(macDNRcode);
- macDNRentry = (DNRProcPtr) *macDNRcode;
-
-
- // check for “hosts” file in System Folder (BRB)
-
- GetSystemFolder(&vRefNum, &dirID);
- rc = HOpen(vRefNum, dirID, "\pHosts", fsRdPerm, &fRef);
- switch (rc) {
- case noErr:
- FSClose(fRef);
- break;
-
- case fnfErr:
- if ((rc = HCreate(vRefNum, dirID, "\pHosts", 'ttxt', 'TEXT')) != noErr)
- ErrorAlert(rc, SpecifyMsg(1001, 1));
- break;
-
- default:
- break;
- }
-
-
- // ask the DNR resource to open the resolver
-
- rc = (*macDNRentry)(OPENRESOLVER, NULL); // send it a null hosts file name
- if (rc != noErr) {
- HUnlock(macDNRcode); // problem with open resolver, flush DNR resource
- DisposHandle(macDNRcode);
- macDNRcode = NULL;
- macDNRentry = NULL;
- FailOSErr(rc); // signal failure of DNR
- }
-
- }
-
-
- /*______________________________________________________________________
- **
- ** CloseResolver (static method)
- **
- ** Shut down the DNR code resource. Does nothing if the resolver was never loaded.
- **
- */
-
- void CTCPResolverCall::CloseResolver (void)
-
- {
-
- // ensure that we had a resolver to begin with
-
- if (macDNRentry == NULL)
- return;
-
-
- // call CloseResolver function in DNR
-
- (void) (*macDNRentry)(CLOSERESOLVER);
-
-
- // release the DNR code resource
-
- HUnlock(macDNRcode);
- DisposHandle(macDNRcode);
- macDNRcode = NULL;
- macDNRentry = NULL;
-
- }
-
-
- /*______________________________________________________________________
- **
- ** OpenTheDNR (protected static method)
- **
- ** Search in several places for the MacTCP DNR code resource. Tries the Control Panels
- ** folder and the System folder.
- **
- ** return (short): reference number to resource file
- **
- */
-
- short CTCPResolverCall::OpenTheDNR (void)
-
- {
- short refnum;
- short vRefNum;
- long dirID;
-
-
- // first search Control Panels for MacTCP 1.1.x
-
- GetCPanelFolder(&vRefNum, &dirID);
- refnum = SearchFolderForDNRP('cdev', 'ztcp', vRefNum, dirID);
- if (refnum != -1)
- return (refnum);
-
-
- // next search System Folder for MacTCP 1.0.x
-
- GetSystemFolder(&vRefNum, &dirID);
- refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
- if (refnum != -1)
- return (refnum);
-
-
- // finally, search Control Panels for MacTCP 1.0.x
-
- GetCPanelFolder(&vRefNum, &dirID);
- refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
- if (refnum != -1)
- return (refnum);
-
- return (-1);
-
- }
-
-
- /*______________________________________________________________________
- **
- ** SearchFolderForDNRP (protected static method)
- **
- ** Search a folder for files that might contain the 'dnrp' resource.
- **
- ** targetType (OSType): file type that we are looking for
- ** targetCreator (OSType): file creator "" ""
- ** vRefNum (short): volume ref num
- ** dirID (long): directory number on the volume
- **
- ** return (short): the refnum of the file if found, -1 if not found
- **
- */
-
- short CTCPResolverCall::SearchFolderForDNRP (long targetType, long targetCreator,
- short vRefNum, long dirID)
-
- {
- HParamBlockRec fi;
- Str255 filename;
- short refnum;
-
-
- // initialize our search mechanism
-
- fi.fileParam.ioCompletion = nil;
- fi.fileParam.ioNamePtr = filename;
- fi.fileParam.ioVRefNum = vRefNum;
- fi.fileParam.ioDirID = dirID;
- fi.fileParam.ioFDirIndex = 1;
-
-
- // keep looking till we run out of files
-
- while (PBHGetFInfo(&fi, false) == noErr) {
-
- // scan the folder for files that match our type & creator
-
- if (fi.fileParam.ioFlFndrInfo.fdType == targetType &&
- fi.fileParam.ioFlFndrInfo.fdCreator == targetCreator) {
-
- // type/creator match, look for the resource
-
- refnum = HOpenResFile(vRefNum, dirID, filename, fsRdPerm);
- if (GetIndResource('dnrp', 1) == NULL)
- CloseResFile(refnum);
- else
- return (refnum);
- }
-
- // no match or no resource, try next file in folder
-
- fi.fileParam.ioFDirIndex++;
- fi.fileParam.ioDirID = dirID; // PBHGetFInfo() clobbers ioDirID
- }
-
- return (-1); // nothing found
-
- }
-
-
- /*______________________________________________________________________
- **
- ** GetSystemFolder (protected static method)
- **
- ** Return the ID of the current system folder.
- **
- ** vRefNumP (short *): returns volume ref number
- ** dirIDP (long *): returns directory ID
- **
- */
-
- void CTCPResolverCall::GetSystemFolder (short *vRefNumP, long *dirIDP)
-
- {
- SysEnvRec info;
- long wdProcID;
-
- SysEnvirons(1, &info);
- if (GetWDInfo(info.sysVRefNum, vRefNumP, dirIDP, &wdProcID) != noErr) {
- *vRefNumP = 0;
- *dirIDP = 0;
- }
- }
-
-
- /*______________________________________________________________________
- **
- ** GetCPanelFolder (protected static method)
- **
- ** Return the ID of the current “Control Panels” folder.
- **
- ** vRefNumP (short *): returns volume ref number
- ** dirIDP (long *): returns directory ID
- **
- */
-
- void CTCPResolverCall::GetCPanelFolder (short *vRefNumP, long *dirIDP)
-
- {
- Boolean hasFolderMgr = false;
- long feature;
-
-
- // see if we have the Folder Manager available
-
- if (TrapAvailable((short) _Gestalt))
- if (Gestalt(gestaltFindFolderAttr, &feature) == noErr)
- hasFolderMgr = TRUE;
-
-
- // if folder manager, use it; else return system folder
-
- if (!hasFolderMgr) {
- GetSystemFolder(vRefNumP, dirIDP);
- return;
- }
- else {
- if (FindFolder(kOnSystemDisk, kControlPanelFolderType,
- kDontCreateFolder, vRefNumP, dirIDP) != noErr) {
- *vRefNumP = 0;
- *dirIDP = 0;
- }
- }
-
- }
-
-
- /***********************************************************************
- ************************************************************************
- **
- ** INTERRUPT-LEVEL routines follow. These routines cannot make memory allocations, cannot make
- ** synchronous TCP calls, and cannot use the Think C profiler.
- **
- */
-
- #pragma options(!profile)
-
-
- // —— interrupt-level methods: delay processing for non-interrupt status ——
-
- /*______________________________________________________________________
- **
- ** PostponeNotify
- **
- ** Respond to notification that a DNR call was completed. Delays processing of notification
- ** until the next net-event call. This method merely logs the kind of notification and adds this
- ** resolver to the list of resolvers to be processed next time through the event loop.
- **
- ** theNotifType (NotifType): which resolver call was completed
- **
- */
-
- void CTCPResolverCall::PostponeNotify (NotifType theNotifType)
-
- {
- pendingNotify = theNotifType;
- Enqueue((QElemPtr) &qEntry, &(gTCPDriver->asyncQueue));
- }
-
-
- /*______________________________________________________________________
- **
- ** PostponeStrToAddr (protected static method)
- **
- ** Respond to notification that the StrToAddr call was completed.
- **
- ** hostInfoPtr (…): pointer to the DNR data structure (ignored)
- ** userDataPtr (char *): user data pointer (assumed to be CTCPResolver *)
- **
- */
-
- pascal void CTCPResolverCall::PostponeStrToAddr (struct hostInfo *hostInfoPtr, char *userDataPtr)
-
- {
- if (userDataPtr)
- ((CTCPResolverCall *) userDataPtr)->PostponeNotify(notifStrToAddr);
- }
-
-
- /*______________________________________________________________________
- **
- ** PostponeAddrToName (protected static method)
- **
- ** Respond to notification that the AddrToName call was completed.
- **
- ** hostInfoPtr (…): pointer to the DNR data structure (ignored)
- ** userDataPtr (char *): user data pointer (assumed to be CTCPResolver *)
- **
- */
-
- pascal void CTCPResolverCall::PostponeAddrToName (struct hostInfo *hostInfoPtr, char *userDataPtr)
-
- {
- if (userDataPtr)
- ((CTCPResolverCall *) userDataPtr)->PostponeNotify(notifAddrToName);
- }
-
-
- /*______________________________________________________________________
- **
- ** PostponeHInfo (protected static method)
- **
- ** Respond to notification that the HInfo call was completed.
- **
- ** hostInfoPtr (…): pointer to the DNR data structure (ignored)
- ** userDataPtr (char *): user data pointer (assumed to be CTCPResolver *)
- **
- */
-
- pascal void CTCPResolverCall::PostponeHInfo (struct returnRec *returnRecPtr, char *userDataPtr)
-
- {
- if (userDataPtr)
- ((CTCPResolverCall *) userDataPtr)->PostponeNotify(notifHInfo);
- }
-
-
- /*______________________________________________________________________
- **
- ** PostponeMXInfo (protected static method)
- **
- ** Respond to notification that the MXInfo call was completed.
- **
- ** hostInfoPtr (…): pointer to the DNR data structure (ignored)
- ** userDataPtr (char *): user data pointer (assumed to be CTCPResolver *)
- **
- */
-
- pascal void CTCPResolverCall::PostponeMXInfo (struct returnRec *returnRecPtr, char *userDataPtr)
-
- {
- if (userDataPtr)
- ((CTCPResolverCall *) userDataPtr)->PostponeNotify(notifMXInfo);
- }
-
-