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.
 
 
 
 
 
 

405 lines
12 KiB

/* node.c, appletalk/source, Garth Conboy, 11/10/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 - (08/18/90): New error logging mechanism.
GC - (10/08/90): Half port support.
GC - (02/07/92): Added PRAM address support.
GC - (11/22/92): Added reference counts and locking support.
*** Make the PVCS source control system happy:
$Header$
$Log$
***
Manage "our" nodes on our various ports.
*/
#define IncludeNodeErrors 1
#include "atalk.h"
ExternForVisibleFunction Boolean
OpenStaticSockets(int port,
ExtendedAppleTalkNodeNumber node);
AppleTalkErrorCode far GetNodeOnPort(int port,
Boolean allowStartupRange,
Boolean serverNode,
Boolean routersNode,
ExtendedAppleTalkNodeNumber far *node)
{
int nodeNumber;
ActiveNode activeNode;
ExtendedAppleTalkNodeNumber newNode;
ExtendedAppleTalkNodeNumber desiredNode = {UnknownNetworkNumber,
UnknownNodeNumber};
/* If the "default port" is requested, demystify it. */
if (not appleTalkRunning)
return(ATappleTalkShutDown);
if (port is DefaultPort)
if ((port = FindDefaultPort()) < 0)
return(ATappleTalkShutDown);
if (not PortDescriptor(port)->portActive)
return(ATappleTalkShutDown);
/* Don't let anybody use these databases while we're chaning them! */
DeferTimerChecking();
DeferIncomingPackets();
/* Don't allow too many nodes per port! */
if (ElementsOnList(PortDescriptor(port)->activeNodes) > MaximumNodesPerPort)
{
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(ATnoMoreNodes);
}
/* On non-extended ports we only allow one node! The theory being that some
LocalTalk cards are too smart for their own good and have a conecpt of
their "source node number" and thus only support one node, also on
non-extended ports, nodes are scarse. */
TakeLock(DdpLock);
if (not PortDescriptor(port)->extendedNetwork and
PortDescriptor(port)->activeNodes isnt empty)
{
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(ATnoMoreNodes);
}
else if (not PortDescriptor(port)->extendedNetwork)
PortDescriptor(port)->activeNodes = (ActiveNode)2; /* Hold our slot. */
/* Only one node would ever be usefull on half ports. */
if (PortDescriptor(port)->portType is NonAppleTalkHalfPort and
PortDescriptor(port)->activeNodes isnt empty)
{
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(ATnoMoreNodes);
}
else if (PortDescriptor(port)->portType is NonAppleTalkHalfPort)
PortDescriptor(port)->activeNodes = (ActiveNode)2; /* Hold our slot. */
ReleaseLock(DdpLock);
/* Find a node... */
if (PortDescriptor(port)->portType is NonAppleTalkHalfPort)
{
/* Build a dummy active node; invalid network/node values. */
newNode.networkNumber = UnknownNetworkNumber;
newNode.nodeNumber = UnknownNodeNumber;
if ((activeNode = (ActiveNode)Calloc(sizeof(*activeNode), 1)) is empty)
{
ErrorLog("GetNodeOnPort", ISevError, __LINE__, port,
IErrNodeOutOfMemory, IMsgNodeOutOfMemory,
Insert0());
PortDescriptor(port)->activeNodes = Empty;
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(AToutOfMemory);
}
activeNode->port = port;
activeNode->extendedNode = newNode;
TakeLock(DdpLock);
PortDescriptor(port)->activeNodes = Link(activeNode);
ReleaseLock(DdpLock);
HandleIncomingPackets();
HandleDeferredTimerChecks();
}
else if (PortDescriptor(port)->portType is LocalTalkNetwork)
{
/* Pick a desired node, if we have a PRAM value. */
if (routersNode and
PortDescriptor(port)->routersPRamStartupNode.networkNumber
isnt UnknownNetworkNumber)
desiredNode = PortDescriptor(port)->routersPRamStartupNode;
else if (not routersNode and
PortDescriptor(port)->usersPRamStartupNode.networkNumber
isnt UnknownNetworkNumber)
desiredNode = PortDescriptor(port)->usersPRamStartupNode;
/* Let the LocalTalk hardware have a crack at it. */
nodeNumber = FindLocalTalkNodeNumber(port, desiredNode,
PortDescriptor(port)->controllerInfo);
if (nodeNumber < 0)
{
ErrorLog("GetNodeOnPort", ISevError, __LINE__, port,
IErrNodeNoLocalTalkNode, IMsgNodeNoLocalTalkNode,
Insert0());
PortDescriptor(port)->activeNodes = Empty;
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(ATnoMoreNodes);
}
newNode.networkNumber =
PortDescriptor(port)->thisCableRange.firstNetworkNumber;
newNode.nodeNumber = (char)nodeNumber;
/* Build a new active node structure and tack it onto the port. */
if ((activeNode = (ActiveNode)Calloc(sizeof(*activeNode), 1)) is empty)
{
ErrorLog("GetNodeOnPort", ISevError, __LINE__, port,
IErrNodeOutOfMemory, IMsgNodeOutOfMemory,
Insert0());
PortDescriptor(port)->activeNodes = Empty;
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(AToutOfMemory);
}
activeNode->port = port;
activeNode->extendedNode = newNode;
TakeLock(DdpLock);
PortDescriptor(port)->activeNodes = Link(activeNode);
ReleaseLock(DdpLock);
HandleIncomingPackets();
HandleDeferredTimerChecks();
}
else
{
/* Pick a desired node, if we have a PRAM value. */
if (routersNode and
PortDescriptor(port)->routersPRamStartupNode.networkNumber
isnt UnknownNetworkNumber)
desiredNode = PortDescriptor(port)->routersPRamStartupNode;
else if (not routersNode and
not PortDescriptor(port)->firstUserNodeAllocated and
PortDescriptor(port)->usersPRamStartupNode.networkNumber
isnt UnknownNetworkNumber)
desiredNode = PortDescriptor(port)->usersPRamStartupNode;
/* Okay, let AARP have a crack at finding a node! */
HandleIncomingPackets();
HandleDeferredTimerChecks();
if (not AarpForNodeOnPort(port, allowStartupRange, serverNode,
desiredNode, &newNode))
return(ATnoMoreNodes);
}
/* Set up the RTMP, NBP and EP listeners on the new node. */
if (not OpenStaticSockets(port, newNode))
ErrorLog("GetNodeOnPort", ISevError, __LINE__, port,
IErrNodeCouldStartListeners, IMsgNodeCouldStartListeners,
Insert0());
if (node isnt empty)
*node = newNode;
/* Try to save PRAM info... */
if (routersNode)
{
SavePRamAddress(port, True, newNode);
PortDescriptor(port)->routersPRamStartupNode = newNode;
}
else if (not routersNode and
not PortDescriptor(port)->firstUserNodeAllocated)
{
SavePRamAddress(port, False, newNode);
PortDescriptor(port)->firstUserNodeAllocated = True;
PortDescriptor(port)->usersPRamStartupNode = newNode;
}
return(ATnoError);
} /* GetNodeOnPort */
AppleTalkErrorCode far ReleaseNodeOnPort(int port,
ExtendedAppleTalkNodeNumber node)
{
ActiveNode activeNode;
OpenSocket openSocket, nextOpenSocket;
/* If the "default port" is requested, demystify it. */
if (port is DefaultPort)
if ((port = FindDefaultPort()) < 0)
return(ATappleTalkShutDown);
/* Don't let anybody use these databases while we're chaning them! */
DeferTimerChecking();
DeferIncomingPackets();
/* Find the node on the port's active node list. */
TakeLock(DdpLock);
for (activeNode = PortDescriptor(port)->activeNodes;
activeNode isnt Empty;
activeNode = activeNode->next)
if (ExtendedAppleTalkNodesEqual(&activeNode->extendedNode, &node))
break;
Link(activeNode);
if (activeNode is empty)
{
ReleaseLock(DdpLock);
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(ATnodeNotInUse);
}
activeNode->closing = True;
/* Close any sockets that are still open. */
openSocket = Link(activeNode->openSockets);
ReleaseLock(DdpLock);
while (openSocket isnt empty)
{
if (CloseSocketOnNode(openSocket->socket, Empty, (long)0) isnt ATnoError)
ErrorLog("ReleaseNodeOnPort", ISevError, __LINE__, port,
IErrNodeCouldNotClose, IMsgNodeCouldNotClose,
Insert0());
TakeLock(DdpLock);
nextOpenSocket = Link(openSocket->next);
ReleaseLock(DdpLock);
UnlinkOpenSocket(openSocket);
openSocket = nextOpenSocket;
}
/* Unlink the beast; the link we just got and the link from the active
node list. */
UnlinkActiveNode(activeNode);
UnlinkActiveNode(activeNode);
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(ATnoError);
} /* ReleaseNodeOnPort */
void far UnlinkActiveNode(ActiveNode targetActiveNode)
{
ActiveNode activeNode, previousActiveNode;
int port;
/* Are we the last referant? */
TakeLock(DdpLock);
if (not UnlinkNoFree(targetActiveNode))
{
ReleaseLock(DdpLock);
return;
}
/* Okay, we're the last, remove from the active node list. */
port = targetActiveNode->port;
for (activeNode = PortDescriptor(port)->activeNodes,
previousActiveNode = empty;
activeNode isnt empty;
previousActiveNode = activeNode,
activeNode = activeNode->next)
if (ExtendedAppleTalkNodesEqual(&activeNode->extendedNode,
&targetActiveNode->extendedNode))
break;
if (activeNode is Empty)
ErrorLog("UnlinkActiveNode", ISevError, __LINE__, activeNode->port,
IErrNodeMissing, IMsgNodeMissing,
Insert0());
else
if (previousActiveNode is empty)
PortDescriptor(port)->activeNodes = targetActiveNode->next;
else
previousActiveNode->next = targetActiveNode->next;
/* Okay, free the beast and run away. */
ReleaseLock(DdpLock);
Free(targetActiveNode);
} /* UnlinkActiveNode */
void SavePRamAddress(int port, Boolean routersNode,
ExtendedAppleTalkNodeNumber node)
{
/* If the target environment supports the concept, this is a good place
to save away the last used AppleTalk addresses in PRAM. This information
should then be passed back to Initialize() (in the PRam fields of
portInfo[]) on subsequent stack/router startup calls. */
port;
routersNode;
node;
}
Boolean far RoutersNodeOnPort(int port,
ExtendedAppleTalkNodeNumber *extendedNode)
{
ActiveNode activeNode;
Boolean found = False;
if (port is DefaultPort)
if ((port = FindDefaultPort()) < 0)
return(empty);
DeferTimerChecking();
DeferIncomingPackets();
TakeLock(DdpLock);
for (activeNode = PortDescriptor(port)->activeNodes;
activeNode isnt empty;
activeNode = activeNode->next)
if (activeNode->routersNode)
break;
if (activeNode isnt Empty)
{
found = True;
*extendedNode = activeNode->extendedNode;
}
ReleaseLock(DdpLock);
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(found);
} /* RoutersNodeOnPort */
ExternForVisibleFunction Boolean
OpenStaticSockets(int port,
ExtendedAppleTalkNodeNumber node)
{
long nbpSocket, epSocket, rtmpSocket;
if (OpenSocketOnNode(&nbpSocket, port, &node, NamesInformationSocket,
NbpPacketIn, (long)0, False, empty, 0,
empty) is ATnoError)
if (OpenSocketOnNode(&epSocket, port, &node, EchoerSocket, EpPacketIn,
(long)0, False, empty, 0, empty) is ATnoError)
if (OpenSocketOnNode(&rtmpSocket, port, &node, RtmpSocket,
RtmpPacketIn, (long)0, False, empty,
0, empty) is ATnoError)
return(True);
else
{
CloseSocketOnNode(nbpSocket, Empty, (long)0);
CloseSocketOnNode(epSocket, Empty, (long)0);
}
else
CloseSocketOnNode(nbpSocket, Empty, (long)0);
return(False);
} /* OpenStaticSockets */