[comp.sys.mac.programmer] HELP! -- ATPGetRequest

dsmith@cg-atla.UUCP (Dave Smith) (03/07/91)

I am experiencing some difficulty with my MAC applications usage of the ATP.
I am running System 6.0.3, and developing under MPW C v3.0.
Any help or suggestions that you may have would be greatly appreciated.

The intent of the application is to appear as a "LaserWriter" printer node on
the Chooser, and behave as a printer adhering to the PAP protocol.
The application opens a socket, and registers itself as a "LaserWriter" via a
call to NBPRegister().  This is all well and good.

The printer name shows up in the Chooser as you would expect.
By running "Peek", I can see that the NBP is broadcasting the printer name
accordingly, and responds to a Chooser "=.LaserWriter" query correctly.

However, I am unable to get the application to receive anything via the socket.
My application issues an ATPGetRequest() in ASYNC mode to read incoming
messages, and waits for the "abResult" field to NOT be 1 (which indicates that
the command is completed).

If I query the printer status from another MAC (say, with LaserTalk), my
application does not receive any of these packets.  By running "Peek", I can
see the printer query packets being sent to my node w/ the correct socket #,
but my application never sees these.

This behaves the same if I issue the ATPGetRequest() in SYNC mode too.

Below I've included the C code for 2 routines which I've used;
	ListenerProc()
	RegisterOnNet()
ListenerProc() sets up the ATP initialization stuff, calls RegisterOnNet() to
put name into NBP table, calls ATPGetRequest(), and then waits for the command
to complete.

/*-----------------------------------------------------------------------*
| Procedure:	ListenerProc()
| Description:
|	This routine sets up the ATP interface via calls to ATPLoad(), and
|	PSetSelfSend().  A socket is opened, and the socket is registered as a
|	"LaserWriter" (via call to local procedure RegisterNode()).
|	After the socket is registered, it makes a single ASYNC call to
|	GetATPRequest(), and waits for the abResult field to change from 1
|	(indicating that the command has completed, II-273).
|	When the command has completed, a message is displayed via debugstr(),
|	and the routine returns.
| Input:
|	name	- char * to the printer name
|	type	- char * to the printer type
*------------------------------------------------------------------------*/
ListenerProc()
{
	OSErr stat;
	SetSelfparms enableLoopback;
	AddrBlock rxFilter;
	ATATPRecHandle getRqstHandle;
	char foo[256];

	/*------------------------------------------------*
	| Ensure .ATP & .MPP drivers are loaded & running
	*-------------------------------------------------*/
	stat = ATPLoad();
	if (stat != noErr) {
		pbuflen = sprintf (pbuf, "ATPload returned %d\n", stat);
		pbuf[pbuflen] = 0; debugstr (pbuf);
		exit (-1);
		};

	/*----------------------------------------------------*
	|  Enable loopback for all appleTalk protocol levels.
	*-----------------------------------------------------*/
	enableLoopback.newSelfFlag = 1;
	stat = PSetSelfSend ((MPPPBPtr)&enableLoopback, false);
	if (stat != noErr) {
		pbuflen = sprintf (pbuf, "PSetSelfSend returned %d\n", stat);
		pbuf[pbuflen] = 0; debugstr (pbuf);
		exit (-1);
		};

	/*------------------------------------------------*
	| Open up a listening socket via ATPOpenSocket()
	*-------------------------------------------------*/
	rxFilter.aNet = 0;		/* accept requests from any net */
	rxFilter.aNode = 0;		/*	any node */
	rxFilter.aSocket = 0;		/*	and any socket */
	listenerSocket = 0;		/* ATP assigns socket ID */

	stat = ATPOpenSocket (&rxFilter, &listenerSocket);
	if (stat != noErr) {
		pbuflen = sprintf (pbuf, "ATPOpenSocket returned %d\n", stat);
		pbuf[pbuflen] = 0; debugstr (pbuf);
		exit (-1);
		};

	/*---------------------------------------------------*
	| Register on network.
	| This binds the "listenerSocket" value with the name.
	*-----------------------------------------------------*/
	RegisterOnNet ("thePrinterName", "LaserWriter");

	/*------------------------------------------*
	| Allocate and initialize an ATATPRecHandle
	*-------------------------------------------*/
	getRqstHandle = (ATATPRecHandle)NewHandle (atpSize);
	if (getRqstHandle == (ATATPRecHandle)NULL) {
		pbuflen = sprintf (pbuf, "NewHandle() bombed\n");
		pbuf[pbuflen] = 0; debugstr (pbuf);
		exit (-1);
		};
	(*getRqstHandle)->atpSocket = listenerSocket;
	(*getRqstHandle)->atpDataPtr = foo;
	(*getRqstHandle)->atpReqCount = sizeof(foo);

	/*--------------------------------------------------------------*
	| Call ATPGetRequest in ASYNC mode, and wait for command to
	| complete by monitoring the abResult field until it is not 1.
	*---------------------------------------------------------------*/
	stat = ATPGetRequest (getRqstHandle, true);
	if (stat != noErr) {
		pbuflen = sprintf (pbuf, "ATPGetRequest returned %d\n", stat);
		pbuf[pbuflen] = 0; debugstr (pbuf);
		exit (-1);
		};

        /*---------------------------------------------------------------*
	|
	|   THE FOLLOWING IS THE LOOP THAT WE NEVER SEEM TO GET OUT OF!
	|
        *----------------------------------------------------------------*/
	while ((*getRqstHandle)->abResult == 1)
		;

	/*------------------------------------------------------*
	| If we've gotten here, the ATPGetRequest has completed
	*-------------------------------------------------------*/
	pbuflen = sprintf (pbuf, "ATPGetRequest returned\n");
	pbuf[pbuflen] = 0; debugstr (pbuf);

}	/* ListenerInit */


/*-----------------------------------------------------------------------*
| Procedure:	RegisterOnNet()
| Description:
|	This routine registers the socket "listenerSocket" through
| 	NBPRegister, with the name and type passed in the params.  The
|	zone is "*".
| Input:
|	name	- char * to the printer name
|	type	- char * to the printer type
*------------------------------------------------------------------------*/
static RegisterOnNet (name, type)
	char *name, *type;
{
	char *sp, *dp;
	ATNBPRecHandle NBPRequest;
	OSErr stat;

	/*--------------------------------------------------------------*
	| The name, type, and zone names are inserted into the appropriate
	| fields as Pascal type strings (byte count in byte 0).
	*---------------------------------------------------------------*/
	for (sp = name, dp = &serverName.objStr[1]; *sp; ) {
		*(dp++) = *(sp++);
		};
	serverName.objStr[0] = sp - name;

	for (sp = type, dp = &serverName.typeStr[1]; *sp; ) {
		*(dp++) = *(sp++);
		};
	serverName.typeStr[0] = sp - type;

	serverName.zoneStr[0] = 1;
	serverName.zoneStr[1] = '*';

	/*------------------------------------------------------------------*
	| Allocate an ATNBPRecHandle, and initialize with the EntityName from
	| above, the "listenerSocket" previously opened in ListenerInit(),
	| and a name buffer a global static buffer.
	*-------------------------------------------------------------------*/
	NBPRequest = (ATNBPRecHandle) NewHandle (nbpSize);
	if (NBPRequest == (ATNBPRecHandle)0) {
		pbuflen = sprintf (pbuf, "RegisterOnNet: NewHandle() bombed\n");
		pbuf[pbuflen] = 0; debugstr (pbuf);
		ATPCloseSocket (listenerSocket);
		exit (-1);
		};
	(*NBPRequest)->nbpEntityPtr = &serverName;
	(*NBPRequest)->nbpBufPtr = (Ptr)&NBPUseOnly;
	(*NBPRequest)->nbpBufSize = sizeof(NBPUseOnly);
	(*NBPRequest)->nbpAddress.aSocket = listenerSocket;
	(*NBPRequest)->nbpRetransmitInfo.retransInterval = 11;	/* from MacTutor article */
	(*NBPRequest)->nbpRetransmitInfo.retransCount = 5;		/* from MacTutor article */

	/*-----------------------------------------*
	| Call NBPRegister in SYNCH mode
	*------------------------------------------*/
	stat = NBPRegister (NBPRequest, false);
	if (stat != noErr) {
		pbuflen = sprintf (pbuf, "RegisterOnNet: NBPRegister() returned %d\n", stat);
		pbuf[pbuflen] = 0; debugstr (pbuf);
		ATPCloseSocket (listenerSocket);
		exit (-1);
		};

}	/* RegisterOnNet */
-- 
==========================================================================
  David D. Smith ...!{ulowell,samsung,decvax,ism780c,ima}!cg-atla!dsmith
	"Sssshhhhh, the maestro is decomposing"
						- Gary Larson