/* File: PPCNetwork.c Contains: PPCNetwork related functions. Written by: Sangam, Eric M. Trehus Copyright: © 1989-1992 by Apple Computer, Inc., all rights reserved. Change History (most recent first): <46> 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. <45> 10/4/91 JSM Change PsychoticFarmerOrLater conditionals to TheFuture. <44> 9/29/91 DTY Conditionalize <42> and <43> out of CubeE. <43> 6/10/91 EMT continue code reduction <42> 6/4/91 EMT Roll in StoreAndForward Revisions <41> 1/14/91 EMT Fix race condition in RemoveNetworkConnection. <40> 1/11/91 EMT Fix bug in IPCListPorts. <39> 12/13/90 EMT Remove race condition, add debug code (for debug versions) <38> 11/13/90 EMT Remove redundant error checks in StartNetworkSession and ListNetworkPorts, add noUserNameErr back in (bug fix). <37> 11/8/90 EMT Change key used in scramble, and some error codes. <36> 11/6/90 EMT use STATIC in place of static for link maps <35> 10/30/90 EMT Remove a tiny window of oppertunity <34> 10/24/90 EMT Update error codes <33> 10/11/90 EMT Add conditionals around debug code, remove reference to Assembly language completion routine glue. <32> 9/21/90 EMT Update constants, types, and field names as dictated by PPCToolBox.h <31> 9/14/90 EMT Fix type problem <30> 9/5/90 EMT Remove a conditional that appears to cause 3.0C some problems <29> 9/4/90 EMT Fix priority 1 bug <27+> 9/4/90 EMT Roll in Eric's changes <27> 8/14/90 S Fixed Bug in copying the user name in ProcessInform. <26> 8/6/90 S Bug Fixes. <25> 6/28/90 S To Improve Dynamic allocation of sessions. <23+> 6/1/90 EMT Fix ConnectionRequestCompletion bug that causes failure in RepostConnectionListener when ADSP calls it directly <23> 6/1/90 VC Added the checking of UserFlag after getting the user record. <22> 5/31/90 EMT Added support to clear the originated flag on inform calls, and set it on start. <21> 4/23/90 JSM Add CopyReadBlk routine to copy readBlk to writeHdrBlk and writeBlk in NetIPCParams, fix bug in AuthAcceptCompletion, add AvoidDuplicateCompletion prototype, misc. other code size reductions. <20> 4/10/90 S To Include Checking of PPC Global Flag. <19> 3/20/90 S Fix Bugs Related NetInvisible Ports. <17> 2/28/90 S IPCListPort Info Returned to refelect Guest Selected Icon. <16> 2/27/90 S Fix the Guest Stuff. <15> 2/27/90 S To Make it work with ADSP 1.5(it did not). <14> 2/23/90 S Bug fix <13> 2/20/90 S Fix the actual length in write completion during error condition. <12> 2/20/90 S Bug Fix. <11> 2/13/90 S Bug Fix. <10> 2/8/90 S No Change. <9> 2/5/90 S Changed Error Code For PPCStart(portClosedErr) if user close the port after making start. <8> 2/2/90 S Fixed Crash on noInform Error. <7> 1/30/90 S Changed ErrorCode on Open Completion. <6> 1/30/90 S Bug Fixes for some error codes. <5> 1/26/90 S Fix Writeing > 32k problem & reading 0 byte <4> 1/24/90 S Fix Bug related ppcportclose when the session is being opened. <1.7> 11/8/89 CVC Made changes to fix ppcreject crash <1.6> 11/6/89 KON Fixed typo: SdssReject -> SessReject <1.5> 11/6/89 CVC Fixed a bug in PPCReject <1.4> 10/12/89 CCH Fixed header <¥1.3> 10/12/89 CVC Added access control stuff <1.2> 10/2/89 CVC Fixed a bug in PPCInform call. <1.1> 9/25/89 ss Added support for 'more' in PPCwrite call <1.0> 9/18/89 CVC Adding PPC toolbox for the first time. Old Revision History: 06/05/89 Sangam New Today 07/20/89 Sangam 1.0d2 release today! 08/01/89 Sangam Fixed Bug in End session call 08/02/89 Sangam Fixed ADSP bug with a work around (ReadCompletion & RemoveCompletion) 08/10/89 Sangam Made Change to IPCListPorts calls 08/10/89 Sangam Added userEntry filed for read/write headers 08/10/89 Sangam Fixed a bug in listport call 08/29/89 Sangam Fixed duplicate completion with informPB 08/30/89 Sangam Fixed actualLength filed in Read Calls 09/07/89 Sangam Added Appletalk Phase2 Transition Routines so that Network can be switched dynamicallly. 09/07/89 Sangam Took out the gracefull end for outstanding write. Looks like ADSP will not time out anyway 09/08/89 Sangam Fixed a bug in WriteData (i.e. res->deadLock was set to 1 which prevented completion routines being not called 09/21/89 Sangam Changed GetPortNames interface 09/22/89 Sangam Removed destportName and destlocname from session data structure 09/25/89 Sangam Added support for 'more' in PPCwrite call 09/26/89 Sangam Major changes to support authentication 09/27/89 Sangam Made change to ListRead to take size of PortInfo 10/09/89 Sangam Made changes to support guest login 11/08/89 Sangam Made changes to fix ppcreject crash 1/4/90 Sangam Several Bug Fixes */ #include "PPCCommon.h" #include /*---------------------------------------------------------------------------------------- Constants used only in this file. ----------------------------------------------------------------------------------------*/ #define MaxADSPWrite 0x7FFF // 32767 bytes is the most we should ever write. /*---------------------------------------------------------------------------------------- Prototypes for procedures used only in this file. ----------------------------------------------------------------------------------------*/ STATIC NetIPCParamsPtr GetRemSess(PPCGlobalParamsPtr ppcglobPtr); STATIC void FreeRemSess(NetIPCParamsPtr theSess); STATIC void RemoveCompletion(void); // <44> STATIC void BeginNetworkConnection(NetIPCParamsPtr sessPtr); STATIC void AcceptNetworkConnection(NetIPCParamsPtr sessPtr); STATIC void RemoveNetworkConnection(NetIPCParamsPtr sessPtr,Boolean abortFlag); STATIC void NetLookUpCompletion(void); STATIC void ConnectionEndCompletion(void); STATIC void OpenCompletion(void); STATIC void StartSendCompletion(void); STATIC void StartCommandCompletion(void); STATIC void AuthRespSendCompletion(void); STATIC void AuthAcceptCompletion(void); STATIC void ListSendCompletion(void); STATIC void ListReadCompletion(void); STATIC void ListCommandCompletion(void); STATIC void RespConnectionEndCompletion(void); STATIC void RespOpenCompletion(void); STATIC void RecvSessReqCompletion(void); STATIC void GuestRecCompletion(UserRecPb *uRec); STATIC void UserRecCompletion(UserRecPb *uRec); STATIC void AuthSendCompletion(void); STATIC void AuthRespCompletion(void); STATIC void ProcessInform(NetIPCParams *sessPtr,unsigned short userFlags); STATIC void RespSendCompletion(void); STATIC void ARepostConnectionListener(void); STATIC void RepostConnectionListener(DSPParamBlock *dsp); STATIC void ListWrite(NetIPCParams *sessPtr); STATIC void ListWriteCompletion(void); STATIC void ListRespCompletion(void); STATIC void BeginWriteBlock(NetIPCParamsPtr sessPtr); STATIC void WriteHdrCompletion(void); STATIC void WriteBlockData(NetIPCParamsPtr sessPtr); STATIC void WriteBlockDataCompletion(void); STATIC void CompleteWriteRequest(NetIPCParamsPtr sessPtr,OSErr result); STATIC void BeginReadBlock(NetIPCParamsPtr sessPtr); STATIC void ReadHdrCompletion(void); STATIC void ReadBlockData(NetIPCParamsPtr sessPtr); STATIC void ReadDataCompletion(void); STATIC void ReadData(NetIPCParamsPtr sessPtr); STATIC void CompleteReadRequest(NetIPCParamsPtr sessPtr,OSErr result); STATIC void CopyReadBlk(NetIPCParamsPtr sessPtr); /*---------------------------------------------------------------------------------------- GetRemSess ----------------------------------------------------------------------------------------*/ STATIC NetIPCParamsPtr GetRemSess(PPCGlobalParamsPtr ppcglobPtr) { NetIPCParamsPtr sessPtr; if(sessPtr = ServeQueue(&ppcglobPtr->freeRemSessQueue)) { memset(sessPtr,0,sizeof(NetIPCParams)); // Wipe it clean sessPtr->sessUse = netUse; EnQueue(sessPtr,&ppcglobPtr->RemSessQueue); } return(sessPtr); } /*---------------------------------------------------------------------------------------- FreeRemSess ----------------------------------------------------------------------------------------*/ STATIC void FreeRemSess(NetIPCParamsPtr theSess) { PPCGlobalParamsPtr ppcglobPtr; PPCPortEntryPtr portPtr; ppcglobPtr = (PPCGlobalParamsPtr)getGlobal(); portPtr = theSess->portEntry; DeleteFromQueue(&ppcglobPtr->RemSessQueue,(unsigned long)theSess,PointerCompare); if(portPtr) // <44>if this session belongs to a port. --portPtr->sessCount; // <44> update the port table. theSess->portEntry = (void *)-1; // check for bug! EnQueue(theSess,&ppcglobPtr->freeRemSessQueue); } /*---------------------------------------------------------------------------------------- RemoveNetworkConnection is responsible for scheduling a job to remove the network connection. ----------------------------------------------------------------------------------------*/ STATIC void RemoveNetworkConnection(NetIPCParamsPtr sessPtr,Boolean abortFlag) { PPCGlobalParamsPtr ppcglobPtr; short sr; sr = spl(kNoInterrupts); if(sessPtr->sessState != AwaitAbortComp) // if we arn't already aborting it thenÉ { sessPtr->sessState = AwaitAbortComp; sessPtr->abortFlag = abortFlag; // remember how we are aborting this. ppcglobPtr = (PPCGlobalParamsPtr)getGlobal(); DeleteFromQueue(&ppcglobPtr->RemSessQueue,(unsigned long)sessPtr,PointerCompare); EnQueue(sessPtr,&ppcglobPtr->dspAbortQueue); // place it in the queue of things to do. if(!ppcglobPtr->killSessPtr) // if we are not busy thenÉ { ppcglobPtr->killSessPtr = ServeQueue(&ppcglobPtr->dspAbortQueue); spl(sr); BlockMove((Ptr)&sessPtr->readBlk.dsp,(Ptr)&ppcglobPtr->dspRemovePB,sizeof(DSPParamBlock)); RemoveConnectionEnd(sessPtr->abortFlag, // abort flag (Kill all pending requests) true, (ProcPtr)RemoveCompletion, // Completion Routine &ppcglobPtr->dspRemovePB); return; } } spl(sr); } /*--------------------------------------------------------------------------------------------------- RemoveCompletion ---------------------------------------------------------------------------------------------------*/ STATIC void RemoveCompletion(void) { PPCGlobalParamsPtr ppcglobPtr; PPCPortEntryPtr portPtr; PPCParamBlockPtr PB; NetIPCParams *sessPtr; ppcglobPtr = (PPCGlobalParamsPtr)getGlobal(); sessPtr = ppcglobPtr->killSessPtr; #ifdef DEBUG if(ppcglobPtr->dspRemovePB.ioResult) DebugStr("\pError in removing a network connection"); #endif PB = (PPCParamBlockPtr)sessPtr->endPB; KillReadAndWrite(sessPtr); portPtr = (PPCPortEntryPtr)sessPtr->portEntry; FreeRemSess(sessPtr); if (PB) CompleteWithResult(PB,noErr); else if (portPtr) // Must be a PPCClose operation. CompleteClosePort(portPtr); // Don't change the next two lines or some day you may be sorry!!! ppcglobPtr->killSessPtr = sessPtr = ServeQueue(&ppcglobPtr->dspAbortQueue); if(sessPtr) { BlockMove((Ptr)&sessPtr->readBlk.dsp,(Ptr)&ppcglobPtr->dspRemovePB,sizeof(DSPParamBlock)); RemoveConnectionEnd(sessPtr->abortFlag, true, (ProcPtr)RemoveCompletion, // Completion Routine &ppcglobPtr->dspRemovePB); } } /*---------------------------------------------------------------------------------------- StartNetworkSession ----------------------------------------------------------------------------------------*/ void StartNetworkSession(PPCStartPBPtr startPB, PPCPortEntryPtr portPtr, PPCGlobalParamsPtr ppcglobPtr) { NetIPCParamsPtr sessPtr; if ((startPB->userRefNum) && (!findUserByRef(startPB->userRefNum))) { CompleteWithResult(startPB,noUserRecErr); return; } if (!(sessPtr = GetRemSess(ppcglobPtr))) { CompleteWithResult(startPB,sessTableErr); return; } SetSessionTable((CommonSessionParamsPtr)sessPtr, portPtr, ppcglobPtr); sessPtr->PBPtr = startPB; // First PB for this Session BeginNetworkConnection(sessPtr); } /*---------------------------------------------------------------------------------------- AcceptNetworkSession ----------------------------------------------------------------------------------------*/ void AcceptNetworkSession(PPCAcceptPBPtr acceptPB, NetIPCParamsPtr sessPtr) { IPCAcceptBlkPtr accept; accept = (IPCAcceptBlkPtr)&((sessPtr)->writeBlk.buffer); accept->respType = SessAccept; // Stuff the message sessPtr->PBPtr = acceptPB; AcceptNetworkConnection(sessPtr); } // AcceptNetworkSession /*---------------------------------------------------------------------------------------- RejectNetworkSession ----------------------------------------------------------------------------------------*/ void RejectNetworkSession(PPCRejectPBPtr rejectPB, NetIPCParamsPtr sessPtr) { IPCRejectBlkPtr reject; reject = (IPCRejectBlkPtr)&((sessPtr)->writeBlk.buffer); reject->respType = UserReject; // Stuff the message reject->rejectInfo = rejectPB->rejectInfo; sessPtr->PBPtr = rejectPB; // This will make sure that connection gets closed AcceptNetworkConnection(sessPtr); } // RejectNetworkSession /*---------------------------------------------------------------------------------------- WriteNetworkData Begins to write the clients data immediatly if not already doing so in a previous request, otherwise it just leaves it on the queue for processing later. ----------------------------------------------------------------------------------------*/ void WriteNetworkData(PPCWritePBPtr writePB, NetIPCParamsPtr sessPtr) { short sr; AddWritePB(sessPtr,writePB); sr = spl(kNoInterrupts); if(!sessPtr->writePB) { sessPtr->writePB = GetWritePB(sessPtr); spl(sr); BeginWriteBlock(sessPtr); } else spl(sr); } // WriteNetworkData /*---------------------------------------------------------------------------------------- ReadNetworkData begins to read data immediatly if not already doing so in a previous request, otherwise it just places the read on the queue for later processing. ----------------------------------------------------------------------------------------*/ void ReadNetworkData(PPCReadPBPtr readPB, NetIPCParamsPtr sessPtr) { short sr; AddReadPB(sessPtr,readPB); sr = spl(kNoInterrupts); if(!sessPtr->readPB) { sessPtr->readPB = GetReadPB(sessPtr); spl(sr); BeginReadBlock(sessPtr); } else spl(sr); } // ReadNetworkData /*---------------------------------------------------------------------------------------- EndNetworkSession ----------------------------------------------------------------------------------------*/ void EndNetworkSession(PPCEndPBPtr endPB,NetIPCParamsPtr sessPtr) { sessPtr->endPB = endPB; // Save it for later use. RemoveNetworkConnection(sessPtr,true); } /*---------------------------------------------------------------------------------------- ListNetworkPorts is the entry point for a network Initiated IPCListPorts requests. A session table is gotten, and initialized here. ----------------------------------------------------------------------------------------*/ void ListNetworkPorts(IPCListPortsPBPtr listPB,PPCGlobalParamsPtr ppcglobPtr) { NetIPCParamsPtr sessPtr; PBWriteResPtr res; res =(PBWriteResPtr)(listPB->Reserved); if (sessPtr = GetRemSess(ppcglobPtr)) { SetSessionTable((CommonSessionParamsPtr)sessPtr, nil, ppcglobPtr); sessPtr->PBPtr = listPB; // First PB for this Session sessPtr->portEntry = nil; BeginNetworkConnection(sessPtr); } else CompleteWithResult(listPB,sessTableErr); } // ListNetworkPorts /*---------------------------------------------------------------------------------------- BeginNetworkConnection is where session establishment begins for both IPCListPorts and PPCStart. The first thing that occurs is an NBPLookup to find the destination address. ----------------------------------------------------------------------------------------*/ STATIC void BeginNetworkConnection(NetIPCParamsPtr sessPtr) { IPCListPortsPBPtr listPB = sessPtr->PBPtr; PPCStartPBPtr startPB = sessPtr->PBPtr; LocationNamePtr locationName; if (startPB->csCode == PPCStartCall) locationName = startPB->locationName; else locationName = listPB->locationName; sessPtr->sessState = AwaitLookupResp; NBPSetEntity((unsigned char *)sessPtr->miscData.nbpData.lkupentity, (Ptr)&(locationName->u.nbpEntity.objStr), (Ptr)&(locationName->u.nbpEntity.typeStr), (Ptr)&(locationName->u.nbpEntity.zoneStr)); LookupName((EntityName *)sessPtr->miscData.nbpData.lkupentity, true, // Get Asynchronously (ProcPtr)NetLookUpCompletion, // Completion Routine (unsigned char *)sessPtr->miscData.nbpData.lkupbuf, //lookup bufferptr lkupbufSize, // BufferSize (NBPparms *)&(sessPtr->miscData.nbpData.nbpPB)); } // BeginNetworkConnection /*--------------------------------------------------------------------------------------------------- AcceptNetworkConnection ---------------------------------------------------------------------------------------------------*/ STATIC void AcceptNetworkConnection(NetIPCParamsPtr sessPtr) { sessPtr->sessState = AwaitAcceptSendComp; WriteToConnection(sizeof(IPCAcceptBlk), (char *)&(sessPtr->writeBlk.buffer), 1, // eom 1, // flush true, // Asynchronously (ProcPtr)RespSendCompletion, // Completion Routine (DSPParamBlock *)&(sessPtr->writeBlk.dsp)); } // AcceptNetworkConnection /*---------------------------------------------------------------------------------------- NetLookUpCompletion is chained from BeginNetworkConnection. This is a completion routine for an NBPLookup. We are either trying to perform an IPCListPorts, or a PPCStart. ----------------------------------------------------------------------------------------*/ STATIC void NetLookUpCompletion(void) { NBPparms *nbpPB; NetIPCParamsPtr sessPtr; PPCGlobalParamsPtr ppcglobPtr; PPCStartPBPtr startPB; nbpPB = GetA0(); sessPtr = TOP_OF_RECORD_PTR(nbpPB,NetIPCParams,miscData.nbpData.nbpPB); startPB = (PPCStartPBPtr)sessPtr->PBPtr; // Might be IPCListPorts as well. if (nbpPB->ioResult) { FreeRemSess(sessPtr); CompleteWithResult(startPB,nbpPB->ioResult); } else if (nbpPB->parm.Lookup.numGotten == 0) { FreeRemSess(sessPtr); CompleteWithResult(startPB,noResponseErr); } else { BlockMove((char *)(nbpPB->parm.Lookup.retBuffPtr), (char *)&(sessPtr->destAddr), sizeof(AddrBlock)); ppcglobPtr = (PPCGlobalParamsPtr)getGlobal(); sessPtr->sessState = AwaitDSPInit; CreateConnectionEnd((TRCCB *)&(sessPtr->ce), //ccbPtr nil, // no user Routine DspSendQSize, sessPtr->sendQ, DspRecvQSize, sessPtr->recvQ, sessPtr->attnBuffer, 0, // ADSP picks our socket. ppcglobPtr->dspDrvrRef, true, // Asynhcronous (ProcPtr)ConnectionEndCompletion, // CompletionRoutine &sessPtr->readBlk.dsp); } } // NetLookUpCompletion /*---------------------------------------------------------------------------------------- ConnectionEndCompletion is chained from NetLookUpCompletion. This is a completion routine for a dspInit. A new ADSP Connection Listener has been established. The socket for this connection listener is different than the one where PPCToolBox name is registered. ----------------------------------------------------------------------------------------*/ STATIC void ConnectionEndCompletion(void) { NetIPCParams *sessPtr; PPCStartPBPtr startPB; DSPParamBlock *dsp; dsp = GetA0(); sessPtr= TOP_OF_RECORD_PTR(dsp,NetIPCParams,readBlk.dsp); startPB = sessPtr->PBPtr; if (dsp->ioResult) { CompleteWithResult(startPB,dsp->ioResult); FreeRemSess(sessPtr); } else { sessPtr->sessState = AwaitOpenComp; /* Copy the parameter Block */ CopyReadBlk(sessPtr); OpenConnectionEnd(0, // remoteCID (AddrBlock *)&(sessPtr->destAddr), // Remote Addess (AddrBlock *)&(sessPtr->destAddr), // Filter Addess 0, // Initial sendSeq 0, // Initial sendWindow 0, // attnSendSeq ocRequest, // ocMode true, // Asynchronous (ProcPtr)OpenCompletion, // Completion Routine &sessPtr->readBlk.dsp); } } /*---------------------------------------------------------------------------------------- OpenCompletion is chained from ConnectionEndCompletion. This is a completion routine for a dspOpen call. If all went well, we will have an ADSP connection established at this time. At this point we begin to diverge if we are performing an IPCListPorts, or a PPCStart. If PPCStart, then we transmit an IPCStartBlk structure (See PPCCommon.h for the format). If IPCListPorts, then we transmit an IPCListReqBlk structure. (See PPCCommon.h for the format). ----------------------------------------------------------------------------------------*/ STATIC void OpenCompletion(void) { DSPParamBlock *dsp; NetIPCParams *sessPtr; PPCStartPBPtr startPB; UserEntryPtr uEntry; dsp = GetA0(); sessPtr= TOP_OF_RECORD_PTR(dsp,NetIPCParams,readBlk.dsp); startPB = sessPtr->PBPtr; // in fact may be an IPCListPorts PB. if (dsp->ioResult) { CompleteWithResult(startPB,sessPtr->sessState != AwaitAbortComp? noResponseErr:portClosedErr); sessPtr->PBPtr = NULL; RemoveNetworkConnection(sessPtr,false); return; } CopyReadBlk(sessPtr); /* Copy the parameter Block */ if (startPB->csCode == PPCStartCall) { IPCStartBlkPtr startBlk; // Protocol to begin PPCStart. startBlk = &sessPtr->writeBlk.buffer.buffer.startBlk; if (startPB->userRefNum == 0) startBlk->userName[0] = 0; // No User Name // FIXME -- Can this be done earlier in the game??? else if ((uEntry = findUserByRef(startPB->userRefNum)) == nil) { CompleteWithResult(startPB,noUserRecErr); RemoveNetworkConnection(sessPtr,false); return; } else { // This unscrambles the name we just looked up in the table. scramble (kNameKey, uEntry->name, (char *)(startBlk->userName)); } sessPtr->sessState = AwaitStartSendComp; /* Prepare the header block */ startBlk->reqType = SessRequest; startBlk->userData = startPB->userData; CopyPortName(&sessPtr->portEntry->portName,&startBlk->reqportName); CopyPortName(startPB->portName,&startBlk->destportName); GetLocationName((PPCGlobalParamsPtr)getGlobal(),sessPtr->portEntry,&startBlk->locationName); WriteToConnection(sizeof(IPCStartBlk), (char *)startBlk, 1, // eom 1, // flush true, // Asynchronously (ProcPtr)StartSendCompletion, // Completion Routine (DSPParamBlock *)&(sessPtr->writeBlk.dsp) ); } else if (startPB->csCode == IPCListPortsCall) { IPCListReqBlkPtr list; IPCListPortsPBPtr listPB; sessPtr->sessState = AwaitListSendComp; list = (IPCListReqBlkPtr)&(sessPtr->writeBlk.buffer); listPB = (IPCListPortsPBPtr)(startPB); list->reqType = ListRequest; list->startIndex = listPB->startIndex; list->requestCount = listPB->requestCount; CopyPortName(listPB->portName, &(list->portName)); WriteToConnection(sizeof(IPCListReqBlk), (char *)list, 1, // eom 1, // flush true, // Asynchronously (ProcPtr)ListSendCompletion, // Completion Routine &sessPtr->writeBlk.dsp); } } // OpenCompletion /*---------------------------------------------------------------------------------------- StartSendCompletion is chained from OpenCompletion. This is a completion routine for a dspWrite call. At this point we have written the IPCStartBlk structure. We now prepare to read in the reply. The format of the reply is described in an AuthInfoBlk structure. ----------------------------------------------------------------------------------------*/ STATIC void StartSendCompletion(void) { DSPParamBlock *dsp; NetIPCParams *sessPtr; PPCStartPBPtr startPB; dsp = GetA0(); sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,writeBlk.dsp); if (dsp->ioResult) { if(startPB = sessPtr->PBPtr) { sessPtr->PBPtr = NULL; CompleteWithResult(startPB,dsp->ioResult); } RemoveNetworkConnection(sessPtr,false); } else { if(sessPtr->sessState == AwaitStartSendComp) sessPtr->sessState = AwaitAcceptResp; else sessPtr->sessState = AwaitAuthAccept; ReadFromConnection(sizeof(IPCBufBlk), (char *)&(sessPtr->readBlk.buffer), true, // Asynchronously (ProcPtr)StartCommandCompletion, // completion Routine &sessPtr->readBlk.dsp); } } // StartSendCompletion /*---------------------------------------------------------------------------------------- StartCommandCompletion ----------------------------------------------------------------------------------------*/ STATIC void StartCommandCompletion(void) { DSPParamBlock *dsp; IPCReadBlk *rblk; NetIPCParams *sessPtr; PPCStartPBPtr startPB; IPCAcceptBlk *ablk; AuthInfoBlk *auth1, *auth2; dsp = GetA0(); sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,readBlk.dsp); rblk = &sessPtr->readBlk; startPB = sessPtr->PBPtr; startPB->rejectInfo = nil; // Assume this (If reject, this will change) if(sessPtr->sessState != AwaitAcceptResp && sessPtr->sessState != AwaitAuthAccept) startPB->ioResult = portClosedErr; // Port must be closing. else if(dsp->ioResult) startPB->ioResult = dsp->ioResult; else if(!dsp->u.ioParams.actCount && !dsp->u.ioParams.eom) startPB->ioResult = destPortErr; else { ablk = (IPCAcceptBlk *)&(rblk->buffer); switch (ablk->respType) { case SessAccept: { sessPtr->sessState = DataXferState; sessPtr->PBPtr = NULL; // Nothing in the Que sessPtr->originator = true; // we started this session. startPB->sessRefNum = sessPtr->sessRefNum; CompleteWithResult(startPB,noErr); return; } break; case AuthContinue: { #ifdef DEBUG if(sessPtr->sessState != AwaitAcceptResp) Debugger(); #endif // Server wants the connection to be authenticated auth1 = (AuthInfoBlk *)ablk; if (!(GetAuthInfo((long *)auth1->authInfo, startPB->userRefNum))) startPB->ioResult = noUserRecErr; else { sessPtr->sessState = AwaitAuthRespSend; auth2 =(AuthInfoBlk *)&(sessPtr->writeBlk.buffer); auth2->respType = AuthInfoResp; auth2->authInfo[0] = auth1->authInfo[0]; auth2->authInfo[1] = auth1->authInfo[1]; WriteToConnection(sizeof(AuthInfoBlk), (char *)auth2, 1, // eom 1, // flush true, // Asynchronously (ProcPtr)StartSendCompletion, // Completion Routine (DSPParamBlock *)&(sessPtr->writeBlk.dsp) ); return; } } break; case SessReject: { switch (ablk->rejectInfo) { case notVisible: case noPort: startPB->ioResult = destPortErr; break; case noInforms: startPB->ioResult = noInformErr; break; case noGuestEnabled: startPB->ioResult = guestNotAllowedErr; break; case iacDisabled: startPB->ioResult = userRejectErr; break; case noUserRec: // UnKnown User on target computer. startPB->ioResult = noUserNameErr; break; case AuthFailure: startPB->ioResult = authFailErr; break; } // end switch ablk->rejectInfo startPB->rejectInfo = 0; } break; case UserReject: { startPB->ioResult = userRejectErr; startPB->rejectInfo = ablk->rejectInfo; } break; default: // I don't think we can get here, unless were talking to a non-PPCToolBox. startPB->ioResult = networkErr; break; } // end switch ablk->respType } // End else CompleteWithResult(startPB,startPB->ioResult); sessPtr->PBPtr = NULL; RemoveNetworkConnection(sessPtr,false); } /*---------------------------------------------------------------------------------------- ListSendCompletion is chained from OpenCompletion. ----------------------------------------------------------------------------------------*/ STATIC void ListSendCompletion(void) { DSPParamBlock *dsp; NetIPCParams *sessPtr; IPCListPortsPBPtr listPB; dsp = GetA0(); sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,writeBlk.dsp); listPB = sessPtr->PBPtr; if (dsp->ioResult != noErr) { CompleteWithResult(listPB,dsp->ioResult); sessPtr->PBPtr = NULL; RemoveNetworkConnection(sessPtr,false); } else { sessPtr->sessState = AwaitListRead; ReadFromConnection(sizeof(PortInfoRec) * listPB->requestCount, (Ptr)listPB->bufferPtr, true, // Asynchronously (ProcPtr)ListReadCompletion, // completion Routine &sessPtr->readBlk.dsp); } } // ListSendCompletion /*---------------------------------------------------------------------------------------- ListReadCompletion is chained from ListSendCompletion. ----------------------------------------------------------------------------------------*/ STATIC void ListReadCompletion(void) { DSPParamBlock *dsp; NetIPCParams *sessPtr; IPCListPortsPBPtr listPB; dsp = GetA0(); sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,readBlk.dsp); listPB = sessPtr->PBPtr; if (dsp->ioResult != noErr) { CompleteWithResult(listPB,dsp->ioResult); sessPtr->PBPtr = NULL; RemoveNetworkConnection(sessPtr,false); } else { sessPtr->sessState = AwaitListResp; ReadFromConnection(sizeof(IPCListRespBlk), (char *)&(sessPtr->readBlk.buffer), true, // Asynchronously (ProcPtr)ListCommandCompletion, // completion Routine &sessPtr->readBlk.dsp); } } // ListReadCompletion /*---------------------------------------------------------------------------------------- ListCommandCompletion is chained from ListReadCompletion. ----------------------------------------------------------------------------------------*/ STATIC void ListCommandCompletion(void) { DSPParamBlock *dsp; IPCReadBlk *rblk; NetIPCParams *sessPtr; IPCListPortsPBPtr listPB; IPCListRespBlk *lblk; dsp = GetA0(); rblk = (IPCReadBlk *)dsp; sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,readBlk.dsp); listPB = sessPtr->PBPtr; sessPtr->PBPtr = NULL; if (dsp->ioResult != noErr) listPB->ioResult = dsp->ioResult; else { lblk = (IPCListRespBlk *)&(rblk->buffer); if (lblk->respType == ListResp) { listPB->ioResult = noErr; listPB->actualCount = lblk->actualCount; } else listPB->ioResult = networkErr; } CompleteWithResult(listPB,listPB->ioResult); sessPtr->PBPtr = NULL; RemoveNetworkConnection(sessPtr,false); } // ListCommandCompletion /*---------------------------------------------------------------------------------------- ConnectionRequestCompletion is chained from PPCInit.c:SetUpConnectionListeners, and RepostConnectionListener. On Entry A0 has a pointer to a completed dspCLListen parameter block. This is the point at which session conception begins for PPCToolbox. Either its an IPCListPorts or a PPCStart that initiated the session, and we are here receiving it. ----------------------------------------------------------------------------------------*/ void ConnectionRequestCompletion(void) { DSPParamBlock *dsp; NetIPCParamsPtr sessPtr; TRopenParams *open, *open2; DSPParamBlock *dsp2; PPCGlobalParams *ppcglobPtr; dsp = GetA0(); ppcglobPtr = (PPCGlobalParams *)getGlobal(); if (dsp->ioResult == errAborted) return; // Looks like someone wants to remove listeners else if ((!(ppcglobPtr->allowIncommingRequests)) || (!(sessPtr = GetRemSess(ppcglobPtr)))) RejectConnectionRequest(dsp, true, // Asynchronous (ProcPtr)ARepostConnectionListener ); else { sessPtr->portEntry = 0; // we don't have them yet sessPtr->endPB = 0; // we don't have them yet dsp2 = (DSPParamBlock *)&(sessPtr->writeBlk.dsp); open = (TRopenParams *)&(dsp->u.initParams); /* Copy the Session Parameters */ open2 = (TRopenParams *)&(dsp2->u.initParams); open2->remoteCID = open->remoteCID; open2->remoteAddress.aNet = open->remoteAddress.aNet; open2->remoteAddress.aNode = open->remoteAddress.aNode; open2->remoteAddress.aSocket = open->remoteAddress.aSocket; open2->sendSeq = open->sendSeq; open2->sendWindow = open->sendWindow; open2->attnSendSeq = open->attnSendSeq; sessPtr->sessState = AwaitRecvDSPInit; CreateConnectionEnd((TRCCB *)&(sessPtr->ce), //ccbPtr nil, // no user Routine (we need a routine to release session DspSendQSize, sessPtr->sendQ, DspRecvQSize, sessPtr->recvQ, sessPtr->attnBuffer, ppcglobPtr->adspSocket, ppcglobPtr->dspDrvrRef, true, // Asynhcronous (ProcPtr)RespConnectionEndCompletion, // CompletionRoutine (DSPParamBlock *)&(sessPtr->readBlk.dsp) ); RepostConnectionListener(dsp); } } // ConnectionRequestCompletion /*---------------------------------------------------------------------------------------- RespConnectionEndCompletion is chained from ConnectionRequestCompletion. On Entry A0 contains a pointer to a completed dspInit parameter block that corresponds to the readBlk of our session. In the session table there is a copy of a completed dspCLListen PB in the writeBlk. We use this PB to make the dspOpen since the remoteCID, remoteAddress, sendSeq, sendWindow, and attnSendSeq numbers are already correctly filled in. ----------------------------------------------------------------------------------------*/ STATIC void RespConnectionEndCompletion(void) { DSPParamBlock *dsp; IPCReadBlk *rblk; NetIPCParams *sessPtr; TRopenParams *open; DSPParamBlock *dsp2; dsp = GetA0(); rblk = (IPCReadBlk *)dsp; sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,readBlk.dsp); dsp2 = (DSPParamBlock *)&(sessPtr->writeBlk.dsp); open = (TRopenParams *)&(dsp2->u.initParams); if (dsp->ioResult) // some error occured FreeRemSess(sessPtr); else { sessPtr->sessState = AwaitocAcceptComp; OpenConnectionEnd(open->remoteCID, // remoteCID (AddrBlock *)&(open->remoteAddress), // Remote Addess (AddrBlock *)&(open->remoteAddress), // Filter Addess open->sendSeq, // Initial sendSeq open->sendWindow, // Initial sendWindow open->attnSendSeq, // attnSendSeq ocAccept, // ocMode true, // Asynchronous (ProcPtr)RespOpenCompletion, // Completion Routine (DSPParamBlock *)&(sessPtr->readBlk.dsp) ); } } // RespConnectionEndCompletion /*---------------------------------------------------------------------------------------- RespOpenCompletion is chained from RespConnectionEndCompletion. At this point the ADSP session is fully established. On Entry A0 cointains a pointer to a completed dspOpen parameter block that corresponds to the sessions writeBlk. Read in the first block of data that was written by PPC. ----------------------------------------------------------------------------------------*/ STATIC void RespOpenCompletion(void) { DSPParamBlock *dsp; NetIPCParams *sessPtr; dsp = GetA0(); sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,readBlk.dsp); if (dsp->ioResult) { // some Error occured RemoveNetworkConnection(sessPtr,false); } else { sessPtr->sessState = AwaitRecvSessReq; ReadFromConnection(sizeof(IPCStartBlk), (char *)&(sessPtr->readBlk.buffer), true, // Asynchronously (ProcPtr)RecvSessReqCompletion, // completion Routine &sessPtr->readBlk.dsp); } } // RespOpenCompletion /*---------------------------------------------------------------------------------------- RecvSessReqCompletion is chained from RespOpenCompletion. ----------------------------------------------------------------------------------------*/ STATIC void RecvSessReqCompletion(void) { DSPParamBlock *dsp; IPCReadBlk *rblk; NetIPCParams *sessPtr; IPCStartBlk *sblk; PPCPortEntryPtr portPtr; PPCGlobalParams *ppcglobPtr; IPCAcceptBlkPtr accept; IPCListReqBlkPtr list; unsigned short sr; dsp = GetA0(); ppcglobPtr = (PPCGlobalParams *)getGlobal(); rblk = (IPCReadBlk *)dsp; sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,readBlk.dsp); sblk = (IPCStartBlk *)&(rblk->buffer); accept = (IPCAcceptBlkPtr)&(sessPtr->writeBlk.buffer); if (dsp->ioResult == noErr && dsp->u.ioParams.actCount != 0) { /* Copy the parameter Block */ CopyReadBlk(sessPtr); switch(sblk->reqType) { case SessRequest: if (portPtr = CheckPortName((PPCPortPtr)&(sblk->destportName),ppcglobPtr)) { // We Have a valid Port SetSessionTable((CommonSessionParamsPtr)sessPtr, portPtr, ppcglobPtr); if (portPtr->networkVisible) { // We have Port exported for network access if (portPtr->authRequest) { if (sblk->userName[0] == 0) { sessPtr->miscData.btreeData.guestRec = true; } else sessPtr->miscData.btreeData.guestRec = false; // Requires Authentication sessPtr->sessState = AwaitBtreeComp; if (ppcglobPtr->ugFile.refNum != 0) { getUserRec((UserRecPb *)&(sessPtr->miscData.btreeData), 0, // Key ID (char *)sblk->userName, (ProcPtr)UserRecCompletion, ppcglobPtr->ugFile.refNum); } else { accept->rejectInfo = noUserRec; // Trouble with BTree, deny knowing this user. accept->respType = SessReject; sessPtr->PBPtr = NULL; AcceptNetworkConnection(sessPtr); } return; } else { ProcessInform(sessPtr, 0 ); return; } } else accept->rejectInfo = notVisible; //Only Internal } else accept->rejectInfo = noPort; accept->respType = SessReject; sessPtr->PBPtr = NULL; AcceptNetworkConnection(sessPtr); return; case ListRequest: DeleteFromQueue(&ppcglobPtr->RemSessQueue,(unsigned long)sessPtr,PointerCompare); SetSessionTable((CommonSessionParamsPtr)sessPtr, nil, ppcglobPtr); sessPtr->PBPtr = NULL; sessPtr->portEntry = nil; sessPtr->sessState = AwaitListWriteComp; // For Later Guest Record Checkup list = (IPCListReqBlkPtr)sblk; list->userName[0] =0; sessPtr->miscData.btreeData.guestRec = true; EnQueue(sessPtr,&ppcglobPtr->ListSessQueue); sr = spl(kNoInterrupts); if (!ppcglobPtr->listsessPtr) { // we can process the request ppcglobPtr->listsessPtr = ServeQueue(&ppcglobPtr->ListSessQueue); spl(sr); ppcglobPtr->totalCount = 0; // Total count so far ppcglobPtr->listIndex = list->startIndex; if (ppcglobPtr->ugFile.refNum != 0) { getUserRec((UserRecPb *)&(sessPtr->miscData.btreeData), 0, // Key ID (char *)list->userName, (ProcPtr)GuestRecCompletion, ppcglobPtr->ugFile.refNum); } else { ppcglobPtr->guestUnchecked = false; ListWrite(sessPtr); } } else { spl(sr); } return; } // end switch } // If it is not anyyone of the above abort it any way RemoveNetworkConnection(sessPtr,false); } // RecvSessReqCompletion /*---------------------------------------------------------------------------------------- GuestRecCompletion chained from RecvSessReqCompletion and UserRecCompletion. ----------------------------------------------------------------------------------------*/ STATIC void GuestRecCompletion(UserRecPb *uRec) { NetIPCParams *sessPtr; PPCGlobalParams *ppcglobPtr; sessPtr = TOP_OF_RECORD_PTR(uRec,NetIPCParams,miscData.btreeData); ppcglobPtr = (PPCGlobalParams *)getGlobal(); if (sessPtr->sessState == AwaitListWriteComp) { ppcglobPtr->guestUnchecked = false; if ((uRec->btPb.ioResult == noErr) && (uRec->u.ulRecord.ServerFlags & IACGuestEnabled)) ppcglobPtr->guestUnchecked = true; ListWrite(sessPtr); } } // GuestRecCompletion /*---------------------------------------------------------------------------------------- UserRecCompletion chained from RecvSessReqCompletion. ----------------------------------------------------------------------------------------*/ STATIC void UserRecCompletion(UserRecPb *uRec) { NetIPCParams *sessPtr; IPCAcceptBlkPtr accept; // <44> AuthInfoBlkPtr auth; // <44> sessPtr = TOP_OF_RECORD_PTR(uRec,NetIPCParams,miscData.btreeData); accept = (IPCAcceptBlkPtr)&(sessPtr->writeBlk.buffer); if (sessPtr->sessState != AwaitBtreeComp) { RemoveNetworkConnection(sessPtr,false); } else if (uRec->btPb.ioResult) { accept->rejectInfo = noUserRec; // User name not in my BTree. accept->respType = SessReject; sessPtr->PBPtr = NULL; AcceptNetworkConnection(sessPtr); } else if (uRec->guestRec) { if (uRec->u.ulRecord.ServerFlags & IACGuestEnabled) // Guest is enabled ProcessInform(sessPtr, 0x0001); else { accept->rejectInfo = noGuestEnabled; accept->respType = SessReject; sessPtr->PBPtr = NULL; AcceptNetworkConnection(sessPtr); } } else if (uRec->u.record.UserFlags & 0x0001) { sessPtr->sessState = AwaitRandWrite; auth = (AuthInfoBlkPtr)&(sessPtr->writeBlk.buffer); auth->respType = AuthContinue; // Send AuthInfo auth->authInfo[0] = uRec->random[0]; auth->authInfo[1] = uRec->random[1]; WriteToConnection(sizeof(AuthInfoBlk), (char *)&(sessPtr->writeBlk.buffer), 1, // eom 1, // flush true, // Asynchronously (ProcPtr)AuthSendCompletion, // Completion Routine (DSPParamBlock *)&(sessPtr->writeBlk.dsp)); } else { accept->rejectInfo = iacDisabled; // <44> accept->respType = SessReject; // <44> sessPtr->PBPtr = NULL; // <44> AcceptNetworkConnection(sessPtr); } } /*---------------------------------------------------------------------------------------- AuthSendCompletion is chained from UserRecCompletion. ----------------------------------------------------------------------------------------*/ STATIC void AuthSendCompletion(void) { DSPParamBlock *dsp; NetIPCParams *sessPtr; dsp = GetA0(); sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,writeBlk.dsp); if ((dsp->ioResult) || (sessPtr->sessState != AwaitRandWrite)) { RemoveNetworkConnection(sessPtr,false); } else { sessPtr->sessState = AwaitAuthResp; ReadFromConnection(sizeof(AuthInfoBlk), (char *)&(sessPtr->readBlk.authBuf), true, // Asynchronously (ProcPtr)AuthRespCompletion, // completion Routine &sessPtr->readBlk.dsp); } } // AuthSendCompletion /*---------------------------------------------------------------------------------------- AuthRespCompletion is chained from AuthSendCompletion. ----------------------------------------------------------------------------------------*/ STATIC void AuthRespCompletion(void) { DSPParamBlock *dsp; // <44> AuthInfoBlkPtr auth; // <44> NetIPCParams *sessPtr; IPCReadBlk *rblk; UserRecPbPtr uRec; IPCAcceptBlkPtr accept; dsp = GetA0(); rblk = (IPCReadBlk *)dsp; sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,readBlk.dsp); auth = (AuthInfoBlkPtr)&(sessPtr->readBlk.authBuf); if ((dsp->ioResult) || (sessPtr->sessState != AwaitAuthResp) || (dsp->u.ioParams.actCount == 0) || (auth->respType != AuthInfoResp)) { RemoveNetworkConnection(sessPtr,false); } else { uRec = (UserRecPbPtr)&(sessPtr->miscData.btreeData); if ((auth->authInfo[0] == uRec->encryptedRandom[0]) && (auth->authInfo[1] == uRec->encryptedRandom[1])) { ProcessInform(sessPtr, uRec->u.record.UserFlags); // Authenticated } else { accept = (IPCAcceptBlkPtr)&(sessPtr->writeBlk.buffer); accept->rejectInfo = AuthFailure; accept->respType = SessReject; sessPtr->PBPtr = NULL; AcceptNetworkConnection(sessPtr); } } } /*---------------------------------------------------------------------------------------- ProcessInform gets a pending PPCInform for the associated port and completes it, it also writes back the session accept response. If no Informs are pending for the port, PPC Rejects the request and sets the rejectInfo to noInforms. ----------------------------------------------------------------------------------------*/ STATIC void ProcessInform(NetIPCParams *sessPtr,unsigned short userFlags) { IPCStartBlk *sblk; // <44> PPCPortEntryPtr portPtr; PPCInformPBPtr informPB; IPCAcceptBlkPtr accept; PBWriteResPtr res; sblk = (IPCStartBlk *)&(sessPtr->readBlk.buffer); portPtr = sessPtr->portEntry; accept = (IPCAcceptBlkPtr)&(sessPtr->writeBlk.buffer); if (!(informPB = ServeQueue(&portPtr->informPBQueue))) { accept->respType = SessReject; // <44> Stuff the message accept->rejectInfo = noInforms; // <44> No Oustanding Informs sessPtr->PBPtr = NULL; // <44> AcceptNetworkConnection(sessPtr); return; } informPB->sessRefNum = sessPtr->sessRefNum; informPB->userData = sblk->userData; // <44> informPB->serviceType = ppcServiceRealTime; informPB->requestType = ppcRemoteOrigin; res = (PBWriteResPtr)informPB->Reserved; if (userFlags & 0x0001) res->multiFinder = 0x01; else res->multiFinder = 0x00; if (informPB->portName) CopyPortName(&(sblk->reqportName), informPB->portName); if (informPB->locationName) BlockMove((char *)&(sblk->locationName), (char *)(informPB->locationName), sizeof(LocationNameRec)); if(sblk->userName[0] < 31) { if (sblk->userName[0] == 0) BlockMove("\p",sessPtr->userName,8); else BlockMove((char *)sblk->userName,sessPtr->userName, sblk->userName[0] +1); if (informPB->userName) BlockMove((char *)sblk->userName, (informPB->userName), sblk->userName[0] +1); } sessPtr->originator = false; // We did not originate this session. if (informPB->autoAccept) { sessPtr->PBPtr = informPB; accept->respType = SessAccept; // <44> Stuff the message AcceptNetworkConnection(sessPtr); } else { sessPtr->PBPtr = NULL; sessPtr->sessState = AwaitAcceptReq; CompleteWithResult(informPB,noErr); } } /*---------------------------------------------------------------------------------------- RespSendCompletion is chained from AcceptNetworkConnection. ----------------------------------------------------------------------------------------*/ STATIC void RespSendCompletion(void) { DSPParamBlock *dsp; NetIPCParams *sessPtr; PPCAcceptPBPtr acceptPB; PBWriteResPtr res; OSErr result; dsp = GetA0(); sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,writeBlk.dsp); acceptPB = sessPtr->PBPtr; res =(PBWriteResPtr)(acceptPB->Reserved); if ((acceptPB) && (acceptPB->csCode == PPCRejectCall)) sessPtr->PBPtr = NULL; if ((result=dsp->ioResult) || (acceptPB==nil) || acceptPB->csCode == PPCRejectCall) { sessPtr->PBPtr = NULL; RemoveNetworkConnection(sessPtr,false); } else { sessPtr->sessState = DataXferState; sessPtr->PBPtr = NULL; } if (result && acceptPB && acceptPB->csCode == PPCInformCall) SetPortInformQue((PPCInformPBPtr)acceptPB, sessPtr->portEntry); // Add the PB back else if (acceptPB) CompleteWithResult(acceptPB,result?noSessionErr:noErr); } // RespSendCompletion /*---------------------------------------------------------------------------------------- ARepostConnectionListener is chained from ConnectionRequestCompletion. ----------------------------------------------------------------------------------------*/ STATIC void ARepostConnectionListener(void) { RepostConnectionListener(GetA0()); } STATIC void RepostConnectionListener(DSPParamBlock *dsp) { PPCGlobalParams *ppcglobPtr; ppcglobPtr = (PPCGlobalParams *)getGlobal(); if (ppcglobPtr->allowIncommingRequests) { // Incomming Requests are allowed. if ((ListenConnectionRequest(dsp, true, (ProcPtr)ConnectionRequestCompletion))) { #ifdef DEBUG Debugger(); // should not happen #endif } } } // RepostConnectionListener /*---------------------------------------------------------------------------------------- ListWrite is called to write out the portInfo on an established network connection. ----------------------------------------------------------------------------------------*/ STATIC void ListWrite(NetIPCParams *sessPtr) { IPCReadBlk *rblk; // <44> PPCGlobalParams *ppcglobPtr; IPCListReqBlkPtr list; // <44> Boolean eom; unsigned short actCount=0, remCount, reqCount; ppcglobPtr = (PPCGlobalParams *)getGlobal(); rblk = (IPCReadBlk *)&(sessPtr->readBlk); list = (IPCListReqBlkPtr)&(rblk->buffer); remCount = list->requestCount - ppcglobPtr->totalCount; if (remCount > MaxListEntries) reqCount = MaxListEntries; else reqCount = remCount; eom = true; // assume we are going to exhaust ppcglobPtr->listContinue = false; // assume we are going to exhaust if (!(GetPortNames(ppcglobPtr, &list->portName, // <44> false, // nework request ppcglobPtr->guestUnchecked, // Secure Machine ports or Not ppcglobPtr->listIndex, ppcglobPtr->listBuffer, reqCount, &actCount))) { ppcglobPtr->totalCount += actCount; if (list->requestCount > ppcglobPtr->totalCount) { // User can receive some more eom = false; // we have some more processing ppcglobPtr->listContinue = true; } } else ppcglobPtr->totalCount += actCount; ppcglobPtr->listIndex += actCount; WriteToConnection(sizeof(PortInfoRec) * actCount, (char *)ppcglobPtr->listBuffer, eom, // eom 1, // flush true, // Asynchronously (ProcPtr)ListWriteCompletion, // Completion Routine (DSPParamBlock *)&(sessPtr->writeBlk.dsp)); } // ListWrite /*---------------------------------------------------------------------------------------- ListWriteCompletion is chained from ListWrite. ----------------------------------------------------------------------------------------*/ STATIC void ListWriteCompletion(void) { DSPParamBlock *dsp; IPCReadBlk *rblk; NetIPCParams *sessPtr, *sessPtr1; IPCListReqBlkPtr list; IPCListRespBlkPtr resp; PPCGlobalParams *ppcglobPtr; dsp = GetA0(); ppcglobPtr = (PPCGlobalParams *)getGlobal(); rblk = (IPCReadBlk *)dsp; sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,writeBlk.dsp); list = (IPCListReqBlkPtr)&(rblk->buffer); if (dsp->ioResult) { // some Error occured RemoveNetworkConnection(sessPtr,false); ppcglobPtr->listsessPtr = sessPtr1 = ServeQueue(&ppcglobPtr->ListSessQueue); if (sessPtr1) { // First Lookfor Guest Icon 2/28/90 list = (IPCListReqBlkPtr)&sessPtr1->readBlk.buffer; ppcglobPtr->totalCount = 0; ppcglobPtr->listIndex = list->startIndex; if (ppcglobPtr->ugFile.refNum != 0) { getUserRec((UserRecPb *)&(sessPtr1->miscData.btreeData), 0, // Key ID (char *)list->userName, (ProcPtr)GuestRecCompletion, ppcglobPtr->ugFile.refNum); } else { ppcglobPtr->guestUnchecked = false; ListWrite((NetIPCParams *)(ppcglobPtr->listsessPtr)); } } } else if (ppcglobPtr->listContinue) ListWrite(sessPtr); // need some more writing else { resp = (IPCListRespBlkPtr)&(sessPtr->writeBlk.buffer); resp->respType = ListResp; // Stuff the message resp->actualCount = ppcglobPtr->totalCount; sessPtr->sessState = AwaitListRespComp; WriteToConnection(sizeof(IPCListRespBlk), (char *)&(sessPtr->writeBlk.buffer), 1, // eom 1, // flush true, // Asynchronously (ProcPtr)ListRespCompletion, // Completion Routine &sessPtr->writeBlk.dsp); } } // ListWriteCompletion /*---------------------------------------------------------------------------------------- ListRespCompletion is chained from ListWriteCompletion. We have just completed the writing the response to an IPCListPorts request. If we have another request pending, we begin processing that request here. ----------------------------------------------------------------------------------------*/ STATIC void ListRespCompletion(void) { DSPParamBlock *dsp; IPCReadBlk *rblk; NetIPCParams *sessPtr, *sessPtr1; IPCListReqBlkPtr list; PPCGlobalParams *ppcglobPtr; dsp = GetA0(); ppcglobPtr = (PPCGlobalParams *)getGlobal(); rblk = (IPCReadBlk *)dsp; sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,writeBlk.dsp); list = (IPCListReqBlkPtr)&(rblk->buffer); RemoveNetworkConnection(sessPtr,false); ppcglobPtr->listsessPtr = sessPtr1 = ServeQueue(&ppcglobPtr->ListSessQueue); if (sessPtr1) { // First Lookfor Guest Icon 2/28/90 list = (IPCListReqBlkPtr)&sessPtr1->readBlk.buffer; ppcglobPtr->totalCount = 0; ppcglobPtr->listIndex = list->startIndex; if (ppcglobPtr->ugFile.refNum != 0) { getUserRec((UserRecPb *)&(sessPtr1->miscData.btreeData), 0, // Key ID (char *)list->userName, (ProcPtr)GuestRecCompletion, ppcglobPtr->ugFile.refNum); } else { ppcglobPtr->guestUnchecked = false; ListWrite(ppcglobPtr->listsessPtr); } } } // ListRespCompletion /*---------------------------------------------------------------------------------------- BeginWriteBlock is the first real step in processing of a writePB. It initializes the reserved fields for in the PPCWrite PB, and if we are to write a header, we do so, otherwise we call WriteBlockData to append data onto the current block. ----------------------------------------------------------------------------------------*/ STATIC void BeginWriteBlock(NetIPCParamsPtr sessPtr) { PBWriteResPtr res; // <44> PPCWritePBPtr writePB; // Setup reserved fields in PPCWrite PB to initial values. writePB = sessPtr->writePB; res = (PBWriteResPtr)(writePB->Reserved); res->length = writePB->bufferLength; res->curBufPos = writePB->bufferPtr; if(sessPtr->writeHdr) { IPCHdrBlk *hdr; // <44> Boolean HeaderOnly; // True if client just wants the header only written. // This pisses me off, If I could change the protocol, // I could save 12 bytes, and the following 4 lines of code. hdr = &sessPtr->writeBlk.buffer.buffer.headerBlk; hdr->blockCreator = writePB->blockCreator; hdr->blockType = writePB->blockType; hdr->userData = writePB->userData; HeaderOnly = !writePB->more && !writePB->bufferLength; // usually false! sessPtr->writeHdr = !writePB->more; // for next PPCWrite pb. WriteToConnection(sizeof(IPCHdrBlk), (char *)hdr, HeaderOnly, // eom. HeaderOnly, // flush. true, // Asynchronously (ProcPtr)WriteHdrCompletion, // Completion Routine &sessPtr->writeBlk.dsp); } else WriteBlockData(sessPtr); } /*---------------------------------------------------------------------------------------- WriteHdrCompletion is chained from BeginWriteBlock. Assuming success, and their is data that is to follow the header, we call WrtieBlockData to handle that, otherwise we complete their PPCWrite call. ----------------------------------------------------------------------------------------*/ STATIC void WriteHdrCompletion(void) { DSPParamBlock *dsp; // <44> NetIPCParamsPtr sessPtr; PPCWritePBPtr writePB; dsp = GetA0(); sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,writeBlk.dsp); if (dsp->ioResult) { RemoveNetworkConnection(sessPtr,false); return; } writePB = sessPtr->writePB; if(writePB->bufferLength) WriteBlockData(sessPtr); else CompleteWriteRequest(sessPtr,noErr); } /*---------------------------------------------------------------------------------------- WriteBlockData is responsible for writing the data portion of a PPCBlock. It breaks a block into MaxADSPWrite size chuncks so that ADSP can easily swallow it. ----------------------------------------------------------------------------------------*/ STATIC void WriteBlockData(NetIPCParamsPtr sessPtr) { unsigned short len; unsigned char eom; PBWriteResPtr res; // <44> PPCWritePBPtr writePB; writePB = sessPtr->writePB; res = (PBWriteResPtr)(writePB->Reserved); if (res->length > MaxADSPWrite) { len = MaxADSPWrite; eom =false; } else { len = res->length; // <44> eom = !writePB->more; } sessPtr->writeHdr = !writePB->more; WriteToConnection(len, res->curBufPos, eom, // eom eom, // flush when we finish a block. true, // Asynchronously (ProcPtr)WriteBlockDataCompletion, // Completion Routine &sessPtr->writeBlk.dsp); } /*---------------------------------------------------------------------------------------- WriteBlockDataCompletion is chained from WriteBlockData. If more data for a given PPCWrite is to be written, it calls WriteBlockData, otherwise the Write PB has completed, and it is time to complete that, and process any pending writes. ----------------------------------------------------------------------------------------*/ STATIC void WriteBlockDataCompletion(void) { DSPParamBlock *dsp; // <44> NetIPCParamsPtr sessPtr; PPCWritePBPtr writePB; PBWriteResPtr res; dsp = GetA0(); sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,writeBlk.dsp); writePB = sessPtr->writePB; res = (PBWriteResPtr)(writePB->Reserved); // Update reserved fields to indicate the amount to be written. res->length -= dsp->u.ioParams.actCount; res->curBufPos += dsp->u.ioParams.actCount; writePB->actualLength += dsp->u.ioParams.actCount; if (dsp->ioResult) { RemoveNetworkConnection(sessPtr,false); return; } if(res->length) // <44> if there is more to write { WriteBlockData(sessPtr); } else { CompleteWriteRequest(sessPtr,noErr); } } /*---------------------------------------------------------------------------------------- CompleteWriteRequest is responsible for completing a current write request, and start the next if any are pending. ----------------------------------------------------------------------------------------*/ STATIC void CompleteWriteRequest(NetIPCParamsPtr sessPtr,OSErr result) { short sr; CompleteWithResult(sessPtr->writePB,result); sr = spl(kNoInterrupts); if(sessPtr->writePB = GetWritePB(sessPtr)) { spl(sr); BeginWriteBlock(sessPtr); } else spl(sr); } /*---------------------------------------------------------------------------------------- BeginReadBlock ----------------------------------------------------------------------------------------*/ STATIC void BeginReadBlock(NetIPCParamsPtr sessPtr) { PPCReadPBPtr readPB; PBReadResPtr res; // <44> IPCHdrBlk *hdr; // <44> readPB = sessPtr->readPB; // Setup reserved fields in PPCRead PB to initial values. res = (PBReadResPtr)(readPB->Reserved); res->length = readPB->bufferLength; // Count down from this length. res->curBufPos = readPB->bufferPtr; if(!sessPtr->readMore) // if readHeader. { ReadFromConnection(sizeof(IPCHdrBlk), (Ptr)&sessPtr->readBlk.buffer, true, // Asynchronously (ProcPtr)ReadHdrCompletion, // completion Routine &sessPtr->readBlk.dsp); } else { hdr = &sessPtr->readBlk.buffer.buffer.headerBlk; readPB->blockCreator = hdr->blockCreator; readPB->blockType = hdr->blockType; readPB->userData = hdr->userData; ReadBlockData(sessPtr); } } /*---------------------------------------------------------------------------------------- ReadHdrCompletion is chained from ReadData. ----------------------------------------------------------------------------------------*/ STATIC void ReadHdrCompletion(void) { DSPParamBlock *dsp; // <44> PPCReadPBPtr readPB; NetIPCParamsPtr sessPtr; PBReadResPtr res; // <44> IPCHdrBlk *hdr; dsp = GetA0(); sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,readBlk); readPB = sessPtr->readPB; res = (PBReadResPtr)(readPB->Reserved); readPB->more = sessPtr->readMore = !dsp->u.ioParams.eom; // do we need to read a different header? if (dsp->ioResult || (dsp->u.ioParams.actCount == 0 && dsp->u.ioParams.eom == 0) && (sessPtr->ce.state == sClosing || sessPtr->ce.state == sClosed)) { RemoveNetworkConnection(sessPtr,false); return; } hdr = &sessPtr->readBlk.buffer.buffer.headerBlk; readPB->blockCreator = hdr->blockCreator; readPB->blockType = hdr->blockType; readPB->userData = hdr->userData; if(sessPtr->readMore) ReadBlockData(sessPtr); else CompleteReadRequest(sessPtr,noErr); } /*---------------------------------------------------------------------------------------- ReadBlockData ----------------------------------------------------------------------------------------*/ STATIC void ReadBlockData(NetIPCParamsPtr sessPtr) { PBReadResPtr res; unsigned short len; res = (PBReadResPtr)(sessPtr->readPB->Reserved); len = res->length < MaxADSPWrite?res->length:MaxADSPWrite; if (len) // User Does not want to read zero bytes { ReadFromConnection(len, res->curBufPos, true, // Asynchronously (ProcPtr)ReadDataCompletion, // completion Routine &sessPtr->readBlk.dsp); } else CompleteReadRequest(sessPtr,noErr); } /*---------------------------------------------------------------------------------------- ReadDataCompletion ----------------------------------------------------------------------------------------*/ STATIC void ReadDataCompletion(void) { DSPParamBlock *dsp; // <44> PPCReadPBPtr readPB; NetIPCParamsPtr sessPtr; PBReadResPtr res; dsp = GetA0(); sessPtr = TOP_OF_RECORD_PTR(dsp,NetIPCParams,readBlk); readPB = sessPtr->readPB; res = (PBReadResPtr)(readPB->Reserved); res->length -= dsp->u.ioParams.actCount; // we have this much less to read. res->curBufPos += dsp->u.ioParams.actCount; // next spot to append to clients buffer. readPB->actualLength += dsp->u.ioParams.actCount; // update how much we put into clients buffer. readPB->more = sessPtr->readMore = !dsp->u.ioParams.eom; // do we need to read a different header? if (dsp->ioResult || (dsp->u.ioParams.actCount == 0 && dsp->u.ioParams.eom == 0) && (sessPtr->ce.state == sClosing || sessPtr->ce.state == sClosed)) { RemoveNetworkConnection(sessPtr,false); return; } if(res->length && sessPtr->readMore) // <44> ReadBlockData(sessPtr); else // EOM or clients buffer full. CompleteReadRequest(sessPtr,noErr); } // ReadDataCompletion /*---------------------------------------------------------------------------------------- CompleteReadRequest is responsible for completing a current read request, and start the next if any are pending for this session. ----------------------------------------------------------------------------------------*/ STATIC void CompleteReadRequest(NetIPCParamsPtr sessPtr,OSErr result) { short sr; CompleteWithResult(sessPtr->readPB,result); sr = spl(kNoInterrupts); if(sessPtr->readPB = GetReadPB(sessPtr)) { spl(sr); BeginReadBlock(sessPtr); } else spl(sr); } /*---------------------------------------------------------------------------------------- CopyReadBlk, copies the contents of a DSP parameter block (used for read operations). To a another parameter block (used for writing). ----------------------------------------------------------------------------------------*/ STATIC void CopyReadBlk(NetIPCParamsPtr sessPtr) { BlockMove((char *)&(sessPtr->readBlk.dsp), (char *)&(sessPtr->writeBlk.dsp), sizeof(DSPParamBlock)); } // CopyReadBlk