public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, ITranslator translator) { if (packetType == NodePacketType.NodeShutdown) { RemoveNodeFromMapping(nodeId); } _packetFactory.DeserializeAndRoutePacket(nodeId, packetType, translator); }
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; } } }
/// <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); }
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); }
/// <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> /// 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); } }
/// <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)); }
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"); }
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"); }
/// <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."); }
/// <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> /// 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> /// 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> /// 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."); }
/// <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"); }
/// <summary> /// Deserialize a packet /// </summary> public INodePacket DeserializePacket(NodePacketType type, byte[] serializedPacket) { throw new NotImplementedException(); }
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(); }
/// <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); }
/// <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(); }
/// <summary> /// Registers a packet handler /// </summary> public void RegisterPacketHandler(NodePacketType packetType, NodePacketFactoryMethod factory, INodePacketHandler handler) { _packetFactories[packetType] = new PacketFactoryRecord(handler, factory); }
/// <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); }
/// <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(); }
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(); }
/// <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(); }
/// <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); }