예제 #1
0
        /// <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);
        }
예제 #2
0
        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);
        }
예제 #3
0
파일: EFTPManager.cs 프로젝트: shirriff/IFS
        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);
        }
예제 #4
0
파일: EFTPChannel.cs 프로젝트: shirriff/IFS
        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;
        }
예제 #5
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();
        }
예제 #6
0
        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);
                }
            }
        }