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.
Atalk.c
/***************************************************************** |
Program: < ATP Demo > |
File: < Atalk.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 |
/********************************************************************/ |
ATPPBPtr gATPPBPtr; /* the parameter block for GetZoneList call */ |
XPPParmBlkPtr gXPBPBPtr; /* structure for Phase 2 NBP lookups */ |
short xppDriverRefNum; |
Str255 gZoneString, gObjStr, gTypeStr; |
Str32 myName; |
short gMenuItem; |
NamesTableEntry myNTE; |
AddrBlock theBridgeAddress; |
/*****************************************************************/ |
/* |
/* E X T E R N A L S |
/* |
/*****************************************************************/ |
extern SysEnvRec gMac; /* set up by Initialize */ |
extern void ShowError(short index); |
extern void CopyPstr(Ptr pSource, Ptr pDest); |
extern void Terminate(); |
extern void Exit(short message); |
extern qsort (Ptr base, long n, long size, ProcPtr compare); |
#pragma segment Main |
//#pragma segment atlk |
// ***************************************************************** |
// * registerMyName |
// * |
// * registers our nbp name on the network so we can find other |
// * machines that are running our application. |
// ***************************************************************** |
void registerMyName(char socket) |
{ |
MPPParamBlock pb; |
StringHandle userName; |
userName = GetString(-16096); |
myName[0] = 0; |
if (userName != nil) |
{ |
if (*userName[0] != 0) |
BlockMove(*userName,&myName,*userName[0]+1); |
} |
NBPSetNTE((Ptr)&myNTE, &myName, atpEntityFilter, "\p*", socket); |
pb.NBP.interval = 2; |
pb.NBP.count = 3; |
pb.NBP.NBPPtrs.entityPtr = (Ptr)&myNTE; |
pb.NBP.parm.verifyFlag = 1; |
if (PRegisterName(&pb,false) != noErr) |
ShowError(nbpErr); |
} |
// ***************************************************************** |
// * removeMyName |
// * |
// * removes our nbp name from the network. |
// ***************************************************************** |
void removeMyName() |
{ |
MPPParamBlock pb; |
OSErr err; |
pb.NBP.NBPPtrs.entityPtr = (Ptr)&myNTE.nt.entityData; |
err = PRemoveName(&pb, false); |
} |
// ***************************************************************** |
// * myCompare |
// * |
// * this uses stand International Utilites package for sorting |
// ***************************************************************** |
long myCompare (Str255 aStr, Str255 bStr) |
{ |
return ((long)IUCompString(bStr, aStr)); |
} |
// ***************************************************************** |
// * letsSort |
// * |
// * calls a standard C qSort routine compiled with Pascal calling |
// * conventions the 33 is the standard size of a Str32 type, which |
// * is the standard size of an AppleTalk NBP object. |
// ***************************************************************** |
void letsSort (Ptr theBuffPtr, long numZonesGot) |
{ |
qsort(theBuffPtr, numZonesGot, 33, &myCompare); |
} |
// ***************************************************************** |
// * addZonesToBuffer |
// * |
// * |
// ***************************************************************** |
void addZonesToBuffer (Ptr LkUpBuffer, |
Ptr BufferForZoneMenu, |
short NumZonesGot, |
short CurrentTotal) |
{ |
char curLength; |
long index; |
short i; |
index = 0; |
curLength = 0; |
for (i=CurrentTotal;i<=(NumZonesGot + CurrentTotal) && (i < maxZones);++i) |
{ |
curLength = *(LkUpBuffer + index); |
BlockMove((LkUpBuffer + index), (BufferForZoneMenu + (i * 33)), 33); |
index = index + curLength + 1; |
} |
} |
// ***************************************************************** |
// * parseItemsAddToMenu |
// * |
// * this routine adds zone name items to our zones popup menu |
// ***************************************************************** |
void parseItemsAddToMenu (Ptr theBuffPtr, |
MenuHandle zoneMenu, |
short NumZonesGot) |
{ |
long index; |
Str255 tempString; |
short i; |
letsSort(theBuffPtr, NumZonesGot); |
index = 0; |
for (i=0; i<=(NumZonesGot - 1); ++i) |
{ |
BlockMove((theBuffPtr + i * 33), &tempString, 33); |
/* initially insert a blank item so meta-characters aren't used */ |
AppendMenu(zoneMenu, "\p "); |
/* use SetItem so we can display meta-chars in zone names */ |
SetItem(zoneMenu, i + 1, tempString); |
} |
} |
// ***************************************************************** |
// * zonesPresent |
// * |
// * this checks to see if there is a local bridge available |
// ***************************************************************** |
Boolean zonesPresent() |
{ |
short mynode, ignore; |
theBridgeAddress.aNode = 0; |
theBridgeAddress.aNode = GetBridgeAddress(); |
ignore = GetNodeAddress(&mynode, &theBridgeAddress.aNet); |
if (theBridgeAddress.aNode != 0) |
{ |
theBridgeAddress.aSocket = theBridgeSocket; |
return true; |
} |
else |
{ |
CopyPstr("\p*", &gZoneString); |
return false; |
} |
} |
// ***************************************************************** |
// * parseLkupBuffAddToMenu |
// * |
// * this routine takes all the names returned from the nbp lookup |
// * and checks to see if the item is already in the list. If not, |
// * the item is added to the appropriate popup menu. |
// ***************************************************************** |
void parseLkupBuffAddToMenu (Ptr theBuffPtr, |
Ptr bigBuffer, |
MenuHandle lookupMenu, |
short NumGot, |
Boolean doObjects) |
{ |
Str255 menuString, str; |
short i, j, k; |
EntityName abEntity; |
AddrBlock address; |
OSErr resultCode; |
Boolean weHaveDupe; |
k = 1; |
for (i=1; i<=NumGot; ++i) |
{ |
resultCode = NBPExtract(theBuffPtr, NumGot, i, &abEntity, &address); |
if (doObjects) |
BlockMove(&abEntity.objStr,&menuString,abEntity.objStr[0]+1); |
else /* do type strings */ |
BlockMove(&abEntity.typeStr,&menuString,abEntity.typeStr[0]+1); |
weHaveDupe = false; |
j = 0; |
do |
{ |
j = j + 1; |
BlockMove((bigBuffer + (j - 1) * 33), &str, 33); |
if (EqualString(str, menuString, false, true)) |
weHaveDupe = true; |
} |
while ((j <= k) && (weHaveDupe == false)); |
if (weHaveDupe == false) |
{ |
BlockMove(&menuString, (bigBuffer + (k - 1) * 33), 33); |
k = k + 1; |
} |
} |
parseItemsAddToMenu(bigBuffer, lookupMenu, k - 1); |
} |
// ***************************************************************** |
// * LookupNames |
// * |
// * issues an nbp lookup for the desired object, type and zone |
// * the user has specified with the target machine popup menus. |
// ***************************************************************** |
void LookupNames (MenuHandle lookupMenu, |
Boolean doObjects) |
{ |
Str32 NBPObject, NBPType, NBPZone; |
NamesTableEntry lookupEntity; |
Ptr buffer; /* totally gross mondo buffer for returned zones */ |
Ptr bigBuffer; |
MPPParamBlock pbLKP; |
buffer = nil; |
bigBuffer = nil; |
buffer = NewPtr(BigLookupBuffer); |
if (buffer == nil) |
return; |
bigBuffer = NewPtr(250 * 33); |
if (bigBuffer == nil) |
goto Exit; |
CopyPstr("\p=", NBPObject); |
if (!doObjects) |
CopyPstr("\p=", NBPType); |
else |
BlockMove(&gTypeStr,&NBPType,gTypeStr[0]+1); |
if (zonesPresent()) |
BlockMove(&gZoneString,&NBPZone,gZoneString[0]+1); |
else |
CopyPstr("\p*", NBPZone); |
NBPSetEntity((Ptr)&lookupEntity.nt.entityData, NBPObject, NBPType, NBPZone); |
pbLKP.NBP.ioCompletion = nil; |
pbLKP.NBP.interval = 3; |
pbLKP.NBP.count = 3; |
pbLKP.NBPentityPtr = &lookupEntity.nt.entityData; |
pbLKP.NBPretBuffSize = BigLookupBuffer; |
pbLKP.NBPretBuffPtr = buffer; |
pbLKP.NBPmaxToGet = (BigLookupBuffer/sizeof(NTElement)); |
if (PLookupName(&pbLKP, false) == noErr) |
if (pbLKP.NBPnumGotten > 0) |
parseLkupBuffAddToMenu(buffer, bigBuffer, lookupMenu, pbLKP.NBPnumGotten, doObjects); |
Exit: |
if (buffer != nil) |
DisposPtr(buffer); |
if (bigBuffer != nil) |
DisposPtr(bigBuffer); |
} |
// ***************************************************************** |
// * BuildZoneListPhase1 |
// * |
// * Create the list of zones on the network. Find a bridge to talk to , if one is |
// * present, then ask it for zone names. Add the names to the list in the dialog. |
// ***************************************************************** |
void BuildZoneListPhase1(MenuHandle zoneMenu) |
{ |
BDSElement dBDS; /* the BDS for GetZoneList call */ |
ATPPBPtr gATPPBPtr; |
Ptr gZones,sortBuffer; |
long tempUserData; |
short zIndex,zoneCallType; |
Boolean DontGetMoreZones; |
short NumZonesGot, totalZones; |
gATPPBPtr = nil; /* init some important variables*/ |
gZones = nil; |
sortBuffer = nil; |
if (zonesPresent() == false) |
return; |
gATPPBPtr = (ATPPBPtr)NewPtr(sizeof(ATPParamBlock)); |
if (gATPPBPtr == nil) |
goto Exit; |
gZones = NewPtr(kZonesSize); |
if (gZones == nil) |
goto Exit; |
sortBuffer = NewPtr(ZoneBufSize); |
if (sortBuffer == nil) |
goto Exit; |
zoneCallType = kGetZoneList; |
zIndex = 1; |
dBDS.buffSize = kZonesSize; /* set up BDS */ |
dBDS.buffPtr = gZones; |
dBDS.dataSize = 0; |
dBDS.userBytes = 0; |
gATPPBPtr->ATPatpFlags = 0; |
gATPPBPtr->ATPaddrBlock.aNet = theBridgeAddress.aNet; |
gATPPBPtr->ATPaddrBlock.aNode = theBridgeAddress.aNode; /* get node of bridge */ |
gATPPBPtr->ATPaddrBlock.aSocket = kZIPSocket; /* the socket we want */ |
gATPPBPtr->ATPreqLength = 0; |
gATPPBPtr->ATPreqPointer = nil; |
gATPPBPtr->ATPbdsPointer = (Ptr) &dBDS; |
gATPPBPtr->ATPnumOfBuffs = 1; |
gATPPBPtr->ATPtimeOutVal = kATPTimeOutVal; |
gATPPBPtr->ATPretryCount = kATPRetryCount; |
NumZonesGot = 0; |
totalZones = 0; |
DontGetMoreZones = false; |
/* keep going until none left (and we haven't exceeded our buffer size) */ |
while (!DontGetMoreZones && (totalZones <= maxZones)) |
{ |
zIndex += NumZonesGot; /* index count. 1 for start */ |
BlockMove((Ptr) &zoneCallType + 1, (Ptr) &tempUserData, 1L); |
BlockMove((Ptr) &zIndex, (Ptr)&tempUserData + 2, 2L); |
gATPPBPtr->ATPuserData = tempUserData; /* indicate GetZoneList request */ |
if (PSendRequest(gATPPBPtr, false) != noErr) /* send sync request */ |
Exit(DrvrErr); |
tempUserData = dBDS.userBytes; |
BlockMove((Ptr) &tempUserData, (Ptr) &DontGetMoreZones, 1); /* the highbyte will be nonzero if its the last packet of zones */ |
BlockMove((Ptr)&tempUserData + 2, (Ptr) &NumZonesGot, 2); |
addZonesToBuffer(dBDS.buffPtr,sortBuffer,NumZonesGot,totalZones); |
totalZones += NumZonesGot; |
} |
totalZones = (totalZones <= maxZones) ? totalZones : maxZones; |
parseItemsAddToMenu(sortBuffer,zoneMenu,totalZones); |
Exit: |
if (gATPPBPtr != nil) |
DisposePtr((Ptr)gATPPBPtr); |
if (gZones != nil) |
DisposePtr(gZones); |
if (sortBuffer != nil) |
DisposePtr(sortBuffer); |
} /* BuildZoneList */ |
// ***************************************************************** |
// * BuildZoneListPhase2 |
// * |
// * Create the list of zones on the network. Find a bridge to talk to , if one is |
// * present, then ask it for zone names. Add the names to the list in the dialog. |
// ***************************************************************** |
void BuildZoneListPhase2(MenuHandle zoneMenu) |
{ |
Ptr bigBuffer; |
short TotalZones; |
Ptr gZones; /* the data buffer for GetZoneList call */ |
gXPBPBPtr = nil; /* init some important variables*/ |
gZones = nil; |
bigBuffer = nil; |
if (zonesPresent() == false) |
return; |
gXPBPBPtr = (XPPParmBlkPtr)NewPtr(sizeof(XCallParam)); |
if (gXPBPBPtr == nil) |
return; |
gZones = NewPtr(kZonesSize); |
if (gZones == nil) |
goto Exit; |
/* big, ugly mondo buffer to hold complete zone list so we can sort them */ |
bigBuffer = NewPtr(ZoneBufSize); |
if (bigBuffer == nil) |
goto Exit; |
gXPBPBPtr->XCALL.zipInfoField[0] = 0; /* ALWAYS 0 on first call. has state info on subsequent calls */ |
gXPBPBPtr->XCALL.zipInfoField[1] = 0; /* ALWAYS 0 on first call. has state info on subsequent calls */ |
gXPBPBPtr->XCALL.zipLastFlag = 0; |
gXPBPBPtr->XCALL.ioRefNum = xppDriverRefNum; |
gXPBPBPtr->XCALL.csCode = xCall; |
gXPBPBPtr->XCALL.xppSubCode = zipGetZoneList; |
gXPBPBPtr->XCALL.xppTimeout = kATPTimeOutVal; |
gXPBPBPtr->XCALL.xppRetry = kATPRetryCount; |
gXPBPBPtr->XCALL.zipBuffPtr = (Ptr) gZones; |
TotalZones = 0; |
do |
{ |
if (PBControl((ParmBlkPtr) gXPBPBPtr, false) != noErr) |
Exit(DrvrErr); |
addZonesToBuffer(gZones,bigBuffer,gXPBPBPtr->XCALL.zipNumZones,TotalZones); |
TotalZones = TotalZones + gXPBPBPtr->XCALL.zipNumZones; /* find out how many returned */ |
} while ((gXPBPBPtr->XCALL.zipLastFlag == 0) && (TotalZones <= maxZones)); /* keep going until none left */ |
TotalZones = (TotalZones <= maxZones) ? TotalZones : maxZones; |
parseItemsAddToMenu(bigBuffer,zoneMenu,TotalZones); |
Exit: |
if (gXPBPBPtr != nil) |
DisposPtr((Ptr)gXPBPBPtr); /* get rid of pb block */ |
if (gZones != nil) |
DisposPtr(gZones); /* and buffer */ |
if (bigBuffer != nil) |
DisposPtr(bigBuffer); /* and buffer */ |
} /* BuildZoneList */ |
// ***************************************************************** |
// * GetZones |
// * |
// * checks which version of AppleTalk we are using and then calls |
// * the appropriate routine for building the zone list. |
// ***************************************************************** |
void GetZones(MenuHandle ZoneMenu) |
{ |
if(gMac.atDrvrVersNum > 52) |
BuildZoneListPhase2(ZoneMenu); /* put the stuff into the list */ |
else |
BuildZoneListPhase1(ZoneMenu); /* put the stuff into the list */ |
} |
//#pragma segment Initialize |
// ***************************************************************** |
// * getOurZonePhase2 |
// * |
// * gets our local zone using AppleTalk Phase 2 calls |
// ***************************************************************** |
void getOurZonePhase2() |
{ |
gXPBPBPtr = nil; /* init some important variables*/ |
gZoneString[0] = 0; |
if (zonesPresent() == false) |
return; |
gXPBPBPtr = (XPPParmBlkPtr)NewPtr(sizeof(XCallParam)); |
if (gXPBPBPtr == nil) |
return; |
gXPBPBPtr->XCALL.zipInfoField[0] = 0; /* ALWAYS 0 on first call. has state info on subsequent calls */ |
gXPBPBPtr->XCALL.zipInfoField[1] = 0; /* ALWAYS 0 on first call. has state info on subsequent calls */ |
gXPBPBPtr->XCALL.zipLastFlag = 0; |
gXPBPBPtr->XCALL.ioRefNum = xppDriverRefNum; |
gXPBPBPtr->XCALL.csCode = xCall; |
gXPBPBPtr->XCALL.xppSubCode = zipGetMyZone; |
gXPBPBPtr->XCALL.xppTimeout = kATPTimeOutVal; |
gXPBPBPtr->XCALL.xppRetry = kATPRetryCount; |
gXPBPBPtr->XCALL.zipBuffPtr = (Ptr)&gZoneString; |
if (PBControl((ParmBlkPtr) gXPBPBPtr, false) != noErr) /* send sync control call */ |
Exit(DrvrErr); |
if (gXPBPBPtr != nil) |
DisposPtr((Ptr)gXPBPBPtr); /* get rid of pb block */ |
} |
// ***************************************************************** |
// * getOurZonePhase1 |
// * |
// * gets our local zone using AppleTalk Phase 1 calls |
// ***************************************************************** |
void getOurZonePhase1() |
{ |
BDSElement myZoneBDS; |
ATPParamBlock ZonePB; |
long tempUserData; |
Ptr theBufferPtr; |
char zoneCallType; |
zoneCallType = 7; /*8 for zone list 7 returns my zone */ |
theBufferPtr = nil; |
gZoneString[0] = 0; |
if (zonesPresent() == true) |
{ |
theBufferPtr = NewPtr(33); |
if (theBufferPtr != nil) |
{ |
myZoneBDS.buffSize = 33; |
myZoneBDS.buffPtr = theBufferPtr; |
myZoneBDS.dataSize = 0; |
myZoneBDS.userBytes = 0; |
ZonePB.ATP.atpFlags = 0; |
ZonePB.ATP.ioCompletion = nil; |
ZonePB.ATP.userData = 0;/* ATP user data */ |
ZonePB.ATP.addrBlock = theBridgeAddress; |
ZonePB.ATP.reqLength = 0; |
ZonePB.ATP.reqPointer = nil; |
ZonePB.ATP.bdsPointer = (Ptr)&myZoneBDS; |
ZonePB.ATPnumOfBuffs = 1; |
ZonePB.ATPtimeOutVal = 2; |
ZonePB.ATPretryCount = 3; |
/* 0 this out so bottom three bytes are 0 */ |
tempUserData = 0; |
BlockMove(&zoneCallType, (Ptr)&tempUserData, 1); |
ZonePB.ATP.userData = tempUserData; |
gZoneString[0] = 0; |
if (PSendRequest(&ZonePB, false) == noErr) |
{ |
BlockMove(myZoneBDS.buffPtr, &gZoneString, 33); |
} |
DisposPtr(theBufferPtr); |
} |
} |
} |
// ***************************************************************** |
// * InitAppleTalk |
// * |
// * opens the appropriate AppleTalk drivers |
// ***************************************************************** |
OSErr InitAppleTalk() |
{ |
OSErr err; |
short ref; |
if (gMac.atDrvrVersNum > 52) |
{ |
err = OpenDriver("\p.MPP",&ref); |
if (err != noErr) |
return err; |
err = OpenDriver("\p.XPP",&xppDriverRefNum); |
} |
else |
err = MPPOpen(); |
return err; |
} |
// ***************************************************************** |
// * GetOurZone |
// * |
// * checks which version of AppleTalk we are using and then calls |
// * the appropriate phase 1 or phase 2 call to get the local zone. |
// ***************************************************************** |
void GetOurZone() |
{ |
if(gMac.atDrvrVersNum > 52) |
getOurZonePhase2(); /* put the stuff into the list */ |
else |
getOurZonePhase1(); /* put the stuff into the list */ |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14