/* pap.h, /appletalk/ins, Garth Conboy, 07/12/89 */ /* Copyright (c) 1989 by Pacer Software Inc., La Jolla, CA */ /* GC - Initial coding. GC - (12/11/89): AppleTalk phase II comes to town. GC - (03/24/92): Removed some internal buffering; we now allow Atp to pass up pointers into incoming Ddp buffers. GC - (09/02/92): BufferLength for PapReadComplete should be a long. GC - (11/14/92): Added "usersCookie" field to ActiveJobInfo. *** Make the PVCS source control system happy: $Header$ $Log$ *** PAP specific declarations. */ /* PAP command type bytes: */ #define PapOpenConnectionCommand 1 #define PapOpenConnectionReplyCommand 2 #define PapSendDataCommand 3 #define PapDataCommand 4 #define PapTickleCommand 5 #define PapCloseConnectionCommand 6 #define PapCloseConnectionReplyCommand 7 #define PapSendStatusCommand 8 #define PapStatusReplyCommand 9 /* Error codes for OpenConnectionReply: */ #define PapNoError 0x0000 #define PapPrinterBusy 0xFFFF /* PAP sizes: */ #define PapMaximumDataPacketSize 512 #define PapMaximumStatusSize 255 #define PapMaximumFlowQuantum 8 #define PapMaximumAtpDataBytesToSL 4 /* In "OpenConn" */ /* PAP timer values: */ #define PapOpenConnRequestRetryCount 5 #define PapOpenConnAtpRetrySeconds 2 #define PapTickleSeconds 60 #define PapConnectionSeconds 120 #define PapSendDataRequestRetrySeconds 15 /* The following aren't documented... so we'll take a wild guess... */ #define PapGetStatusRequestRetryCount 5 #define PapGetStatusAtpRetrySeconds 2 /* Offsets within ATP userBytes and data buffer for the various fields of the PAP header: */ #define PapConnectionIdOffset 0 #define PapCommandTypeOffset 1 #define PapEofFlagOffset 2 #define PapSequenceNumberOffset 2 #define PapRespondingSocketOffset 0 #define PapFlowQuantumOffset 1 #define PapWaitTimeOffset 2 #define PapResultOffset 2 #define PapStatusOffset 4 /* How many AtpGetRequest's should we have pending on each active job? These guys will handle incoming Tickle's, Close's, and SendData's. */ #define PapPendingReadsPerJob 2 /* PAP server (service listening) states. For the time being, we assume that our caller is implementing a multi-threaded server and we don't need to play "arbitrating" games. Thus, currently, we use only Blocked and Unblocked. This assumption will never cause a failure (even in a single- threaded server), but will simply implement "luck of the draw" rather than a "whos waiting longest" access to the server. */ typedef enum { PapBlockedState = 1, PapWaitingState, PapArbitratingState, PapUnblockedState, PapCaliforniaState } PapServerState; /* Routine types that will be used as arguments to the various externally visible PAP entry points. */ typedef void far PapNbpRegisterComplete(APPLETALK_ERROR errorCode, long unsigned userData, long serviceListenerRefNum); typedef void far StartJobHandler(APPLETALK_ERROR errorCode, long unsigned userData, long jobRefNum, short workstationQuantum, short waitTime); typedef void far CloseJobHandler(APPLETALK_ERROR errorCode, long unsigned userData, long jobRefNum); typedef void far SendPossibleHandler(long refNum, long unsigned eventContext, long sendWindowSize); typedef void far PapGetStatusComplete(APPLETALK_ERROR errorCode, long unsigned userData, void far *opaqueStatusBuffer, int statusSize); typedef void far PapOpenComplete(APPLETALK_ERROR errorCode, long unsigned userData, long jobRefNum, short serverQuantum, void far *opaqueStatusBuffer, int statusSize); typedef void far PapReadComplete(APPLETALK_ERROR errorCode, long unsigned userData, long jobRefNum, void far *opaqueBuffer, long bufferLength, Boolean eofFlag); typedef void far PapWriteComplete(APPLETALK_ERROR errorCode, long unsigned userData, long jobRefNum); /* The node that ATP and NBP needs to point to (as userData) in order for us (PAP) to be able to continue processing when these lower-level services finish doing our bidding. The various fields are used for various perposes depending on what type of operation is completing. */ typedef struct { void far *completionRoutine; long unsigned userData; long serviceListenerRefNum; Boolean initialRegister; Boolean lookupForStatus; Boolean mustCloseAtpSocket; long socket; long jobRefNum; void far *usersOpaqueStatusBuffer; char responseUserBytes[AtpUserBytesSize]; void far *opaqueResponse; /* "Opaque" desscriptor for below buffer. */ Boolean freeOpaqueResponse; /* Do we have to free the above? */ char responseBuffer[1]; } far *PapCompletionInfo; /* Structure used to hold all pending GetNextJobs for a server. */ typedef struct njTag { struct njTag far *next; /* Next on list. */ long jobRefNum; /* The JobRefNum that will be used for this job when it gets started. */ StartJobHandler *startJobRoutine; /* Routine to call when this job starts. */ long unsigned startJobUserData; /* User data passed to the above. */ CloseJobHandler *closeJobRoutine; /* Routine to call when this job finishes. */ long unsigned closeJobUserData; /* User data passed to the above. */ } far *GetNextJobInfo; /* Structure used to define all currently active jobs (server or workstation). */ typedef struct ajTag { struct ajTag far *next; /* Hash overflow link. */ struct ajTag far *nextForMyServiceListener; /* All jobs active on a single server. */ long jobRefNum; /* My ref num. */ Boolean serverJob; /* Server or workstation? */ long unsigned usersCookie; /* A 32-bit magic cookie that may be associated with the job. */ struct slTag far *ourServiceListener; /* If server job, which service listener do we belong to? */ long ourSocket; /* "Our" side of the connection. */ Boolean closeOurSocket; /* Do we close this socket when we close the job? */ int ourPort; /* The "port" ourAddress is on. */ AppleTalkAddress theirAddress; /* The other side of the link. */ AppleTalkAddress serviceListenerAddress; /* SL address. */ unsigned char connectionId; /* Our connection ID. */ short receiveFlowQuantum; /* Max size we will read from the other side of the connection. */ short sendFlowQuantum; /* Max size we can write to the other side of the connection. */ long unsigned connectionTimerId; /* 2 minute timer. */ long unsigned lastContactTime; /* When did we last hear from the other side? */ Boolean incomingSendDataPending; /* The "other" side has posted a PapRead, we're waiting for our client to do a PapWrite. */ short unsigned incomingSendDataTransactionId; /* Tid of the incoming PapRead. */ Boolean incomingSendDataExactlyOnce; /* Should always be True. */ AppleTalkAddress incomingSendDataSource; /* Where did the most recent SendData come from? It may not be "theirAddress". Sigh. */ short unsigned lastIncomingSequenceNumber; /* Sequence number of the last accepted incoming sendData. */ Boolean writeDataWaiting; /* Our side has done a PapWrite before the other side did a PapRead... data is waiting; this not cleared until the ATP release for the above sendData tranaction completes. */ void far *writeOpaqueBuffer; /* The waiting data "buffer". */ int writeBufferSize; /* Size of waiting buffer. */ Boolean writeEofFlag; /* Is waiting buffer the last one? */ PapWriteComplete *writeCompletionRoutine; /* When we get to write the waiting buffer, who do we call on completion. */ long unsigned writeUserData; /* Passed on to the above. */ Boolean outgoingSendDataPending; /* We have posted a PapRead and are awaiting a response. */ char outgoingSendDataUserBytes[AtpUserBytesSize]; /* ATP user bytes for the response to our sendData. */ short unsigned lastOutgoingSequenceNumber; /* The last sequence number that we used for an outgoing sendData. */ SendPossibleHandler *sendPossibleRoutine; /* send ok routine */ long unsigned sendPossibleUserData; /* user data for above */ CloseJobHandler *closeJobRoutine; /* Routine to call when this job finishes. */ long unsigned closeJobUserData; /* User data passed to the above. */ } far *ActiveJobInfo; /* Structure used to describe an active service listener: */ typedef struct slTag { struct slTag far *next; /* Next on list. */ long serviceListenerRefNum; /* Our ref num. */ int port; /* The port that the service listener is open on. */ long socket; /* The address of the service listener. */ Boolean closeSocket; /* True if we opened the service listener socket. */ PapServerState serverState; /* Our current state. */ short serverFlowQuantum; /* How many packets per data exchange. */ short statusSize; /* How amny bytes of status information do we have. */ char far *statusBuffer; /* Just like it sounds! */ GetNextJobInfo getNextJobList; /* List of pending GetNextJobs. */ ActiveJobInfo activeJobList; /* Currently active jobs to this server list. */ /* Incoming connection event handling is provided by allowing a StartJobHandler to be set on the listener. This will be called after an incoming connection is established. If the connection is not desired, the indicated client will need to do a explicit disconnect. */ StartJobHandler *startJobRoutine; /* Routine to call for an incoming job */ long unsigned startJobUserData; /* User data passed to the above. */ } far *ServiceListenerInfo; /* Structure used to keep track of all pending PapOpenJob calls... */ typedef struct ojTag { struct ojTag far *next; /* Link. */ int port; /* Port that we should open the enventual workstation responding socket on. */ long existingAtpSocket; /* Use existing socket? */ int desiredSocket; /* Desired socket? */ long jobRefNum; /* The job refNum that will be assigned when the job is started. */ AppleTalkAddress serviceListenerAddress; /* After the NBP lookup, what is the SL address? */ unsigned char connectionId; /* The connection ID that will be used. */ short workstationQuantum; /* Supplied workstation flow quantum. */ long unsigned startTime; /* When did the first OpenConn request go out? */ CloseJobHandler *closeJobRoutine; /* Who should be called when this job is eventually closed. */ long unsigned closeJobUserData; /* User data for the above. */ char buffer[PapMaximumAtpDataBytesToSL]; /* Used to store the open connection Atp data while we're processing the open. */ void far *opaqueDataDescriptor; /* "Opaque" data descriptor built for the above buffer. */ Boolean freeOpaqueDataDescriptor; /* Do we need to free the above? */ } far *OpenJobInfo; /* Hash table for finding an active job (by jobRefNum). */ #define NumberOfActiveJobHashBuckets 23 #ifndef InitializeData extern #endif ActiveJobInfo activeJobHashBuckets[NumberOfActiveJobHashBuckets]; /* Head of the service listener list: */ #ifndef InitializeData extern #endif ServiceListenerInfo serviceListenerInfoHead; #ifndef InitializeData extern #endif OpenJobInfo openJobInfoHead; /* Last values for various reference numbers... */ #ifndef InitializeData extern #endif long lastServiceListenerRefNum; #ifndef InitializeData extern #endif long lastJobRefNum; #ifndef InitializeData extern #endif unsigned char lastConnectionId;