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.
273 lines
9.7 KiB
273 lines
9.7 KiB
/* RtmpStub.c, /appletalk/source, Garth Conboy, 10/07/88 */
|
|
/* Copyright (c) 1988 by Pacer Software Inc., La Jolla, CA */
|
|
|
|
/* GC - Initial coding.
|
|
GC - (12/10/89): AppleTalk phase II comes to town; we're now just
|
|
an RTMP stub.
|
|
GC - (08/18/90): New error logging mechanism.
|
|
GC - (01/20/92): Removed usage of numberOfConfiguredPorts; portDescriptors
|
|
may now be sparse, we use portActive instead.
|
|
GC - (03/23/92): Try a little harder to figure out our port's zone name
|
|
when a router comes up on a cable, after startup or after
|
|
all routers have aged out.
|
|
|
|
*** Make the PVCS source control system happy:
|
|
$Header$
|
|
$Log$
|
|
***
|
|
|
|
Handle the RTMP protocol for a non-routing node.
|
|
|
|
*/
|
|
|
|
#define IncludeRtmpStubErrors 1
|
|
|
|
#include "atalk.h"
|
|
|
|
ExternForVisibleFunction TimerHandler RtmpAgingTimerExpired;
|
|
|
|
static Boolean firstCall = True;
|
|
|
|
void far ShutdownRtmpStub(void)
|
|
{
|
|
|
|
firstCall = True;
|
|
|
|
} /* ShutdownRtmpStub */
|
|
|
|
long far RtmpPacketIn(AppleTalkErrorCode errorCode,
|
|
long unsigned userData,
|
|
int port,
|
|
AppleTalkAddress source,
|
|
long destinationSocket,
|
|
int protocolType,
|
|
char far *datagram,
|
|
int datagramLength,
|
|
AppleTalkAddress actualDestination)
|
|
{
|
|
ExtendedAppleTalkNodeNumber sendersNode, ourNode;
|
|
AppleTalkNetworkRange cableRange;
|
|
AppleTalkAddress ourAddress;
|
|
|
|
/* "Use" unused formals. */
|
|
|
|
userData, source, actualDestination;
|
|
|
|
/* Do we care? */
|
|
|
|
if (errorCode is ATsocketClosed)
|
|
return((long)True);
|
|
else if (errorCode isnt ATnoError)
|
|
{
|
|
ErrorLog("RtmpPacketIn", ISevError, __LINE__, port,
|
|
IErrRtmpStubBadIncomingError, IMsgRtmpStubBadIncomingError,
|
|
Insert0());
|
|
return((long)True);
|
|
}
|
|
if (protocolType isnt DdpProtocolRtmpResponseOrData)
|
|
return((long)True);
|
|
|
|
if (firstCall)
|
|
{
|
|
StartTimer(RtmpAgingTimerExpired, RtmpAgingTimerSeconds, 0, empty);
|
|
firstCall = False;
|
|
}
|
|
|
|
/* Non-routing half port? Shouldn't really ever happen, except at startup,
|
|
and we don't care then. */
|
|
|
|
if (portDescriptors[port].portType is NonAppleTalkHalfPort)
|
|
return((long)True);
|
|
|
|
/* Is the packet long enough to have any interestng data? */
|
|
|
|
if (portDescriptors[port].extendedNetwork and
|
|
datagramLength < RtmpRangeEndOffset + 2)
|
|
{
|
|
ErrorLog("RtmpPacketIn", ISevWarning, __LINE__, port,
|
|
IErrRtmpStubTooShortExt, IMsgRtmpStubTooShortExt,
|
|
Insert0());
|
|
return((long)True);
|
|
}
|
|
else if (not portDescriptors[port].extendedNetwork and
|
|
datagramLength < RtmpSendersIdOffset)
|
|
{
|
|
ErrorLog("RtmpPacketIn", ISevWarning, __LINE__, port,
|
|
IErrRtmpStubTooShort, IMsgRtmpStubTooShort,
|
|
Insert0());
|
|
return((long)True);
|
|
}
|
|
|
|
/* Okay, pull out what we're interested in. */
|
|
|
|
sendersNode.networkNumber =
|
|
(short unsigned)(datagram[RtmpSendersNetworkOffset] << 8);
|
|
sendersNode.networkNumber +=
|
|
(unsigned char)datagram[RtmpSendersNetworkOffset + 1];
|
|
if (datagram[RtmpSendersIdLengthOffset] isnt 8)
|
|
{
|
|
ErrorLog("RtmpPacketIn", ISevWarning, __LINE__, port,
|
|
IErrRtmpStubBadIdLength, IMsgRtmpStubBadIdLength,
|
|
Insert0());
|
|
return((long)True);
|
|
}
|
|
sendersNode.nodeNumber = datagram[RtmpSendersIdOffset];
|
|
if (portDescriptors[port].extendedNetwork)
|
|
{
|
|
cableRange.firstNetworkNumber =
|
|
(short unsigned)(datagram[RtmpRangeStartOffset] << 8);
|
|
cableRange.firstNetworkNumber +=
|
|
(unsigned char )datagram[RtmpRangeStartOffset + 1];
|
|
cableRange.lastNetworkNumber =
|
|
(short unsigned)(datagram[RtmpRangeEndOffset] << 8);
|
|
cableRange.lastNetworkNumber +=
|
|
(unsigned char )datagram[RtmpRangeEndOffset + 1];
|
|
if (not CheckNetworkRange(cableRange))
|
|
return((long)True);
|
|
}
|
|
|
|
/* On a non-extended network, we don't have to do any checking, just copy
|
|
the information into A-ROUTER and THIS-NET. */
|
|
|
|
if (not portDescriptors[port].extendedNetwork)
|
|
{
|
|
portDescriptors[port].seenRouterRecently = True;
|
|
portDescriptors[port].lastRouterTime = CurrentRelativeTime();
|
|
portDescriptors[port].aRouter = sendersNode;
|
|
if (portDescriptors[port].thisCableRange.firstNetworkNumber is
|
|
UnknownNetworkNumber)
|
|
portDescriptors[port].activeNodes->extendedNode.networkNumber =
|
|
portDescriptors[port].thisCableRange.firstNetworkNumber =
|
|
sendersNode.networkNumber;
|
|
else if (portDescriptors[port].thisCableRange.firstNetworkNumber isnt
|
|
sendersNode.networkNumber)
|
|
ErrorLog("RtmpPacketIn", ISevWarning, __LINE__, port,
|
|
IErrRtmpStubNetNumChanged, IMsgRtmpStubNetNumChanged,
|
|
Insert0());
|
|
return((long)True);
|
|
}
|
|
|
|
/* On extended networks, we may want to reject the information: If we
|
|
already know about a router, the cable ranges must exacly match; If we
|
|
don't know about a router, our node's network number must be within
|
|
the cable range specified by the first tuple. The latter test will
|
|
discard the information if our node is in the startup range (which is
|
|
the right thing to do). */
|
|
|
|
if (portDescriptors[port].seenRouterRecently)
|
|
if (cableRange.firstNetworkNumber isnt
|
|
portDescriptors[port].thisCableRange.firstNetworkNumber or
|
|
cableRange.lastNetworkNumber isnt
|
|
portDescriptors[port].thisCableRange.lastNetworkNumber)
|
|
return((long)True);
|
|
else
|
|
/* Okay */ ;
|
|
|
|
/* Okay, we've seen a valid Rtmp data, this should allow us to find the
|
|
zone name for the port. We do this outside of the "not seenRouterRecently"
|
|
case because the first time a router send out an Rtmp data it may not
|
|
know everything yet, or GetNetworkInfoForNode() (which calls WaitFor) may
|
|
really do a hard wait and we may need to try it a second time (due to not
|
|
repsonding to Aarp LocateNode's the first time through... the second time
|
|
our addresses should be cached by the remote router and he won't need
|
|
to do a LocateNode again). */
|
|
|
|
if (not portDescriptors[port].thisZoneValid)
|
|
{
|
|
if (MapSocketToAddress(destinationSocket, &ourAddress) isnt ATnoError)
|
|
{
|
|
ErrorLog("RtmpPacketIn", ISevError, __LINE__, port,
|
|
IErrRtmpStubCouldntMapAddr, IMsgRtmpStubCouldntMapAddr,
|
|
Insert0());
|
|
return((long)True);
|
|
}
|
|
if (not IsWithinNetworkRange(ourAddress.networkNumber, &cableRange))
|
|
return((long)True);
|
|
|
|
/* Oh boy, a new router, see if it will tell us our zone name. */
|
|
|
|
ourNode.networkNumber = ourAddress.networkNumber;
|
|
ourNode.nodeNumber = ourAddress.nodeNumber;
|
|
GetNetworkInfoForNode(port, ourNode, False);
|
|
}
|
|
|
|
/* Well, it looks like we win. Copy the information. Don't do it
|
|
if we're a router [maybe a proxy node on arouting port] -- we don't
|
|
want "aRouter" to shift away from "us." */
|
|
|
|
if (not portDescriptors[port].routerRunning)
|
|
{
|
|
portDescriptors[port].seenRouterRecently = True;
|
|
portDescriptors[port].lastRouterTime = CurrentRelativeTime();
|
|
portDescriptors[port].aRouter = sendersNode;
|
|
portDescriptors[port].thisCableRange = cableRange;
|
|
}
|
|
|
|
/* All set! */
|
|
|
|
return((long)True);
|
|
|
|
} /* RtmpPacketIn */
|
|
|
|
ExternForVisibleFunction void far
|
|
RtmpAgingTimerExpired(long unsigned timerId,
|
|
int additionalDataSize,
|
|
char far *additionalData)
|
|
{
|
|
int port;
|
|
long unsigned now = CurrentRelativeTime();
|
|
|
|
/* "Use" unused formals. */
|
|
|
|
timerId, additionalData, additionalDataSize;
|
|
|
|
/* Walk through our active ports; have any routers aged out? */
|
|
|
|
for (port = 0; port < MaximumNumberOfPorts; port += 1)
|
|
if (portDescriptors[port].portActive and
|
|
not portDescriptors[port].routerRunning and
|
|
portDescriptors[port].seenRouterRecently and
|
|
(portDescriptors[port].lastRouterTime +
|
|
RtmpAgingTimerSeconds) < now)
|
|
{
|
|
|
|
/* Age out A-ROUTER; on extended networks age out THIS-CABLE-RANGE
|
|
and THIS-ZONE too. */
|
|
|
|
portDescriptors[port].seenRouterRecently = False;
|
|
if (portDescriptors[port].extendedNetwork)
|
|
{
|
|
PortHandlers portHandlers;
|
|
portHandlers = &portSpecificInfo[portDescriptors[port].portType];
|
|
|
|
portDescriptors[port].thisZoneValid = False;
|
|
portDescriptors[port].thisCableRange.firstNetworkNumber =
|
|
FirstValidNetworkNumber;
|
|
portDescriptors[port].thisCableRange.lastNetworkNumber =
|
|
LastStartupNetworkNumber;
|
|
|
|
/* If we have a zone-multicast address that is not broadcast,
|
|
age it out too. */
|
|
|
|
if (not FixedCompareCaseSensitive(portDescriptors[port].
|
|
zoneMulticastAddress,
|
|
portHandlers->
|
|
hardwareAddressLength,
|
|
portHandlers->broadcastAddress,
|
|
portHandlers->
|
|
hardwareAddressLength))
|
|
(*portHandlers->removeMulticastAddress)(port, 1,
|
|
portDescriptors[port].
|
|
zoneMulticastAddress);
|
|
FillMem(portDescriptors[port].zoneMulticastAddress,
|
|
0, portHandlers->hardwareAddressLength);
|
|
}
|
|
}
|
|
|
|
/* Restart the timer and flee. */
|
|
|
|
StartTimer(RtmpAgingTimerExpired, RtmpAgingTimerSeconds, 0, empty);
|
|
HandleDeferredTimerChecks();
|
|
return;
|
|
|
|
} /* RtmpAgingTimerExpired */
|