/* File: PPCPort.c Contains: PPCPort Management Functions. Written by: Sangam, Eric M. Trehus Copyright: © 1990-1993 by Apple Computer, Inc., all rights reserved. Change History (most recent first): 3/9/93 PN Remove ReQueueInformPB,Insert, Push,InitQueue, TraverseQueue which is no longer used <27> 4/14/92 BBM : Remove unfinished PPC code that is under the contitional ÒTheFututeÓ, and remove the conditional ÒCubeEÓ since that is reality. Remove conditionals, since all they do is confuse. <26> 10/4/91 JSM Change PsychoticFarmerOrLater conditionals to TheFuture. <25> 9/29/91 DTY Conditionalize <21> through <24> out of CubeE. <24> 6/26/91 EMT Add more range checking to ValidPortName <23> 6/12/91 EMT Stop attempting to keep track of the number of pending messages. <22> 6/10/91 EMT Optimize code for size, Combined WildPortMatch and ComparePortName into 1 procedure, while fixing bugs in both of these procedures. <21> 6/4/91 EMT Roll in StoreAndForward Revisions <20> 1/11/91 EMT Fix bug in GetPortNames. <19> 11/8/90 EMT Continue working on the IPCListPorts fix <18> 11/6/90 EMT Begin work on fixing IPCListPorts, change not yet in place, but needed to check in file <17> 10/30/90 EMT Fix GetPortTable <16> 10/18/90 EMT Change userName to machineName where needed <15> 10/11/90 EMT Make changes to obsole CompletionGlue.a <14> 9/21/90 EMT Update constants, types, and field names as dictated by PPCToolBox.h <13> 9/15/90 EMT make reserved byte in portInfo always 0. <12> 9/5/90 EMT Make this file C3.0 Friendly <10+> 9/4/90 EMT Roll in Eric's changes <10> 7/10/90 dba fix C warnings <9> 6/28/90 S To Improve dynamic allocation scheme for the ports. <8> 3/20/90 S Bug Fix in GetPortNames Call. <7> 2/28/90 S To support Guest Selection in GetPortNames. <6> 2/27/90 S To Make authRequest nonOptional. <5> 1/24/90 S Fix Some Comments. <4> 1/24/90 S Fix Bug in WildPortMatch function & returning authRequired false for local ipclistport calls. <2+> 1/5/90 Sangam Some Error Code Changes Old Revision History: 05/31/89 Sangam New Today 07/20/89 Sangam 1.0d2 release today! 07/25/89 Sangam Changed FreePortTable and added ClosePortCompletion 08/25/89 Sangam Chganged GetPortNames to new IPCListPorts 09/19/89 Sangam Started changing to new PortName interface Added ValidPortName and CopyPortName routines 09/27/89 Sangam Copying script code in CopyPortName 1/4/90 Sangam Some Bug Fixes */ #include "PPCCommon.h" #include /*---------------------------------------------------------------------------------------- Prototypes used in this file only! ----------------------------------------------------------------------------------------*/ STATIC void NBPRemoveCompletion(void); STATIC Boolean WildPortMatch(PPCPortPtr name1,PPCPortPtr name2); OSErr ClosePortTable(PPCClosePBPtr closePB, PPCPortEntryPtr portPtr, PPCGlobalParamsPtr ppcglobPtr) { Boolean freePortTable; PPCInformPBPtr informPB; freePortTable = true; portPtr->openPB = (Ptr)closePB; // Keep for later. while (informPB = ServeQueue(&portPtr->informPBQueue)) CompleteWithResult(informPB,portClosedErr); #ifdef IPMIncluded if(portPtr->PortQueueRef) { freePortTable = false; } #endif if (portPtr->nbpRegistered) // PortName was registered with nbp { PortLocationTablePtr locInfo; freePortTable = false; locInfo = portPtr->locationInfo; RemoveName((EntityName *)&locInfo->nteQEle.nt.entityData, true, (ProcPtr)NBPRemoveCompletion, &locInfo->nbpPB); } if (portPtr->sessCount) { freePortTable = false; CleanSessions(portPtr, ppcglobPtr); } if(freePortTable) CompleteClosePort(portPtr); return(noErr); } STATIC void NBPRemoveCompletion(void) { PPCPortEntryPtr portPtr; PortLocationTablePtr locInfo; locInfo = GetA0(); portPtr = locInfo->portPtr; portPtr->nbpRegistered = false; // nolonger registered. CompleteClosePort(portPtr); } // PortCloseCompletion /*--------------------------------------------------------------------------------------------------- CompleteClosePort makes sure that the PPCClose operation has completed all outstanding PPCInform calls, Ended all sessions, and un-registered the NBP LocName. With all these accomplished, the port table is freed and the closePB is completed with a result of noErr. ---------------------------------------------------------------------------------------------------*/ void CompleteClosePort(PPCPortEntryPtr portPtr) { if(portPtr->nbpRegistered || #ifdef IPMIncluded portPtr->PortQueueRef || #endif portPtr->sessCount || portPtr->informPBQueue.qSize) return; // Port not fully closed. else { PPCClosePBPtr closePB; if (closePB = (PPCClosePBPtr)portPtr->openPB) // if there was a PPCClose call { portPtr->openPB = NULL; // Prevention FreePortTable(portPtr); CompleteWithResult(closePB,noErr); } } } /*---------------------------------------------------------------------------------------- CheckPortName returns the port that has the given port name. ----------------------------------------------------------------------------------------*/ PPCPortEntryPtr CheckPortName(PPCPortPtr portName,PPCGlobalParamsPtr ppcglobPtr) { PPCPortEntryPtr portPtr; FOREACHELEMENT(portPtr,&ppcglobPtr->OpenPortQueue) { if (ComparePortName(portName, (PPCPortPtr)(&portPtr->portName.nameScript))) return portPtr; } return(NULL); } /*---------------------------------------------------------------------------------------- ValidPortName verifies the structure and portKindSelector for any detectable errors. ----------------------------------------------------------------------------------------*/ Boolean ValidPortName(PPCPortPtr name) { if (name->portKindSelector == ppcByString || name->portKindSelector == ppcByCreatorAndType) { if (name->name[0] > 32) return false; if (name->portKindSelector == ppcByString) { if (name->u.portTypeStr[0] > 32) return false; } return true; } return false; } // ValidPortName Boolean ComparePortName(PPCPortPtr name1,PPCPortPtr name2) { unsigned char len; if (name1->nameScript != name2->nameScript) return false; if (name1->portKindSelector != name2->portKindSelector) return false; if (!(CompareByte(name1->name, name2->name, name1->name[0]+1))) return false; if (name1->portKindSelector == ppcByCreatorAndType) len = 8; else len = name1->u.portTypeStr[0]+1; return CompareByte(name1->u.portTypeStr, name2->u.portTypeStr, len); } // ComparePortName /*---------------------------------------------------------------------------------------- Since a PPCPortEntry nolonger wastes space by keeping a locationName structure in tact, we have this routine that constructs one based on the given port. ----------------------------------------------------------------------------------------*/ void GetLocationName(PPCGlobalParamsPtr ppcglobPtr, PPCPortEntryPtr portPtr, LocationNamePtr locationName) { locationName->locationKindSelector = ppcNBPLocation; BlockMove(ppcglobPtr->machineName,&locationName->u.nbpEntity.objStr,sizeof(Str32)); BlockMove(ppcglobPtr->zoneName,&locationName->u.nbpEntity.zoneStr,sizeof(Str32)); if(portPtr->locationInfo) BlockMove(portPtr->locationInfo->typeStr,&locationName->u.nbpEntity.typeStr,sizeof(Str32)); else BlockMove(ppcglobPtr->configData.ppctoolboxName,&locationName->u.nbpEntity.typeStr,sizeof(Str32)); } /*---------------------------------------------------------------------------------------- PortRefNumCompare compares the portRefNum passed in to the portRefNum in the port. ----------------------------------------------------------------------------------------*/ STATIC Boolean PortRefNumCompare(PPCPortEntryPtr portPtr,unsigned long portRefNum) { return(portPtr->portRefNum == (PPCPortRefNum)portRefNum); } /*---------------------------------------------------------------------------------------- DeletePortByRefNum removes and returns the port specified by the portRefNum parameter. ----------------------------------------------------------------------------------------*/ PPCPortEntryPtr DeletePortByRefNum(unsigned short portRefNum,PPCGlobalParamsPtr ppcglobPtr) { return DeleteFromQueue(&ppcglobPtr->OpenPortQueue,(unsigned long)portRefNum,(SearchFuncPtr)PortRefNumCompare); } /*---------------------------------------------------------------------------------------- PortRefNumtoPtr finds the port specified by its portRefNum parameter. ----------------------------------------------------------------------------------------*/ PPCPortEntryPtr PortRefNumtoPtr(unsigned short portRefNum,PPCGlobalParamsPtr ppcglobPtr) { return SearchQueue(&ppcglobPtr->OpenPortQueue,(unsigned long)portRefNum,(SearchFuncPtr)PortRefNumCompare,1); } /*---------------------------------------------------------------------------------------- GetUniquePortRefNum returns a portRefNum that is not in use ----------------------------------------------------------------------------------------*/ STATIC short GetUniquePortRefNum(PPCGlobalParamsPtr ppcglobPtr) { PPCPortEntryPtr portPtr; short portRefNum; short p; p = spl(kNoInterrupts); StartOver: portRefNum = ppcglobPtr->nextPortRefNum++; if(!ppcglobPtr->nextPortRefNum) // nextPortRefNum can't be 0. ++ppcglobPtr->nextPortRefNum; FOREACHELEMENT(portPtr,&ppcglobPtr->OpenPortQueue) { if(portPtr->portRefNum == portRefNum) goto StartOver; // Should rarely happen! } spl(p); return(portRefNum); } /*---------------------------------------------------------------------------------------- GetPortTable puts together and initializes a port structure. If the port has a location name associated with it, a PortLocationTable is linked with the port. If the port supports store and forward, then a PortSFTable is linked with the port. NULL is returned if some strucute cannot be gotten that is required, and all associated memory is returned to the proper pools. ----------------------------------------------------------------------------------------*/ PPCPortEntryPtr GetPortTable(PPCOpenPBPtr openPB,PPCGlobalParamsPtr ppcglobPtr) { PPCPortEntryPtr portPtr; if(portPtr = ServeQueue(&ppcglobPtr->freePortQueue)) { PortLocationTablePtr locInfo; // <25> memset(portPtr,0,sizeof(PPCPortEntry)); openPB->portRefNum = portPtr->portRefNum = GetUniquePortRefNum(ppcglobPtr); CopyPortName((openPB->portName), &(portPtr->portName)); portPtr->serviceType = openPB->serviceType; portPtr->authRequest = true; // no longer an option (openPB->authRequest;) portPtr->networkVisible = openPB->networkVisible; portPtr->serviceType = openPB->serviceType; portPtr->openPB = (Ptr)openPB; if(openPB->networkVisible && openPB->locationName) { if(portPtr->locationInfo = locInfo = ServeQueue(&ppcglobPtr->freeLocationQueue)) { locInfo->portPtr = portPtr; BlockMove(openPB->locationName->u.nbpType,locInfo->typeStr,sizeof(Str32)); } else // Should not ever ever happen in a million billion years, but just in case! { FreePortTable(portPtr); return(NULL); } } EnQueue(portPtr,&ppcglobPtr->OpenPortQueue); // Its open! return(portPtr); } return(NULL); } /*---------------------------------------------------------------------------------------- FreePortTable frees a port and any linked structures. ----------------------------------------------------------------------------------------*/ void FreePortTable(PPCPortEntryPtr portPtr) { PPCGlobalParamsPtr ppcglobPtr; ppcglobPtr = (PPCGlobalParamsPtr)getGlobal(); DeleteFromQueue(&ppcglobPtr->OpenPortQueue,(unsigned long)portPtr,PointerCompare); if(portPtr->locationInfo) EnQueue(portPtr->locationInfo,&ppcglobPtr->freeLocationQueue); EnQueue(portPtr,&ppcglobPtr->freePortQueue); } void SetPortInformQue(PPCInformPBPtr PB,PPCPortEntryPtr portPtr) { EnQueue(PB,&portPtr->informPBQueue); } /*---------------------------------------------------------------------------------------- GetPortNames fills a buffer with PortInfo. The result of this operation is true if all of the remaining would fit into the specified buffer. False is returned if the reqCount+1 port is found. ----------------------------------------------------------------------------------------*/ Boolean GetPortNames(PPCGlobalParamsPtr ppcglobPtr, PPCPortPtr name, Boolean local, Boolean guestUnChecked, unsigned short index, PortInfoPtr buffPtr, unsigned short reqCount, unsigned short *actCount) { PPCPortEntryPtr portPtr; unsigned short currentIndex = 0; unsigned long offSet =0; *actCount = 0; if (!reqCount) return true; FOREACHELEMENT(portPtr,&ppcglobPtr->OpenPortQueue) { if (index != currentIndex) { if (local || portPtr->networkVisible) { if (WildPortMatch(name, &portPtr->portName)) ++currentIndex; } } else { if (local || portPtr->networkVisible) { if (WildPortMatch(name, &portPtr->portName)) { if (*actCount == reqCount) return false; // we don't have enough space in the buffer buffPtr->filler1 = 0; // Reserved for future expansion. if (local || guestUnChecked) buffPtr->authRequired = false; // Local or Guest is Enabled in user&Groups else buffPtr->authRequired = true; // CopyPortName(&portPtr->portName, &buffPtr->name); buffPtr++; ++*actCount; } } } } return true; } // GetPortNames STATIC Boolean WildPortMatch(PPCPortPtr name1,PPCPortPtr name2) { Boolean wildType = false; Boolean wildName = false; unsigned char len; if ((name1->name[0] == 1) && (name1->name[1] == metaCharacter)) wildName = true; if ((name1->u.portTypeStr[0] == 1) && (name1->u.portTypeStr[1] == metaCharacter)) wildType = true; if (wildName && wildType) return true; // some one wants all the names if (!wildName) { if (!(wildName = CompareByte((Ptr)(name1->name), (Ptr)(name2->name), name1->name[0]+1))) return false; // Name Did not Match } if (!wildType) { if (name1->portKindSelector != name2->portKindSelector) return false; else { if (name1->portKindSelector == ppcByCreatorAndType) len = 8; else len = name1->u.portTypeStr[0]+1; if (!(wildType = CompareByte((Ptr)(name1->u.portTypeStr), (Ptr)(name2->u.portTypeStr), len))) return false; } } if (wildName && wildType) return true; // Both Name and Type Match } // WildPortMatch