private void SendEventAsync(string methodName, IMessage message) { var requestMetrics = Metrics.StartRequestMetrics(ConnectionMetrics); var conversationId = AllocateNextConversationId(); var sendContext = new SimpleInMemSendContext(this, ConnectionMetrics, requestMetrics); IBonded layerData = null; ILayerStack layerStack; Error layerError = transport.GetLayerStack(requestMetrics.request_id, out layerStack); if (layerError == null) { layerError = LayerStackUtils.ProcessOnSend(layerStack, MessageType.Event, sendContext, out layerData, logger); } if (layerError != null) { logger.Site().Error("{0}: Sending event {1}/{2} failed due to layer error (Code: {3}, Message: {4}).", this, conversationId, methodName, layerError.error_code, layerError.message); return; } var payload = Util.NewPayLoad(conversationId, PayloadType.Event, layerData, message, null); payload.headers.method_name = methodName; writeQueue.Enqueue(payload); }
// Deserialize T from IBonded<T> containing an instance or payload of derived class. void BondedDeserialize <T, D>() where T : class where D : class, T, new() { var from = Random.Init <D>(); IBonded <T> bondedInstance = new Bonded <D>(from); IBonded <T> bondedPayloadCB = Util.MakeBondedCB(from); IBonded <T> bondedPayloadCB2 = Util.MakeBondedCB2(from); IBonded <T> bondedPayloadSP = Util.MakeBondedSP(from); IBonded <BondClass <IBonded <T> > > nestedBonded = new Bonded <BondClass <IBonded <T> > >(new BondClass <IBonded <T> > { field = bondedInstance }); for (var i = 2; --i != 0;) { var to1 = bondedInstance.Deserialize(); var to2 = bondedPayloadCB.Deserialize(); var toCb2 = bondedPayloadCB2.Deserialize(); var to3 = bondedPayloadSP.Deserialize(); Assert.IsTrue(to1.IsEqual <T>(from)); Assert.IsTrue(to2.IsEqual <T>(from)); Assert.IsTrue(toCb2.IsEqual <T>(from)); Assert.IsTrue(to3.IsEqual <T>(from)); Assert.IsTrue(nestedBonded.Deserialize().field.Deserialize().IsEqual(from)); } }
private void DispatchEvent(EpoxyHeaders headers, ArraySegment <byte> payload, ArraySegment <byte> layerData) { if (headers.error_code != (int)ErrorCode.OK) { Log.Error("{0}.{1}: Received event with a non-zero error code. Conversation ID: {2}", this, nameof(DispatchEvent), headers.conversation_id); return; } IMessage request = Message.FromPayload(Unmarshal.From(payload)); var receiveContext = new EpoxyReceiveContext(this); IBonded bondedLayerData = (layerData.Array == null) ? null : Unmarshal.From(layerData); Error layerError = LayerStackUtils.ProcessOnReceive(parentTransport.LayerStack, MessageType.Event, receiveContext, bondedLayerData); if (layerError != null) { Log.Error("{0}.{1}: Receiving event {2}/{3} failed due to layer error (Code: {4}, Message: {5}).", this, nameof(DispatchEvent), headers.conversation_id, headers.method_name, layerError.error_code, layerError.message); return; } Task.Run(async() => { await serviceHost.DispatchEvent(headers.method_name, receiveContext, request, connectionMetrics); }); }
private Error DeserializeLayerData(IBonded layerData, out TLayerData realLayerData) { Error error = null; if (layerData == null) { realLayerData = new TLayerData(); } else { try { realLayerData = layerData.Deserialize <TLayerData>(); } catch (Exception ex) { error = new Error { error_code = (int)ErrorCode.UnhandledLayerError }; Log.Error(ex, "{0}.{1}: While unmarshaling layer data: {2}", nameof(LayerStack <TLayerData>), nameof(DeserializeLayerData), ex.Message); realLayerData = new TLayerData(); } } return(error); }
private Task <IMessage> SendRequestAsync(string methodName, IMessage request) { var requestMetrics = Metrics.StartRequestMetrics(ConnectionMetrics); var conversationId = AllocateNextConversationId(); var sendContext = new SimpleInMemSendContext(this, ConnectionMetrics, requestMetrics); IBonded layerData = null; ILayerStack layerStack; Error layerError = transport.GetLayerStack(requestMetrics.request_id, out layerStack); if (layerError == null) { layerError = LayerStackUtils.ProcessOnSend(layerStack, MessageType.Request, sendContext, out layerData, logger); } if (layerError != null) { logger.Site().Error("{0}: Sending request {1}/{2} failed due to layer error (Code: {3}, Message: {4}).", this, conversationId, methodName, layerError.error_code, layerError.message); return(Task.FromResult <IMessage>(Message.FromError(layerError))); } // Pass the layer stack instance as state in response task completion source. var responseCompletionSource = new TaskCompletionSource <IMessage>(layerStack); var payload = Util.NewPayLoad(conversationId, PayloadType.Request, layerData, request, responseCompletionSource); payload.headers.method_name = methodName; writeQueue.Enqueue(payload); return(payload.outstandingRequest.Task); }
internal void SendReply(ulong conversationId, IMessage response, TaskCompletionSource <IMessage> taskSource, ILayerStack layerStack, InMemFrameQueue queue) { var requestMetrics = Metrics.StartRequestMetrics(connection.ConnectionMetrics); var sendContext = new SimpleInMemSendContext(connection, connection.ConnectionMetrics, requestMetrics); IBonded layerData = null; Error layerError = LayerStackUtils.ProcessOnSend(layerStack, MessageType.RESPONSE, sendContext, out layerData, logger); // If there was a layer error, replace the response with the layer error if (layerError != null) { logger.Site().Error("Sending reply for conversation {0} failed due to layer error (Code: {1}, Message: {2}).", conversationId, layerError.error_code, layerError.message); // Set layer error as result of this Bond method call, replacing original response. // Since this error will be returned to client, cleanse out internal server error details, if any. response = Message.FromError(Errors.CleanseInternalServerError(layerError)); } var payload = Util.NewPayLoad(conversationId, SimpleInMemMessageType.RESPONSE, layerData, response, taskSource); queue.Enqueue(payload); }
internal async Task SendEventAsync(string methodName, IMessage message) { var conversationId = AllocateNextConversationId(); var sendContext = new EpoxySendContext(this); IBonded layerData = null; ILayerStack layerStack; Error layerError = parentTransport.GetLayerStack(out layerStack); if (layerError == null) { layerError = LayerStackUtils.ProcessOnSend( layerStack, MessageType.Event, sendContext, out layerData, logger); } if (layerError != null) { logger.Site().Error("{0} Sending event {1}/{2} failed due to layer error (Code: {3}, Message: {4}).", this, conversationId, methodName, layerError.error_code, layerError.message); return; } var frame = MessageToFrame(conversationId, methodName, PayloadType.Event, message, layerData, logger); logger.Site().Debug("{0} Sending event {1}/{2}.", this, conversationId, methodName); bool wasSent = await SendFrameAsync(frame); logger.Site().Debug("{0} Sending event {1}/{2} {3}.", this, conversationId, methodName, wasSent ? "succeeded" : "failed"); }
private void DispatchResponse(EpoxyHeaders headers, ArraySegment <byte> payload, ArraySegment <byte> layerData) { IMessage response; if (headers.error_code != (int)ErrorCode.OK) { response = Message.FromError(Unmarshal <Error> .From(payload)); } else { response = Message.FromPayload(Unmarshal.From(payload)); } var receiveContext = new EpoxyReceiveContext(this); IBonded bondedLayerData = (layerData.Array == null) ? null : Unmarshal.From(layerData); Error layerError = LayerStackUtils.ProcessOnReceive(parentTransport.LayerStack, MessageType.Response, receiveContext, bondedLayerData); if (layerError != null) { Log.Error("{0}.{1}: Receiving response {2}/{3} failed due to layer error (Code: {4}, Message: {5}).", this, nameof(DispatchResponse), headers.conversation_id, headers.method_name, layerError.error_code, layerError.message); response = Message.FromError(layerError); } if (!responseMap.Complete(headers.conversation_id, response)) { Log.Error("{0}.{1}: Response for unmatched request. Conversation ID: {2}", this, nameof(DispatchResponse), headers.conversation_id); } }
private State?DispatchRequest(EpoxyHeaders headers, EpoxyProtocol.MessageData messageData, ArraySegment <byte> layerData) { Task.Run(async() => { var totalTime = Stopwatch.StartNew(); var requestMetrics = Metrics.StartRequestMetrics(ConnectionMetrics); var receiveContext = new EpoxyReceiveContext(this, ConnectionMetrics, requestMetrics); ILayerStack layerStack = null; IMessage result; if (messageData.IsError) { logger.Site().Error("{0} Received request with an error message. Only payload messages are allowed. Conversation ID: {1}", this, headers.conversation_id); result = Message.FromError(new Error { error_code = (int)ErrorCode.INVALID_INVOCATION, message = "Received request with an error message" }); } else { IMessage request = Message.FromPayload(Unmarshal.From(messageData.Data)); IBonded bondedLayerData = (layerData.Array == null) ? null : Unmarshal.From(layerData); Error layerError = parentTransport.GetLayerStack(requestMetrics.request_id, out layerStack); if (layerError == null) { layerError = LayerStackUtils.ProcessOnReceive( layerStack, MessageType.REQUEST, receiveContext, bondedLayerData, logger); } if (layerError == null) { result = await serviceHost.DispatchRequest(headers.service_name, headers.method_name, receiveContext, request); } else { logger.Site().Error("{0} Receiving request {1}/{2}.{3} failed due to layer error (Code: {4}, Message: {5}).", this, headers.conversation_id, headers.service_name, headers.method_name, layerError.error_code, layerError.message); // Set layer error as result of this Bond method call and do not dispatch to method. // Since this error will be returned to client, cleanse out internal server error details, if any. result = Message.FromError(Errors.CleanseInternalServerError(layerError)); } } await SendReplyAsync(headers.conversation_id, result, layerStack, requestMetrics); Metrics.FinishRequestMetrics(requestMetrics, totalTime); metrics.Emit(requestMetrics); }); // no state change needed return(null); }
public static void SerializeFB(IBonded obj, Stream stream) { var output = new OutputStream(stream, 11); var writer = new FastBinaryWriter <OutputStream>(output); Serialize.To(writer, obj); output.Flush(); }
protected override Task WriteToStreamBondedAsync(Stream stream, IBonded value) { var sjw = new SimpleJsonWriter(stream); value.Serialize(sjw); sjw.Flush(); return(Task.CompletedTask); }
public static void SerializeCB2 <T>(IBonded <T> obj, Stream stream) { var output = new OutputStream(stream, 11); var writer = new CompactBinaryWriter <OutputStream>(output, 2); Serialize.To(writer, obj); output.Flush(); }
public static void SerializeSP <T>(IBonded <T> obj, Stream stream) { var output = new OutputStream(stream, 11); var writer = new SimpleBinaryWriter <OutputStream>(output); Serialize.To(writer, obj); output.Flush(); }
public EpoxyProtocolErrorException( string message, Exception innerException = null, IBonded<Error> details = null) : base(message, innerException) { Details = details; }
public EpoxyProtocolErrorException( string message, Exception innerException = null, IBonded <Error> details = null) : base(message, innerException) { Details = details; }
/// <summary> /// Creates an error message from the given Error. /// </summary> /// <param name="err">The Error for the message.</param> /// <returns>An error message of unknown payload type.</returns> public static IMessage FromError(IBonded <Error> err) { if (err == null) { throw new ArgumentNullException(nameof(err)); } return(new Message(err)); }
/// <summary> /// Creates a message from the given payload. /// </summary> /// <param name="payload">The payload for the message.</param> /// <returns>A payload message of unknown payload type.</returns> public static IMessage FromPayload(IBonded payload) { if (payload == null) { throw new ArgumentNullException(nameof(payload)); } return(new Message(payload)); }
public static void SerializeXml <T>(IBonded <T> obj, Stream stream) { var writer = new SimpleXmlWriter(stream, new SimpleXmlWriter.Settings { UseNamespaces = true }); Serialize.To(writer, obj); writer.Flush(); }
internal static ArraySegment <byte> Marshal(IBonded bonded) { var output = new OutputBuffer(4096); var writer = new CompactBinaryWriter <OutputBuffer>(output); writer.WriteVersion(); bonded.Serialize(writer); return(output.Data); }
/// <summary> /// Creates a message from the given <see cref="IBonded{T}">IBonded instance</see>. /// </summary> /// <typeparam name="TPayload"> /// The type of the message payload. /// </typeparam> /// <param name="payload">The payload for the message.</param> /// <returns>A message of the given payload type.</returns> public static IMessage <TPayload> From <TPayload>(IBonded <TPayload> payload) { if (payload == null) { throw new ArgumentNullException(nameof(payload)); } return(new Message <TPayload>(payload)); }
private async Task <IMessage> SendRequestAsync <TPayload>(string serviceName, string methodName, IMessage <TPayload> request) { var conversationId = AllocateNextConversationId(); var totalTime = Stopwatch.StartNew(); var requestMetrics = Metrics.StartRequestMetrics(ConnectionMetrics); var sendContext = new EpoxySendContext(this, ConnectionMetrics, requestMetrics); IBonded layerData = null; ILayerStack layerStack; Error layerError = parentTransport.GetLayerStack(requestMetrics.request_id, out layerStack); if (layerError == null) { layerError = LayerStackUtils.ProcessOnSend( layerStack, MessageType.REQUEST, sendContext, out layerData, logger); } if (layerError != null) { logger.Site().Error("{0} Sending request {1}/{2}.{3} failed due to layer error (Code: {4}, Message: {5}).", this, conversationId, serviceName, methodName, layerError.error_code, layerError.message); return(Message.FromError(layerError)); } var frame = MessageToFrame(conversationId, serviceName, methodName, EpoxyMessageType.REQUEST, request, layerData, logger); logger.Site().Debug("{0} Sending request {1}/{2}.", this, conversationId, methodName); var responseTask = responseMap.Add(conversationId, layerStack); bool wasSent = await SendFrameAsync(frame); logger.Site().Debug("{0} Sending request {1}/{2}.{3} {4}.", this, conversationId, serviceName, methodName, wasSent ? "succeeded" : "failed"); if (!wasSent) { bool wasCompleted = responseMap.Complete( conversationId, Message.FromError(new Error { error_code = (int)ErrorCode.TRANSPORT_ERROR, message = "Request could not be sent" })); if (!wasCompleted) { logger.Site().Information("{0} Unsuccessfully sent request {1}/{2}.{3} still received response.", this, conversationId, serviceName, methodName); } } var message = await responseTask; Metrics.FinishRequestMetrics(requestMetrics, totalTime); metrics.Emit(requestMetrics); return(message); }
// To create an error Message, use Message.FromError<TPayload>() or Message.FromError(). // // This ctor is internal so that a non-error Message<Error> can be created. If this were // public, then new Message<Error>(SomeError) would resolve to this ctor, creating an error // message, instead of to the generic ctor. We need new Message<Error>(SomeError) to resolve // to the generic ctor to create a non-error Message. internal Message(IBonded <Error> error) { if (error == null) { throw new ArgumentNullException(nameof(error)); } payload = null; this.error = error; }
/// <summary> /// Initializes a Message with the given payload. /// </summary> /// <param name="payload">The payload for the message.</param> public Message(IBonded payload) { if (payload == null) { throw new ArgumentNullException(nameof(payload)); } this.payload = payload; error = null; }
/// <summary> /// Creates an error message from the given error. /// </summary> /// <param name="err">The error for the message.</param> /// <returns>An error message of unknown payload type.</returns> public static IMessage FromError(IBonded <Error> err) { if (err == null) { throw new ArgumentNullException(nameof(err)); } // can't check that err has a non-zero error code without deserializaing, so we skip that return(new Message(err)); }
protected ArraySegment <byte> SerializeToBytes(IBonded value) { if (value == null) { throw new ArgumentNullException(nameof(value)); } this.Buffer.Position = 0; value.Serialize(this.Writer); return(this.Buffer.Data); }
/// <summary> /// Attempt to deserialize an object contained within a Bonded field as its derived type. /// </summary> /// <typeparam name="T">The base type of the Bonded field.</typeparam> /// <typeparam name="U">The desired derived type of the field.</typeparam> /// <param name="bonded">The Bonded source for the data.</param> /// <returns>Non-null object if the data was successfully desieralized, null otherwise.</returns> public static U TryDeserialize <T, U>(this IBonded <T> bonded) where U : class { try { return(bonded.Deserialize <U>()); } catch (InvalidDataException) { return(null); } }
internal static Frame MessageToFrame( ulong conversationId, string serviceName, string methodName, EpoxyMessageType type, IMessage message, IBonded layerData, Logger logger) { var frame = new Frame(logger); { var headers = new EpoxyHeaders { conversation_id = conversationId, message_type = type, service_name = serviceName ?? string.Empty, // service_name is not nullable method_name = methodName ?? string.Empty // method_name is not nullable }; const int initialHeaderBufferSize = 150; var outputBuffer = new OutputBuffer(initialHeaderBufferSize); var fastWriter = new FastBinaryWriter <OutputBuffer>(outputBuffer); Serialize.To(fastWriter, headers); frame.Add(new Framelet(FrameletType.EpoxyHeaders, outputBuffer.Data)); } if (layerData != null) { const int initialLayerDataBufferSize = 150; var outputBuffer = new OutputBuffer(initialLayerDataBufferSize); var compactWriter = new CompactBinaryWriter <OutputBuffer>(outputBuffer); compactWriter.WriteVersion(); layerData.Serialize(compactWriter); frame.Add(new Framelet(FrameletType.LayerData, outputBuffer.Data)); } { FrameletType frameletType = message.IsError ? FrameletType.ErrorData : FrameletType.PayloadData; IBonded userData = message.IsError ? message.Error : message.RawPayload; const int initialMessageBufferSize = 1024; var outputBuffer = new OutputBuffer(initialMessageBufferSize); var compactWriter = new CompactBinaryWriter <OutputBuffer>(outputBuffer); compactWriter.WriteVersion(); userData.Serialize(compactWriter); frame.Add(new Framelet(frameletType, outputBuffer.Data)); } return(frame); }
private State?DispatchRequest(EpoxyHeaders headers, ArraySegment <byte> payload, ArraySegment <byte> layerData) { if (headers.error_code != (int)ErrorCode.OK) { logger.Site().Error("{0} Received request with a non-zero error code. Conversation ID: {1}", this, headers.conversation_id); protocolError = ProtocolErrorCode.PROTOCOL_VIOLATED; return(State.SendProtocolError); } Task.Run(async() => { var totalTime = Stopwatch.StartNew(); var requestMetrics = Metrics.StartRequestMetrics(ConnectionMetrics); var receiveContext = new EpoxyReceiveContext(this, ConnectionMetrics, requestMetrics); IMessage request = Message.FromPayload(Unmarshal.From(payload)); IBonded bondedLayerData = (layerData.Array == null) ? null : Unmarshal.From(layerData); ILayerStack layerStack; Error layerError = parentTransport.GetLayerStack(requestMetrics.request_id, out layerStack); if (layerError == null) { layerError = LayerStackUtils.ProcessOnReceive( layerStack, MessageType.Request, receiveContext, bondedLayerData, logger); } IMessage result; if (layerError == null) { result = await serviceHost.DispatchRequest(headers.method_name, receiveContext, request); } else { logger.Site().Error("{0} Receiving request {1}/{2} failed due to layer error (Code: {3}, Message: {4}).", this, headers.conversation_id, headers.method_name, layerError.error_code, layerError.message); // Set layer error as result of this Bond method call and do not dispatch to method. // Since this error will be returned to client, cleanse out internal server error details, if any. result = Message.FromError(Errors.CleanseInternalServerError(layerError)); } await SendReplyAsync(headers.conversation_id, result, layerStack, requestMetrics); Metrics.FinishRequestMetrics(requestMetrics, totalTime); metrics.Emit(requestMetrics); }); // no state change needed return(null); }
private async Task <IMessage> SendRequestAsync <TPayload>(string methodName, IMessage <TPayload> request) { var conversationId = AllocateNextConversationId(); var sendContext = new EpoxySendContext(this); IBonded layerData = null; ILayerStack layerStack; Error layerError = parentTransport.GetLayerStack(out layerStack); if (layerError == null) { layerError = LayerStackUtils.ProcessOnSend( layerStack, MessageType.Request, sendContext, out layerData, logger); } if (layerError != null) { logger.Site().Error("{0} Sending request {1}/{2} failed due to layer error (Code: {3}, Message: {4}).", this, conversationId, methodName, layerError.error_code, layerError.message); return(Message.FromError(layerError)); } var frame = MessageToFrame(conversationId, methodName, PayloadType.Request, request, layerData, logger); logger.Site().Debug("{0} Sending request {1}/{2}.", this, conversationId, methodName); var responseTask = responseMap.Add(conversationId, layerStack); bool wasSent = await SendFrameAsync(frame); logger.Site().Debug("{0} Sending request {1}/{2} {3}.", this, conversationId, methodName, wasSent ? "succeeded" : "failed"); if (!wasSent) { bool wasCompleted = responseMap.Complete( conversationId, Message.FromError(new Error { error_code = (int)ErrorCode.TransportError, message = "Request could not be sent" })); if (!wasCompleted) { logger.Site().Information("{0} Unsuccessfully sent request {1}/{2} still received response.", this, conversationId, methodName); } } return(await responseTask); }
protected Lazy(IBonded bonded) { Debug.Assert(!(bonded is Bonded <T>)); var lazy = bonded as Lazy <T, R>; if (lazy != null) { instance = lazy.instance; } this.bonded = bonded.Convert <T>(); }
void DispatchEvent(EpoxyHeaders headers, EpoxyProtocol.MessageData messageData, ArraySegment <byte> layerData) { if (messageData.IsError) { logger.Site().Error( "{0} Received event with an error message. Only payload messages are allowed. Conversation ID: {1}", this, headers.conversation_id); return; } Task.Run( async() => { IMessage request = Message.FromPayload(Unmarshal.From(messageData.Data)); var totalTime = Stopwatch.StartNew(); var requestMetrics = Metrics.StartRequestMetrics(ConnectionMetrics); var receiveContext = new RelayEpoxyReceiveContext(this, ConnectionMetrics, requestMetrics); IBonded bondedLayerData = (layerData.Array == null) ? null : Unmarshal.From(layerData); ILayerStack layerStack; Error layerError = parentTransport.GetLayerStack(requestMetrics.request_id, out layerStack); if (layerError == null) { layerError = LayerStackUtils.ProcessOnReceive( layerStack, MessageType.EVENT, receiveContext, bondedLayerData, logger); } if (layerError != null) { logger.Site().Error( "{0}: Receiving event {1}/{2}.{3} failed due to layer error (Code: {4}, Message: {5}).", this, headers.conversation_id, headers.service_name, headers.method_name, layerError.error_code, layerError.message); return; } await serviceHost.DispatchEvent(headers.service_name, headers.method_name, receiveContext, request); Metrics.FinishRequestMetrics(requestMetrics, totalTime); metrics.Emit(requestMetrics); }); }
public static Error ProcessOnSend( ILayerStack layerStack, MessageType messageType, SendContext sendContext, out IBonded layerData, Logger logger) { Error error = null; layerData = null; if (layerStack != null) { error = layerStack.OnSend(messageType, sendContext, out layerData); if (error != null) { logger.Site().Warning("Layer error occurred sending message of type {0} (Code: {1} Message: {2}).", messageType, error.error_code, error.message); } } return error; }
internal static InMemFrame NewPayLoad(ulong conversationId, PayloadType payloadType, IBonded layerData, IMessage message, TaskCompletionSource<IMessage> taskSource) { var headers = new SimpleInMemHeaders { conversation_id = conversationId, payload_type = payloadType }; var payload = new InMemFrame { headers = headers, layerData = layerData, message = message, outstandingRequest = taskSource }; Validate(payload); return payload; }
public static Error ProcessOnReceive( ILayerStack layerStack, MessageType messageType, ReceiveContext receiveContext, IBonded layerData, Logger logger) { Error error = null; if (layerStack != null) { if (layerData == null) { logger.Site().Warning("Layer stack present but no layer data received."); } error = layerStack.OnReceive(messageType, receiveContext, layerData); if (error != null) { logger.Site().Warning("Layer error occurred receiving message of type {0} (Code: {1} Message: {2}).", messageType, error.error_code, error.message); } } return error; }