protected void ProcessCall(ProcessState state) { MemoryStream messageStream = null; MemoryStream replyStream = null; MessageState message = null; try { messageStream = state.message.Item; if (asyncMessageHandler != null) { message = new MessageState { CommandId = state.commandId, Message = messageStream, Length = state.messageLength, ClientIP = state.remoteEndpoint }; asyncMessageHandler.BeginHandleMessage(message, (asyncResult) => { try { MemoryStream reply = asyncMessageHandler.EndHandleMessage(asyncResult); CompleteProcessCall(state, reply); //not APM } catch (Exception exc) { if (log.IsErrorEnabled) log.Error(exc); } }); return; //very important } if (AsynMessageHandler != null) { replyStream = AsynMessageHandler.Invoke((int)state.commandId, messageStream, state.remoteEndpoint.Address); } else if (MessageHandler != null) { replyStream = MessageHandler.HandleMessage((int)state.commandId, messageStream, state.messageLength); } } catch (Exception ex) { try { string endPoint = state.socket.RemoteEndPoint.ToString(); if (log.IsErrorEnabled) log.ErrorFormat("Socket Server Exception handling message from {0}: {1}.", endPoint, ex); replyStream = null; } catch (ObjectDisposedException) { } } finally { if (message != null) { message.Message = null; message.Length = 0; } bufferPool.ReleaseItem(state.message); state.message = null; } CompleteProcessCall(state, replyStream); }
/// <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; }