/// <summary> /// Ends the handling of a message and returns the memory stream to send back to the client. /// </summary> /// <param name="asyncResult">The <see cref="IAsyncResult"/> returned from <see cref="BeginHandleMessage"/>.</param> /// <returns>Retuns a <see cref="MemoryStream"/> to send back to the client, if the stream is <see langword="null"/> an empty response is sent.</returns> public MemoryStream EndHandleMessage(IAsyncResult asyncResult) { MemoryStream replyStream = null; SocketHandlerAsyncResult socketAsyncResult = (SocketHandlerAsyncResult)asyncResult; if (socketAsyncResult.Exception != null) { if (log.IsErrorEnabled) { log.ErrorFormat("Exception handling async message: {0}", socketAsyncResult.Exception); } throw socketAsyncResult.Exception; } //only 1 should be not null int replyCount = 0; if (socketAsyncResult.ReplyMessage != null) { replyCount++; } if (socketAsyncResult.ReplyMessages != null) { replyCount++; } if (socketAsyncResult.RuntimeInfo != null) { replyCount++; } if (replyCount > 1) { throw new InvalidOperationException( string.Format("Only 1 reply at a time is supported. ReplyMessage: {0}, ReplyMessages: {1}, RuntimeInfo: {2}", socketAsyncResult.ReplyMessage, socketAsyncResult.ReplyMessages, socketAsyncResult.RuntimeInfo)); } if (socketAsyncResult.ReplyMessage != null) { replyStream = RelayMessageFormatter.WriteRelayMessage(socketAsyncResult.ReplyMessage); } else if (socketAsyncResult.ReplyMessages != null) { replyStream = RelayMessageFormatter.WriteRelayMessageList(socketAsyncResult.ReplyMessages); } else if (socketAsyncResult.RuntimeInfo != null) { replyStream = (MemoryStream)RelayMessageFormatter.WriteRuntimeInfo(socketAsyncResult.RuntimeInfo); } return(replyStream); }
/// <summary> /// Handles a new message from a <see cref="MemoryStream"/> and if appropriate translates /// and passes the message to the contained <see cref="RelayNode"/>. /// </summary> /// <param name="commandID"></param> /// <param name="messageStream"></param> /// <param name="messageLength"></param> /// <returns></returns> public MemoryStream HandleMessage(int commandID, MemoryStream messageStream, int messageLength) { SocketCommand command = SocketCommand.Unknown; RelayMessage message = null; List <RelayMessage> messages = null; MemoryStream replyStream = null; try { command = (SocketCommand)commandID; } catch { if (RelayNode.log.IsErrorEnabled) { RelayNode.log.ErrorFormat("Unrecognized commandID {0} sent to Relay Service via socket transport", commandID); } } Stream reply; switch (command) { case SocketCommand.Unknown: if (RelayNode.log.IsErrorEnabled) { RelayNode.log.Error("SocketCommand.Unknown received"); } break; case SocketCommand.HandleOneWayMessage: message = RelayMessageFormatter.ReadRelayMessage(messageStream); _dataHandler.HandleMessage(message); break; case SocketCommand.HandleSyncMessage: message = RelayMessageFormatter.ReadRelayMessage(messageStream); message.ResultOutcome = RelayOutcome.Received; _dataHandler.HandleMessage(message); reply = RelayMessageFormatter.WriteRelayMessage(message); if (reply != null && reply != Stream.Null) { replyStream = (MemoryStream)reply; } break; case SocketCommand.HandleOneWayMessages: messages = RelayMessageFormatter.ReadRelayMessageList(messageStream); _dataHandler.HandleMessages(messages); break; case SocketCommand.HandleSyncMessages: messages = RelayMessageFormatter.ReadRelayMessageList(messageStream, msg => msg.ResultOutcome = RelayOutcome.Received); _dataHandler.HandleMessages(messages); reply = RelayMessageFormatter.WriteRelayMessageList(messages); if (reply != null && reply != Stream.Null) { replyStream = (MemoryStream)reply; } break; case SocketCommand.GetRuntimeInfo: ComponentRuntimeInfo[] runtimeInfo = _relayNode.GetComponentsRuntimeInfo(); reply = RelayMessageFormatter.WriteRuntimeInfo(runtimeInfo); if (reply != null && reply != Stream.Null) { replyStream = (MemoryStream)reply; } break; default: if (RelayNode.log.IsErrorEnabled) { RelayNode.log.ErrorFormat("Unhandled command {0} sent to Relay Service via socket transport", command); } break; } return(replyStream); }
/// <summary> /// Sends a list of messages synchronously, regardless of its type /// </summary> /// <param name="messages">The messages to send.</param> /// <remarks> /// added cbrown /// due to the extensive use of the sockettransport, and the desire not /// to break existing code, this interface is being used to extend the /// transport protocol. /// usage: /// IRelayTransportExtended xTend = Transport as IRelayTransportExtended; /// if (null == xTend) /// { /// use "tradidional" handling /// } /// else /// { /// use extended handling /// } /// </remarks> public void SendSyncMessageList(List <RelayMessage> messages) { ResourcePoolItem <MemoryStream> pooledBuffer; MemoryStream nextMessageChunk; int chunkLength = defaultChunkLength; if (messages.Count > 0) { chunkLength = messages.Count; pooledBuffer = bufferPool.GetItem(); try { nextMessageChunk = pooledBuffer.Item; int cursor = 0; while (cursor < messages.Count) { int currentLocalIndexStart = cursor; nextMessageChunk.Seek(0, SeekOrigin.Begin); cursor += RelayMessageFormatter.WriteRelayMessageList(messages, cursor, chunkLength, nextMessageChunk); MemoryStream replyStream = socketClient.SendSync((int)SocketCommand.HandleSyncMessages, nextMessageChunk); if (replyStream != null) { List <RelayMessage> replyMessages = RelayMessageFormatter.ReadRelayMessageList(replyStream); if (replyMessages.Count != messages.Count) { string errMsg = string.Format("Reply messages from {0} has length {1} but request messages has length {2}. Discarding replies.", node, replyMessages.Count, messages.Count); log.Error(errMsg); #if DEBUG throw new ApplicationException(errMsg); #else break; #endif } for (int i = 0; i < replyMessages.Count; i++) { try { if (replyMessages[i].Id != messages[i + currentLocalIndexStart].Id) { string errMsg = string.Format("OutMessage Receive Got Wrong Id on Reply Message. Message Sent: {0}, Message Received: {1}", messages[i + currentLocalIndexStart], replyMessages[i]); log.Error(errMsg); #if DEBUG throw new ApplicationException(errMsg); #endif } else { messages[i + currentLocalIndexStart].ExtractResponse(replyMessages[i]); } } catch (ArgumentOutOfRangeException) { string errMsg = string.Format("Bad index while processing out message list for {0}. i = {1}. currentLocalIndexStart = {2}. Cursor = {3}. Message count = {4}.", node, i, currentLocalIndexStart, cursor, messages.Count); if (log.IsErrorEnabled) { log.Error(errMsg); } cursor = messages.Count + 1; //break out of while loop as well #if DEBUG throw new ArgumentOutOfRangeException(errMsg); #else break; #endif } } } } } finally { bufferPool.ReleaseItem(pooledBuffer); } } }