using Google.Protobuf; using System; using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Formatting; using System.Net.Http.Headers; using System.Threading.Tasks; using System.Web.Http; using Tango.PMR.Stubs; using Tango.PMR.Synchronization; namespace Tango.Web.Formatters { /// /// Represents a protobuf web request/response formatter capable of formatting messages using protobuf. /// /// public class ProtoBufFormatter : MediaTypeFormatter { private static readonly MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/x-protobuf"); /// /// Initializes a new instance of the class. /// public ProtoBufFormatter() { SupportedMediaTypes.Add(mediaType); } /// /// Gets the default type of the media. /// /// /// The default type of the media. /// public static MediaTypeHeaderValue DefaultMediaType { get { return mediaType; } } /// /// Queries whether this can deserializean object of the specified type. /// /// The type to deserialize. /// /// true if the can deserialize the type; otherwise, false. /// public override bool CanReadType(Type type) { return true; } /// /// Queries whether this can serializean object of the specified type. /// /// The type to serialize. /// /// true if the can serialize the type; otherwise, false. /// public override bool CanWriteType(Type type) { return true; } /// /// Reads from stream asynchronous. /// /// The type. /// The stream. /// The content. /// The formatter logger. /// public override Task ReadFromStreamAsync(Type type, Stream stream, HttpContent content, IFormatterLogger formatterLogger) { var tcs = new TaskCompletionSource(); try { MessageParser parser = type.GetProperty("Parser").GetValue(null, null) as MessageParser; IMessage req = parser.ParseFrom(stream); tcs.SetResult(req); } catch (Exception ex) { tcs.SetException(ex); } return tcs.Task; } /// /// Writes to stream asynchronous. /// /// The type. /// The value. /// The stream. /// The content. /// The transport context. /// public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext) { var tcs = new TaskCompletionSource(); if (value is IMessage) { try { (value as IMessage).WriteTo(stream); tcs.SetResult(null); } catch (Exception ex) { tcs.SetException(ex); } return tcs.Task; } else if (value is HttpError) { var httpError = value as HttpError; try { HttpProtoException msg = new HttpProtoException(); msg.Message = httpError["Message"].ToString(); msg.StatusCode = (int)HttpStatusCode.InternalServerError; msg.WriteTo(stream); tcs.SetResult(null); } catch (Exception ex) { tcs.SetException(ex); } return tcs.Task; } return base.WriteToStreamAsync(type, value, stream, content, transportContext); } } }