e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
217 lines
7.7 KiB
C#
217 lines
7.7 KiB
C#
//------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//------------------------------------------------------------
|
|
|
|
namespace System.ServiceModel.Channels
|
|
{
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Runtime.Serialization;
|
|
using System.Threading;
|
|
using System.Xml;
|
|
using System.Runtime;
|
|
|
|
[Serializable]
|
|
public class CallbackContextMessageProperty : IMessageProperty
|
|
{
|
|
const string PropertyName = "CallbackContextMessageProperty";
|
|
|
|
// these hold init data from ctors
|
|
[NonSerializedAttribute]
|
|
readonly EndpointAddress listenAddress;
|
|
readonly IDictionary<string, string> context;
|
|
|
|
// used to cache "assembled" EndpointAddress that contains context property
|
|
[NonSerializedAttribute]
|
|
EndpointAddress callbackAddress;
|
|
|
|
// if this constructor is used, the listen address will have to be provided later by setting it in the ContextBindingElement
|
|
// CallbackContextMessageProperty will flow on the wire only if listenaddress is set.
|
|
public CallbackContextMessageProperty(IDictionary<string, string> context)
|
|
: this((EndpointAddress)null, context)
|
|
{
|
|
}
|
|
|
|
public CallbackContextMessageProperty(string listenAddress, IDictionary<string, string> context)
|
|
: this(new Uri(listenAddress), context)
|
|
{
|
|
}
|
|
|
|
public CallbackContextMessageProperty(Uri listenAddress, IDictionary<string, string> context)
|
|
: this(new EndpointAddress(listenAddress), context)
|
|
{
|
|
}
|
|
|
|
public CallbackContextMessageProperty(EndpointAddress listenAddress, IDictionary<string, string> context)
|
|
{
|
|
if (listenAddress != null && listenAddress.Headers.FindHeader(ContextMessageHeader.ContextHeaderName, ContextMessageHeader.ContextHeaderNamespace) != null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.ListenAddressAlreadyContainsContext));
|
|
}
|
|
this.listenAddress = listenAddress;
|
|
this.context = context;
|
|
}
|
|
|
|
public CallbackContextMessageProperty(EndpointAddress callbackAddress)
|
|
{
|
|
if (callbackAddress == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackAddress");
|
|
}
|
|
this.callbackAddress = callbackAddress;
|
|
}
|
|
|
|
public static string Name
|
|
{
|
|
get
|
|
{
|
|
return PropertyName;
|
|
}
|
|
}
|
|
|
|
public EndpointAddress CallbackAddress
|
|
{
|
|
get
|
|
{
|
|
if (this.callbackAddress == null && this.listenAddress != null)
|
|
{
|
|
this.callbackAddress = CreateCallbackAddress(this.listenAddress, this.context);
|
|
}
|
|
return this.callbackAddress;
|
|
}
|
|
}
|
|
|
|
public IDictionary<string, string> Context
|
|
{
|
|
get
|
|
{
|
|
return this.context;
|
|
}
|
|
}
|
|
|
|
public EndpointAddress CreateCallbackAddress(Uri listenAddress)
|
|
{
|
|
if (listenAddress == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("listenAddress");
|
|
}
|
|
|
|
return CreateCallbackAddress(new EndpointAddress(listenAddress), this.context);
|
|
}
|
|
|
|
static EndpointAddress CreateCallbackAddress(EndpointAddress listenAddress, IDictionary<string, string> context)
|
|
{
|
|
if (listenAddress == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
EndpointAddressBuilder builder = new EndpointAddressBuilder(listenAddress);
|
|
if (context != null)
|
|
{
|
|
builder.Headers.Add(new ContextAddressHeader(context));
|
|
}
|
|
return builder.ToEndpointAddress();
|
|
}
|
|
|
|
public static bool TryGet(Message message, out CallbackContextMessageProperty contextMessageProperty)
|
|
{
|
|
if (message == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
|
|
}
|
|
|
|
return TryGet(message.Properties, out contextMessageProperty);
|
|
}
|
|
|
|
public static bool TryGet(MessageProperties properties, out CallbackContextMessageProperty contextMessageProperty)
|
|
{
|
|
if (properties == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("properties");
|
|
}
|
|
|
|
object value = null;
|
|
if (properties.TryGetValue(PropertyName, out value))
|
|
{
|
|
contextMessageProperty = value as CallbackContextMessageProperty;
|
|
}
|
|
else
|
|
{
|
|
contextMessageProperty = null;
|
|
}
|
|
|
|
return contextMessageProperty != null;
|
|
}
|
|
|
|
public void AddOrReplaceInMessage(Message message)
|
|
{
|
|
if (message == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
|
|
}
|
|
|
|
this.AddOrReplaceInMessageProperties(message.Properties);
|
|
}
|
|
|
|
public void AddOrReplaceInMessageProperties(MessageProperties properties)
|
|
{
|
|
if (properties == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("properties");
|
|
}
|
|
|
|
properties[PropertyName] = this;
|
|
}
|
|
|
|
public IMessageProperty CreateCopy()
|
|
{
|
|
if (this.callbackAddress != null)
|
|
{
|
|
return new CallbackContextMessageProperty(this.callbackAddress);
|
|
}
|
|
else
|
|
{
|
|
return new CallbackContextMessageProperty(this.listenAddress, this.context);
|
|
}
|
|
}
|
|
|
|
[SuppressMessage(FxCop.Category.Design, FxCop.Rule.AvoidOutParameters,
|
|
Justification = "The method needs to return two objects with one parsing")]
|
|
public void GetListenAddressAndContext(out EndpointAddress listenAddress, out IDictionary<string, string> context)
|
|
{
|
|
// we expect the callback address to be already set when this is called
|
|
if (this.CallbackAddress == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackaddress");
|
|
}
|
|
EndpointAddressBuilder builder = new EndpointAddressBuilder(this.CallbackAddress);
|
|
AddressHeader contextHeader = null;
|
|
int contextHeaderIndex = -1;
|
|
for (int i = 0; i < builder.Headers.Count; ++i)
|
|
{
|
|
if (builder.Headers[i].Name == ContextMessageHeader.ContextHeaderName && builder.Headers[i].Namespace == ContextMessageHeader.ContextHeaderNamespace)
|
|
{
|
|
if (contextHeader != null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(SR.MultipleContextHeadersFoundInCallbackAddress)));
|
|
}
|
|
contextHeader = builder.Headers[i];
|
|
contextHeaderIndex = i;
|
|
}
|
|
}
|
|
if (contextHeader != null)
|
|
{
|
|
builder.Headers.RemoveAt(contextHeaderIndex);
|
|
}
|
|
context = (contextHeader != null) ? ContextMessageHeader.ParseContextHeader(contextHeader.GetAddressHeaderReader()).Context : null;
|
|
listenAddress = builder.ToEndpointAddress();
|
|
}
|
|
}
|
|
}
|