Add (not-working) callback instance context mode test and FIXME comment.
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel / ClientRuntimeChannel.cs
index b4464634fa12a86805227784f5cfa33c80377d8c..97d603be14e3e2681f6563ca25835c6f2c9367a3 100644 (file)
@@ -26,6 +26,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 using System;
+using System.Collections.Generic;
 using System.Reflection;
 using System.Runtime.Serialization;
 using System.ServiceModel.Channels;
@@ -37,9 +38,27 @@ using System.Xml;
 
 namespace System.ServiceModel.MonoInternal
 {
+#if DISABLE_REAL_PROXY
        // FIXME: This is a quick workaround for bug #571907
-       public class ClientRuntimeChannel
-               : CommunicationObject, IClientChannel
+       public
+#endif
+       interface IInternalContextChannel
+       {
+               ContractDescription Contract { get; }
+
+               object Process (MethodBase method, string operationName, object [] parameters);
+
+               IAsyncResult BeginProcess (MethodBase method, string operationName, object [] parameters, AsyncCallback callback, object asyncState);
+
+               object EndProcess (MethodBase method, string operationName, object [] parameters, IAsyncResult result);
+       }
+
+#if DISABLE_REAL_PROXY
+       // FIXME: This is a quick workaround for bug #571907
+       public
+#endif
+       class ClientRuntimeChannel
+               : CommunicationObject, IClientChannel, IInternalContextChannel
        {
                ClientRuntime runtime;
                EndpointAddress remote_address;
@@ -72,10 +91,12 @@ namespace System.ServiceModel.MonoInternal
 
                public ClientRuntimeChannel (ClientRuntime runtime, ContractDescription contract, TimeSpan openTimeout, TimeSpan closeTimeout, IChannel contextChannel, IChannelFactory factory, MessageVersion messageVersion, EndpointAddress remoteAddress, Uri via)
                {
+                       if (runtime == null)
+                               throw new ArgumentNullException ("runtime");
                        this.runtime = runtime;
                        this.remote_address = remoteAddress;
                        if (runtime.Via == null)
-                               runtime.Via = via ?? remote_address.Uri;
+                               runtime.Via = via ?? (remote_address != null ?remote_address.Uri : null);
                        this.contract = contract;
                        this.message_version = messageVersion;
                        default_open_timeout = openTimeout;
@@ -360,7 +381,8 @@ namespace System.ServiceModel.MonoInternal
                protected override void OnClose (TimeSpan timeout)
                {
                        DateTime start = DateTime.Now;
-                       channel.Close (timeout);
+                       if (channel.State == CommunicationState.Opened)
+                               channel.Close (timeout);
                }
 
                Action<TimeSpan> open_callback;
@@ -413,42 +435,13 @@ namespace System.ServiceModel.MonoInternal
 
                #region Request/Output processing
 
-               class TempAsyncResult : IAsyncResult
-               {
-                       public TempAsyncResult (object returnValue, object state)
-                       {
-                               ReturnValue = returnValue;
-                               AsyncState = state;
-                               CompletedSynchronously = true;
-                               IsCompleted = true;
-                               AsyncWaitHandle = new ManualResetEvent (true);
-                       }
-                       
-                       public object ReturnValue { get; set; }
-                       public object AsyncState { get; set; }
-                       public bool CompletedSynchronously { get; set; }
-                       public bool IsCompleted { get; set; }
-                       public WaitHandle AsyncWaitHandle { get; set; }
-               }
-
                public IAsyncResult BeginProcess (MethodBase method, string operationName, object [] parameters, AsyncCallback callback, object asyncState)
                {
                        if (context != null)
                                throw new InvalidOperationException ("another operation is in progress");
                        context = OperationContext.Current;
 
-                       // FIXME: this is a workaround for bug #633945
-                       switch (Environment.OSVersion.Platform) {
-                       case PlatformID.Unix:
-                       case PlatformID.MacOSX:
-                               return _processDelegate.BeginInvoke (method, operationName, parameters, callback, asyncState);
-                       default:
-                               var result = Process (method, operationName, parameters);
-                               var ret = new TempAsyncResult (asyncState, result);
-                               if (callback != null)
-                                       callback (ret);
-                               return ret;
-                       }
+                       return _processDelegate.BeginInvoke (method, operationName, parameters, callback, asyncState);
                }
 
                public object EndProcess (MethodBase method, string operationName, object [] parameters, IAsyncResult result)
@@ -460,14 +453,7 @@ namespace System.ServiceModel.MonoInternal
                                throw new ArgumentNullException ("parameters");
                        // FIXME: the method arguments should be verified to be 
                        // identical to the arguments in the corresponding begin method.
-                       // FIXME: this is a workaround for bug #633945
-                       switch (Environment.OSVersion.Platform) {
-                       case PlatformID.Unix:
-                       case PlatformID.MacOSX:
-                               return _processDelegate.EndInvoke (result);
-                       default:
-                               return ((TempAsyncResult) result).ReturnValue;
-                       }
+                       return _processDelegate.EndInvoke (result);
                }
 
                public object Process (MethodBase method, string operationName, object [] parameters)
@@ -574,11 +560,18 @@ namespace System.ServiceModel.MonoInternal
                {
                        if (RequestChannel != null)
                                return RequestChannel.Request (msg, timeout);
-                       else {
-                               DateTime startTime = DateTime.Now;
-                               OutputChannel.Send (msg, timeout);
-                               return ((IDuplexChannel) OutputChannel).Receive (timeout - (DateTime.Now - startTime));
-                       }
+                       else
+                               return RequestCorrelated (msg, timeout, OutputChannel);
+               }
+
+               internal virtual Message RequestCorrelated (Message msg, TimeSpan timeout, IOutputChannel channel)
+               {
+                       // FIXME: implement ConcurrencyMode check:
+                       // if it is .Single && this instance for a callback channel && the operation is invoked inside service operation, then error.
+
+                       DateTime startTime = DateTime.Now;
+                       OutputChannel.Send (msg, timeout);
+                       return ((IDuplexChannel) channel).Receive (timeout - (DateTime.Now - startTime));
                }
 
                internal IAsyncResult BeginRequest (Message msg, TimeSpan timeout, AsyncCallback callback, object state)
@@ -650,7 +643,7 @@ namespace System.ServiceModel.MonoInternal
                                        msg.Headers.MessageId = new UniqueId ();
                                if (msg.Headers.ReplyTo == null)
                                        msg.Headers.ReplyTo = new EndpointAddress (Constants.WsaAnonymousUri);
-                               if (msg.Headers.To == null)
+                               if (msg.Headers.To == null && RemoteAddress != null)
                                        msg.Headers.To = RemoteAddress.Uri;
                        }