/// <summary> /// Sends a message synchronously, regardless of its type /// </summary> /// <param name="message"></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 SendSyncMessage(RelayMessage message) { MemoryStream replyStream; ResourcePoolItem <MemoryStream> bufferItem = null; try { bufferItem = bufferPool.GetItem(); // there is not need to check the type, we are FORCING sync handling RelayMessageFormatter.WriteRelayMessage(message, bufferItem.Item); bufferItem.Item.Seek(0, SeekOrigin.Begin); replyStream = socketClient.SendSync((int)SocketCommand.HandleSyncMessage, bufferItem.Item); } finally { if (bufferItem != null) { bufferPool.ReleaseItem(bufferItem); } } if (replyStream != null) { RelayMessage replyMessage = RelayMessageFormatter.ReadRelayMessage(replyStream); message.ExtractResponse(replyMessage); } //this doesn't make any sense, the incoming message already //has error occured with no respones? fwise 5/09 else if (message.ErrorOccurred) { message.Payload = null; } }
void IRelayTransport.SendMessage(SerializedRelayMessage serializedMessage) { if (DoDispatchMessages) { RelayMessage message = RelayMessageFormatter.ReadRelayMessage(serializedMessage.MessageStream); _messageRecieved(message); } }
/// <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); }
public SerializedRelayMessage(RelayMessage message) { MessageStream = new MemoryStream(); RelayMessageFormatter.WriteRelayMessage(message, MessageStream); MessageStream.Seek(0, SeekOrigin.Begin); MessageType = message.MessageType; EnteredCurrentSystemAt = message.EnteredCurrentSystemAt; if (message.Payload != null && message.Payload.ByteArray != null) { PayloadLength = message.Payload.ByteArray.Length; } }
IAsyncResult IAsyncRelayTransport.BeginSendMessageList(List <RelayMessage> messages, AsyncCallback callback, object state) { if (messages == null) { throw new ArgumentNullException("messages"); } var result = new RoundTripAsyncResult <List <RelayMessage> >(callback, state) { SentMessage = messages }; if (messages.Count > 0) { _asyncSocketClient.SendRoundTripAsync <List <RelayMessage> >( (short)SocketCommand.HandleSyncMessages, messages, RelayMessageFormatter.WriteRelayMessageList, args => { try { if (args.Error != null) { result.Error = args.Error; return; } if (args.Response != null) { result.ResponseMessage = RelayMessageFormatter.ReadRelayMessageList(args.Response); } } catch (Exception ex) { result.Error = ex; } finally { result.Complete(args.CompletedSynchronously); } }); } else { result.ResponseMessage = messages; result.Complete(true); } return(result); }
private void _serializedMessageListReceive(IEnumerable <SerializedRelayMessage> messages) { if (DoDispatchMessages) { using (var stream = new MemoryStream()) { foreach (var message in messages) { message.MessageStream.WriteTo(stream); } List <RelayMessage> messageList = RelayMessageFormatter.ReadRelayMessageList(stream); _messageListRecieved(messageList); } } }
/// <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); }
IAsyncResult IAsyncRelayTransport.BeginSendMessage(RelayMessage message, bool forceRoundTrip, AsyncCallback callback, object state) { if (message == null) { throw new ArgumentNullException("message"); } if (message.IsTwoWayMessage) { var result = new RoundTripAsyncResult <RelayMessage>(callback, state) { SentMessage = message }; asyncSocketClient.SendRoundTripAsync <RelayMessage>( (short)SocketCommand.HandleSyncMessage, message, RelayMessageFormatter.WriteRelayMessage, args => { try { if (args.Error != null) { result.Error = args.Error; return; } if (args.Response != null) { result.ResponseMessage = RelayMessageFormatter.ReadRelayMessage(args.Response); } } catch (Exception ex) { result.Error = ex; } finally { result.Complete(args.CompletedSynchronously); } }); return(result); } else { var result = new SimpleAsyncResult(callback, state); if (forceRoundTrip) { asyncSocketClient.SendRoundTripAsync <RelayMessage>( (short)SocketCommand.HandleSyncMessage, message, RelayMessageFormatter.WriteRelayMessage, args => { result.Error = args.Error; result.CompleteOperation(args.CompletedSynchronously); }); } else { asyncSocketClient.SendOneWayAsync <RelayMessage>( (short)SocketCommand.HandleOneWayMessage, message, RelayMessageFormatter.WriteRelayMessage, args => { result.Error = args.Error; result.CompleteOperation(args.CompletedSynchronously); }); } return(result); } }
/// <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); } } }
/// <summary> /// Begins the handling of a complete message from a stream. All references /// to <see cref="MessageState.Message"/> must be released by the end of this method. /// </summary> /// <param name="message">The complete message that is to be handled.</param> /// <param name="callback">The delegate to call when complete.</param> /// <returns>Returns an <see cref="IAsyncResult"/>.</returns> /// <remarks> /// <para> /// All implementors must release any references to <see cref="MessageState.Message"/> /// by the time that <see cref="BeginHandleMessage"/> returns. /// </para> /// </remarks> public IAsyncResult BeginHandleMessage(MessageState message, AsyncCallback callback) { SocketHandlerAsyncResult result = new SocketHandlerAsyncResult(null, callback); //don't use callback directly, use result.Complete(); callback = null; const bool wasSyncronous = true; //VERY IMPORTANT! don't hold any references to message or it's properties after leaving this method try { SocketCommand command = SocketCommand.Unknown; RelayMessage relayMessage = null; List <RelayMessage> relayMessages = null; try { command = (SocketCommand)message.CommandId; } catch { if (RelayNode.log.IsErrorEnabled) { RelayNode.log.ErrorFormat("Unrecognized commandID {0} sent to Relay Service via socket transport", message.CommandId); } result.CompleteOperation(wasSyncronous); return(result); } switch (command) { case SocketCommand.Unknown: if (RelayNode.log.IsErrorEnabled) { RelayNode.log.Error("SocketCommand.Unknown received"); } result.CompleteOperation(wasSyncronous); return(result); case SocketCommand.HandleOneWayMessage: case SocketCommand.HandleSyncMessage: relayMessage = RelayMessageFormatter.ReadRelayMessage(message.Message); relayMessage.ResultOutcome = RelayOutcome.Received; _dataHandler.BeginHandleMessage(relayMessage, null, async => { try { _dataHandler.EndHandleMessage(async); if (command == SocketCommand.HandleSyncMessage) { result.ReplyMessage = relayMessage; } } catch (Exception exc) { result.Exception = exc; } finally { result.CompleteOperation(async.CompletedSynchronously); } }); break; case SocketCommand.HandleOneWayMessages: case SocketCommand.HandleSyncMessages: relayMessages = RelayMessageFormatter.ReadRelayMessageList(message.Message, msg => msg.ResultOutcome = RelayOutcome.Received); _dataHandler.BeginHandleMessages(relayMessages, null, async => { try { _dataHandler.EndHandleMessages(async); if (command == SocketCommand.HandleSyncMessages) { result.ReplyMessages = relayMessages; } } catch (Exception exc) { result.Exception = exc; } finally { result.CompleteOperation(async.CompletedSynchronously); } }); break; case SocketCommand.GetRuntimeInfo: _enqueueGetComponentRuntimeInfo(result); break; default: if (RelayNode.log.IsErrorEnabled) { RelayNode.log.ErrorFormat("Unhandled command {0} sent to Relay Service via socket transport", command); } result.CompleteOperation(wasSyncronous); return(result); } } catch (Exception exc) { result.Exception = exc; result.CompleteOperation(wasSyncronous); } return(result); }