Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
ATP.c
/***************************************************************** |
Program: < ATP Demo > |
File: < ATP.c > |
Written by Scott Kuechle |
of <Apple Macintosh Developer Technical Support> |
10/92 SRK created |
8/94 SRK Modified to use a queue of parameter |
blocks. |
Copyright © 1992, 1994 Apple Computer, Inc. |
All rights reserved. |
*****************************************************************/ |
/*****************************************************************/ |
/* I N C L U D E S |
/*****************************************************************/ |
#include "ATP Demo.h" |
#include "ATP Demo.protos" |
/******************************************************************** |
/* G L O B A L V A R I A B L E D E C L A R A T I O N S |
/********************************************************************/ |
char gOurATPSocket; |
Str255 gDataSizeStr; |
Boolean gDoContinuous; |
AddrBlock gTargetAddress; |
myATPParamBlock gOurPB[maxQElements]; |
ourRespBuf gRespBuf[maxQElements]; |
BDSType gBDS[maxQElements]; |
ourReqData gOurReqData[maxQElements]; |
QHdr gAvailQueue; |
QHdr gDoneQueue; |
QHdr gRequestQueue; |
/*****************************************************************/ |
/* |
/* E X T E R N A L S |
/* |
/*****************************************************************/ |
extern void ShowError(short index); |
extern void Exit(short message); |
extern Str255 gZoneString, gObjStr, gTypeStr; |
extern void registerMyName(char socket); |
extern DialogPtr myDialog; |
extern void removeMyName(); |
extern void FatalError(error); |
extern void HiliteSendReqButton (short mode); |
extern void PreCompletion(); |
extern Boolean gReqClockTime,gSingleRequest,gStopRequests; |
extern Handle gTestDataHdl; |
extern long gTestDataSize; |
#pragma segment atp |
// ***************************************************************** |
// * GetASocket |
// * |
// * Opens a socket for us to receive requests - we will accept |
// * requests from any machine. |
// * |
// ***************************************************************** |
Boolean GetASocket(char *socket) |
{ |
ATPParamBlock atp; |
*socket = 0; |
atp.ATP.ioCompletion = nil; |
/* dynamically allocate us a socket */ |
atp.ATP.atpSocket = 0; |
/* accept requests from anyone */ |
atp.ATP.addrBlock.aNet = 0; |
atp.ATP.addrBlock.aNode = 0; |
atp.ATP.addrBlock.aSocket = 0; |
if (POpenATPSkt(&atp,false) == noErr) |
{ |
if (atp.ATP.ioResult == noErr) |
{ |
*socket = atp.ATP.atpSocket; |
return true; |
} |
} |
return false; |
} |
// ***************************************************************** |
// * InitQueues |
// * |
// * initialize our "Available" , "Done" and "Read" queues |
// ***************************************************************** |
void InitQueues() |
{ |
short i; |
long myA5; |
gAvailQueue.qHead = NULL; |
gAvailQueue.qTail = NULL; |
gDoneQueue.qHead = NULL; |
gDoneQueue.qTail = NULL; |
gRequestQueue.qHead = NULL; |
gRequestQueue.qTail = NULL; |
myA5 = *(long *)CurrentA5; |
for (i=0; (i < maxQElements); ++i) |
{ |
gOurPB[i].reqData = (Ptr)&gOurReqData[i]; |
gOurPB[i].respData = (Ptr)&gRespBuf[i]; |
gOurPB[i].bdsPtr = (Ptr)&gBDS[i]; |
gOurPB[i].myA5 = myA5; |
gOurPB[i].u.ATP.ioCompletion = (ProcPtr)&PreCompletion; |
Enqueue((QElemPtr)&gOurPB[i].u,&gAvailQueue); |
} |
} |
// ***************************************************************** |
// * GetQElement |
// * |
// * retrieve a queue element from the specified queue |
// ***************************************************************** |
ATPPBPtr GetQElement(QHdrPtr qHdrPtr) |
{ |
OSErr err; |
QElemPtr qElemPtr; |
CheckDoneQueue(); |
qElemPtr = qHdrPtr->qHead; |
if (qElemPtr != NULL) |
{ |
err = Dequeue((QElemPtr)qElemPtr,qHdrPtr); |
if (err != noErr) |
{ |
return NULL; |
} |
else |
{ |
return (ATPPBPtr)(qElemPtr); |
} |
} |
else |
return NULL; |
} |
// ***************************************************************** |
// * GetOurPBPtr |
// * |
// * Returns a pointer to our custom parameter block |
// ***************************************************************** |
myATPParamBlockPtr GetOurPBPtr(ATPPBPtr atpPBPtr) |
{ |
Ptr p; |
myATPParamBlockPtr myATPPBPtr; |
p = (Ptr)atpPBPtr; |
/* set a pointer to our parameter block, |
which is offset kOurPBNegOffset bytes |
above the standard ATP param block */ |
myATPPBPtr = (myATPParamBlockPtr)(p - kOurPBNegOffset); |
return (myATPPBPtr); |
} |
// ***************************************************************** |
// * SetOurCompletionRoutine |
// * |
// * Sets the "real" completion routine for our async. calls |
// ***************************************************************** |
void SetOurCompletionRoutine(ProcPtr procPtr, |
ATPPBPtr atpPBPtr) |
{ |
myATPParamBlockPtr myATPPBPtr; |
myATPPBPtr = GetOurPBPtr(atpPBPtr); |
myATPPBPtr->ourCompletion = procPtr; |
} |
// ***************************************************************** |
// * SaveFunctionResultCode |
// * |
// * Places the function result code in our pb structure for later |
// * reporting. |
// ***************************************************************** |
void SaveFunctionResultCode(OSErr err, |
ATPPBPtr atpPBPtr) |
{ |
myATPParamBlockPtr myATPPBPtr; |
myATPPBPtr = GetOurPBPtr(atpPBPtr); |
/* save off the function result */ |
myATPPBPtr->functionResult = err; |
/* place pb in "done" queue so we |
can report the error later */ |
Enqueue((QElemPtr)atpPBPtr,&gDoneQueue); |
} |
// ***************************************************************** |
// * doGetRequestIOComp |
// * |
// * Completion routine for our get request call. We get here if |
// * another machine sends us a request with the send request call. |
// ***************************************************************** |
pascal void doGetRequestIOComp(ATPPBPtr atpPBPtr) |
{ |
if (atpPBPtr->ATP.ioResult == noErr) |
/* place parameter block into the "Request" queue */ |
Enqueue((QElemPtr)atpPBPtr,&gRequestQueue); |
else /* some kind of error was returned */ |
/* place parameter block back into the "Done" queue */ |
Enqueue((QElemPtr)atpPBPtr,&gDoneQueue); |
} |
// ***************************************************************** |
// * doGetRequest |
// * |
// * We issue an asynchronous get request call here. It will complete |
// * if a request is received from another machine. |
// ***************************************************************** |
void doGetRequest(ATPPBPtr atpPBPtr, |
char socket, |
short reqLength, |
Ptr reqPointer) |
{ |
OSErr err; |
SetOurCompletionRoutine((ProcPtr)&doGetRequestIOComp, |
atpPBPtr); |
atpPBPtr->ATP.atpSocket = socket; |
atpPBPtr->ATP.reqLength = reqLength; |
atpPBPtr->ATP.reqPointer = reqPointer; |
err = PGetRequest(atpPBPtr,true); |
if (err != noErr) |
{ |
SaveFunctionResultCode(err, |
atpPBPtr); |
} |
} |
// ***************************************************************** |
// * doSndRequestIOComp |
// * |
// * This is the completion routine for our send request call. It |
// * will get called as soon as a response is received from the target. |
// ***************************************************************** |
pascal void doSndRequestIOComp(ATPPBPtr atpPBPtr) |
{ |
if (atpPBPtr->ATP.ioResult == noErr) |
{ |
/* place parameter block into the "Request" queue */ |
Enqueue((QElemPtr)atpPBPtr,&gRequestQueue); |
} |
else /* we got an error */ |
{ /* place parameter block into the "Done" queue */ |
Enqueue((QElemPtr)atpPBPtr,&gDoneQueue); |
} |
} |
// ***************************************************************** |
// * doSndRequest |
// * |
// * This is our send request call. We send a request to the target, |
// * as specified in the popup menu. The call completes when a |
// * response is received back. |
// ***************************************************************** |
void doSndRequest(ATPPBPtr atpPBPtr, |
AddrBlock address, |
char socket, |
Ptr bdsPtr, |
short reqLength, |
Ptr reqPointer, |
char numOfBuffs) |
{ |
OSErr err; |
SetOurCompletionRoutine((ProcPtr)&doSndRequestIOComp, |
atpPBPtr); |
atpPBPtr->SREQ.atpSocket = socket; |
atpPBPtr->SREQ.addrBlock.aNet = address.aNet; |
atpPBPtr->SREQ.addrBlock.aNode = address.aNode; |
atpPBPtr->SREQ.addrBlock.aSocket = address.aSocket; |
atpPBPtr->SREQ.reqLength = reqLength; |
atpPBPtr->SREQ.reqPointer = reqPointer; |
atpPBPtr->SREQ.bdsPointer = bdsPtr; |
atpPBPtr->SREQ.atpFlags = atpEOMvalue + atpSendChkvalue; |
atpPBPtr->SREQ.timeOutVal = kATPTimeOutVal; |
atpPBPtr->SREQ.retryCount = kATPRetryCount; |
/* number of response datagrams that will be accepted */ |
atpPBPtr->SREQ.filler = numOfBuffs; |
err = PNSendRequest(atpPBPtr,true); |
if (err != noErr) |
{ |
SaveFunctionResultCode(err, |
atpPBPtr); |
} |
} |
// ***************************************************************** |
// * SendOurResponseData |
// * |
// ***************************************************************** |
void SendOurResponseData(ATPPBPtr atpPBPtr) |
{ |
char reqCode; |
BDSPtr bdsPtr; |
myATPParamBlockPtr myATPBPtr; |
short nElements; |
reqCode = *(atpPBPtr->ATP.reqPointer); |
switch( reqCode ) |
{ |
case kSendTime: |
myATPBPtr = GetOurPBPtr(atpPBPtr); |
bdsPtr = (BDSPtr)myATPBPtr->bdsPtr; |
GetClockTime(myATPBPtr->respData); |
nElements = BuildBDS(myATPBPtr->respData, |
myATPBPtr->bdsPtr, |
4); |
doSendResponse(atpPBPtr, |
gOurATPSocket, |
(Ptr)bdsPtr, |
nElements, |
nElements); |
break; |
case kSendData: |
myATPBPtr = GetOurPBPtr(atpPBPtr); |
bdsPtr = (BDSPtr)myATPBPtr->bdsPtr; |
/* copy "data" from our resource into our buffer */ |
HLock(gTestDataHdl); |
BlockMove(*gTestDataHdl, |
myATPBPtr->respData, |
gTestDataSize); |
/* fill the BDS with our "data" */ |
nElements = BuildBDS(myATPBPtr->respData, |
myATPBPtr->bdsPtr, |
gTestDataSize); |
HUnlock(gTestDataHdl); |
doSendResponse(atpPBPtr, |
gOurATPSocket, |
(Ptr)bdsPtr, |
nElements, |
nElements); |
break; |
} |
} |
// ***************************************************************** |
// * doSendResponseIOComp |
// * |
// * completion routine for our send response call. |
// ***************************************************************** |
pascal void doSendResponseIOComp(ATPPBPtr atpPBPtr) |
{ |
myATPParamBlockPtr myATPPBPtr; |
if (atpPBPtr->ATP.ioResult == noErr) |
{ |
myATPPBPtr = GetOurPBPtr(atpPBPtr); |
/* our response was sent, so issue another async. GetRequest |
so that we may receive another request */ |
doGetRequest(atpPBPtr, |
gOurATPSocket, |
sizeof(struct ourReqData), |
myATPPBPtr->reqData); |
} |
else |
{ |
/* place parameter block back into the "Done" queue */ |
Enqueue((QElemPtr)atpPBPtr,&gDoneQueue); |
} |
} |
// ***************************************************************** |
// * doSendResponse |
// * |
// * We send a response back to the requestor in this routine. |
// ***************************************************************** |
void doSendResponse(ATPPBPtr atpPBPtr, |
char socket, |
Ptr bdsPtr, |
char numOfBuffs, |
char bdsSize) |
{ |
OSErr err; |
SetOurCompletionRoutine((ProcPtr)&doSendResponseIOComp, |
atpPBPtr); |
atpPBPtr->ATP.atpSocket = socket; |
atpPBPtr->ATP.atpFlags = atpEOMvalue + atpSendChkvalue; |
atpPBPtr->ATP.bdsPointer = bdsPtr; |
atpPBPtr->OTH1.u0.numOfBuffs = numOfBuffs; /* num. of resp. bufs being sent */ |
atpPBPtr->OTH2.bdsSize = bdsSize; |
/* note: the "addrBlock" and "transID' fields are already |
set up for us by the just completed GetRequest call */ |
err = PSendResponse(atpPBPtr,true); |
if (err != noErr) |
{ |
SaveFunctionResultCode(err, |
atpPBPtr); |
} |
} |
// ***************************************************************** |
// * closeOurSocket |
// * |
// * close the socket that we used to listen for requests. |
// ***************************************************************** |
void closeOurSocket(char socket) |
{ |
ATPParamBlock pb; |
pb.ATP.atpSocket = socket; |
PCloseATPSkt(&pb,false); |
} |
// ***************************************************************** |
// * CheckDoneQueue |
// * |
// * This routine looks through the "Done" queue for calls that |
// * have completed and reports any errors. |
// ***************************************************************** |
void CheckDoneQueue() |
{ |
QElemPtr qElemPtr; |
ATPPBPtr atpPBPtr; |
myATPParamBlockPtr myATPPBPtr; |
OSErr err; |
/* have any calls completed? */ |
if (gDoneQueue.qHead != nil) |
{ |
qElemPtr = gDoneQueue.qHead; |
err = Dequeue((QElemPtr)qElemPtr,&gDoneQueue); |
if (err == noErr) |
{ |
atpPBPtr = (ATPPBPtr)qElemPtr; |
/* first check function result - was the |
call queued successfully by the driver? */ |
myATPPBPtr = GetOurPBPtr(atpPBPtr); |
if (myATPPBPtr->functionResult != noErr) |
{ |
ShowError(DrvrErr); |
} |
/* now check ioResult - were there any |
errors on this particular call? */ |
else if (atpPBPtr->ATP.ioResult != noErr) |
{ |
ShowATPError(atpPBPtr); |
} |
/* place queue element back into the "available" queue */ |
Enqueue((QElemPtr)qElemPtr,&gAvailQueue); |
} |
} |
} |
// ***************************************************************** |
// * VerifyData |
// * |
// * Verifies that the test data we received matches our own |
// ***************************************************************** |
Boolean VerifyData(myATPParamBlockPtr myATPPbPtr) |
{ |
BDSPtr bds; |
Ptr original,received; |
Boolean valid; |
short i,j; |
valid = true; |
bds = (BDSPtr)myATPPbPtr->bdsPtr; |
HLock(gTestDataHdl); |
original = *gTestDataHdl; |
for (i = 0; |
(i < (myATPPbPtr->u.SREQ.numOfResps)) && (valid == true); |
++i) |
{ |
received = bds->buffPtr; |
for (j = 0; |
(j < bds->dataSize) && (valid == true); |
++j) |
{ |
if (*original != *received) |
valid = false; |
++original; |
++received; |
} |
++bds; /* next BDS Element */ |
} |
HUnlock(gTestDataHdl); |
return valid; |
} |
// ***************************************************************** |
// * CheckRequests |
// * |
// ***************************************************************** |
void CheckRequests() |
{ |
QElemPtr qElemPtr; |
ATPPBPtr atpPBPtr; |
OSErr err; |
short reqCode; |
myATPParamBlockPtr myATPPBPtr; |
Boolean valid; |
short nElements; |
/* have we received any requests? or have any requests that we |
sent completed? */ |
if (gRequestQueue.qHead != nil) |
{ |
qElemPtr = gRequestQueue.qHead; |
err = Dequeue((QElemPtr)qElemPtr,&gRequestQueue); |
if (err == noErr) |
{ |
atpPBPtr = (ATPPBPtr)qElemPtr; |
switch (atpPBPtr->ATP.csCode) |
{ |
case nSendRequest: /* request that we sent */ |
case sendRequest: |
/* did we request clock time or data? */ |
reqCode = *(atpPBPtr->ATP.reqPointer); |
switch (reqCode) |
{ |
case kSendTime: |
/* show the clock time */ |
ShowClockTime(atpPBPtr); |
break; |
case kSendData: |
myATPPBPtr = GetOurPBPtr(atpPBPtr); |
/* insert your routine here to verify data */ |
valid = VerifyData(myATPPBPtr); |
/* if "single request" mode is selected, |
put up a dialog to report status */ |
if (gSingleRequest == true) |
{ |
if (valid == true) |
ShowError(dataIsValid); |
else |
ShowError(dataNotValidErr); |
} |
else /* "continuous" mode, so print status text in window */ |
{ |
if (valid == true) |
ShowStatusString(kTestDataCorrect); |
else |
ShowStatusString(kTestDataIncorrect); |
} |
break; |
} |
/* should we re-issue another request to the target? */ |
if ((gSingleRequest == false) && |
(gStopRequests == false)) |
{ |
myATPPBPtr = GetOurPBPtr(atpPBPtr); |
if (gReqClockTime == true) |
{ |
*(myATPPBPtr->reqData) = kSendTime; |
/* setup response BDS to hold our |
clock/time value */ |
nElements = BuildBDS(myATPPBPtr->respData, |
myATPPBPtr->bdsPtr, |
4); |
} |
else /* send test "data" */ |
{ |
*(myATPPBPtr->reqData) = kSendData; |
nElements = BuildBDS(myATPPBPtr->respData, |
myATPPBPtr->bdsPtr, |
gTestDataSize); |
} |
/* clear status string first */ |
ShowStatusString(kBlankText); |
/* send a request to target machine */ |
doSndRequest(atpPBPtr, |
gTargetAddress, |
gOurATPSocket, |
myATPPBPtr->bdsPtr, |
2, |
myATPPBPtr->reqData, |
nElements); |
} |
else |
{ |
/* place parameter block back into the "Avail" queue */ |
Enqueue((QElemPtr)atpPBPtr,&gAvailQueue); |
} |
break; |
case getRequest: /* request that we received */ |
/* send back either our machines's clock time |
or test "data" */ |
SendOurResponseData(atpPBPtr); |
break; |
} |
} |
} |
} |
// ***************************************************************** |
// * ATPLoop |
// * |
// ***************************************************************** |
void ATPLoop() |
{ |
CheckDoneQueue(); |
CheckRequests(); |
} |
// ***************************************************************** |
// * SendReqToTarget |
// * |
// * issues a request to the selected target machine. The target is |
// * selected using the popup menus. |
// ***************************************************************** |
Boolean SendReqToTarget() |
{ |
MPPParamBlock pbLKP; |
Ptr ntePtr, buffer; |
EntityName abEntity; |
AddrBlock address; |
ATPPBPtr atpPBPtr; |
myATPParamBlockPtr myATPPBPtr; |
Boolean reqSent; |
short nElements; |
reqSent = false; |
ntePtr = nil; |
buffer = nil; |
ntePtr = NewPtr(sizeof(NamesTableEntry)); |
if (ntePtr == nil) |
goto Done; |
buffer = NewPtr(100); |
if (buffer == nil) |
goto Done; |
NBPSetEntity(ntePtr, gObjStr, gTypeStr, gZoneString); |
pbLKP.NBP.interval = 3; |
pbLKP.NBP.count = 3; |
pbLKP.NBP.NBPPtrs.entityPtr = ntePtr; |
pbLKP.NBP.parm.Lookup.retBuffSize = 100; |
pbLKP.NBP.parm.Lookup.retBuffPtr = buffer; |
pbLKP.NBP.parm.Lookup.maxToGet = 1; |
/* first let's try and locate the selected machine on the network */ |
if (PLookupName(&pbLKP, false) == noErr) |
{ /* did we find it? */ |
if ( pbLKP.NBP.parm.Lookup.numGotten > 0) |
{ /* go ahead and send a request to the target */ |
if (NBPExtract(buffer, pbLKP.NBP.parm.Lookup.numGotten, 1, &abEntity, &address) == noErr) |
{ |
/* save the target address */ |
gTargetAddress = address; |
atpPBPtr = GetQElement(&gAvailQueue); |
if (atpPBPtr != NULL) |
{ |
myATPPBPtr = GetOurPBPtr(atpPBPtr); |
/* sending clock time or "data" ? */ |
if (gReqClockTime == true) |
{ |
*(myATPPBPtr->reqData) = kSendTime; |
/* setup response BDS to hold our |
clock/time value */ |
nElements = BuildBDS(myATPPBPtr->respData, |
myATPPBPtr->bdsPtr, |
4); |
} |
else /* send test "data" */ |
{ |
*(myATPPBPtr->reqData) = kSendData; |
nElements = BuildBDS(myATPPBPtr->respData, |
myATPPBPtr->bdsPtr, |
gTestDataSize); |
} |
/* send a request to target machine */ |
doSndRequest(atpPBPtr, |
address, |
gOurATPSocket, |
myATPPBPtr->bdsPtr, |
2, |
myATPPBPtr->reqData, |
nElements); |
reqSent = true; |
} |
} |
} |
else /* target not found */ |
{ |
ShowError(noTargetErr); |
/* re-enable send request button */ |
HiliteSendReqButton (0); |
} |
} |
Done: |
if (ntePtr != nil) |
DisposPtr(ntePtr); |
if (buffer != nil) |
DisposPtr(buffer); |
return reqSent; |
} |
// ***************************************************************** |
// * initializeATP |
// * |
// * allocates parameter blocks for our atp calls, opens a socket |
// * for us to receive requests on, registers our name on the network. |
// ***************************************************************** |
void initializeATP() |
{ |
InitQueues(); |
if (GetASocket(&gOurATPSocket) == true) |
registerMyName(gOurATPSocket); |
else |
FatalError(SktErr); |
} |
// ***************************************************************** |
// * removeATP |
// * |
// * removes our nbp name from the network, closes our atp socket |
// * and de-allocates the memory we used for our parameter blocks. |
// ***************************************************************** |
void removeATP() |
{ |
closeOurSocket(gOurATPSocket); |
removeMyName(); |
} |
// ***************************************************************** |
// * GetClockTime |
// * |
// ***************************************************************** |
void GetClockTime(Ptr buf) |
{ |
unsigned long secs; |
GetDateTime(&secs); |
BlockMove(&secs, buf, 4); |
} |
// ***************************************************************** |
// * ShowStatusString |
// * |
// ***************************************************************** |
void ShowStatusString(StringPtr str) |
{ |
Rect r; |
short kind; |
Handle h; |
GetDItem(myDialog, kStatusText, &kind, &h, &r); |
SetIText(h, str); |
} |
// ***************************************************************** |
// * ShowClockTime |
// * |
// ***************************************************************** |
void ShowClockTime(ATPPBPtr atpPBPtr) |
{ |
Rect r; |
short kind; |
Handle h; |
Str255 str,str2; |
BDSPtr bdsPtr; |
long dateTime; |
GetDItem(myDialog, kClockTime, &kind, &h, &r); |
GetIText(h, str2); |
bdsPtr = (BDSPtr)atpPBPtr->ATP.bdsPointer; |
BlockMove(bdsPtr->buffPtr, &dateTime, 4); |
IUTimeString(dateTime, true, str); |
/* this just checks to see that we're not already displaying this time already */ |
/* flashing text sucks... so sayeth me */ |
if (IUCompString(str,str2) != 0) |
SetIText(h, &str); |
} |
// ***************************************************************** |
// * SetUpATPError |
// * |
// * sets our error string for the desired error code |
// ***************************************************************** |
void SetUpATPError(OSErr err, |
StringPtr displayStr) |
{ |
switch (err) |
{ |
case reqFailed: |
PStrCat("\pSend Request failed. Retry count exceeded.",(Ptr)displayStr); |
break; |
case tooManyReqs: |
PStrCat("\pToo many concurrent requests.",(Ptr)displayStr); |
break; |
case noDataArea: |
PStrCat("\pToo many outstanding ATP calls.",(Ptr)displayStr); |
break; |
case badATPSkt: |
PStrCat("\pBad responding socket.",(Ptr)displayStr); |
break; |
case noRelErr: |
PStrCat("\pNo release received.",(Ptr)displayStr); |
break; |
case badBuffNum: |
PStrCat("\pBad sequence number.",(Ptr)displayStr); |
break; |
case sktClosedErr: |
PStrCat("\pAsynchronous call aborted because socket was closed.",(Ptr)displayStr); |
break; |
default: |
NumToString(err,(Ptr)displayStr); |
} |
} |
// ***************************************************************** |
// * ShowATPError |
// * |
// * If one of our asynchronous atp calls returned an error, the |
// * parameter block gets stuffed into an error OSQueue by the completion |
// * routine. This error queue is checked periodically by this routine. |
// * If the queue is not empty, then we got an error so we display it here |
// * and do any processing of the error that we want. |
// ***************************************************************** |
void ShowATPError(ATPPBPtr atpPBPtr) |
{ |
Rect r; |
short kind; |
Handle h; |
short itemHit; |
Str255 displayStr,theError; |
displayStr[0] = 0; |
/* Use cscode field of the parameter block |
to see which call this error is for*/ |
switch (atpPBPtr->ATP.csCode) |
{ |
case getRequest: |
/* dont report errors if we cancel the call */ |
if (atpPBPtr->ATP.ioResult != reqAborted) |
{ |
CopyPstr("\pGetRequest error. ",&displayStr); |
SetUpATPError(atpPBPtr->ATP.ioResult, &displayStr); |
} |
break; |
case nSendRequest: |
CopyPstr("\pSendRequest error. ",&displayStr); |
SetUpATPError(atpPBPtr->ATP.ioResult, &displayStr); |
/* we got an error so stop sending requests if we are in |
"continuous" mode */ |
if (gDoContinuous == true) |
{ |
GetDItem(myDialog, kReqDataButton, &kind, &h, &r); |
SetCTitle((ControlHandle)h, "\pRequest Data"); |
} |
break; |
case sendResponse: |
CopyPstr("\pSendResponse error. ",&displayStr); |
SetUpATPError(atpPBPtr->ATP.ioResult, &displayStr); |
break; |
default: |
CopyPstr("\pError: ",&displayStr); |
NumToString(atpPBPtr->ATP.ioResult,theError); |
PStrCat(theError,(Ptr)displayStr); |
break; |
} |
/* if we have a message we want to show, put up a dialog |
for the user */ |
if (displayStr[0] != 0) |
{ |
ParamText(displayStr,"\p","\p","\p"); |
itemHit = Alert(rErrorDialog, nil); |
} |
/* re-enable send request button */ |
HiliteSendReqButton (0); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14