Beispiel #1
0
        public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, ITranslator translator)
        {
            if (packetType == NodePacketType.NodeShutdown)
            {
                RemoveNodeFromMapping(nodeId);
            }

            _packetFactory.DeserializeAndRoutePacket(nodeId, packetType, translator);
        }
Beispiel #2
0
            public async Task RunPacketReadLoopAsync()
            {
                while (true)
                {
                    try
                    {
                        int bytesRead = await CommunicationsUtilities.ReadAsync(_clientToServerStream, _headerByte, _headerByte.Length);

                        if (!ProcessHeaderBytesRead(bytesRead))
                        {
                            return;
                        }
                    }
                    catch (IOException e)
                    {
                        CommunicationsUtilities.Trace(_nodeId, "EXCEPTION in RunPacketReadLoopAsync: {0}", e);
                        _packetFactory.RoutePacket(_nodeId, new NodeShutdown(NodeShutdownReason.ConnectionFailed));
                        Close();
                        return;
                    }

                    NodePacketType packetType   = (NodePacketType)_headerByte[0];
                    int            packetLength = BinaryPrimitives.ReadInt32LittleEndian(new Span <byte>(_headerByte, 1, 4));

                    _readBufferMemoryStream.SetLength(packetLength);
                    byte[] packetData = _readBufferMemoryStream.GetBuffer();

                    try
                    {
                        int bytesRead = await CommunicationsUtilities.ReadAsync(_clientToServerStream, packetData, packetLength);

                        if (!ProcessBodyBytesRead(bytesRead, packetLength, packetType))
                        {
                            return;
                        }
                    }
                    catch (IOException e)
                    {
                        CommunicationsUtilities.Trace(_nodeId, "EXCEPTION in RunPacketReadLoopAsync (Reading): {0}", e);
                        _packetFactory.RoutePacket(_nodeId, new NodeShutdown(NodeShutdownReason.ConnectionFailed));
                        Close();
                        return;
                    }

                    // Read and route the packet.
                    if (!ReadAndRoutePacket(packetType, packetData, packetLength))
                    {
                        return;
                    }

                    if (packetType == NodePacketType.NodeShutdown)
                    {
                        Close();
                        return;
                    }
                }
            }
Beispiel #3
0
        /// <summary>
        /// Creates and routes a packet with data from a binary stream.
        /// </summary>
        public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, ITranslator translator)
        {
            // PERF: Not using VerifyThrow to avoid boxing of packetType in the non-error case
            if (!_packetFactories.TryGetValue(packetType, out PacketFactoryRecord record))
            {
                ErrorUtilities.ThrowInternalError("No packet handler for type {0}", packetType);
            }

            record.DeserializeAndRoutePacket(nodeId, translator);
        }
Beispiel #4
0
 private bool ProcessBodyBytesRead(int bytesRead, int packetLength, NodePacketType packetType)
 {
     if (bytesRead != packetLength)
     {
         CommunicationsUtilities.Trace(_nodeId, "Bad packet read for packet {0} - Expected {1} bytes, got {2}", packetType, packetLength, bytesRead);
         _packetFactory.RoutePacket(_nodeId, new NodeShutdown(NodeShutdownReason.ConnectionFailed));
         Close();
         return(false);
     }
     return(true);
 }
        /// <summary>
        /// Creates and routes a packet with data from a binary stream.
        /// </summary>
        public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, INodePacketTranslator translator)
        {
            // PERF: Not using VerifyThrow to avoid boxing of packetType in the non-error case
            if (!_packetFactories.ContainsKey(packetType))
            {
                ErrorUtilities.ThrowInternalError("No packet handler for type {0}", packetType);
            }

            PacketFactoryRecord record = _packetFactories[packetType];
            record.DeserializeAndRoutePacket(nodeId, translator);
        }
Beispiel #6
0
 /// <summary>
 /// Takes a serializer, deserializes the packet and routes it to the appropriate handler.
 /// </summary>
 /// <param name="nodeId">The node from which the packet was received.</param>
 /// <param name="packetType">The packet type.</param>
 /// <param name="translator">The translator containing the data from which the packet should be reconstructed.</param>
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, INodePacketTranslator translator)
 {
     if (_nodeIdToPacketFactory.ContainsKey(nodeId))
     {
         _nodeIdToPacketFactory[nodeId].DeserializeAndRoutePacket(nodeId, packetType, translator);
     }
     else
     {
         _localPacketFactory.DeserializeAndRoutePacket(nodeId, packetType, translator);
     }
 }
Beispiel #7
0
 /// <summary>
 /// Takes a serializer, deserializes the packet and routes it to the appropriate handler.
 /// </summary>
 /// <param name="nodeId">The node from which the packet was received.</param>
 /// <param name="packetType">The packet type.</param>
 /// <param name="translator">The translator containing the data from which the packet should be reconstructed.</param>
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, ITranslator translator)
 {
     if (_nodeIdToPacketFactory.TryGetValue(nodeId, out INodePacketFactory nodePacketFactory))
     {
         nodePacketFactory.DeserializeAndRoutePacket(nodeId, packetType, translator);
     }
     else
     {
         _localPacketFactory.DeserializeAndRoutePacket(nodeId, packetType, translator);
     }
 }
Beispiel #8
0
            /// <summary>
            /// Method called when the body of a packet has been read.
            /// </summary>
            private void BodyReadComplete(IAsyncResult result)
            {
                NodePacketType packetType = (NodePacketType)_headerByte[0];
                var            state      = (Tuple <byte[], int>)result.AsyncState;

                byte[] packetData   = state.Item1;
                int    packetLength = state.Item2;
                int    bytesRead;

                try
                {
                    try
                    {
                        bytesRead = _clientToServerStream.EndRead(result);
                    }

                    // Workaround for CLR stress bug; it sporadically calls us twice on the same async
                    // result, and EndRead will throw on the second one. Pretend the second one never happened.
                    catch (ArgumentException)
                    {
                        CommunicationsUtilities.Trace(_nodeId, "Hit CLR bug #825607: called back twice on same async result; ignoring");
                        return;
                    }

                    if (!ProcessBodyBytesRead(bytesRead, packetLength, packetType))
                    {
                        return;
                    }
                }
                catch (IOException e)
                {
                    CommunicationsUtilities.Trace(_nodeId, "EXCEPTION in BodyReadComplete (Reading): {0}", e);
                    _packetFactory.RoutePacket(_nodeId, new NodeShutdown(NodeShutdownReason.ConnectionFailed));
                    Close();
                    return;
                }

                // Read and route the packet.
                if (!ReadAndRoutePacket(packetType, packetData, packetLength))
                {
                    return;
                }

                if (packetType != NodePacketType.NodeShutdown)
                {
                    // Read the next packet.
                    BeginAsyncPacketRead();
                }
                else
                {
                    Close();
                }
            }
            /// <summary>
            /// Callback invoked by the completion of a read of a header byte on one of the named pipes.
            /// </summary>
            private void HeaderReadComplete(IAsyncResult result)
            {
                int bytesRead;

                try
                {
                    try
                    {
                        bytesRead = _clientToServerStream.EndRead(result);
                    }

                    // Workaround for CLR stress bug; it sporadically calls us twice on the same async
                    // result, and EndRead will throw on the second one. Pretend the second one never happened.
                    catch (ArgumentException)
                    {
                        CommunicationsUtilities.Trace(_nodeId, "Hit CLR bug #825607: called back twice on same async result; ignoring");
                        return;
                    }

                    if (!ProcessHeaderBytesRead(bytesRead))
                    {
                        return;
                    }
                }
                catch (IOException e)
                {
                    CommunicationsUtilities.Trace(_nodeId, "EXCEPTION in HeaderReadComplete: {0}", e);
                    _packetFactory.RoutePacket(_nodeId, new NodeShutdown(NodeShutdownReason.ConnectionFailed));
                    Close();
                    return;
                }

                NodePacketType packetType   = (NodePacketType)_headerByte[0];
                int            packetLength = BitConverter.ToInt32(_headerByte, 1);

                byte[] packetData;
                if (packetLength < _smallReadBuffer.Length)
                {
                    packetData = _smallReadBuffer;
                }
                else
                {
                    // Preallocated buffer is not large enough to hold the body. Allocate now, but don't hold it forever.
                    packetData = new byte[packetLength];
                }

                _clientToServerStream.BeginRead(packetData, 0, packetLength, BodyReadComplete, new Tuple <byte[], int>(packetData, packetLength));
            }
Beispiel #10
0
 private bool ReadAndRoutePacket(NodePacketType packetType, byte [] packetData, int packetLength)
 {
     try
     {
         // The buffer is publicly visible so that InterningBinaryReader doesn't have to copy to an intermediate buffer.
         // Since the buffer is publicly visible dispose right away to discourage outsiders from holding a reference to it.
         using (var packetStream = new MemoryStream(packetData, 0, packetLength, /*writeable*/ false, /*bufferIsPubliclyVisible*/ true))
         {
             ITranslator readTranslator = BinaryTranslator.GetReadTranslator(packetStream, _sharedReadBuffer);
             _packetFactory.DeserializeAndRoutePacket(_nodeId, packetType, readTranslator);
         }
     }
     catch (IOException e)
     {
         CommunicationsUtilities.Trace(_nodeId, "EXCEPTION in ReadAndRoutPacket: {0}", e);
         _packetFactory.RoutePacket(_nodeId, new NodeShutdown(NodeShutdownReason.ConnectionFailed));
         Close();
         return(false);
     }
     return(true);
 }
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, INodePacketTranslator translator)
 {
     throw new NotImplementedException();
 }
 public void UnregisterPacketHandler(NodePacketType packetType)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Deserializes and routes a packet.  Not used in the in-proc node.
 /// </summary>
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, INodePacketTranslator translator)
 {
     // Not used
     ErrorUtilities.ThrowInternalErrorUnreachable();
 }
 /// <summary>
 /// Unregisters a packet handler.
 /// </summary>
 /// <param name="packetType">The packet type.</param>
 public void UnregisterPacketHandler(NodePacketType packetType)
 {
     _packetFactory.UnregisterPacketHandler(packetType);
 }
        /// <summary>
        /// This method handles the asynchronous message pump.  It waits for messages to show up on the queue
        /// and calls FireDataAvailable for each such packet.  It will terminate when the terminate event is
        /// set.
        /// </summary>
        private void PacketPumpProc()
        {
            NamedPipeServerStream localPipeServer          = _pipeServer;
            AutoResetEvent        localPacketAvailable     = _packetAvailable;
            AutoResetEvent        localTerminatePacketPump = _terminatePacketPump;
            Queue <INodePacket>   localPacketQueue         = _packetQueue;

            DateTime originalWaitStartTime = DateTime.UtcNow;
            bool     gotValidConnection    = false;

            while (!gotValidConnection)
            {
                DateTime restartWaitTime = DateTime.UtcNow;

                // We only wait to wait the difference between now and the last original start time, in case we have multiple hosts attempting
                // to attach.  This prevents each attempt from resetting the timer.
                TimeSpan usedWaitTime      = restartWaitTime - originalWaitStartTime;
                int      waitTimeRemaining = Math.Max(0, CommunicationsUtilities.NodeConnectionTimeout - (int)usedWaitTime.TotalMilliseconds);

                try
                {
                    // Wait for a connection
                    IAsyncResult resultForConnection = localPipeServer.BeginWaitForConnection(null, null);
                    CommunicationsUtilities.Trace("Waiting for connection {0} ms...", waitTimeRemaining);

                    bool connected = resultForConnection.AsyncWaitHandle.WaitOne(waitTimeRemaining, false);
                    if (!connected)
                    {
                        CommunicationsUtilities.Trace("Connection timed out waiting a host to contact us.  Exiting comm thread.");
                        ChangeLinkStatus(LinkStatus.ConnectionFailed);
                        return;
                    }

                    CommunicationsUtilities.Trace("Parent started connecting. Reading handshake from parent");
                    localPipeServer.EndWaitForConnection(resultForConnection);

                    // The handshake protocol is a simple long exchange.  The host sends us a long, and we
                    // respond with another long.  Once the handshake is complete, both sides can be assured the
                    // other is ready to accept data.
                    // To avoid mixing client and server builds, the long is the MSBuild binary timestamp.

                    // Compatibility issue here.
                    // Previous builds of MSBuild 4.0 would exchange just a byte.
                    // Host would send either 0x5F or 0x60 depending on whether it was the toolset or not respectively.
                    // Client would return either 0xF5 or 0x06 respectively.
                    // Therefore an old host on a machine with new clients running will hang,
                    // sending a byte and waiting for a byte until it eventually times out;
                    // because the new client will want 7 more bytes before it returns anything.
                    // The other way around is not a problem, because the old client would immediately return the (wrong)
                    // byte on receiving the first byte of the long sent by the new host, and the new host would disconnect.
                    // To avoid the hang, special case here:
                    // Make sure our handshakes always start with 00.
                    // If we received ONLY one byte AND it's 0x5F or 0x60, return 0xFF (it doesn't matter what as long as
                    // it will cause the host to reject us; new hosts expect 00 and old hosts expect F5 or 06).
                    try
                    {
                        long            handshake       = localPipeServer.ReadLongForHandshake(/* reject these leads */ new byte[] { 0x5F, 0x60 }, 0xFF /* this will disconnect the host; it expects leading 00 or F5 or 06 */);
                        WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
                        string          remoteUserName  = localPipeServer.GetImpersonationUserName();

                        if (handshake != GetHostHandshake())
                        {
                            CommunicationsUtilities.Trace("Handshake failed. Received {0} from host not {1}. Probably the host is a different MSBuild build.", handshake, GetHostHandshake());
                            localPipeServer.Disconnect();
                            continue;
                        }

                        // We will only talk to a host that was started by the same user as us.  Even though the pipe access is set to only allow this user, we want to ensure they
                        // haven't attempted to change those permissions out from under us.  This ensures that the only way they can truly gain access is to be impersonating the
                        // user we were started by.
                        WindowsIdentity clientIdentity = null;
                        localPipeServer.RunAsClient(delegate() { clientIdentity = WindowsIdentity.GetCurrent(true); });

                        if (clientIdentity == null || !String.Equals(clientIdentity.Name, currentIdentity.Name, StringComparison.OrdinalIgnoreCase))
                        {
                            CommunicationsUtilities.Trace("Handshake failed. Host user is {0} but we were created by {1}.", (clientIdentity == null) ? "<unknown>" : clientIdentity.Name, currentIdentity.Name);
                            localPipeServer.Disconnect();
                            continue;
                        }
                    }
                    catch (IOException e)
                    {
                        // We will get here when:
                        // 1. The host (OOP main node) connects to us, it immediately checks for user priviledges
                        //    and if they don't match it disconnects immediately leaving us still trying to read the blank handshake
                        // 2. The host is too old sending us bits we automatically reject in the handshake
                        CommunicationsUtilities.Trace("Client connection failed but we will wait for another connection. Exception: {0}", e.Message);
                        if (localPipeServer.IsConnected)
                        {
                            localPipeServer.Disconnect();
                        }

                        continue;
                    }

                    gotValidConnection = true;
                }
                catch (Exception e)
                {
                    if (ExceptionHandling.IsCriticalException(e))
                    {
                        throw;
                    }

                    CommunicationsUtilities.Trace("Client connection failed.  Exiting comm thread. {0}", e);
                    if (localPipeServer.IsConnected)
                    {
                        localPipeServer.Disconnect();
                    }

                    ExceptionHandling.DumpExceptionToFile(e);
                    ChangeLinkStatus(LinkStatus.Failed);
                    return;
                }
            }

            CommunicationsUtilities.Trace("Writing handshake to parent");
            localPipeServer.WriteLongForHandshake(GetClientHandshake());
            ChangeLinkStatus(LinkStatus.Active);

            // Ordering of the wait handles is important.  The first signalled wait handle in the array
            // will be returned by WaitAny if multiple wait handles are signalled.  We prefer to have the
            // terminate event triggered so that we cannot get into a situation where packets are being
            // spammed to the endpoint and it never gets an opportunity to shutdown.
            CommunicationsUtilities.Trace("Entering read loop.");
            byte[]       headerByte = new byte[5];
            IAsyncResult result     = localPipeServer.BeginRead(headerByte, 0, headerByte.Length, null, null);

            bool exitLoop = false;

            do
            {
                // Ordering is important.  We want packetAvailable to supercede terminate otherwise we will not properly wait for all
                // packets to be sent by other threads which are shutting down, such as the logging thread.
                WaitHandle[] handles = new WaitHandle[] { result.AsyncWaitHandle, localPacketAvailable, localTerminatePacketPump };

                int waitId = WaitHandle.WaitAny(handles);
                switch (waitId)
                {
                case 0:
                {
                    int bytesRead = 0;
                    try
                    {
                        bytesRead = localPipeServer.EndRead(result);
                    }
                    catch (Exception e)
                    {
                        // Lost communications.  Abort (but allow node reuse)
                        CommunicationsUtilities.Trace("Exception reading from server.  {0}", e);
                        ExceptionHandling.DumpExceptionToFile(e);
                        ChangeLinkStatus(LinkStatus.Inactive);
                        exitLoop = true;
                        break;
                    }

                    if (bytesRead != headerByte.Length)
                    {
                        // Incomplete read.  Abort.
                        if (bytesRead == 0)
                        {
                            CommunicationsUtilities.Trace("Parent disconnected abruptly");
                        }
                        else
                        {
                            CommunicationsUtilities.Trace("Incomplete header read from server.  {0} of {1} bytes read", bytesRead, headerByte.Length);
                        }

                        ChangeLinkStatus(LinkStatus.Failed);
                        exitLoop = true;
                        break;
                    }

                    NodePacketType packetType   = (NodePacketType)Enum.ToObject(typeof(NodePacketType), headerByte[0]);
                    int            packetLength = BitConverter.ToInt32(headerByte, 1);

                    try
                    {
                        _packetFactory.DeserializeAndRoutePacket(0, packetType, NodePacketTranslator.GetReadTranslator(localPipeServer, _sharedReadBuffer));
                    }
                    catch (Exception e)
                    {
                        // Error while deserializing or handling packet.  Abort.
                        CommunicationsUtilities.Trace("Exception while deserializing packet {0}: {1}", packetType, e);
                        ExceptionHandling.DumpExceptionToFile(e);
                        ChangeLinkStatus(LinkStatus.Failed);
                        exitLoop = true;
                        break;
                    }

                    result = localPipeServer.BeginRead(headerByte, 0, headerByte.Length, null, null);
                }

                break;

                case 1:
                case 2:
                    try
                    {
                        int packetCount = localPacketQueue.Count;

                        // Write out all the queued packets.
                        while (packetCount > 0)
                        {
                            INodePacket packet;
                            lock (_packetQueue)
                            {
                                packet = localPacketQueue.Dequeue();
                            }

                            MemoryStream          packetStream    = new MemoryStream();
                            INodePacketTranslator writeTranslator = NodePacketTranslator.GetWriteTranslator(packetStream);

                            packetStream.WriteByte((byte)packet.Type);

                            // Pad for packet length
                            packetStream.Write(BitConverter.GetBytes((int)0), 0, 4);

                            // Reset the position in the write buffer.
                            packet.Translate(writeTranslator);

                            // Now write in the actual packet length
                            packetStream.Position = 1;
                            packetStream.Write(BitConverter.GetBytes((int)packetStream.Length - 5), 0, 4);

                            localPipeServer.Write(packetStream.GetBuffer(), 0, (int)packetStream.Length);

                            packetCount--;
                        }
                    }
                    catch (Exception e)
                    {
                        // Error while deserializing or handling packet.  Abort.
                        CommunicationsUtilities.Trace("Exception while serializing packets: {0}", e);
                        ExceptionHandling.DumpExceptionToFile(e);
                        ChangeLinkStatus(LinkStatus.Failed);
                        exitLoop = true;
                        break;
                    }

                    if (waitId == 2)
                    {
                        CommunicationsUtilities.Trace("Disconnecting voluntarily");
                        ChangeLinkStatus(LinkStatus.Failed);
                        exitLoop = true;
                    }

                    break;

                default:
                    ErrorUtilities.ThrowInternalError("waitId {0} out of range.", waitId);
                    break;
                }
            }while (!exitLoop);

            CommunicationsUtilities.Trace("Ending read loop");

            try
            {
                if (localPipeServer.IsConnected)
                {
                    localPipeServer.WaitForPipeDrain();
                    localPipeServer.Disconnect();
                }
            }
            catch (Exception)
            {
                // We don't really care if Disconnect somehow fails, but it gives us a chance to do the right thing.
            }
        }
 /// <summary>
 /// Registers a packet handler.  Not used in the in-proc node.
 /// </summary>
 public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler)
 {
     // Not used
     ErrorUtilities.ThrowInternalErrorUnreachable();
 }
 /// <summary>
 /// Takes a serializer, deserializes the packet and routes it to the appropriate handler.
 /// </summary>
 /// <param name="nodeId">The node from which the packet was received.</param>
 /// <param name="packetType">The packet type.</param>
 /// <param name="translator">The translator containing the data from which the packet should be reconstructed.</param>
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, INodePacketTranslator translator)
 {
     throw new NotSupportedException("not used");
 }
Beispiel #18
0
 public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler)
 {
     _packetFactory.RegisterPacketHandler(packetType, factory, handler);
 }
 /// <summary>
 /// Registers the specified handler for a particular packet type.
 /// </summary>
 /// <param name="packetType">The packet type.</param>
 /// <param name="factory">The factory for packets of the specified type.</param>
 /// <param name="handler">The handler to be called when packets of the specified type are received.</param>
 public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler)
 {
     throw new NotSupportedException("not used");
 }
 /// <summary>
 /// Unregisters a packet handler.
 /// </summary>
 /// <param name="packetType">The packet type.</param>
 public void UnregisterPacketHandler(NodePacketType packetType)
 {
     throw new NotSupportedException("not used");
 }
Beispiel #21
0
 /// <summary>
 /// Not necessary for in-proc node - we don't serialize.
 /// </summary>
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, ITranslator translator)
 {
     // The in-proc endpoint shouldn't be serializing, just routing.
     ErrorUtilities.ThrowInternalError("Unexpected call to DeserializeAndRoutePacket on the in-proc node.");
 }
Beispiel #22
0
 /// <summary>
 /// Not necessary for in-proc node - we don't serialize.
 /// </summary>
 public void UnregisterPacketHandler(NodePacketType packetType)
 {
     // The in-proc node doesn't need to do this.
 }
Beispiel #23
0
 /// <summary>
 /// Not necessary for in-proc node - we don't serialize.
 /// </summary>
 public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler)
 {
     // The in-proc node doesn't need to do this.
 }
Beispiel #24
0
 /// <summary>
 /// Registers the specified handler for a particular packet type.
 /// </summary>
 /// <param name="packetType">The packet type.</param>
 /// <param name="factory">The factory for packets of the specified type.</param>
 /// <param name="handler">The handler to be called when packets of the specified type are received.</param>
 public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler)
 {
     throw new NotSupportedException("not used");
 }
Beispiel #25
0
 /// <summary>
 /// Not necessary for in-proc node - we don't serialize.
 /// </summary>
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, INodePacketTranslator translator)
 {
     // The in-proc endpoint shouldn't be serializing, just routing.
     ErrorUtilities.ThrowInternalError("Unexpected call to DeserializeAndRoutePacket on the in-proc node.");
 }
Beispiel #26
0
 /// <summary>
 /// Takes a serializer, deserializes the packet and routes it to the appropriate handler.
 /// </summary>
 /// <param name="nodeId">The node from which the packet was received.</param>
 /// <param name="packetType">The packet type.</param>
 /// <param name="translator">The translator containing the data from which the packet should be reconstructed.</param>
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, ITranslator translator)
 {
     throw new NotSupportedException("not used");
 }
Beispiel #27
0
 /// <summary>
 /// Deserialize a packet
 /// </summary>
 public INodePacket DeserializePacket(NodePacketType type, byte[] serializedPacket)
 {
     throw new NotImplementedException();
 }
Beispiel #28
0
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, ITranslator translator)
 {
     _packetFactory.DeserializeAndRoutePacket(nodeId, packetType, translator);
 }
 /// <summary>
 /// Takes a serializer, deserializes the packet and routes it to the appropriate handler.
 /// </summary>
 /// <param name="nodeId">The node from which the packet was received.</param>
 /// <param name="packetType">The packet type.</param>
 /// <param name="translator">The translator containing the data from which the packet should be reconstructed.</param>
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, INodePacketTranslator translator)
 {
     if (_nodeIdToPacketFactory.ContainsKey(nodeId))
     {
         _nodeIdToPacketFactory[nodeId].DeserializeAndRoutePacket(nodeId, packetType, translator);
     }
     else
     {
         _localPacketFactory.DeserializeAndRoutePacket(nodeId, packetType, translator);
     }
 }
 /// <summary>
 /// Deserializes and routes a packet.  Not used in the in-proc node.
 /// </summary>
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, INodePacketTranslator translator)
 {
     // Not used
     ErrorUtilities.ThrowInternalErrorUnreachable();
 }
            public async Task RunPacketReadLoopAsync()
            {
                while (true)
                {
                    try
                    {
                        int bytesRead = await CommunicationsUtilities.ReadAsync(_clientToServerStream, _headerByte, _headerByte.Length);

                        if (!ProcessHeaderBytesRead(bytesRead))
                        {
                            return;
                        }
                    }
                    catch (IOException e)
                    {
                        CommunicationsUtilities.Trace(_nodeId, "EXCEPTION in RunPacketReadLoopAsync: {0}", e);
                        _packetFactory.RoutePacket(_nodeId, new NodeShutdown(NodeShutdownReason.ConnectionFailed));
                        Close();
                        return;
                    }

                    NodePacketType packetType   = (NodePacketType)_headerByte[0];
                    int            packetLength = BitConverter.ToInt32(_headerByte, 1);

                    byte[] packetData;
                    if (packetLength < _smallReadBuffer.Length)
                    {
                        packetData = _smallReadBuffer;
                    }
                    else
                    {
                        // Preallocated buffer is not large enough to hold the body. Allocate now, but don't hold it forever.
                        packetData = new byte[packetLength];
                    }

                    try
                    {
                        int bytesRead = await CommunicationsUtilities.ReadAsync(_clientToServerStream, packetData, packetLength);

                        if (!ProcessBodyBytesRead(bytesRead, packetLength, packetType))
                        {
                            return;
                        }
                    }
                    catch (IOException e)
                    {
                        CommunicationsUtilities.Trace(_nodeId, "EXCEPTION in RunPacketReadLoopAsync (Reading): {0}", e);
                        _packetFactory.RoutePacket(_nodeId, new NodeShutdown(NodeShutdownReason.ConnectionFailed));
                        Close();
                        return;
                    }

                    // Read and route the packet.
                    if (!ReadAndRoutePacket(packetType, packetData, packetLength))
                    {
                        return;
                    }

                    if (packetType == NodePacketType.NodeShutdown)
                    {
                        Close();
                        return;
                    }
                }
            }
 /// <summary>
 /// Unregisters a packet handler.  Not used in the in-proc node.
 /// </summary>
 public void UnregisterPacketHandler(NodePacketType packetType)
 {
     // Not used
     ErrorUtilities.ThrowInternalErrorUnreachable();
 }
Beispiel #33
0
 /// <summary>
 /// Not necessary for in-proc node - we don't serialize.
 /// </summary>
 public void UnregisterPacketHandler(NodePacketType packetType)
 {
     // The in-proc node doesn't need to do this.
 }
 /// <summary>
 /// Registers the specified handler for a particular packet type.
 /// </summary>
 /// <param name="packetType">The packet type.</param>
 /// <param name="factory">The factory for packets of the specified type.</param>
 /// <param name="handler">The handler to be called when packets of the specified type are received.</param>
 public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler)
 {
     _packetFactory.RegisterPacketHandler(packetType, factory, handler);
 }
Beispiel #35
0
 /// <summary>
 /// Not necessary for in-proc node - we don't serialize.
 /// </summary>
 public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler)
 {
     // The in-proc node doesn't need to do this.
 }
 /// <summary>
 /// Takes a serializer, deserializes the packet and routes it to the appropriate handler.
 /// </summary>
 /// <param name="nodeId">The node from which the packet was received.</param>
 /// <param name="packetType">The packet type.</param>
 /// <param name="translator">The translator containing the data from which the packet should be reconstructed.</param>
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, INodePacketTranslator translator)
 {
     _packetFactory.DeserializeAndRoutePacket(nodeId, packetType, translator);
 }
 public void UnregisterPacketHandler(NodePacketType packetType)
 {
     throw new NotImplementedException();
 }
 public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler)
 {
     throw new NotImplementedException();
 }
Beispiel #39
0
 /// <summary>
 /// Registers a packet handler
 /// </summary>
 public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler)
 {
     _packetFactories[packetType] = new PacketFactoryRecord(handler, factory);
 }
Beispiel #40
0
 /// <summary>
 /// Unregisters a packet handler.
 /// </summary>
 public void UnregisterPacketHandler(NodePacketType packetType)
 {
     _packetFactories.Remove(packetType);
 }
 /// <summary>
 /// Unregisters a packet handler.
 /// </summary>
 public void UnregisterPacketHandler(NodePacketType packetType)
 {
     _packetFactories.Remove(packetType);
 }
Beispiel #42
0
 /// <summary>
 /// Unregisters a packet handler.
 /// </summary>
 /// <param name="packetType">The packet type.</param>
 public void UnregisterPacketHandler(NodePacketType packetType)
 {
     throw new NotSupportedException("not used");
 }
 /// <summary>
 /// Registers a packet handler
 /// </summary>
 public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler)
 {
     _packetFactories[packetType] = new PacketFactoryRecord(handler, factory);
 }
        private void RunReadLoop(Stream localReadPipe, Stream localWritePipe,
                                 ConcurrentQueue <INodePacket> localPacketQueue, AutoResetEvent localPacketAvailable, AutoResetEvent localTerminatePacketPump)
        {
            // Ordering of the wait handles is important.  The first signalled wait handle in the array
            // will be returned by WaitAny if multiple wait handles are signalled.  We prefer to have the
            // terminate event triggered so that we cannot get into a situation where packets are being
            // spammed to the endpoint and it never gets an opportunity to shutdown.
            CommunicationsUtilities.Trace("Entering read loop.");
            byte[] headerByte = new byte[5];
#if FEATURE_APM
            IAsyncResult result = localReadPipe.BeginRead(headerByte, 0, headerByte.Length, null, null);
#else
            Task <int> readTask = CommunicationsUtilities.ReadAsync(localReadPipe, headerByte, headerByte.Length);
#endif

            bool exitLoop = false;
            do
            {
                // Ordering is important.  We want packetAvailable to supercede terminate otherwise we will not properly wait for all
                // packets to be sent by other threads which are shutting down, such as the logging thread.
                WaitHandle[] handles = new WaitHandle[] {
#if FEATURE_APM
                    result.AsyncWaitHandle,
#else
                    ((IAsyncResult)readTask).AsyncWaitHandle,
#endif
                    localPacketAvailable, localTerminatePacketPump
                };

                int waitId = WaitHandle.WaitAny(handles);
                switch (waitId)
                {
                case 0:
                {
                    int bytesRead = 0;
                    try
                    {
#if FEATURE_APM
                        bytesRead = localReadPipe.EndRead(result);
#else
                        bytesRead = readTask.Result;
#endif
                    }
                    catch (Exception e)
                    {
                        // Lost communications.  Abort (but allow node reuse)
                        CommunicationsUtilities.Trace("Exception reading from server.  {0}", e);
                        ExceptionHandling.DumpExceptionToFile(e);
                        ChangeLinkStatus(LinkStatus.Inactive);
                        exitLoop = true;
                        break;
                    }

                    if (bytesRead != headerByte.Length)
                    {
                        // Incomplete read.  Abort.
                        if (bytesRead == 0)
                        {
                            CommunicationsUtilities.Trace("Parent disconnected abruptly");
                        }
                        else
                        {
                            CommunicationsUtilities.Trace("Incomplete header read from server.  {0} of {1} bytes read", bytesRead, headerByte.Length);
                        }

                        ChangeLinkStatus(LinkStatus.Failed);
                        exitLoop = true;
                        break;
                    }

                    NodePacketType packetType = (NodePacketType)Enum.ToObject(typeof(NodePacketType), headerByte[0]);

                    try
                    {
                        _packetFactory.DeserializeAndRoutePacket(0, packetType, BinaryTranslator.GetReadTranslator(localReadPipe, _sharedReadBuffer));
                    }
                    catch (Exception e)
                    {
                        // Error while deserializing or handling packet.  Abort.
                        CommunicationsUtilities.Trace("Exception while deserializing packet {0}: {1}", packetType, e);
                        ExceptionHandling.DumpExceptionToFile(e);
                        ChangeLinkStatus(LinkStatus.Failed);
                        exitLoop = true;
                        break;
                    }

#if FEATURE_APM
                    result = localReadPipe.BeginRead(headerByte, 0, headerByte.Length, null, null);
#else
                    readTask = CommunicationsUtilities.ReadAsync(localReadPipe, headerByte, headerByte.Length);
#endif
                }

                break;

                case 1:
                case 2:
                    try
                    {
                        // Write out all the queued packets.
                        INodePacket packet;
                        while (localPacketQueue.TryDequeue(out packet))
                        {
                            MemoryStream packetStream    = new MemoryStream();
                            ITranslator  writeTranslator = BinaryTranslator.GetWriteTranslator(packetStream);

                            packetStream.WriteByte((byte)packet.Type);

                            // Pad for packet length
                            packetStream.Write(BitConverter.GetBytes((int)0), 0, 4);

                            // Reset the position in the write buffer.
                            packet.Translate(writeTranslator);

                            // Now write in the actual packet length
                            packetStream.Position = 1;
                            packetStream.Write(BitConverter.GetBytes((int)packetStream.Length - 5), 0, 4);

                            localWritePipe.Write(packetStream.GetBuffer(), 0, (int)packetStream.Length);
                        }
                    }
                    catch (Exception e)
                    {
                        // Error while deserializing or handling packet.  Abort.
                        CommunicationsUtilities.Trace("Exception while serializing packets: {0}", e);
                        ExceptionHandling.DumpExceptionToFile(e);
                        ChangeLinkStatus(LinkStatus.Failed);
                        exitLoop = true;
                        break;
                    }

                    if (waitId == 2)
                    {
                        CommunicationsUtilities.Trace("Disconnecting voluntarily");
                        ChangeLinkStatus(LinkStatus.Failed);
                        exitLoop = true;
                    }

                    break;

                default:
                    ErrorUtilities.ThrowInternalError("waitId {0} out of range.", waitId);
                    break;
                }
            }while (!exitLoop);
        }
 /// <summary>
 /// Registers a packet handler.  Not used in the in-proc node.
 /// </summary>
 public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler)
 {
     // Not used
     ErrorUtilities.ThrowInternalErrorUnreachable();
 }
Beispiel #46
0
 public void UnregisterPacketHandler(NodePacketType packetType)
 {
     _packetFactory.UnregisterPacketHandler(packetType);
 }
 /// <summary>
 /// Unregisters a packet handler.  Not used in the in-proc node.
 /// </summary>
 public void UnregisterPacketHandler(NodePacketType packetType)
 {
     // Not used
     ErrorUtilities.ThrowInternalErrorUnreachable();
 }
 public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler)
 {
     throw new NotImplementedException();
 }
Beispiel #49
0
 /// <summary>
 /// Deserialize a packet
 /// </summary>
 public INodePacket DeserializePacket(NodePacketType type, byte[] serializedPacket)
 {
     throw new NotImplementedException();
 }
 public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, ITranslator translator)
 {
     throw new NotImplementedException();
 }
Beispiel #51
0
        /// <summary>
        /// Takes a serializer, deserializes the packet and routes it to the appropriate handler.
        /// </summary>
        /// <param name="nodeId">The node from which the packet was received.</param>
        /// <param name="packetType">The packet type.</param>
        /// <param name="translator">The translator containing the data from which the packet should be reconstructed.</param>
        public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, INodePacketTranslator translator)
        {
            if (packetType == NodePacketType.NodeShutdown)
            {
                RemoveNodeFromMapping(nodeId);
            }

            _packetFactory.DeserializeAndRoutePacket(nodeId, packetType, translator);
        }