You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@ -0,0 +1,381 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Channels
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Runtime;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Diagnostics;
|
||||
|
||||
class ClientContextProtocol : ContextProtocol, IContextManager
|
||||
{
|
||||
ContextMessageProperty context;
|
||||
bool contextInitialized;
|
||||
bool contextManagementEnabled;
|
||||
CookieContainer cookieContainer;
|
||||
IChannel owner;
|
||||
object thisLock;
|
||||
Uri uri;
|
||||
Uri callbackAddress;
|
||||
|
||||
public ClientContextProtocol(ContextExchangeMechanism contextExchangeMechanism, Uri uri, IChannel owner, Uri callbackAddress, bool contextManagementEnabled)
|
||||
: base(contextExchangeMechanism)
|
||||
{
|
||||
if (contextExchangeMechanism == ContextExchangeMechanism.HttpCookie)
|
||||
{
|
||||
this.cookieContainer = new CookieContainer();
|
||||
}
|
||||
this.context = ContextMessageProperty.Empty;
|
||||
this.contextManagementEnabled = contextManagementEnabled;
|
||||
this.owner = owner;
|
||||
this.thisLock = new object();
|
||||
this.uri = uri;
|
||||
this.callbackAddress = callbackAddress;
|
||||
}
|
||||
|
||||
protected Uri Uri
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.uri;
|
||||
}
|
||||
}
|
||||
|
||||
bool IContextManager.Enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.contextManagementEnabled;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (this.owner.State != CommunicationState.Created)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
||||
new InvalidOperationException(
|
||||
SR.GetString(SR.ChannelIsOpen)
|
||||
));
|
||||
}
|
||||
this.contextManagementEnabled = value;
|
||||
}
|
||||
}
|
||||
|
||||
public IDictionary<string, string> GetContext()
|
||||
{
|
||||
if (!this.contextManagementEnabled)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
||||
new InvalidOperationException(
|
||||
SR.GetString(SR.ContextManagementNotEnabled)
|
||||
));
|
||||
}
|
||||
return new Dictionary<string, string>(this.GetCurrentContext().Context);
|
||||
}
|
||||
|
||||
public override void OnIncomingMessage(Message message)
|
||||
{
|
||||
if (message == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
|
||||
}
|
||||
|
||||
ContextMessageProperty incomingContext = null;
|
||||
if (this.ContextExchangeMechanism == ContextExchangeMechanism.HttpCookie)
|
||||
{
|
||||
incomingContext = this.OnReceiveHttpCookies(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
incomingContext = this.OnReceiveSoapContextHeader(message);
|
||||
}
|
||||
|
||||
if (incomingContext != null)
|
||||
{
|
||||
if (this.contextManagementEnabled)
|
||||
{
|
||||
EnsureInvariants(true, incomingContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
incomingContext.AddOrReplaceInMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
// verify that the callback context was not sent on an incoming message
|
||||
if (message.Headers.FindHeader(CallbackContextMessageHeader.CallbackContextHeaderName, CallbackContextMessageHeader.CallbackContextHeaderNamespace) != -1)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new ProtocolException(SR.GetString(SR.CallbackContextNotExpectedOnIncomingMessageAtClient, message.Headers.Action, CallbackContextMessageHeader.CallbackContextHeaderName, CallbackContextMessageHeader.CallbackContextHeaderNamespace)));
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnOutgoingMessage(Message message, RequestContext requestContext)
|
||||
{
|
||||
if (message == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
|
||||
}
|
||||
|
||||
ContextMessageProperty outgoingContext = null;
|
||||
|
||||
if (ContextMessageProperty.TryGet(message, out outgoingContext))
|
||||
{
|
||||
if (this.contextManagementEnabled)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
||||
new InvalidOperationException(
|
||||
SR.GetString(SR.InvalidMessageContext)));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.ContextExchangeMechanism == ContextExchangeMechanism.ContextSoapHeader)
|
||||
{
|
||||
if (this.contextManagementEnabled)
|
||||
{
|
||||
outgoingContext = GetCurrentContext();
|
||||
}
|
||||
|
||||
if (outgoingContext != null)
|
||||
{
|
||||
this.OnSendSoapContextHeader(message, outgoingContext);
|
||||
}
|
||||
}
|
||||
else if (this.ContextExchangeMechanism == ContextExchangeMechanism.HttpCookie)
|
||||
{
|
||||
if (this.contextManagementEnabled)
|
||||
{
|
||||
this.OnSendHttpCookies(message, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.OnSendHttpCookies(message, outgoingContext);
|
||||
}
|
||||
}
|
||||
|
||||
// serialize the callback context if the property was supplied
|
||||
CallbackContextMessageProperty callbackContext;
|
||||
if (CallbackContextMessageProperty.TryGet(message, out callbackContext))
|
||||
{
|
||||
// see if the callbackaddress is already set on the CCMP, if it is set use that
|
||||
// else if callbackaddress is set on the binding, use that
|
||||
EndpointAddress callbackAddress = callbackContext.CallbackAddress;
|
||||
if (callbackAddress == null && this.callbackAddress != null)
|
||||
{
|
||||
callbackAddress = callbackContext.CreateCallbackAddress(this.callbackAddress);
|
||||
}
|
||||
// add the CallbackContextMessageHeader only if we have a valid CallbackAddress
|
||||
if (callbackAddress != null)
|
||||
{
|
||||
if (this.ContextExchangeMechanism != ContextExchangeMechanism.ContextSoapHeader)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CallbackContextOnlySupportedInSoap)));
|
||||
}
|
||||
message.Headers.Add(new CallbackContextMessageHeader(callbackAddress, message.Version.Addressing));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetContext(IDictionary<string, string> context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
|
||||
}
|
||||
|
||||
ContextMessageProperty newContext = new ContextMessageProperty(context);
|
||||
|
||||
EnsureInvariants(false, newContext);
|
||||
|
||||
if (this.ContextExchangeMechanism == ContextExchangeMechanism.HttpCookie)
|
||||
{
|
||||
lock (this.cookieContainer)
|
||||
{
|
||||
this.cookieContainer.SetCookies(this.Uri, GetCookieHeaderFromContext(newContext));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Called to update local context
|
||||
//1) From SetContext(to update client provided context)
|
||||
//2) From OnReceive*(to update server issued)
|
||||
void EnsureInvariants(bool isServerIssued, ContextMessageProperty newContext)
|
||||
{
|
||||
//Cannot SetContext when ContextManagement not enabled.
|
||||
if (!this.contextManagementEnabled)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
||||
new InvalidOperationException(
|
||||
SR.GetString(SR.ContextManagementNotEnabled)
|
||||
));
|
||||
}
|
||||
|
||||
//Cannot reset context after initialized in server case.
|
||||
if ((isServerIssued && !this.contextInitialized) ||
|
||||
(this.owner.State == CommunicationState.Created))
|
||||
{
|
||||
lock (this.thisLock)
|
||||
{
|
||||
if ((isServerIssued && !this.contextInitialized) ||
|
||||
(this.owner.State == CommunicationState.Created))
|
||||
{
|
||||
this.context = newContext;
|
||||
this.contextInitialized = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isServerIssued)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
||||
new ProtocolException(
|
||||
SR.GetString(SR.InvalidContextReceived)
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
||||
new InvalidOperationException(
|
||||
SR.GetString(SR.CachedContextIsImmutable)
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
string GetCookieHeaderFromContext(ContextMessageProperty contextMessageProperty)
|
||||
{
|
||||
if (contextMessageProperty.Context.Count == 0)
|
||||
{
|
||||
return HttpCookieToolbox.RemoveContextHttpCookieHeader;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HttpCookieToolbox.EncodeContextAsHttpSetCookieHeader(contextMessageProperty, this.Uri);
|
||||
}
|
||||
}
|
||||
|
||||
ContextMessageProperty GetCurrentContext()
|
||||
{
|
||||
ContextMessageProperty result;
|
||||
|
||||
if (this.cookieContainer != null)
|
||||
{
|
||||
lock (this.cookieContainer)
|
||||
{
|
||||
// This is to allow for the possibility of that the cookie has expired
|
||||
if (this.cookieContainer.GetCookies(this.Uri)[HttpCookieToolbox.ContextHttpCookieName] == null)
|
||||
{
|
||||
result = ContextMessageProperty.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = this.context;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = this.context;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ContextMessageProperty OnReceiveHttpCookies(Message message)
|
||||
{
|
||||
ContextMessageProperty newContext = null;
|
||||
object property;
|
||||
if (message.Properties.TryGetValue(HttpResponseMessageProperty.Name, out property))
|
||||
{
|
||||
HttpResponseMessageProperty httpResponse = property as HttpResponseMessageProperty;
|
||||
if (httpResponse != null)
|
||||
{
|
||||
string setCookieHeader = httpResponse.Headers[HttpResponseHeader.SetCookie];
|
||||
|
||||
if (!string.IsNullOrEmpty(setCookieHeader))
|
||||
{
|
||||
lock (this.cookieContainer)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(setCookieHeader))
|
||||
{
|
||||
this.cookieContainer.SetCookies(this.Uri, setCookieHeader);
|
||||
HttpCookieToolbox.TryCreateFromHttpCookieHeader(setCookieHeader, out newContext);
|
||||
}
|
||||
|
||||
if (!this.contextManagementEnabled)
|
||||
{
|
||||
this.cookieContainer.SetCookies(this.Uri, HttpCookieToolbox.RemoveContextHttpCookieHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return newContext;
|
||||
}
|
||||
|
||||
ContextMessageProperty OnReceiveSoapContextHeader(Message message)
|
||||
{
|
||||
ContextMessageProperty messageProperty = ContextMessageHeader.GetContextFromHeaderIfExists(message);
|
||||
if (messageProperty != null)
|
||||
{
|
||||
if (DiagnosticUtility.ShouldTraceVerbose)
|
||||
{
|
||||
TraceUtility.TraceEvent(System.Diagnostics.TraceEventType.Verbose,
|
||||
TraceCode.ContextProtocolContextRetrievedFromMessage, SR.GetString(SR.TraceCodeContextProtocolContextRetrievedFromMessage),
|
||||
this);
|
||||
}
|
||||
}
|
||||
return messageProperty;
|
||||
}
|
||||
|
||||
|
||||
void OnSendHttpCookies(Message message, ContextMessageProperty context)
|
||||
{
|
||||
string cookieHeader = null;
|
||||
|
||||
if (this.contextManagementEnabled || context == null)
|
||||
{
|
||||
Fx.Assert(context == null, "Context should be null");
|
||||
|
||||
lock (this.cookieContainer)
|
||||
{
|
||||
cookieHeader = this.cookieContainer.GetCookieHeader(this.Uri);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context != null) //User provided context is not null.
|
||||
{
|
||||
string contextCookieHeader = this.GetCookieHeaderFromContext(context);
|
||||
|
||||
lock (this.cookieContainer)
|
||||
{
|
||||
this.cookieContainer.SetCookies(this.Uri, contextCookieHeader);
|
||||
cookieHeader = this.cookieContainer.GetCookieHeader(this.Uri);
|
||||
this.cookieContainer.SetCookies(this.Uri, HttpCookieToolbox.RemoveContextHttpCookieHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(cookieHeader))
|
||||
{
|
||||
object tmpProperty;
|
||||
HttpRequestMessageProperty property = null;
|
||||
if (message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out tmpProperty))
|
||||
{
|
||||
property = tmpProperty as HttpRequestMessageProperty;
|
||||
}
|
||||
if (property == null)
|
||||
{
|
||||
property = new HttpRequestMessageProperty();
|
||||
message.Properties.Add(HttpRequestMessageProperty.Name, property);
|
||||
}
|
||||
property.Headers.Add(HttpRequestHeader.Cookie, cookieHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user