home *** CD-ROM | disk | FTP | other *** search
- /* (C) 1992 Stuart Cheshire <cheshire@cs.stanford.edu>
-
- From: Stuart Cheshire <cheshire@cs.stanford.edu>
- Subject: Re: Looking for some sample appletalk ATP code...
- Date: Wed, 2 Sep 92 18:11:08 GMT
-
- In article <1992Sep1.033635.28604@sunb10.cs.uiuc.edu> Alex Bratton,
- bratton@sparc3.cs.uiuc.edu writes:
- >If you have some sample code (ATP) that opens, registers, and dumps some
- >data, I'd really appreciate seeing it. This has been bugging me for a while
- >and I think I need to look at some working code to see what I'm missing.
-
- Here is some sample code, which opens and registers an ATP socket.
- It could be used to form the basis of a server which will accept
- calls from clients and generate responses. (The code to make the
- ATP call from the client is not included -- that is the easy part.)
-
- Notes:
-
- The code is written for Think C 5.
-
- My style of coding is to start with main() at the bottom, and then
- work UP the file calling routines defined above. This is basically
- because I want full type checking but I'm too lazy to write and
- maintain prototypes for every function so I avoid it by defining
- every routine before I call it. I hope this doesn't give you headaches.
-
- Registering the name "xxxx.xx" (net.node) might seem to invite name
- conflicts with other programs, but remember that the type is also
- registered: "xxxx.xx:ATP tester@*" so it WILL be unique.
- */
-
- #include <Traps.h>
- #include <GestaltEqu.h>
- #include <Folders.h>
- #include <AppleTalk.h>
-
- #include "StuTypes.h"
- #include "StuAppleTalk.h"
-
- static unsigned char entity_type[] = "\pATP tester";
-
- // Define structures to describe your requests and responses here.
- typedef struct { char x; } REQUEST;
- typedef struct { char y; } RESPONSE;
-
- typedef struct { MPPParamBlock p; long *myglobals; } myMPPParamBlock;
- typedef struct { ATPParamBlock p; long *myglobals; } myATPParamBlock;
- typedef struct { ATQEntry e; long *myglobals; } myATQEntry;
-
- local OSErr ErrorStatus; // if non-zero, means that the server is not running
- local NamesTableEntry myNTE; // DONT TOUCH THIS -- IT'S USED CONTINUOUSLY BY NBP
- local myATQEntry AppleTalkTransitionQueueEntry;
-
- // name must be 8 characters long
- local void construct_name(AddrBlock addr, unsigned char *name)
- {
- static unsigned char hextable[] = "0123456789ABCDEF";
- name[0] = 7;
- name[1] = hextable[(addr.aNet >> 12) & 0xF];
- name[2] = hextable[(addr.aNet >> 8) & 0xF];
- name[3] = hextable[(addr.aNet >> 4) & 0xF];
- name[4] = hextable[(addr.aNet >> 0) & 0xF];
- name[5] = '.';
- name[6] = hextable[(addr.aNode >> 4) & 0xF];
- name[7] = hextable[(addr.aNode >> 0) & 0xF];
- }
-
- /**************************************************************************************/
-
- // This pair of routines call each other in an infinite ring. When awaitrequest
- // gets an incoming request, it calls acceptrequest to dispatch a reply. After
- // the reply has been sent, control returns back to awaitrequest.
-
- local void awaitrequest(void);
- local void acceptrequest(void)
- {
- static RESPONSE resp;
- static BDSElement bds;
-
- myATPParamBlock *atp_pb;
- long *saveGptr;
- asm { move.l GLOBREG, saveGptr
- move.l a0, atp_pb
- move.l myATPParamBlock.myglobals(a0), GLOBREG
- }
-
- // if (atp_pb->p.ATPioResult) What to do if error?
-
- // Do whatever you want here to prepare your response...
- // Note: This is an INTERRUPT TIME completion routine, which means that you
- // can't allocate memory, call QuickDraw, put up dialogs to interract with
- // the user etc. These things have to be done from your application's main
- // event loop, or by using the notification manager.
-
- bds.buffSize = sizeof(resp);
- bds.buffPtr = (Ptr)&resp;
- bds.dataSize = 0;
- bds.userBytes = 0;
-
- atp_pb->p.ATPioCompletion = (ProcPtr)awaitrequest;
- atp_pb->p.ATPatpFlags = atpEOMvalue;
- atp_pb->p.ATPbdsPointer = (Ptr)&bds;
- atp_pb->p.ATPnumOfBuffs = 1;
- atp_pb->p.ATPbdsSize = 1;
-
- PSendResponse(&atp_pb->p, TRUE);
-
- asm { move.l saveGptr, GLOBREG }
- }
-
- local void awaitrequest(void)
- {
- static REQUEST req;
- myATPParamBlock *atp_pb;
- long *saveGptr;
- asm { move.l GLOBREG, saveGptr
- move.l a0, atp_pb
- move.l myATPParamBlock.myglobals(a0), GLOBREG
- }
- atp_pb->p.ATPioCompletion = (ProcPtr)acceptrequest;
- atp_pb->p.ATPatpSocket = myNTE.nt.nteAddress.aSocket;
- atp_pb->p.ATPreqLength = sizeof(req);
- atp_pb->p.ATPreqPointer = (Ptr)&req;
- PGetRequest(&atp_pb->p, TRUE);
- asm { move.l saveGptr, GLOBREG }
- }
-
- /**************************************************************************************/
-
- // After the name registration below (in AppleTalkStartUp) completes, this routine
- // is called to check the return codes, and if all is well it calls awaitrequest();
-
- local void register_done(void)
- {
- static myATPParamBlock atp;
- long *saveGptr;
- asm { move.l GLOBREG, saveGptr
- move.l myMPPParamBlock.myglobals(a0), GLOBREG
- tst.w ErrorStatus
- bne.s @e
- move.w OFFSET(MPPParamBlock,MPPioResult)(a0), ErrorStatus
- bne.s @e
- clr.w atp.p.ATPioResult
- move.l GLOBREG, atp.myglobals
- lea atp, a0
- bsr awaitrequest
-
- @e move.l saveGptr, GLOBREG
- }
- }
-
- /**************************************************************************************/
-
- // Startup opens the socket and registers the NBP name on the net.
- // ShutDown deregisters the name and closes the socket.
-
- // These may be called many times during the lifetime of the program,
- // for instance when the PowerBook goes to sleep and then wakes up again,
- // when the user unplugs the PowerBook from the network and turns AppleTalk
- // off and then later re-connects it and turns AppleTalk back on, when the
- // Mac is moved from an Ethernet connection to LocalTalk, or to Token Ring,
- // or to ARA dial-up etc.
-
- local OSErr AppleTalkStartUp(void)
- {
- if (ErrorStatus == noErr)
- {
- ATPParamBlock atp;
- static myMPPParamBlock p;
- static AddrBlock zeroaddress;
- static unsigned char regname[8];
-
- atp.ATPatpSocket = 0;
- atp.ATPaddrBlock = zeroaddress;
- ErrorStatus = POpenATPSkt(&atp, FALSE);
- if (ErrorStatus) return(ErrorStatus);
-
- p.p.SETSELF.newSelfFlag = TRUE;
- PSetSelfSend(&p.p, FALSE); // no need to abort if this fails
-
- myNTE.nt.nteAddress.aNet = ABusVars->sysNetNum;
- myNTE.nt.nteAddress.aNode = ABusVars->sysLAPAddr;
- myNTE.nt.nteAddress.aSocket = atp.ATPatpSocket;
-
- construct_name(myNTE.nt.nteAddress, regname);
-
- NBPSetNTE((Ptr)&myNTE,
- (Ptr)regname, (Ptr)"\pMacintosh Authenticator", (Ptr)"\p*",
- myNTE.nt.nteAddress.aSocket);
-
- p.p.MPPioCompletion = (ProcPtr)register_done;
- p.p.NBPinterval = 2;
- p.p.NBPcount = 8;
- p.p.NBPntQElPtr = (Ptr)&myNTE;
- p.p.NBPverifyFlag = TRUE;
- asm { move.l GLOBREG, p.myglobals }
- ErrorStatus = PRegisterName(&p.p, TRUE);
- }
- return(ErrorStatus);
- }
-
- local void AppleTalkShutDown(void)
- {
- if (ErrorStatus == noErr)
- {
- ATPParamBlock atpb;
- MPPParamBlock p;
- atpb.ATPatpSocket = myNTE.nt.nteAddress.aSocket;
- PCloseATPSkt(&atpb, FALSE);
- p.NBPentityPtr = myNTE.nt.entityData;
- PRemoveName(&p, FALSE);
- }
- }
-
- local long ATalkTransition(long selector, myATQEntry *atq, long param)
- {
- long *saveGptr;
- asm { move.l GLOBREG, saveGptr
- move.l atq, a0
- move.l myATQEntry.myglobals(a0), GLOBREG
- cmp.l #ATTransOpen, selector
- bne.s @1
- bsr AppleTalkStartUp
- bra.s @2
- @1 cmp.l #ATTransClose, selector
- bne.s @2
- bsr AppleTalkShutDown
- @2 move.l saveGptr, GLOBREG
- clr.l d0 ; must return zero
- }
- }
-
- /**************************************************************************************/
-
- // This assembler is here because the LAPAddATQ and LAPRmvATQ calls provided by
- // Apple's nAppleTalk library have a bug which crashes the system when you call them
-
- extern pascal OSErr my_LAPAddATQ(ATQEntryPtr theATQEntry);
- extern pascal OSErr my_LAPRmvATQ(ATQEntryPtr theATQEntry);
- local void assembler(void)
- {
- asm {
- extern my_LAPAddATQ:
- move.w #LAddAEQ, d0
- bra.s @1
- extern my_LAPRmvATQ:
- move.w #LRmvAEQ, d0
- @1 move.l 4(sp), a0
- move.l LAPMgrPtr, a1
- move.l (sp)+, (sp)
- jsr 2(a1)
- move.l (sp)+, a0
- move.w d0, (sp)
- jmp (a0)
- }
- }
-
- /**************************************************************************************/
-
- // Init is used ONCE, when the program is first loaded, and
- // Quit would be called ONCE, finally, if the program exits
-
- local OSErr AppleTalkInit(void) // returns non-zero if init failed
- {
- short MPPRefNum;
- SysEnvRec sysenvirons;
- SysEnvirons(1, &sysenvirons);
- ErrorStatus = OpenDriver("\p.MPP", &MPPRefNum);
- if (ErrorStatus) return(ErrorStatus);
- if (sysenvirons.atDrvrVersNum >= 53)
- {
- AppleTalkTransitionQueueEntry.e.CallAddr = (ProcPtr)ATalkTransition;
- asm { move.l GLOBREG, AppleTalkTransitionQueueEntry.myglobals }
- ErrorStatus = my_LAPAddATQ(&AppleTalkTransitionQueueEntry.e);
- if (ErrorStatus) return(ErrorStatus);
- }
- return(AppleTalkStartUp());
- }
-
- local void AppleTalkQuit(void)
- {
- SysEnvRec sysenvirons;
- SysEnvirons(1, &sysenvirons);
- if (sysenvirons.atDrvrVersNum >= 53) my_LAPRmvATQ(&AppleTalkTransitionQueueEntry.e);
- AppleTalkShutDown();
- }
-