| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- //------------------------------------------------------------
- // 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);
- }
- }
- }
- }
|