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.
247 lines
12 KiB
247 lines
12 KiB
/* socket.h, /appletalk/ins, Garth Conboy, 10/06/88 */
|
|
/* Copyright (c) 1988 by Pacer Software Inc., La Jolla, CA */
|
|
|
|
/* GC - Initial coding.
|
|
GC - (11/25/89): AppleTalk phase II comes to town; no more internal
|
|
network.
|
|
GC - (07/08/92): We now store/retrieve a user-suppiled magic cookie on a
|
|
per-socket basis.
|
|
GC - (11/15/92): Integrated Nikki's (Microsoft) changes to support an
|
|
event handler in addition to a listener for Ddp incoming
|
|
packets. See the comments above the declaration of
|
|
"IncomingDdpHandler" to learn more than you want to know
|
|
about the difference between a listener and an event
|
|
handler.
|
|
|
|
*** Make the PVCS source control system happy:
|
|
$Header$
|
|
$Log$
|
|
***
|
|
|
|
Declarations for socket management.
|
|
|
|
*/
|
|
|
|
/* "Well known" sockets: */
|
|
|
|
#define RtmpSocket 1 /* RTMP */
|
|
#define NamesInformationSocket 2 /* NBP */
|
|
#define EchoerSocket 4 /* EP */
|
|
#define ZonesInformationSocket 6 /* ZIP */
|
|
|
|
#define LastAppleReservedSocket 0x3F /* Apple reserves 1 thru 0x3F */
|
|
|
|
/* What is the maximum number of "user buffers" that we can associate with
|
|
each open socket? */
|
|
|
|
#define MaxDatagramBuffers 10
|
|
|
|
/* Routine type for incoming DDP packets as passed to OpenSocketOnNode or
|
|
DdpRead. If a routine of this type is passed to OpenSocketOnNode (and it
|
|
is not flagged as an "event handler"), when the socket is finally closed
|
|
one call to the routine will be made with the errorCode ATsocketClosed.
|
|
|
|
If a socket has both pending DdpReads and either a listener or an event
|
|
handler, the DdpReads will be satisified first. That is, the listener
|
|
(or event handler) will only be invoked (or indicated) if there is an
|
|
incoming packet and there are NO pending DdpReads.
|
|
|
|
If the routine is flagged as an "event handler" (this is done in the call
|
|
to OpenSocketOnNode) it should return the number of bytes "accepted." Or
|
|
really one could get away with zero (or False) for "no bytes" accepted and
|
|
non-zero (or True) for "some bytes" accepted. So, "why do we care?" you
|
|
might ask. An Ddp incoming packet event handler handler has an odd ability:
|
|
it can internally post a DdpRead and then return "no bytes accepted," when
|
|
the event handler returns, the DdpRead will complete with the SAME packet
|
|
that was just indicated. If an event handler post DdpReads, but returns
|
|
that it accepted some (or all) of the data, no DdpRead will complete until
|
|
the NEXT packet arrives. Got that? It's pretty strange, but that's the
|
|
way things are supposed to work in Windows environment.
|
|
|
|
In the "non-event handler" case (a listener, which is what the stack always
|
|
uses) there is no concept of "accepting the datagram" (the data had better
|
|
have been handled during the call). So, for a listener, the return value
|
|
is ignored (there is no way for a posted DdpRead to see the same packet that
|
|
was handed to a listener).
|
|
|
|
On other note about event handlers (again operating the way one should in
|
|
the Windows environment). Events a serially queued. That is, if Ddp has
|
|
called an event handler (and it has not returned yet), all events of the
|
|
same type (e.g. "incoming packet") will be deferred until the event handler
|
|
returns. Only one event of a type will occur at the "same time" -- the
|
|
event handler is assumed to be non-reentrant.
|
|
|
|
This is not the case for listeners; they are assumed to be reentrant. If
|
|
you send a long time in a listener routine (processing an incoming packet,
|
|
say) it is likely that the listener will be re-called reentrantly when a
|
|
new packet for the same socket arrives. */
|
|
|
|
typedef long far IncomingDdpHandler(AppleTalkErrorCode errorCode,
|
|
long unsigned userData,
|
|
int port,
|
|
AppleTalkAddress source,
|
|
long destinationSocket,
|
|
int protocolType,
|
|
char far *datagram,
|
|
int datagramLength,
|
|
AppleTalkAddress actualDestination);
|
|
|
|
/* List of pending ReadDdp calls: */
|
|
|
|
typedef struct ddpIn { struct ddpIn far *next;
|
|
void *opaqueDatagram;
|
|
long bufferLength;
|
|
IncomingDdpHandler *handler;
|
|
long unsigned userData;
|
|
} far *OutstandingDdpRead;
|
|
|
|
|
|
/* The DeferredDatagramEvent - a single event deferred */
|
|
|
|
typedef struct eventNode { struct eventNode far *next;
|
|
int port;
|
|
AppleTalkAddress source;
|
|
long destinationSocket;
|
|
int protocolType;
|
|
int datagramLength;
|
|
AppleTalkAddress actualDestination;
|
|
char datagram[1];
|
|
} far *DeferredDatagramEvent;
|
|
|
|
/* The DeferredDatagramEventQueue - use first/last to get FIFO */
|
|
|
|
typedef struct eventQueue { DeferredDatagramEvent first;
|
|
DeferredDatagramEvent last;
|
|
/* First/last nodes in list */
|
|
Boolean datagramEventInProgress;
|
|
/* Is a datagram event in
|
|
progress? Do we need to defer
|
|
other datagram events? */
|
|
} DeferredDatagramEventQueue;
|
|
|
|
/* Closes (for Ddp sockets, and higher level connections) don't really
|
|
complete until all operations on the socket (or connection complete,
|
|
the following is the general close completion info. */
|
|
|
|
typedef void far CloseCompletionRoutine(AppleTalkErrorCode errorCode,
|
|
long unsigned userData,
|
|
long cookie);
|
|
|
|
typedef struct { CloseCompletionRoutine far *closeCompletionRoutine;
|
|
long unsigned closeUserData;
|
|
} CloseContext;
|
|
|
|
/* Each ActiveNode contains a list of these guys. All information about
|
|
open sockets are kept here. */
|
|
|
|
typedef struct os {int refCount; /* Reference count for this
|
|
node. */
|
|
struct os far *next; /* Next open socket on this node;
|
|
hanging off an ActiveNode. */
|
|
short port; /* "port" this socket is on. */
|
|
long socket; /* Our unique socket identifier. */
|
|
Boolean closing; /* Are we in the process of closing
|
|
this socket? Waiting for all
|
|
writes to complete, etc. */
|
|
CloseContext closeContext;
|
|
/* If closing, this is the context
|
|
we will use to complete the
|
|
close when refCount goes down
|
|
to zero. */
|
|
long unsigned usersCookie;
|
|
/* A 32-bit "thing" that can be
|
|
stored and retrieved on a per-
|
|
socket basis. */
|
|
struct activeNode *activeNode;
|
|
/* What node are we on? */
|
|
unsigned char actualSocket;
|
|
/* Our AppleTalk socket number. */
|
|
|
|
/* NOTES: the handler below behaves as an incoming datagram
|
|
event handler as well as the listener for the
|
|
socket for the upper layers (specified by the
|
|
"event handler" flag below). In the case of an
|
|
incoming datagram event handler, events happen
|
|
one at a time, and deferrels could take place,
|
|
but not so for the listener. Also, there can only
|
|
be one or the other on this socket. */
|
|
|
|
IncomingDdpHandler *handler;
|
|
/* User routine to call when a
|
|
packet comes in destined for
|
|
this socket. */
|
|
Boolean eventHandler; /* Is above an event handler? */
|
|
DeferredDatagramEventQueue eventQueue;
|
|
/* Deferred incoming datagram
|
|
event queue; for event handler
|
|
only, not listener. */
|
|
|
|
long unsigned userData; /* User data to go to the above
|
|
routine. either listener userdata or
|
|
event context */
|
|
char far *datagramBuffers;
|
|
/* Where do we copy data to before
|
|
calling the handler? */
|
|
short validDatagramBuffers;
|
|
/* How many datagram buffers do
|
|
we have to work with? */
|
|
Boolean datagramInUse[MaxDatagramBuffers];
|
|
/* What buffers are currently
|
|
in use? */
|
|
OutstandingDdpRead outstandingDdpReads;
|
|
/* If the user want's packets
|
|
via the ReadDdp call, this is
|
|
the list of handlers. */
|
|
RegisteredName registeredNames;
|
|
/* Network Visible Entities (NVE)
|
|
registered on this socket. */
|
|
PendingName pendingNames; /* NVE being lookedup, registered,
|
|
or confirmed on this socket. */
|
|
} far *OpenSocket;
|
|
|
|
/* Next available socket identifier. This (in pre-phase II) used to be a 16
|
|
bit quantity, so we start at 65536 to make sure all remnents of the old
|
|
scheme have gone to way of the dodo. */
|
|
|
|
#if not InitializeData
|
|
extern
|
|
#endif
|
|
long nextAvailableSocket
|
|
#if InitializeData
|
|
= 65536;
|
|
#else
|
|
;
|
|
#endif
|
|
|
|
/* Hash table for getting from a socket identifier to an OpenSocket node. */
|
|
|
|
typedef struct sm { struct sm far *nextBySocket;
|
|
struct sm far *nextByAddress;
|
|
long socket;
|
|
OpenSocket openSocket;
|
|
} far *SocketMap;
|
|
#define NumberOfSocketMapHashBuckets 13
|
|
|
|
#if not InitializeData
|
|
extern
|
|
#endif
|
|
SocketMap socketMapBySocketHashBuckets[NumberOfSocketMapHashBuckets],
|
|
socketMapByAddressHashBuckets[NumberOfSocketMapHashBuckets];
|
|
|
|
/* Whos been naughty, whos been nice? */
|
|
|
|
#define UnknownSocket 0
|
|
#define LastValidSocket 254
|
|
#define FirstDynamicSocket 128
|
|
#define LastDynamicSocket LastValidSocket
|
|
#define FirstStaticSocket 1
|
|
#define FirstValidSocket FirstStaticSocket
|
|
#define LastStaticSocket 127
|
|
|
|
/* Each outstanding "DdpRead" takes a little memory for the OutstandingDdpRead
|
|
structure... we don't want to allow a user program go wild calling DddRead
|
|
and use up all of our memory. So, limit the number of concurrent oustanding
|
|
requests. We also use this value to limit other things: ATP request
|
|
handlers, PAP get next jobs, ASP get requests, etc. */
|
|
|
|
#define MaxOutstandingRequests 16
|