Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@ -0,0 +1,11 @@
2009-12-10 Atsushi Enomoto <atsushi@ximian.com>
* IDuplexSessionRouter.cs
IRequestReplyRouter.cs
ISimplexDatagramRouter.cs
ISimplexSessionRouter.cs
RoutingBehavior.cs
RoutingConfiguration.cs
RoutingExtension.cs
RoutingService.cs
SoapProcessingBehavior.cs: initial checkin.

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace System.ServiceModel.Routing
{
// I guess there should be [ServiceContract] here.
[ServiceContract (Namespace = "http://schemas.microsoft.com/netfx/2009/05/routing", SessionMode = SessionMode.Required)]
public interface IDuplexSessionRouter
{
[OperationContract (AsyncPattern = true, IsOneWay = true, Action = "*")]
IAsyncResult BeginProcessMessage (Message message, AsyncCallback callback, object state);
void EndProcessMessage (IAsyncResult result);
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace System.ServiceModel.Routing
{
[ServiceContract (Namespace = "http://schemas.microsoft.com/netfx/2009/05/routing", SessionMode = SessionMode.Allowed)]
public interface IRequestReplyRouter
{
[OperationContract (AsyncPattern = true, IsOneWay = false, Action = "*", ReplyAction = "*")]
IAsyncResult BeginProcessRequest (Message message, AsyncCallback callback, object state);
Message EndProcessRequest (IAsyncResult result);
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace System.ServiceModel.Routing
{
[ServiceContract (Namespace = "http://schemas.microsoft.com/netfx/2009/05/routing", SessionMode = SessionMode.Allowed)]
public interface ISimplexDatagramRouter
{
[OperationContract (AsyncPattern = true, IsOneWay = true, Action = "*")]
IAsyncResult BeginProcessMessage (Message message, AsyncCallback callback, object state);
void EndProcessMessage (IAsyncResult result);
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace System.ServiceModel.Routing
{
[ServiceContract (Namespace = "http://schemas.microsoft.com/netfx/2009/05/routing", SessionMode = SessionMode.Required)]
public interface ISimplexSessionRouter
{
[OperationContract (AsyncPattern = true, IsOneWay = true, Action = "*")]
IAsyncResult BeginProcessMessage (Message message, AsyncCallback callback, object state);
void EndProcessMessage (IAsyncResult result);
}
}

View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace System.ServiceModel.Routing
{
public sealed class RoutingBehavior : IServiceBehavior
{
// seealso http://msdn.microsoft.com/en-us/library/ee517422%28VS.100%29.aspx
[MonoTODO]
public static Type GetContractForDescription (ContractDescription description)
{
throw new NotImplementedException ();
}
// instance members
public RoutingBehavior (RoutingConfiguration routingConfiguration)
{
if (routingConfiguration == null)
throw new ArgumentNullException ("routingConfiguration");
config = routingConfiguration;
}
RoutingConfiguration config;
void IServiceBehavior.AddBindingParameters (ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
// nothing to do here.
}
void IServiceBehavior.ApplyDispatchBehavior (ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
// FIXME: not sure if this is correct.
if (config.SoapProcessingEnabled)
foreach (var ses in config.FilterTable.Values)
foreach (var se in ses)
se.Behaviors.Add (new SoapProcessingBehavior ());
var ext = new RoutingExtension ();
((IExtension<ServiceHostBase>) ext).Attach (serviceHostBase);
ext.ApplyConfiguration (config);
}
void IServiceBehavior.Validate (ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
if (!serviceDescription.ServiceType.IsAssignableFrom (typeof (RoutingService)))
throw new InvalidOperationException ("RoutingBehavior can be applied only to RoutingService");
}
}
}

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace System.ServiceModel.Routing
{
public sealed class RoutingConfiguration
{
public RoutingConfiguration ()
: this (new MessageFilterTable<IEnumerable<ServiceEndpoint>> (), true)
{
// probably init from configuration
}
public RoutingConfiguration (MessageFilterTable<IEnumerable<ServiceEndpoint>> filterTable, bool routeOnHeadersOnly)
{
FilterTable = filterTable;
RouteOnHeadersOnly = routeOnHeadersOnly;
SoapProcessingEnabled = true;
}
public MessageFilterTable<IEnumerable<ServiceEndpoint>> FilterTable { get; private set; }
public bool RouteOnHeadersOnly { get; set; }
public bool SoapProcessingEnabled { get; set; }
}
}

View File

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace System.ServiceModel.Routing
{
public sealed class RoutingExtension : IExtension<ServiceHostBase>
{
class InstanceProvider : IInstanceProvider
{
public InstanceProvider (RoutingConfiguration config)
{
this.config = config;
}
RoutingConfiguration config;
public object GetInstance (InstanceContext instanceContext)
{
return new RoutingService () { Configuration = config };
}
public object GetInstance (InstanceContext instanceContext, Message message)
{
return GetInstance (instanceContext);
}
public void ReleaseInstance (InstanceContext instanceContext, object instance)
{
}
}
internal RoutingExtension ()
{
}
ServiceHostBase host;
RoutingConfiguration configuration;
public void ApplyConfiguration (RoutingConfiguration routingConfiguration)
{
if (routingConfiguration == null)
throw new ArgumentNullException ("routingConfiguration");
configuration = routingConfiguration;
if (host == null)
return;
host.Opened += delegate {
foreach (ChannelDispatcher cd in host.ChannelDispatchers)
foreach (var ed in cd.Endpoints)
if (ed.ContractNamespace == "http://schemas.microsoft.com/netfx/2009/05/routing")
ed.DispatchRuntime.InstanceProvider = new InstanceProvider (configuration);
};
}
void IExtension<ServiceHostBase>.Attach (ServiceHostBase owner)
{
host = owner;
if (configuration != null)
ApplyConfiguration (configuration);
}
void IExtension<ServiceHostBase>.Detach (ServiceHostBase owner)
{
host = null;
}
}
}

View File

@ -0,0 +1,212 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace System.ServiceModel.Routing
{
[ServiceBehavior (AddressFilterMode = AddressFilterMode.Any, InstanceContextMode = InstanceContextMode.PerSession, UseSynchronizationContext = false, ValidateMustUnderstand = false)]
public sealed class RoutingService : ISimplexDatagramRouter, ISimplexSessionRouter, IRequestReplyRouter, IDuplexSessionRouter
{
/*
class SimplexDatagramClient : ClientBase<ISimplexDatagramRouter>, ISimplexDatagramRouter
{
public IAsyncResult BeginProcessMessage (Message message, AsyncCallback callback, object state)
{
return Channel.BeginProcessMessage (message, callback, state);
}
public void EndProcessMessage (IAsyncResult result);
{
Channel.EndProcessMessage (result);
}
}
class SimplexSessionClient : ClientBase<ISimplexSessionRouter>, ISimplexSessionRouter
{
public IAsyncResult BeginProcessMessage (Message message, AsyncCallback callback, object state)
{
return Channel.BeginProcessMessage (message, callback, state);
}
public void EndProcessMessage (IAsyncResult result);
{
Channel.EndProcessMessage (result);
}
}
class DuplexSessionClient : ClientBase<IDuplexSessionRouter>, IDuplexSessionRouter
{
public IAsyncResult BeginProcessMessage (Message message, AsyncCallback callback, object state)
{
return Channel.BeginProcessMessage (message, callback, state);
}
public void EndProcessMessage (IAsyncResult result);
{
Channel.EndProcessMessage (result);
}
}
class RequestReplyClient : ClientBase<IRequestReplyRouter>, IRequestReplyRouter
{
public IAsyncResult BeginProcessRequest (Message message, AsyncCallback callback, object state)
{
return Channel.BeginProcessRequest (message, callback, state);
}
public Message EndProcessRequest (IAsyncResult result);
{
return Channel.EndProcessRequest (result);
}
}
*/
internal RoutingService ()
{
}
internal RoutingConfiguration Configuration { get; set; }
Action<Message> process_message_duplex_session_handler;
Action<Message> process_message_simplex_datagram_handler;
Action<Message> process_message_simplex_session_handler;
//Func<Message,Message> process_request_handler;
Dictionary<ServiceEndpoint,ChannelFactory> factories = new Dictionary<ServiceEndpoint,ChannelFactory> ();
ChannelFactory<IRequestReplyRouter> request_reply_factory;
IRequestReplyRouter request_reply_channel;
//Dictionary<ServiceEndpoint,IChannel> sessions = new Dictionary<ServiceEndpoint,IChannel> ();
IEnumerable<ServiceEndpoint> GetMatchingEndpoints (Message message)
{
IEnumerable<ServiceEndpoint> ret;
if (!Configuration.FilterTable.GetMatchingValue (message, out ret))
throw new EndpointNotFoundException ();
return ret;
}
// static readonly MethodInfo create_factory_method = typeof (ChannelFactory).GetMethod ("CreateFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
void ProcessMessageDuplexSession (Message message)
{
var sel = GetMatchingEndpoints (message);
foreach (var se in sel) {
ChannelFactory cf;
if (!factories.TryGetValue (se, out cf)) {
cf = new ChannelFactory<IDuplexSessionRouter> (se);
factories [se] = cf;
}
// FIXME: possibly reuse session channels, though I doubt saving session *at the router* makes sense...
var ch = ((ChannelFactory<IDuplexSessionRouter>) cf).CreateChannel ();
ch.EndProcessMessage (ch.BeginProcessMessage (message, null, null));
}
}
void ProcessMessageSimplexDatagram (Message message)
{
var sel = GetMatchingEndpoints (message);
foreach (var se in sel) {
ChannelFactory cf;
if (!factories.TryGetValue (se, out cf)) {
cf = new ChannelFactory<ISimplexDatagramRouter> (se);
factories [se] = cf;
}
var ch = ((ChannelFactory<ISimplexDatagramRouter>) cf).CreateChannel ();
ch.EndProcessMessage (ch.BeginProcessMessage (message, null, null));
}
}
void ProcessMessageSimplexSession (Message message)
{
var sel = GetMatchingEndpoints (message);
foreach (var se in sel) {
ChannelFactory cf;
if (!factories.TryGetValue (se, out cf)) {
cf = new ChannelFactory<ISimplexSessionRouter> (se);
factories [se] = cf;
}
// FIXME: possibly reuse session channels, though I doubt saving session *at the router* makes sense...
var ch = ((ChannelFactory<ISimplexSessionRouter>) cf).CreateChannel ();
ch.EndProcessMessage (ch.BeginProcessMessage (message, null, null));
}
}
IAsyncResult IDuplexSessionRouter.BeginProcessMessage (Message message, AsyncCallback callback, object state)
{
if (process_message_duplex_session_handler == null)
process_message_duplex_session_handler = new Action<Message> (ProcessMessageDuplexSession);
return process_message_duplex_session_handler.BeginInvoke (message, callback, state);
}
void IDuplexSessionRouter.EndProcessMessage (IAsyncResult result)
{
if (process_message_duplex_session_handler == null)
throw new InvalidOperationException ("Async operation has not started");
process_message_duplex_session_handler.EndInvoke (result);
}
IAsyncResult IRequestReplyRouter.BeginProcessRequest (Message message, AsyncCallback callback, object state)
{
if (request_reply_channel != null)
throw new InvalidOperationException ("Another async request operation is in progress");
var sel = GetMatchingEndpoints (message);
ServiceEndpoint se = null;
foreach (var se_ in sel) {
if (se != null)
throw new InvalidOperationException ("Multiple endpoints cannot be specified for request-reply channel");
se = se_;
}
if (se == null)
throw new InvalidOperationException ("No service endpoint is registered to the request-reply channel");
if (request_reply_factory == null)
request_reply_factory = new ChannelFactory<IRequestReplyRouter> (se);
request_reply_channel = request_reply_factory.CreateChannel ();
return request_reply_channel.BeginProcessRequest (message, null, null);
}
Message IRequestReplyRouter.EndProcessRequest (IAsyncResult result)
{
if (request_reply_channel == null)
throw new InvalidOperationException ("Async request has not started");
var ch = request_reply_channel;
request_reply_channel = null;
return ch.EndProcessRequest (result);
}
IAsyncResult ISimplexDatagramRouter.BeginProcessMessage (Message message, AsyncCallback callback, object state)
{
if (process_message_simplex_datagram_handler == null)
process_message_simplex_datagram_handler = new Action<Message> (ProcessMessageSimplexDatagram);
return process_message_simplex_datagram_handler.BeginInvoke (message, callback, state);
}
void ISimplexDatagramRouter.EndProcessMessage (IAsyncResult result)
{
if (process_message_simplex_datagram_handler == null)
throw new InvalidOperationException ("Async operation has not started");
process_message_simplex_datagram_handler.EndInvoke (result);
}
IAsyncResult ISimplexSessionRouter.BeginProcessMessage (Message message, AsyncCallback callback, object state)
{
if (process_message_simplex_session_handler == null)
process_message_simplex_session_handler = new Action<Message> (ProcessMessageSimplexSession);
return process_message_simplex_session_handler.BeginInvoke (message, callback, state);
}
void ISimplexSessionRouter.EndProcessMessage (IAsyncResult result)
{
if (process_message_simplex_session_handler == null)
throw new InvalidOperationException ("Async operation has not started");
process_message_simplex_session_handler.EndInvoke (result);
}
}
}

View File

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace System.ServiceModel.Routing
{
public class SoapProcessingBehavior : IEndpointBehavior
{
class MessageInspector : IClientMessageInspector
{
public MessageInspector (SoapProcessingBehavior owner, ServiceEndpoint endpoint)
{
this.endpoint = endpoint;
}
ServiceEndpoint endpoint;
public object BeforeSendRequest (ref Message request, IClientChannel channel)
{
// See "Request processing" at http://msdn.microsoft.com/en-us/library/ee517422%28VS.100%29.aspx
var original = request;
var msg = Message.CreateMessage (endpoint.Binding.MessageVersion, request.Headers.Action, request.GetReaderAtBodyContents ());
// The above page does not explain, but it should do copy headers (other than addressing ones, to be removed later).
msg.Headers.Action = null;
msg.Headers.CopyHeadersFrom (request);
msg.Headers.To = null;
msg.Headers.From = null;
msg.Headers.FaultTo = null;
msg.Headers.RelatesTo = null;
msg.Properties.CopyProperties (request.Properties);
request = msg;
return original;
}
public void AfterReceiveReply (ref Message reply, object correlationState)
{
// See "Response processing" at http://msdn.microsoft.com/en-us/library/ee517422%28VS.100%29.aspx
Message original = (Message) correlationState;
var msg = Message.CreateMessage (original.Version, reply.Headers.Action, reply.GetReaderAtBodyContents ());
// The above page does not explain, but it should do copy headers (other than addressing ones, to be removed later).
msg.Headers.Action = null;
msg.Headers.CopyHeadersFrom (reply);
/*
msg.Headers.To = null;
msg.Headers.From = null;
msg.Headers.FaultTo = null;
msg.Headers.RelatesTo = null;
*/
msg.Properties.CopyProperties (reply.Properties);
reply = msg;
}
}
public SoapProcessingBehavior ()
{
ProcessMessages = true;
}
public bool ProcessMessages { get; set; }
public void AddBindingParameters (ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
// nothing to do here.
}
public void ApplyClientBehavior (ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
if (!ProcessMessages)
return;
clientRuntime.MessageInspectors.Add (new MessageInspector (this, endpoint));
}
public void ApplyDispatchBehavior (ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
throw new NotSupportedException (); // ... right? I assume it is not for services.
}
public void Validate (ServiceEndpoint endpoint)
{
}
}
}