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