You've already forked linux-packaging-mono
Imported Upstream version 4.0.0~alpha1
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
249
external/referencesource/System.ServiceModel/System/ServiceModel/Channels/MessageEncoder.cs
vendored
Normal file
249
external/referencesource/System.ServiceModel/System/ServiceModel/Channels/MessageEncoder.cs
vendored
Normal file
@ -0,0 +1,249 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace System.ServiceModel.Channels
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Mime;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Diagnostics;
|
||||
using System.ServiceModel.Diagnostics;
|
||||
using System.Runtime;
|
||||
using System.Threading;
|
||||
using System.ServiceModel.Diagnostics.Application;
|
||||
|
||||
public abstract class MessageEncoder
|
||||
{
|
||||
private string traceSourceString;
|
||||
|
||||
public abstract string ContentType { get; }
|
||||
|
||||
public abstract string MediaType { get; }
|
||||
|
||||
public abstract MessageVersion MessageVersion { get; }
|
||||
|
||||
public virtual T GetProperty<T>() where T : class
|
||||
{
|
||||
if (typeof(T) == typeof(FaultConverter))
|
||||
{
|
||||
return (T)(object)FaultConverter.GetDefaultFaultConverter(this.MessageVersion);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Message ReadMessage(Stream stream, int maxSizeOfHeaders)
|
||||
{
|
||||
return ReadMessage(stream, maxSizeOfHeaders, null);
|
||||
}
|
||||
|
||||
public abstract Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType);
|
||||
|
||||
public Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager)
|
||||
{
|
||||
Message message = ReadMessage(buffer, bufferManager, null);
|
||||
return message;
|
||||
}
|
||||
|
||||
public abstract Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType);
|
||||
|
||||
// used for buffered streaming
|
||||
internal ArraySegment<byte> BufferMessageStream(Stream stream, BufferManager bufferManager, int maxBufferSize)
|
||||
{
|
||||
byte[] buffer = bufferManager.TakeBuffer(ConnectionOrientedTransportDefaults.ConnectionBufferSize);
|
||||
int offset = 0;
|
||||
int currentBufferSize = Math.Min(buffer.Length, maxBufferSize);
|
||||
|
||||
while (offset < currentBufferSize)
|
||||
{
|
||||
int count = stream.Read(buffer, offset, currentBufferSize - offset);
|
||||
if (count == 0)
|
||||
{
|
||||
stream.Close();
|
||||
break;
|
||||
}
|
||||
|
||||
offset += count;
|
||||
if (offset == currentBufferSize)
|
||||
{
|
||||
if (currentBufferSize >= maxBufferSize)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(MaxMessageSizeStream.CreateMaxReceivedMessageSizeExceededException(maxBufferSize));
|
||||
}
|
||||
|
||||
currentBufferSize = Math.Min(currentBufferSize * 2, maxBufferSize);
|
||||
byte[] temp = bufferManager.TakeBuffer(currentBufferSize);
|
||||
Buffer.BlockCopy(buffer, 0, temp, 0, offset);
|
||||
bufferManager.ReturnBuffer(buffer);
|
||||
buffer = temp;
|
||||
}
|
||||
}
|
||||
|
||||
return new ArraySegment<byte>(buffer, 0, offset);
|
||||
}
|
||||
|
||||
// used for buffered streaming
|
||||
internal virtual Message ReadMessage(Stream stream, BufferManager bufferManager, int maxBufferSize, string contentType)
|
||||
{
|
||||
return ReadMessage(BufferMessageStream(stream, bufferManager, maxBufferSize), bufferManager, contentType);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ContentType;
|
||||
}
|
||||
|
||||
public abstract void WriteMessage(Message message, Stream stream);
|
||||
|
||||
public virtual IAsyncResult BeginWriteMessage(Message message, Stream stream, AsyncCallback callback, object state)
|
||||
{
|
||||
return new WriteMessageAsyncResult(message, stream, this, callback, state);
|
||||
}
|
||||
|
||||
public virtual void EndWriteMessage(IAsyncResult result)
|
||||
{
|
||||
WriteMessageAsyncResult.End(result);
|
||||
}
|
||||
|
||||
public ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager)
|
||||
{
|
||||
ArraySegment<byte> arraySegment = WriteMessage(message, maxMessageSize, bufferManager, 0);
|
||||
return arraySegment;
|
||||
}
|
||||
|
||||
public abstract ArraySegment<byte> WriteMessage(Message message, int maxMessageSize,
|
||||
BufferManager bufferManager, int messageOffset);
|
||||
|
||||
public virtual bool IsContentTypeSupported(string contentType)
|
||||
{
|
||||
if (contentType == null)
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("contentType"));
|
||||
|
||||
return IsContentTypeSupported(contentType, this.ContentType, this.MediaType);
|
||||
}
|
||||
|
||||
internal bool IsContentTypeSupported(string contentType, string supportedContentType, string supportedMediaType)
|
||||
{
|
||||
if (supportedContentType == contentType)
|
||||
return true;
|
||||
|
||||
if (contentType.Length > supportedContentType.Length &&
|
||||
contentType.StartsWith(supportedContentType, StringComparison.Ordinal) &&
|
||||
contentType[supportedContentType.Length] == ';')
|
||||
return true;
|
||||
|
||||
// now check case-insensitively
|
||||
if (contentType.StartsWith(supportedContentType, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (contentType.Length == supportedContentType.Length)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (contentType.Length > supportedContentType.Length)
|
||||
{
|
||||
char ch = contentType[supportedContentType.Length];
|
||||
|
||||
// Linear Whitespace is allowed to appear between the end of one property and the semicolon.
|
||||
// LWS = [CRLF]? (SP | HT)+
|
||||
if (ch == ';')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Consume the [CRLF]?
|
||||
int i = supportedContentType.Length;
|
||||
if (ch == '\r' && contentType.Length > supportedContentType.Length + 1 && contentType[i + 1] == '\n')
|
||||
{
|
||||
i += 2;
|
||||
ch = contentType[i];
|
||||
}
|
||||
|
||||
// Look for a ';' or nothing after (SP | HT)+
|
||||
if (ch == ' ' || ch == '\t')
|
||||
{
|
||||
i++;
|
||||
while (i < contentType.Length)
|
||||
{
|
||||
ch = contentType[i];
|
||||
if (ch != ' ' && ch != '\t')
|
||||
break;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if (ch == ';' || i == contentType.Length)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// sometimes we get a contentType that has parameters, but our encoders
|
||||
// merely expose the base content-type, so we will check a stripped version
|
||||
try
|
||||
{
|
||||
ContentType parsedContentType = new ContentType(contentType);
|
||||
|
||||
if (supportedMediaType.Length > 0 && !supportedMediaType.Equals(parsedContentType.MediaType, StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
if (!IsCharSetSupported(parsedContentType.CharSet))
|
||||
return false;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
// bad content type, so we definitely don't support it!
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal virtual bool IsCharSetSupported(string charset)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void ThrowIfMismatchedMessageVersion(Message message)
|
||||
{
|
||||
if (message.Version != MessageVersion)
|
||||
{
|
||||
throw TraceUtility.ThrowHelperError(
|
||||
new ProtocolException(SR.GetString(SR.EncoderMessageVersionMismatch, message.Version, MessageVersion)),
|
||||
message);
|
||||
}
|
||||
}
|
||||
|
||||
internal string GetTraceSourceString()
|
||||
{
|
||||
if (this.traceSourceString == null)
|
||||
{
|
||||
this.traceSourceString = DiagnosticTraceBase.CreateDefaultSourceString(this);
|
||||
}
|
||||
|
||||
return this.traceSourceString;
|
||||
}
|
||||
|
||||
class WriteMessageAsyncResult : ScheduleActionItemAsyncResult
|
||||
{
|
||||
MessageEncoder encoder;
|
||||
Message message;
|
||||
Stream stream;
|
||||
|
||||
public WriteMessageAsyncResult(Message message, Stream stream, MessageEncoder encoder, AsyncCallback callback, object state)
|
||||
: base(callback, state)
|
||||
{
|
||||
Fx.Assert(encoder != null, "encoder should never be null");
|
||||
|
||||
this.encoder = encoder;
|
||||
this.message = message;
|
||||
this.stream = stream;
|
||||
|
||||
Schedule();
|
||||
}
|
||||
|
||||
protected override void OnDoWork()
|
||||
{
|
||||
this.encoder.WriteMessage(this.message, this.stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user