/// <summary> /// Called when a PUP comes in on a known socket. Establishes a new BSP channel. /// A worker of the appropriate type is woken up to service the channel. /// </summary> /// <param name="p"></param> public static void EstablishRendezvous(PUP p, Type workerType) { if (p.Type != PupType.RFC) { Log.Write(LogType.Error, LogComponent.RTP, "Expected RFC pup, got {0}", p.Type); return; } UInt32 socketID = SocketIDGenerator.GetNextSocketID(); Log.Write(LogType.Error, LogComponent.Exp, "setting up rendezvous on {0} {1} with socketID {2}", p.DestinationPort, p.SourcePort, socketID); BSPChannel newChannel = new BSPChannel(p, socketID); newChannel.OnDestroy += OnChannelDestroyed; _activeChannels.Add(socketID, newChannel); // // Initialize the worker for this channel. InitializeWorkerForChannel(newChannel, workerType); // Send RFC response to complete the rendezvous: // Modify the destination port to specify our network PUPPort sourcePort = p.DestinationPort; sourcePort.Network = DirectoryServices.Instance.LocalNetwork; PUP rfcResponse = new PUP(PupType.RFC, p.ID, newChannel.ClientPort, sourcePort, newChannel.ServerPort.ToArray()); Log.Write(LogComponent.RTP, "Establishing Rendezvous, ID {0}, Server port {1}, Client port {2}.", p.ID, newChannel.ServerPort, newChannel.ClientPort); Router.Instance.SendPup(rfcResponse); }
private void SendGatewayInformationResponse(PUP p) { // // Pup Type: 201 (octal) // Pup ID: same as in Request Pup // Pup Contents: one or more groups of four bytes, each providing routing information for // one network, as follows: // // <target-net> <gateway-net> <gateway-host> <hop-count> // // In each group, the first byte specifies the target network number. If the gateway host is // directly connected to that network, then the <hop-count> is zero and the <gateway-net> and // <gateway-host> describe the gateway’s connection to the network. // If the gateway host is not directly connected to the target network, then the second and // third bytes give the network and host numbers of another gateway through which the // responding gateway routes Pups to that network, and the fourth byte gives the hop count, // i.e., the number of additional gateways (not including itself) through which the responding // gateway believes a Pup must pass to reach the specified network. A hop count greater than // the constant maxHops (presently 15) signifies that the target network is believed to be // inaccessible. // byte[] infoArray = GetGatewayInformationArray(); PUPPort localPort = new PUPPort(DirectoryServices.Instance.LocalHostAddress, p.DestinationPort.Socket); // Response must contain our network number; this is used to tell clients what network they're on if they don't already know. PUPPort remotePort = new PUPPort(DirectoryServices.Instance.LocalNetwork, p.SourcePort.Host, p.SourcePort.Socket); PUP response = new PUP(PupType.GatewayInformationResponse, p.ID, remotePort, localPort, infoArray); Router.Instance.SendPup(response); }
public static void SendFile(PUPPort destination, Stream data) { UInt32 socketID = SocketIDGenerator.GetNextSocketID(); EFTPChannel newChannel = new EFTPChannel(destination, socketID); _activeChannels.Add(socketID, newChannel); EFTPSend.StartSend(newChannel, data); }
public EFTPChannel(PUPPort destination, UInt32 socketID) { _clientConnectionPort = destination; _outputAckEvent = new AutoResetEvent(false); // We create our connection port using a unique socket address. _serverConnectionPort = new PUPPort(DirectoryServices.Instance.LocalHostAddress, socketID); _outputQueue = new Queue <byte>(65536); _sendPos = 0; }
public BSPChannel(PUP rfcPup, UInt32 socketID) { _inputLock = new ReaderWriterLockSlim(); _outputLock = new ReaderWriterLockSlim(); _inputWriteEvent = new AutoResetEvent(false); _inputQueue = new Queue <ushort>(65536); _outputAckEvent = new AutoResetEvent(false); _outputReadyEvent = new AutoResetEvent(false); _dataReadyEvent = new AutoResetEvent(false); _outputQueue = new Queue <byte>(65536); _outputWindow = new List <PUP>(16); _outputWindowLock = new ReaderWriterLockSlim(); _destroyed = false; // Init IDs, etc. based on RFC PUP _lastClientRecvPos = _startPos = _recvPos = _sendPos = rfcPup.ID; // Set up socket addresses. // The client sends the connection port it prefers to use // in the RFC pup. _clientConnectionPort = new PUPPort(rfcPup.Contents, 0); _originalDestinationPort = rfcPup.DestinationPort; // If the client doesn't know what network it's on, it's now on ours. if (_clientConnectionPort.Network == 0) { _clientConnectionPort.Network = DirectoryServices.Instance.LocalNetwork; } // We create our connection port using a unique socket address. _serverConnectionPort = new PUPPort(DirectoryServices.Instance.LocalHostAddress, socketID); // // Init MaxPups to indicate that we need to find out what the client actually supports when we first // start sending data. // _clientLimits.MaxPups = 0xffff; // Create our consumer thread for output and kick it off. _consumerThread = new Thread(OutputConsumerThread); _consumerThread.Start(); }
private void GatewayInformationWorker() { uint infoPupID = (uint)(new Random().Next()); while (true) { // // From gatewayinformation.press: // "Each gateway host must also periodically broadcast Gateway Information Pups, as described above, // on all directly-connected networks. The frequency of this broadcast should be approximately one // every 30 seconds, and immediately whenever the gateway’s own routing table changes (see below). // These Pups should be sent from socket 2 to socket 2." // // At this time, we don't do anything with gateway information PUPs that we receive -- they could // at some point be used as originally intended, to dynamically update routing tables, but it would // require some serious security investments to make sure that the tables don't get poisoned. // However, even though we don't use them, some Alto software does. For example, the PUP libraries // used by Mazewar expect to get periodic updates or eventually it will assume the route is no longer // viable and drop connections. // // Delay 30 seconds Thread.Sleep(30000); byte[] infoArray = GetGatewayInformationArray(); // From us, on socket 2 PUPPort localPort = new PUPPort(DirectoryServices.Instance.LocalHostAddress, 2); // // The set of known networks is by default the set of directly-connected networks. // byte[] knownNetworks = Router.Instance.RoutingTable.GetKnownNetworks(); foreach (byte network in knownNetworks) { // Send a broadcast to the specified network PUPPort remotePort = new PUPPort(network, 0, 2); PUP infoPup = new PUP(PupType.GatewayInformationResponse, infoPupID++, remotePort, localPort, infoArray); Router.Instance.SendPup(infoPup); Log.Write(LogComponent.MiscServices, "Gateway Information packet sent to network {0}", network); } } }