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.
288 lines
8.8 KiB
288 lines
8.8 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rtmpstub.c
|
|
|
|
Abstract:
|
|
|
|
Handle the RTMP protocol for a non-routing node.
|
|
|
|
Author:
|
|
|
|
Garth Conboy (Pacer Software)
|
|
Nikhil Kamkolkar (NikhilK)
|
|
|
|
Revision History:
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
#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 (GET_PORTDESCRIPTOR(port)->PortType is NonAppleTalkHalfPort)
|
|
return((long)True);
|
|
|
|
// Is the packet long enough to have any interestng data?
|
|
|
|
if (GET_PORTDESCRIPTOR(port)->ExtendedNetwork and
|
|
datagramLength < RtmpRangeEndOffset + 2) {
|
|
ErrorLog("RtmpPacketIn", ISevWarning, __LINE__, port,
|
|
IErrRtmpStubTooShortExt, IMsgRtmpStubTooShortExt,
|
|
Insert0());
|
|
return((long)True);
|
|
}
|
|
else if (not GET_PORTDESCRIPTOR(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 (GET_PORTDESCRIPTOR(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 GET_PORTDESCRIPTOR(port)->ExtendedNetwork) {
|
|
GET_PORTDESCRIPTOR(port)->SeenRouterRecently = True;
|
|
GET_PORTDESCRIPTOR(port)->LastRouterTime = CurrentRelativeTime();
|
|
GET_PORTDESCRIPTOR(port)->ARouter = sendersNode;
|
|
if (GET_PORTDESCRIPTOR(port)->ThisCableRange.FirstNetworkNumber is
|
|
UnknownNetworkNumber)
|
|
GET_PORTDESCRIPTOR(port)->ActiveNodes->ExtendedNode.NetworkNumber =
|
|
GET_PORTDESCRIPTOR(port)->ThisCableRange.FirstNetworkNumber =
|
|
sendersNode.networkNumber;
|
|
else if (GET_PORTDESCRIPTOR(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 (GET_PORTDESCRIPTOR(port)->SeenRouterRecently)
|
|
if (cableRange.firstNetworkNumber isnt
|
|
GET_PORTDESCRIPTOR(port)->ThisCableRange.FirstNetworkNumber or
|
|
cableRange.lastNetworkNumber isnt
|
|
GET_PORTDESCRIPTOR(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 GET_PORTDESCRIPTOR(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, 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 GET_PORTDESCRIPTOR(port)->RouterRunning) {
|
|
GET_PORTDESCRIPTOR(port)->SeenRouterRecently = True;
|
|
GET_PORTDESCRIPTOR(port)->LastRouterTime = CurrentRelativeTime();
|
|
GET_PORTDESCRIPTOR(port)->ARouter = sendersNode;
|
|
GET_PORTDESCRIPTOR(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 (GET_PORTDESCRIPTOR(port)->Flags & PD_ACTIVE and
|
|
not GET_PORTDESCRIPTOR(port)->RouterRunning and
|
|
GET_PORTDESCRIPTOR(port)->SeenRouterRecently and
|
|
(GET_PORTDESCRIPTOR(port)->LastRouterTime +
|
|
RtmpAgingTimerSeconds) < now) {
|
|
|
|
//
|
|
// Age out A-ROUTER; on extended networks age out THIS-CABLE-RANGE
|
|
// and THIS-ZONE too.
|
|
//
|
|
|
|
GET_PORTDESCRIPTOR(port)->SeenRouterRecently = False;
|
|
if (GET_PORTDESCRIPTOR(port)->ExtendedNetwork) {
|
|
PortHandlers portHandlers;
|
|
portHandlers = &portSpecificInfo[GET_PORTDESCRIPTOR(port)->PortType];
|
|
|
|
GET_PORTDESCRIPTOR(port)->ThisZoneValid = False;
|
|
GET_PORTDESCRIPTOR(port)->ThisCableRange.FirstNetworkNumber =
|
|
FirstValidNetworkNumber;
|
|
GET_PORTDESCRIPTOR(port)->ThisCableRange.LastNetworkNumber =
|
|
LastStartupNetworkNumber;
|
|
|
|
//
|
|
// If we have a zone-multicast address that is not broadcast,
|
|
// age it out too.
|
|
//
|
|
|
|
if (not FixedCompareCaseSensitive(GET_PORTDESCRIPTOR(port)->
|
|
zoneMulticastAddress,
|
|
portHandlers->
|
|
hardwareAddressLength,
|
|
portHandlers->broadcastAddress,
|
|
portHandlers->
|
|
hardwareAddressLength))
|
|
(*portHandlers->removeMulticastAddress)(port, 1,
|
|
GET_PORTDESCRIPTOR(port)->
|
|
zoneMulticastAddress);
|
|
FillMem(GET_PORTDESCRIPTOR(port)->ZoneMulticastAddress,
|
|
0, portHandlers->hardwareAddressLength);
|
|
}
|
|
}
|
|
|
|
// Restart the timer and flee.
|
|
|
|
StartTimer(RtmpAgingTimerExpired, RtmpAgingTimerSeconds, 0, empty);
|
|
HandleDeferredTimerChecks();
|
|
return;
|
|
|
|
} // RtmpAgingTimerExpired
|
|
|
|
|
|
|