Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1029 lines
34 KiB

/* ZipStub.c, /appletalk/source, Garth Conboy, 10/30/88 */
/* Copyright (c) 1988 by Pacer Software Inc., La Jolla, CA */
/* GC - Initial coding.
GC - (12/03/89): AppleTalk phase II comes to town.
GC - (08/18/90): New error logging mechanism.
GC - (03/31/92): Updated for BufferDescriptors.
GC - (06/27/92): All buffers coming from user space are now "opaque," they
may or may not be "char *." We now use the new routines
MoveFromOpaque() and MoveToOpaque() to access these
"buffer"s rather than MemMove().
GC - (06/29/92): Added capability to find the default zone for a cable;
needed because we now have "defaultOrDesiredZone" as two
separate concepts.
GC - (11/16/92): Corrected above feature!
*** Make the PVCS source control system happy:
$Header$
$Log$
***
ZIP handling for non-routing nodes.
*/
#define IncludeZipStubErrors 1
#include "atalk.h"
#if (Iam an AppleTalkRouter) and (IamNot an AppleTalkStack)
#include "atpconst.h"
#endif
ExternForVisibleFunction IncomingDdpHandler GetMyZoneReply, GetZoneListReply;
ExternForVisibleFunction TimerHandler GetZoneInfoTimerExpired;
ExternForVisibleFunction void SendZipPacketTo(ZipCompletionInfo completionInfo);
/* For the pending GetMyZone and GetZoneList requests we keep a list of
completion infos. */
static ZipCompletionInfo zipCompletionInfoList;
long far ZipPacketIn(AppleTalkErrorCode errorCode,
long unsigned userData,
int port,
AppleTalkAddress source,
long destinationSocket,
int protocolType,
char far *datagram,
int datagramLength,
AppleTalkAddress actualDestination)
{
int commandType;
int index;
StaticForSmallStack char zone[MaximumZoneLength + 1],
defaultZone[MaximumZoneLength + 1];
StaticForSmallStack char multicastAddress[MaximumHardwareAddressLength];
int zoneLength, defaultZoneLength, multicastAddressLength;
PortHandlers portHandlers;
int flags;
/* "Use" unneeded actual parameters. */
destinationSocket, userData, actualDestination;
/* Only play if we've been asked nicely! */
if (errorCode is ATsocketClosed)
return((long)True);
else if (errorCode isnt ATnoError)
{
ErrorLog("ZipPacketIn", ISevError, __LINE__, port,
IErrZipStubBadIncomingError, IMsgZipStubBadIncomingError,
Insert0());
return((long)True);
}
/* We only care about a ZIP Notifies and NetInfoReplies. */
if (not portDescriptors[port].extendedNetwork)
{
ErrorLog("ZipPacketIn", ISevError, __LINE__, port,
IErrZipStubNonExtended, IMsgZipStubNonExtended,
Insert0());
return((long)True);
}
commandType = (unsigned char)datagram[ZipCommandOffset];
if (protocolType isnt DdpProtocolZip or
(commandType isnt ZipNotifyCommand and
commandType isnt ZipNetInfoReplyCommand))
return((long)True);
if (datagramLength < ZipZoneLengthOffset)
return((long)True);
if (portDescriptors[port].lookingForDefaultZone and
commandType isnt ZipNetInfoReplyCommand)
return((long)True); /* Who cares? */
if (not portDescriptors[port].lookingForDefaultZone and
commandType is ZipNetInfoReplyCommand and
portDescriptors[port].thisZoneValid)
return((long)True); /* Who cares... */
portHandlers = &portSpecificInfo[portDescriptors[port].portType];
/* Handle our two cases. Decode both of them as if we have a net info
reply. */
flags = (unsigned char)datagram[ZipFlagsOffset];
index = ZipZoneLengthOffset;
if (datagramLength < index + 1)
{
ErrorLog("ZipPacketIn", ISevWarning, __LINE__, port,
IErrZipStubZoneLenMissing, IMsgZipStubZoneLenMissing,
Insert0());
return((long)True);
}
zoneLength = (unsigned char)datagram[index];
index += 1;
if (zoneLength > MaximumZoneLength)
{
ErrorLog("ZipPacketIn", ISevWarning, __LINE__, port,
IErrZipStubBadZoneLength, IMsgZipStubBadZoneLength,
Insert0());
return((long)True);
}
if (datagramLength < index + zoneLength)
{
ErrorLog("ZipPacketIn", ISevWarning, __LINE__, port,
IErrZipStubZoneMissing, IMsgZipStubZoneMissing,
Insert0());
return((long)True);
}
MoveMem(zone, datagram + index, zoneLength);
zone[zoneLength] = 0;
index += zoneLength;
/* If we're requesting the zone name, make sure the response matches our
request. ZoneLength will be zero when we're looking for the default
zone, so we won't do this test. */
if (commandType is ZipNetInfoReplyCommand and zoneLength isnt 0)
if (not CompareCaseInsensitive(zone, portDescriptors[port].
initialDesiredZone))
{
ErrorLog("ZipPacketIn", ISevVerbose, __LINE__, port,
IErrZipStubZonesDontMatch, IMsgZipStubZonesDontMatch,
Insert0());
return((long)True);
}
/* If we're a notify make sure we're in the zone that is being changed. */
if (commandType is ZipNotifyCommand)
if (portDescriptors[port].thisZoneValid and
not CompareCaseInsensitive(zone, portDescriptors[port].thisZone))
return((long)True);
/* Grab mutlicast address info. */
if (datagramLength < index + 1)
{
ErrorLog("ZipPacketIn", ISevWarning, __LINE__, port,
IErrZipStubMulticastMissing, IMsgZipStubMulticastMissing,
Insert0());
return((long)True);
}
multicastAddressLength = (unsigned char)datagram[index];
index += 1;
if (multicastAddressLength isnt portHandlers->hardwareAddressLength)
{
ErrorLog("ZipPacketIn", ISevWarning, __LINE__, port,
IErrZipStubBadMulticast, IMsgZipStubBadMulticast,
Insert0());
return((long)True);
}
if (datagramLength < index + multicastAddressLength)
{
ErrorLog("ZipPacketIn", ISevWarning, __LINE__, port,
IErrZipStubAddressMissing, IMsgZipStubAddressMissing,
Insert0());
return((long)True);
}
MoveMem(multicastAddress, datagram + index, multicastAddressLength);
index += multicastAddressLength;
if (flags & ZipUseBroadcastFlag)
MoveMem(multicastAddress, portHandlers->broadcastAddress,
multicastAddressLength);
/* Grab second zone name, if needed or present. */
defaultZoneLength = 0;
if (commandType is ZipNotifyCommand or datagramLength > index)
{
if (datagramLength < index + 1)
{
ErrorLog("ZipPacketIn", ISevWarning, __LINE__, port,
IErrZipStubZoneLenMissing, IMsgZipStubZoneLenMissing,
Insert0());
return((long)True);
}
defaultZoneLength = (unsigned char)datagram[index];
index += 1;
if (defaultZoneLength is 0 or defaultZoneLength > MaximumZoneLength)
{
ErrorLog("ZipPacketIn", ISevWarning, __LINE__, port,
IErrZipStubBadZoneLength, IMsgZipStubBadZoneLength,
Insert0());
return((long)True);
}
if (datagramLength < index + defaultZoneLength)
{
ErrorLog("ZipPacketIn", ISevWarning, __LINE__, port,
IErrZipStubZoneMissing, IMsgZipStubZoneMissing,
Insert0());
return((long)True);
}
MoveMem(defaultZone, datagram + index, defaultZoneLength);
defaultZone[defaultZoneLength] = 0;
index += defaultZoneLength;
}
/* Make "defaultZone" be the "new" one. We may not have a default/new
zone in NetInfoReplyCase and we requested with a correct zone. */
if (defaultZoneLength is 0)
{
strcpy(defaultZone, zone);
defaultZoneLength = zoneLength;
}
/* If we're just looking for the default zone, set here and note our
mission completed. */
if (portDescriptors[port].lookingForDefaultZone)
{
strcpy(portDescriptors[port].thisDefaultZone, defaultZone);
portDescriptors[port].thisDefaultZoneValid = True;
}
/* Okay, now we want to "accept" all of the information about "this zone"
for the nodes on the current port.
If the new multicast address is different, remove the old and set
the new. Don't allow mucking with the "broadcast" multicast address. */
if (not FixedCompareCaseSensitive(multicastAddress, multicastAddressLength,
portDescriptors[port].zoneMulticastAddress,
multicastAddressLength))
{
if (portDescriptors[port].thisZoneValid and
not FixedCompareCaseSensitive(portDescriptors[port].
zoneMulticastAddress,
multicastAddressLength,
portHandlers->broadcastAddress,
multicastAddressLength))
(*portHandlers->removeMulticastAddress)(port, 1,
portDescriptors[port].
zoneMulticastAddress);
if (not FixedCompareCaseSensitive(multicastAddress,
multicastAddressLength,
portHandlers->broadcastAddress,
multicastAddressLength))
(*portHandlers->addMulticastAddress)(port, 1, multicastAddress);
MoveMem(portDescriptors[port].zoneMulticastAddress, multicastAddress,
multicastAddressLength);
}
/* Set this cable range if we're a net info reply. */
if (commandType is ZipNetInfoReplyCommand)
{
portDescriptors[port].thisCableRange.firstNetworkNumber =
(short unsigned)((unsigned char)datagram[ZipCableRangeStartOffset] << 8);
portDescriptors[port].thisCableRange.firstNetworkNumber +=
(unsigned char)(datagram[ZipCableRangeStartOffset + 1]);
portDescriptors[port].thisCableRange.lastNetworkNumber =
(short unsigned)((unsigned char)datagram[ZipCableRangeEndOffset] << 8);
portDescriptors[port].thisCableRange.lastNetworkNumber +=
(unsigned char)(datagram[ZipCableRangeEndOffset + 1]);
portDescriptors[port].seenRouterRecently = True;
if (not portDescriptors[port].routingPort)
{
/* Do not mess with these values if we are a router. This is
probably happening when we are coming up, and have switched
the handlers temporarily. */
portDescriptors[port].aRouter.networkNumber = source.networkNumber;
portDescriptors[port].aRouter.nodeNumber = source.nodeNumber;
}
}
/* Okay, now we know the zone! */
strcpy(portDescriptors[port].thisZone, defaultZone);
portDescriptors[port].thisZoneValid = True;
return((long)True);
} /* ZipPacketIn */
Boolean far GetNetworkInfoForNode(int port,
ExtendedAppleTalkNodeNumber extendedNode,
Boolean findDefaultZone)
{
/* Our node is just coming up; send out some ZipGetNetInfo packets,
and see what we can find out! */
BufferDescriptor datagram, copy;
int numberOfRequests = 0;
int datagramLength;
AppleTalkAddress source, destination;
/* Setup. */
if (not portDescriptors[port].extendedNetwork)
{
ErrorLog("GetNetworkInfoForNode", ISevError, __LINE__, port,
IErrZipStubSigh, IMsgZipStubSigh,
Insert0());
return(False);
}
if (findDefaultZone)
{
portDescriptors[port].thisDefaultZoneValid = False;
portDescriptors[port].lookingForDefaultZone = True;
}
else
portDescriptors[port].thisZoneValid = False;
source.networkNumber = extendedNode.networkNumber;
source.nodeNumber = extendedNode.nodeNumber;
source.socketNumber = ZonesInformationSocket;
destination.networkNumber = CableWideBroadcastNetworkNumber;
destination.nodeNumber = AppleTalkBroadcastNodeNumber;
destination.socketNumber = ZonesInformationSocket;
/* Allocate a buffer descriptor. */
if ((datagram = NewBufferDescriptor(ZipZoneNameOffset +
MaximumZoneLength)) is Empty)
{
ErrorLog("GetNetworkInfoForNode", ISevError, __LINE__, port,
IErrZipStubOutOfMemory, IMsgZipStubOutOfMemory,
Insert0());
return(False);
}
/* Build a ZipGetNetInfo datagram... */
datagram->data[ZipCommandOffset] = ZipGetNetInfoCommand;
datagram->data[ZipFlagsOffset] = 0;
datagram->data[ZipCableRangeStartOffset] = 0;
datagram->data[ZipCableRangeStartOffset + 1] = 0;
datagram->data[ZipCableRangeEndOffset] = 0;
datagram->data[ZipCableRangeEndOffset + 1] = 0;
if (findDefaultZone)
{
datagram->data[ZipZoneLengthOffset] = 0;
datagramLength = ZipZoneNameOffset;
}
else
{
datagram->data[ZipZoneLengthOffset] =
(char)strlen(portDescriptors[port].initialDesiredZone);
if (datagram->data[ZipZoneLengthOffset] isnt 0)
{
strcpy(datagram->data + ZipZoneNameOffset,
portDescriptors[port].initialDesiredZone);
datagramLength = ZipZoneNameOffset + datagram->data[ZipZoneLengthOffset];
}
else
datagramLength = ZipZoneNameOffset;
}
/* Okay, blast a few of these guys out to see if any router on the
network knows what's up. */
while (numberOfRequests < NumberOfGetNetInfos)
{
/* Are we done? */
if (findDefaultZone and portDescriptors[port].thisDefaultZoneValid)
break;
if (not findDefaultZone and portDescriptors[port].thisZoneValid)
break;
/* Copy our datagram due to multiple sends and possible asynchronous
transmit completion. */
if ((copy = CopyBufferChain(datagram)) is Empty)
{
ErrorLog("GetNetworkInfoForNode", ISevError, __LINE__, port,
IErrZipStubOutOfMemory, IMsgZipStubOutOfMemory,
Insert0());
return(False);
}
if (not TransmitDdp(port, source, destination,
DdpProtocolZip, copy, datagramLength, 0,
Empty, Empty, Empty, 0))
{
ErrorLog("GetNetworkInfoForNode", ISevError, __LINE__, port,
IErrZipStubBadGetNetSend, IMsgZipStubBadGetNetSend,
Insert0());
FreeBufferChain(datagram);
return(False);
}
numberOfRequests += 1;
if (findDefaultZone)
WaitFor(ZipGetNetInfoHundreths,
&portDescriptors[port].thisDefaultZoneValid);
else
WaitFor(ZipGetNetInfoHundreths, &portDescriptors[port].thisZoneValid);
}
/* Well... did we get anything? */
FreeBufferChain(datagram);
if (findDefaultZone)
{
portDescriptors[port].lookingForDefaultZone = False;
return(portDescriptors[port].thisDefaultZoneValid);
}
return(portDescriptors[port].thisZoneValid);
} /* GetNetworkInfoOnPort */
AppleTalkErrorCode far GetMyZone(
int port, /* On what port? */
void far *opaqueBuffer, /* "Buffer" in which to place the zone
name. */
GetMyZoneComplete *completionRoutine,
/* Routine to call when we're finished. */
long unsigned userData) /* Passed along to above. */
{
long socket;
ZipCompletionInfo completionInfo;
AppleTalkErrorCode errorCode;
/* Call the supplied completion routine with the following arguments when
we've come up with the answer:
errorCode - AppleTalkErrorCode; completion status.
userData - long unsigned; as passed to us.
opaqueBuffer
- void far *; ad passed to us (filled in now).
*/
/* If the "default port" is requested, demystify it. */
if (port is DefaultPort)
if ((port = FindDefaultPort()) < 0)
return(ATappleTalkShutDown);
/* For extended networks, we either know or can't find out! */
DeferTimerChecking();
DeferIncomingPackets();
if (portDescriptors[port].extendedNetwork)
{
if (portDescriptors[port].thisZoneValid)
MoveToOpaque(opaqueBuffer, 0, portDescriptors[port].thisZone,
strlen(portDescriptors[port].thisZone) + 1);
else
MoveToOpaque(opaqueBuffer, 0, "*", 2);
HandleIncomingPackets();
HandleDeferredTimerChecks();
(*completionRoutine)(ATnoError, userData, opaqueBuffer);
return(ATnoError);
}
/* For non-extended networks we need to ask a router. If we don't know
about a router, don't play. */
if (not portDescriptors[port].seenRouterRecently)
{
MoveToOpaque(opaqueBuffer, 0, "*", 2);
HandleIncomingPackets();
HandleDeferredTimerChecks();
(*completionRoutine)(ATnoError, userData, opaqueBuffer);
return(ATnoError);
}
/* Open a socket for handling the replies. */
if ((errorCode = OpenSocketOnNode(&socket, port, empty, UnknownSocket,
GetMyZoneReply, (long)0, False,
empty, 0, empty)) isnt ATnoError)
{
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(errorCode);
}
/* Build a completion node. */
if ((completionInfo =
(ZipCompletionInfo)Calloc(sizeof(*completionInfo), 1)) is empty)
{
CloseSocketOnNode(socket);
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(AToutOfMemory);
}
completionInfo->next = zipCompletionInfoList;
zipCompletionInfoList = completionInfo;
completionInfo->atpRequestType = ZipGetMyZoneCommand;
completionInfo->socket = socket;
completionInfo->router.networkNumber =
portDescriptors[port].aRouter.networkNumber;
completionInfo->router.nodeNumber =
portDescriptors[port].aRouter.nodeNumber;
completionInfo->router.socketNumber = ZonesInformationSocket;
completionInfo->opaqueBuffer = opaqueBuffer;
completionInfo->myZoneCompletionRoutine = completionRoutine;
completionInfo->userData = userData;
/* Start the retry timer, then send the first query. */
completionInfo->timerId = StartTimer(GetZoneInfoTimerExpired,
GetZoneInfoTimerSeconds,
sizeof(socket),
(char far *)&socket);
SendZipPacketTo(completionInfo);
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(ATnoError);
} /* GetMyZone */
AppleTalkErrorCode far GetZoneList(
int port, /* Port to get zone list from. */
Boolean getLocalZones, /* Does the caller want only the local zones? */
void far *opaqueBuffer, /* "Buffer" to fill with zone list. */
int bufferSize, /* Buffer size (bytes). */
GetZoneListComplete *completionRoutine,
/* Routine to call when we're finished. */
long unsigned userData) /* Passed along to above. */
{
long socket;
ZipCompletionInfo completionInfo;
AppleTalkErrorCode errorCode;
/* Call the supplied completion routine with the following arguments when
we've come up with the answer:
errorCode - AppleTalkErrorCode; completion status.
userData - long unsigned; as passed to us.
opaqueBuffer
- void far *; addr passed to us (filled in now).
zoneCount - int; how many zones did we pack in buffer.
*/
/* If the "default port" is requested, demystify it. */
if (port is DefaultPort)
if ((port = FindDefaultPort()) < 0)
return(ATappleTalkShutDown);
if (bufferSize < 0)
return(ATbadBufferSize);
DeferTimerChecking();
DeferIncomingPackets();
/* If we don't know about a router, don't play. */
if (not portDescriptors[port].seenRouterRecently)
{
MoveToOpaque(opaqueBuffer, 0, "*", 2);
HandleIncomingPackets();
HandleDeferredTimerChecks();
(*completionRoutine)(ATnoError, userData, opaqueBuffer, 1);
return(ATnoError);
}
/* Open a socket for handling the replies. */
if ((errorCode = OpenSocketOnNode(&socket, port, empty, UnknownSocket,
GetZoneListReply, (long)0, False,
empty, 0, empty)) isnt ATnoError)
{
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(errorCode);
}
/* Build a completion node. */
if ((completionInfo =
(ZipCompletionInfo)Calloc(sizeof(*completionInfo), 1)) is empty)
{
CloseSocketOnNode(socket);
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(AToutOfMemory);
}
completionInfo->next = zipCompletionInfoList;
zipCompletionInfoList = completionInfo;
if (getLocalZones)
completionInfo->atpRequestType = ZipGetLocalZonesCommand;
else
completionInfo->atpRequestType = ZipGetZoneListCommand;
completionInfo->socket = socket;
completionInfo->router.networkNumber =
portDescriptors[port].aRouter.networkNumber;
completionInfo->router.nodeNumber =
portDescriptors[port].aRouter.nodeNumber;
completionInfo->router.socketNumber = ZonesInformationSocket;
completionInfo->opaqueBuffer = opaqueBuffer;
completionInfo->bufferSize = bufferSize;
completionInfo->zoneListCompletionRoutine = completionRoutine;
completionInfo->userData = userData;
completionInfo->zoneListIndex = 1;
/* Start the retry timer, then send the first query. */
completionInfo->timerId = StartTimer(GetZoneInfoTimerExpired,
GetZoneInfoTimerSeconds,
sizeof(socket),
(char far *)&socket);
SendZipPacketTo(completionInfo);
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(ATnoError);
} /* GetZoneList */
ExternForVisibleFunction void SendZipPacketTo(ZipCompletionInfo completionInfo)
{
BufferDescriptor datagram;
/* Allocate a buffer descriptor. */
if ((datagram = NewBufferDescriptor(ZipGetZoneListDdpSize)) is Empty)
{
ErrorLog("SendZipPacketTo", ISevError, __LINE__, UnknownPort,
IErrZipStubOutOfMemory, IMsgZipStubOutOfMemory,
Insert0());
return;
}
/* Build our toy ATP packet. */
datagram->data[AtpCommandControlOffset] = AtpRequestFunctionCode;
datagram->data[AtpBitmapOffset] = 1;
datagram->data[AtpTransactionIdOffset] = 0;
datagram->data[AtpTransactionIdOffset + 1] = 0;
datagram->data[AtpZipCommandOffset] = (char)completionInfo->atpRequestType;
datagram->data[AtpZipCommandOffset + 1] = 0;
datagram->data[AtpZipStartIndexOffset] =
(char)(completionInfo->zoneListIndex >> 8);
datagram->data[AtpZipStartIndexOffset + 1] =
(char)(completionInfo->zoneListIndex & 0xFF);
/* Send the datagram to the specified destination. */
if (DeliverDdp(completionInfo->socket, completionInfo->router,
DdpProtocolAtp, datagram, ZipGetZoneListDdpSize,
Empty, Empty, 0)
isnt ATnoError)
ErrorLog("SendZipPacketTo", ISevError, __LINE__, UnknownPort,
IErrZipStubBadARouterSend, IMsgZipStubBadARouterSend,
Insert0());
return;
} /* SendZipPacketTo */
ExternForVisibleFunction long far
GetMyZoneReply(AppleTalkErrorCode errorCode,
long unsigned userData,
int port,
AppleTalkAddress source,
long destinationSocket,
int protocolType,
char far *datagram,
int datagramLength,
AppleTalkAddress actualDestination)
{
ZipCompletionInfo completionInfo, previousCompletionInfo;
int zoneCount;
int zoneLength;
void far *opaqueBuffer;
GetMyZoneComplete *completionRoutine;
/* "Use" unused formals. */
port, source, actualDestination;
/* Find our completionInfo structure (tagged by socket). */
DeferTimerChecking();
DeferIncomingPackets();
for (completionInfo = zipCompletionInfoList,
previousCompletionInfo = empty;
completionInfo isnt empty;
previousCompletionInfo = completionInfo,
completionInfo = completionInfo->next)
if (completionInfo->socket is destinationSocket)
break;
if (completionInfo is empty)
{
/* This could be okay if the response was received after all of the
alloted time... */
HandleIncomingPackets();
HandleDeferredTimerChecks();
return((long)True);
}
/* On most error cases flee -- however, remove our completion info on
socket closed. */
if (errorCode is ATsocketClosed)
{
if (previousCompletionInfo is empty)
zipCompletionInfoList = completionInfo->next;
else
previousCompletionInfo->next = completionInfo->next;
Free(completionInfo);
}
if (errorCode isnt ATnoError or
protocolType isnt DdpProtocolAtp or
datagramLength <= AtpZipFirstZoneOffset)
{
HandleIncomingPackets();
HandleDeferredTimerChecks();
return((long)True);
}
/* We should have one quality zone! */
zoneCount = (datagram[AtpZipZoneCountOffset] << 8);
zoneCount += (unsigned char)(datagram[AtpZipZoneCountOffset + 1]);
zoneLength = (unsigned char)datagram[AtpZipFirstZoneOffset];
if (zoneCount isnt 1 or
zoneLength is 0 or
zoneLength > MaximumZoneLength)
{
HandleIncomingPackets();
HandleDeferredTimerChecks();
return((long)True);
}
/* Okay, move the zone name into the user's buffer. */
MoveToOpaque(completionInfo->opaqueBuffer, 0,
datagram + AtpZipFirstZoneOffset + 1, zoneLength);
MoveToOpaque(completionInfo->opaqueBuffer, zoneLength, "", 1);
/* We're all set: cancel the retry timer, close our socket [this will cause
a recursive call which will remove the completion info], call the
completion routine, flee. */
CancelTimer(completionInfo->timerId);
opaqueBuffer = completionInfo->opaqueBuffer;
completionRoutine = completionInfo->myZoneCompletionRoutine;
userData = completionInfo->userData;
if (CloseSocketOnNode(completionInfo->socket) isnt ATnoError)
ErrorLog("GetMyZoneReply", ISevError, __LINE__, port,
IErrZipStubBadSocketClose, IMsgZipStubBadSocketClose,
Insert0());
HandleIncomingPackets();
HandleDeferredTimerChecks();
(*completionRoutine)(ATnoError, userData, opaqueBuffer);
return((long)True);
} /* GetMyZoneReply */
ExternForVisibleFunction void far
GetZoneInfoTimerExpired(long unsigned timerId,
int additionalDataSize,
char far *additionalData)
{
long socket;
ZipCompletionInfo completionInfo;
void far *opaqueBuffer;
GetMyZoneComplete *myZoneCompletionRoutine;
GetZoneListComplete *zoneListCompletionRoutine;
long unsigned userData;
Boolean getMyZone;
int zoneCount;
/* "Use" unused formal. */
timerId;
/* Verify args. */
if (additionalDataSize isnt sizeof(socket))
{
ErrorLog("GetZoneInfoTimerExpired", ISevError, __LINE__, UnknownPort,
IErrZipStubBadData, IMsgZipStubBadData,
Insert0());
return;
}
socket = *(long *)additionalData;
/* Find our completion info. */
DeferIncomingPackets();
for (completionInfo = zipCompletionInfoList;
completionInfo isnt empty;
completionInfo = completionInfo->next)
if (completionInfo->socket is socket)
break;
if (completionInfo is empty)
{
HandleIncomingPackets();
HandleDeferredTimerChecks();
return;
}
/* Bump our expiration count, if there's still time try it again. */
completionInfo->expirationCount += 1;
if (completionInfo->expirationCount < GetZoneInfoRetries)
{
completionInfo->timerId = StartTimer(GetZoneInfoTimerExpired,
GetZoneInfoTimerSeconds,
sizeof(socket),
(char far *)&socket);
SendZipPacketTo(completionInfo);
HandleIncomingPackets();
HandleDeferredTimerChecks();
return;
}
/* Else, we're out of time, just plead ignorance, close the temporary
socket (in turn freeing the completion info), and call the completion
routine. */
getMyZone = (completionInfo->atpRequestType is ZipGetMyZoneCommand);
if (getMyZone)
MoveToOpaque(completionInfo->opaqueBuffer, 0, "*", 2);
else if (completionInfo->zoneCount is 0)
{
MoveToOpaque(completionInfo->opaqueBuffer, 0, "*", 2);
completionInfo->zoneCount = 1;
}
opaqueBuffer = completionInfo->opaqueBuffer;
zoneCount = completionInfo->zoneCount;
if (getMyZone)
myZoneCompletionRoutine = completionInfo->myZoneCompletionRoutine;
else
zoneListCompletionRoutine = completionInfo->zoneListCompletionRoutine;
userData = completionInfo->userData;
if (CloseSocketOnNode(completionInfo->socket) isnt ATnoError)
ErrorLog("GetZoneInfoTimerExpired", ISevError, __LINE__, UnknownPort,
IErrZipStubBadSocketClose, IMsgZipStubBadSocketClose,
Insert0());
HandleIncomingPackets();
HandleDeferredTimerChecks();
if (getMyZone)
(*myZoneCompletionRoutine)(ATnoError, userData, opaqueBuffer);
else
(*zoneListCompletionRoutine)(ATnoError, userData, opaqueBuffer, zoneCount);
return;
} /* GetZoneInfoTimerExpired */
ExternForVisibleFunction long far
GetZoneListReply(AppleTalkErrorCode errorCode,
long unsigned userData,
int port,
AppleTalkAddress source,
long destinationSocket,
int protocolType,
char far *datagram,
int datagramLength,
AppleTalkAddress actualDestination)
{
ZipCompletionInfo completionInfo, previousCompletionInfo;
int zoneCount;
int zoneLength;
void far *opaqueBuffer;
GetZoneListComplete *completionRoutine;
Boolean lastFlag, formatError = False, overflow = False;
int datagramIndex;
char far *currentZone;
int validZones = 0;
/* "Use" unused formals. */
source, port, actualDestination;
/* Find our completionInfo structure (tagged by socket). */
DeferTimerChecking();
DeferIncomingPackets();
for (completionInfo = zipCompletionInfoList,
previousCompletionInfo = empty;
completionInfo isnt empty;
previousCompletionInfo = completionInfo,
completionInfo = completionInfo->next)
if (completionInfo->socket is destinationSocket)
break;
if (completionInfo is empty)
{
/* This could be okay if the response was received after all of the
alloted time... */
HandleIncomingPackets();
HandleDeferredTimerChecks();
return((long)True);
}
/* On most error cases flee -- however, remove our completion info on
socket closed. */
if (errorCode is ATsocketClosed)
{
if (previousCompletionInfo is empty)
zipCompletionInfoList = completionInfo->next;
else
previousCompletionInfo->next = completionInfo->next;
Free(completionInfo);
}
if (errorCode isnt ATnoError or
protocolType isnt DdpProtocolAtp or
datagramLength < AtpZipFirstZoneOffset)
{
HandleIncomingPackets();
HandleDeferredTimerChecks();
return((long)True);
}
/* We should have a zone list now. */
lastFlag = (datagram[AtpZipLastFlagOffset] isnt 0);
zoneCount = (datagram[AtpZipZoneCountOffset] << 8);
zoneCount += (unsigned char)(datagram[AtpZipZoneCountOffset + 1]);
if (zoneCount is 0)
lastFlag = True;
datagramIndex = AtpZipFirstZoneOffset;
while (zoneCount > 0)
{
/* Pull out the next zoneLength/zone pair. */
if (datagramIndex + 1 > datagramLength)
{
formatError = True;
break;
}
zoneLength = (unsigned char)datagram[datagramIndex];
if (zoneLength is 0 or
zoneLength > MaximumZoneLength)
{
formatError = True;
break;
}
datagramIndex += 1;
if (datagramIndex + zoneLength > datagramLength)
{
formatError = True;
break;
}
currentZone = datagram + datagramIndex;
datagramIndex += zoneLength;
/* Place the new zone into the user's buffer. */
if (completionInfo->nextZoneOffset + zoneLength + 1 >
completionInfo->bufferSize)
{
overflow = True;
break;
}
MoveToOpaque(completionInfo->opaqueBuffer, completionInfo->nextZoneOffset,
currentZone, zoneLength);
MoveToOpaque(completionInfo->opaqueBuffer,
completionInfo->nextZoneOffset + zoneLength, "", 1);
completionInfo->nextZoneOffset += (zoneLength + 1);
completionInfo->zoneCount += 1;
validZones += 1;
zoneCount -= 1;
}
/* The next one we'll want will be past the ones we've just read. If
we've had a format error or we don't have them all yet, retry the
request. */
completionInfo->zoneListIndex += validZones;
if (formatError or (not overflow and not lastFlag))
{
SendZipPacketTo(completionInfo);
HandleIncomingPackets();
HandleDeferredTimerChecks();
return((long)True);
}
/* Otherwise, we're set, either due to overflow or we have them all:
cancel the retry timer, close our socket [this will cause
a recursive call which will remove the completion info], call the
completion routine, flee. */
CancelTimer(completionInfo->timerId);
opaqueBuffer = completionInfo->opaqueBuffer;
completionRoutine = completionInfo->zoneListCompletionRoutine;
userData = completionInfo->userData;
zoneCount = completionInfo->zoneCount;
if (CloseSocketOnNode(completionInfo->socket) isnt ATnoError)
ErrorLog("GetZoneListReply", ISevError, __LINE__, port,
IErrZipStubBadSocketClose, IMsgZipStubBadSocketClose,
Insert0());
HandleIncomingPackets();
HandleDeferredTimerChecks();
if (overflow)
errorCode = ATzipBufferTooSmall;
else
errorCode = ATnoError;
(*completionRoutine)(errorCode, userData, opaqueBuffer, zoneCount);
return((long)True);
} /* GetZoneListReply */