mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
562 lines
27 KiB
562 lines
27 KiB
/* adsp.h, /atalk-ii/ins, Garth Conboy, 03/29/90 */
|
|
/* Copyright (c) 1989 by Pacer Software Inc., La Jolla, CA */
|
|
|
|
/* GC - Initial coding.
|
|
GC - 09/02/92): Added declaration for AdspGetAnythingHandler().
|
|
GC - (11/15/92): Integrated Nikki's (Microsoft) changes to support
|
|
event handlers. Event handlers are esentially
|
|
"listeners" for various Adsp events: incoming
|
|
connection to a connection listener, connection
|
|
disconnect, incoming data, and incoming attention.
|
|
See the comments above the declaration of
|
|
"IncomingDdpHandler" in "socket.h" to learn more
|
|
than you want to know about event handlers and how
|
|
they work.
|
|
|
|
*** Make the PVCS source control system happy:
|
|
$Header$
|
|
$Log$
|
|
***
|
|
|
|
ADSP specific declarations.
|
|
|
|
*/
|
|
|
|
/* Adsp version. */
|
|
|
|
#define AdspVersionStamp 0x0100
|
|
|
|
/* Adsp field offsets within a Ddp datagram. */
|
|
|
|
#define AdspSourceConnectionIdOffset 0
|
|
#define AdspFirstByteSeqNumOffset 2
|
|
#define AdspThisAttentionSeqNumOffset 2
|
|
#define AdspNextReceiveByteSeqNumOffset 6
|
|
#define AdspNextReceiveAttnSeqNumOffset 6
|
|
#define AdspReceiveWindowSizeOffset 10
|
|
#define AdspReceiveAttentionSizeOffset 10
|
|
#define AdspDescriptorOffset 12
|
|
#define AdspDataOffset 13
|
|
#define AdspVersionStampOffset 13
|
|
#define AdspAttentionCodeOffset 13
|
|
#define AdspAttentionDataOffset 15
|
|
#define AdspDestConnectionIdOffset 15
|
|
#define AdspNextAttentionSeqNumOffset 17
|
|
|
|
/* Bit fields in the Adsp descriptor: */
|
|
|
|
#define AdspControlFlag 0x80
|
|
#define AdspAckRequestFlag 0x40
|
|
#define AdspEndOfMessageFlag 0x20
|
|
#define AdspAttentionFlag 0x10
|
|
|
|
/* Control codes in the Adsp descriptor: */
|
|
|
|
#define AdspControlCodeMask 0x0F
|
|
#define AdspProbeOrAckCode 0
|
|
#define AdspOpenConnectionReqCode 1
|
|
#define AdspOpenConnectionAckCode 2
|
|
#define AdspOpenConnectionReqAndAckCode 3
|
|
#define AdspOpenConnectionDenyCode 4
|
|
#define AdspCloseConnectionCode 5
|
|
#define AdspForwardResetCode 6
|
|
#define AdspForwardResetAckCode 7
|
|
#define AdspRetransmitCode 8
|
|
|
|
/* Data sizes: */
|
|
|
|
#define AdspMaxDataSize 572
|
|
#define AdspMaxAttentionDataSize 570
|
|
|
|
/* Largest allowed send/receive window size. */
|
|
|
|
#define MaxSendReceiveWindowSize 0xFFFF
|
|
#define DefaultSendReceiveWindowSize 4096
|
|
|
|
/* Attention code info: */
|
|
|
|
#define MinAdspAttentionCode 0x0000
|
|
#define MaxAdspAttentionCode 0xEFFF
|
|
|
|
/* How long do we try Open's for? */
|
|
|
|
#define AdspMaxOpenAttempts 10
|
|
#define AdspOpenIntervalSeconds 2
|
|
|
|
/* Connection maintenance timer values: */
|
|
|
|
#define ProbeTimerIntervalSeconds 30
|
|
#define ConnectionDeadSeconds 120
|
|
|
|
/* Retransmit timer values: */
|
|
|
|
#define RetransmitTimerIntervalSeconds 2
|
|
|
|
/* How often do we retransmit attentions? */
|
|
|
|
#define AttentionTimerIntervalSeconds 2
|
|
|
|
/* How often do we retransmit forward resets? */
|
|
|
|
#define ForwardResetTimerIntenvalSecs 2
|
|
|
|
/* How many out of sequence packets do we allow before requesting a
|
|
retransmition. */
|
|
|
|
#define OutOfSequencePacketsMax 3
|
|
|
|
/* Routine type to call when an AdspOpen() completes. */
|
|
|
|
typedef void far AdspOpenCompleteHandler(APPLETALK_ERROR errorCode,
|
|
long unsigned userData,
|
|
long refNum,
|
|
long socket,
|
|
AppleTalkAddress remoteAddress);
|
|
|
|
/* Routine type to call when an Attention comes in. */
|
|
|
|
typedef void far AdspIncomingAttentionRoutine(APPLETALK_ERROR errorCode,
|
|
long unsigned userData,
|
|
long refNum,
|
|
short unsigned attentionCode,
|
|
void far *attentionData,
|
|
int attentionDataSize);
|
|
|
|
/* Routine type to call when a read completes. */
|
|
|
|
typedef void far AdspReceiveHandler(APPLETALK_ERROR errorCode,
|
|
long unsigned userData,
|
|
long refNum,
|
|
void far *opaqueBuffer,
|
|
long bufferSize,
|
|
Boolean endOfMessage);
|
|
|
|
/* Routine type to call when we want to indicate incoming data. */
|
|
|
|
typedef long far AdspReceiveEventHandler(long refNum,
|
|
long unsigned eventContext,
|
|
char far *lookaheadData,
|
|
long lookaheadDataSize,
|
|
Boolean endOfMessage,
|
|
long bytesAvailable);
|
|
|
|
/* Routine type to call when we want to indicate incoming *attention* data. */
|
|
|
|
typedef long far AdspReceiveAttnEventHandler(long refNum,
|
|
long unsigned eventContext,
|
|
char far *lookaheadData,
|
|
long lookaheadDataSize,
|
|
long bytesAvailable);
|
|
|
|
/* Rotuine type to call when the send window goes from zero to non-zero. */
|
|
|
|
typedef void far AdspSendOkayEventHandler(long refNum,
|
|
long unsigned eventContext,
|
|
long sendWindowSize);
|
|
|
|
/* Routine type to call when a GetAynthing (data or attention) completes. */
|
|
|
|
typedef void far AdspGetAnythingHandler(APPLETALK_ERROR errorCode,
|
|
long unsigned userData,
|
|
long refNum,
|
|
Boolean attentionData,
|
|
void far *opaqueBuffer,
|
|
long bufferSize,
|
|
Boolean endOfMessage);
|
|
|
|
/* Routine type to call when a open connection request comes in to a connection
|
|
listener. */
|
|
|
|
typedef void far AdspIncomingOpenRequestHandler(APPLETALK_ERROR errorCode,
|
|
long unsigned userData,
|
|
AppleTalkAddress sourceAddress,
|
|
long listenerRefNum,
|
|
long refNum);
|
|
|
|
/* Event handler type for incoming connection events */
|
|
|
|
typedef void far AdspConnectionEventHandler(long listenerRefNum,
|
|
long unsigned eventContext,
|
|
AppleTalkAddress sourceAddress,
|
|
long refNum);
|
|
|
|
/* Event handler type for incoming disconnect on a connection */
|
|
|
|
typedef void far AdspDisconnectEventHandler(long refNum,
|
|
long unsigned eventContext,
|
|
APPLETALK_ERROR errorCode);
|
|
|
|
/* Routine type to call when we get an Ack to an outgoing forward reset. */
|
|
|
|
typedef void far AdspForwardResetAckHandler(APPLETALK_ERROR errorCode,
|
|
long unsigned userData,
|
|
long refNum);
|
|
|
|
/* Routine type to call when a SendAttention completes. */
|
|
|
|
typedef void far AdspAttentionAckHandler(APPLETALK_ERROR errorCode,
|
|
long unsigned userData,
|
|
long refNum);
|
|
|
|
/* The state of a connection... Closed is used only when we're denying an
|
|
open request and about to make the connection end go away, HalfOpen is
|
|
used during open (before we have an OpenConnectionAck), Open is used
|
|
after we get the Ack. */
|
|
|
|
typedef enum {AdspClosed, AdspHalfOpen, AdspOpen} AdspConnectionState;
|
|
|
|
/* Type fo Adsp Open to perform: */
|
|
|
|
typedef enum {AdspPassiveOpen, AdspActiveOpen} AdspOpenType;
|
|
|
|
/* We don't use circular buffers for the send and receive queues -- we use a
|
|
set of buffer chunks: */
|
|
|
|
typedef struct bcTag { struct bcTag far *next; /* Chunk link */
|
|
long dataSize; /* Size of data (in bytes) */
|
|
Boolean endOfMessage; /* An implied EOM? */
|
|
char data[1]; /* Data block; variable size */
|
|
} far *BufferChunk;
|
|
|
|
typedef struct { long startIndex; /* Index into first chunk of
|
|
valid data -- EOM counts
|
|
as a byte; thus if head->
|
|
size is 10 and head->eom
|
|
is true and startIndex is
|
|
10, the eom is unread, if
|
|
startIndex is 11, all data
|
|
and eom have been read */
|
|
BufferChunk head; /* First chunk */
|
|
BufferChunk tail; /* Last chunk */
|
|
} BufferQueue;
|
|
|
|
/* A handling for an incoming open request to a given connection listener */
|
|
|
|
typedef struct orTag { struct orTag *next; /* Next on list */
|
|
long getConnectionRequestRefNum;
|
|
/* RefNum for this guy, so
|
|
we can cancel. */
|
|
AdspIncomingOpenRequestHandler *completionRoutine;
|
|
/* Routine to call when an
|
|
open request comes in. */
|
|
long unsigned userData; /* UserData for the call to
|
|
the above routine */
|
|
Boolean eventHandler; /* If True, this is being used
|
|
to defer a connection event.
|
|
For opens this must be set
|
|
to False. If True, the
|
|
completionRoutine and
|
|
userData fields are
|
|
invalid */
|
|
Boolean inUse; /* Has the above routine been
|
|
called yet? (i.e. are the
|
|
following fields valid?) */
|
|
short unsigned remoteConnectionId;
|
|
/* If inUse, their con ID */
|
|
AppleTalkAddress remoteAddress;
|
|
/* If inUse, the other end
|
|
of the connection */
|
|
long refNum; /* If inUse, the tentative
|
|
refNum before accept or
|
|
deny */
|
|
|
|
/* If inUse, the remainder of the parameters from the
|
|
openRequest, we'll use these when we actually
|
|
create the connection end. */
|
|
|
|
long unsigned remoteNextReceiveSeqNum;
|
|
long remoteReceiveWindowSize;
|
|
long unsigned receiveAttentionSeqNum;
|
|
} *OpenRequestHandler;
|
|
|
|
/* A connection listener (we just keep a list of these guys, don't bother
|
|
hashing): */
|
|
|
|
typedef struct clTag { struct clTag *next; /* Next CL on list */
|
|
long connectionListenerRefNum;
|
|
/* The refNum of this CL */
|
|
long socket; /* Socket that the connection
|
|
listener is open on */
|
|
Boolean closeSocket; /* Did we open the listener's
|
|
socket? */
|
|
Boolean connectEventInProgress;
|
|
/* Is there an connect event
|
|
being indicated from this
|
|
listener? */
|
|
OpenRequestHandler openRequestHandlers;
|
|
/* The list of handlers for
|
|
incoming Adsp opens */
|
|
OpenRequestHandler deferredConnectionEvents;
|
|
/* List of deferred
|
|
connection events. */
|
|
AdspConnectionEventHandler far *connectionEventHandler;
|
|
/* Incoming connection event
|
|
handler. */
|
|
long unsigned connectionEventContext;
|
|
/* Context to pass to above. */
|
|
} *ConnectionListenerInfo;
|
|
|
|
/* A connection end: */
|
|
|
|
typedef struct ceTag { struct ceTag far *next; /* Hash overflow (by refNum) */
|
|
struct ceTag far *nextByLocalInfo;
|
|
/* Hash overflow (by conId and
|
|
socket) */
|
|
struct ceTag far *nextByRemoteInfo;
|
|
/* Hash overflow (by remote
|
|
ConId and remote address) */
|
|
AdspConnectionState connectionState;
|
|
/* How are we? */
|
|
long refNum; /* Our conn refNum */
|
|
long unsigned usersCookie;
|
|
/* A 32-bit cookie that we can
|
|
store for our client. */
|
|
short unsigned connectionId;
|
|
/* Our con ID */
|
|
long socket; /* Our Ddp socket */
|
|
Boolean closeSocket; /* Did we open the socket? */
|
|
short unsigned remoteConnectionId;
|
|
/* Their con ID */
|
|
AppleTalkAddress remoteAddress;
|
|
/* The other end of the con */
|
|
Boolean passiveOpen; /* Open is passive */
|
|
int openAttemptsCount; /* How many times have we
|
|
tried the Open so far? */
|
|
long unsigned openTimerId;
|
|
/* During Open, the retry
|
|
timerId */
|
|
Boolean seenRemoteOpenRequest;
|
|
/* Have we seen an open
|
|
request from the other
|
|
side yet? */
|
|
AdspOpenCompleteHandler *openCompletionRoutine;
|
|
/* Routine to call when the
|
|
Open compeletes */
|
|
long unsigned openUserData;
|
|
/* Data to pass to the above
|
|
routine */
|
|
long unsigned lastContactTime;
|
|
/* When did we last here from
|
|
the other end? */
|
|
long unsigned probeTimerId;
|
|
/* Connection maintenance
|
|
timer handle */
|
|
long unsigned sendSeqNum; /* Next byte to send */
|
|
long unsigned retransmitSeqNum;
|
|
/* Oldest non-acked byte to
|
|
re-send. */
|
|
long unsigned sendWindowSeqNum;
|
|
/* Highest seqNum that remote
|
|
has buffer space for */
|
|
long unsigned retransmitTimerId;
|
|
/* As it sounds. */
|
|
long unsigned lastRetransmitSeqNum;
|
|
/* From last time the above
|
|
timer fired. */
|
|
Boolean retransmitAckRequestSent;
|
|
/* Have we already tried an
|
|
AckRequest due to the
|
|
previous timer. */
|
|
long unsigned receiveSeqNum;
|
|
/* Next byte we expect */
|
|
long receiveWindowSize; /* Bytes we can accept */
|
|
int outOfSequencePackets; /* How many out of seq pacekts
|
|
have we gotten in a row. */
|
|
Boolean receivePending; /* Is there an outstanding
|
|
read? */
|
|
AdspReceiveHandler *receiveCompletionRoutine;
|
|
/* Routine to call with data */
|
|
long unsigned receiveUserData;
|
|
/* UserData for above. */
|
|
void far *receiveOpaqueBuffer;
|
|
/* User buffer for data */
|
|
long receiveBufferSize; /* Size of above. */
|
|
Boolean getAnythingPending;
|
|
/* Is there a getAnyting
|
|
pending? */
|
|
AdspGetAnythingHandler *getAnythingCompletionRoutine;
|
|
/* Routine to call with data */
|
|
long unsigned getAnythingUserData;
|
|
/* UserData for above. */
|
|
void far *getAnythingOpaqueBuffer;
|
|
/* User buffer for data */
|
|
long getAnythingBufferSize;
|
|
/* Size of above. */
|
|
long unsigned sendAttentionSeqNum;
|
|
/* SeqNum of next attention
|
|
that we will send. */
|
|
long unsigned receiveAttentionSeqNum;
|
|
/* SeqNum of next attention
|
|
that we will accept */
|
|
Boolean waitingForAttentionAck;
|
|
/* We've sent an attention,
|
|
but it hasn't been acked
|
|
yet. */
|
|
long unsigned outgoingAttentionTimerId;
|
|
/* We're sending an Attn, this
|
|
is the try timer. */
|
|
short unsigned outgoingAttentionCode;
|
|
/* Code for resend. */
|
|
char far *outgoingAttentionBuffer;
|
|
/* Buffer for resend. */
|
|
int outgoingAttentionBufferSize;
|
|
/* Size of above. */
|
|
AdspAttentionAckHandler *outgoingAttentionAckHandler;
|
|
/* Routine to call when send
|
|
attention completes. */
|
|
long unsigned outgoingAttentionAckUserData;
|
|
/* User data for the above. */
|
|
AdspIncomingAttentionRoutine *incomingAttentionHandler;
|
|
/* User routine to call when
|
|
an attention comes in;
|
|
empty if none. */
|
|
long unsigned incomingAttentionUserData;
|
|
/* Specified data to be passed
|
|
to the attn handler. */
|
|
void far *incomingAttentionOpaqueBuffer;
|
|
/* User "buffer" to fill with
|
|
attention data. */
|
|
long sendQueueMax; /* Max size of send queue */
|
|
BufferQueue sendQueue; /* Send list; both older un-
|
|
acked data and newer un-
|
|
sent -- old to new */
|
|
BufferQueue nextSendQueue;
|
|
/* Points into above queue;
|
|
division between unacked
|
|
and unsent data */
|
|
long receiveQueueMax; /* Max size of receive queue */
|
|
BufferQueue receiveQueue; /* Reveive list */
|
|
Boolean incomingForwardReset;
|
|
/* We've gotten a reset;
|
|
inform our caller about it
|
|
on the next receive. */
|
|
Boolean outgoingForwardReset;
|
|
/* We're sending a reset and
|
|
waiting for an Ack. */
|
|
long unsigned forwardResetTimerId;
|
|
/* For retransmitting outgoing
|
|
forward resets. */
|
|
AdspForwardResetAckHandler *forwardResetAckHandler;
|
|
/* To call when Ack comes
|
|
in */
|
|
long unsigned forwardResetAckUserData;
|
|
/* To pass to above routine. */
|
|
|
|
/* Event handling information. */
|
|
|
|
long previouslyIndicatedData;
|
|
/* Amount of data in previous
|
|
indication still to be
|
|
read. */
|
|
AdspReceiveEventHandler far *receiveEventHandler;
|
|
/* Incoming receive event
|
|
handler. */
|
|
long unsigned receiveEventContext;
|
|
/* Context for above. */
|
|
Boolean dataEventInProgress;
|
|
/* Are we currently indicating
|
|
incoming data? */
|
|
AdspReceiveAttnEventHandler far
|
|
*receiveAttentionEventHandler;
|
|
/* Incoming attention receive
|
|
event handler. */
|
|
long unsigned receiveAttentionEventContext;
|
|
/* Context for above. */
|
|
Boolean attentionEventInProgress;
|
|
/* Are we current processing
|
|
an attention event? */
|
|
AdspSendOkayEventHandler far *sendOkayEventHandler;
|
|
/* Send window now non-zero
|
|
event handler. */
|
|
long unsigned sendOkayEventContext;
|
|
/* Context for above. */
|
|
Boolean sendWindowHasClosed;
|
|
/* Did the send window go
|
|
to zero? Do we invoke the
|
|
above when it expands? */
|
|
AdspDisconnectEventHandler far *disconnectEventHandler;
|
|
/* Disconnect event handler. */
|
|
long unsigned disconnectEventContext;
|
|
/* Context for above. */
|
|
} far *ConnectionEnd;
|
|
|
|
/* We need to be able to find connection ends by connection refNums (hash
|
|
by RefNum): */
|
|
|
|
#define NumberOfConnectionEndHashBkts 23
|
|
|
|
#ifndef InitializeData
|
|
extern
|
|
#endif
|
|
ConnectionEnd connectionEndRefNumHashBuckets[NumberOfConnectionEndHashBkts];
|
|
|
|
/* We need to be able to find connection ends by remoteAddress/remoteConId
|
|
pairs (hash by remote ConId): */
|
|
|
|
#ifndef InitializeData
|
|
extern
|
|
#endif
|
|
ConnectionEnd connectionEndRemoteHashBuckets[NumberOfConnectionEndHashBkts];
|
|
|
|
/* We need to be able to find connection ends by localSocket/localConId
|
|
pairs (hash by socket): */
|
|
|
|
#ifndef InitializeData
|
|
extern
|
|
#endif
|
|
ConnectionEnd connectionEndLocalHashBuckets[NumberOfConnectionEndHashBkts];
|
|
|
|
/* List of valid connection listeners: */
|
|
|
|
#ifndef InitializeData
|
|
extern
|
|
#endif
|
|
ConnectionListenerInfo connectionListenerList;
|
|
|
|
/* Current values for new connection window sizes. */
|
|
|
|
#ifndef InitializeData
|
|
extern
|
|
#endif
|
|
long maxSendWindowSize
|
|
#ifdef InitializeData
|
|
= DefaultSendReceiveWindowSize;
|
|
#else
|
|
;
|
|
#endif
|
|
|
|
#ifndef InitializeData
|
|
extern
|
|
#endif
|
|
long maxReceiveWindowSize
|
|
#ifdef InitializeData
|
|
= DefaultSendReceiveWindowSize;
|
|
#else
|
|
;
|
|
#endif
|
|
|
|
/* Next connection refNum to try. */
|
|
|
|
#ifndef InitializeData
|
|
extern
|
|
#endif
|
|
long nextConnectionRefNum;
|
|
|
|
/* Next connection ID to try. */
|
|
|
|
#ifndef InitializeData
|
|
extern
|
|
#endif
|
|
short unsigned nextConnectionId
|
|
#ifdef InitializeData
|
|
= 1;
|
|
#else
|
|
;
|
|
#endif
|
|
|
|
/* Next connection listener refNum to try. */
|
|
|
|
#ifndef InitializeData
|
|
extern
|
|
#endif
|
|
long nextConnectionListenerRefNum, nextGetConnectionRequestRefNum;
|