From 9afba05efd2f0e14f43393a44b477ed38e519bd1 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Tue, 15 Jun 2010 05:45:38 +0000 Subject: [PATCH] 2010-05-28 Atsushi Enomoto * TcpBinaryFrameManager.cs : lock read and write respectively. Finally fixed bug #567672 ('IsOneWay=false' case). * CallbackBehaviorAttributeTest.cs : added test for bug #567672 ('IsOneWay=false' case). svn path=/trunk/mcs/; revision=158912 --- .../System.ServiceModel.Channels/ChangeLog | 5 ++ .../TcpBinaryFrameManager.cs | 33 ++++++++- .../CallbackBehaviorAttributeTest.cs | 72 ++++++++++++++++++- .../Test/System.ServiceModel/ChangeLog | 5 ++ 4 files changed, 113 insertions(+), 2 deletions(-) diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog index 9380749489e..e5a137dbbdd 100755 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog @@ -1,3 +1,8 @@ +2010-05-28 Atsushi Enomoto + + * TcpBinaryFrameManager.cs : lock read and write respectively. + Finally fixed bug #567672 ('IsOneWay=false' case). + 2010-05-28 Atsushi Enomoto * DirectionalAction.cs : remove old code from winfx beta. diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TcpBinaryFrameManager.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TcpBinaryFrameManager.cs index 466719e25af..42ada319382 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TcpBinaryFrameManager.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/TcpBinaryFrameManager.cs @@ -155,6 +155,8 @@ namespace System.ServiceModel.Channels public byte [] ReadSizedChunk () { + lock (read_lock) { + int length = reader.ReadVariableInt (); if (length == 0) return empty_bytes; @@ -166,9 +168,11 @@ namespace System.ServiceModel.Channels for (int readSize = 0; readSize < length; ) readSize += reader.Read (buffer, readSize, length - readSize); return buffer; + + } } - public void WriteSizedChunk (byte [] data, int index, int length) + void WriteSizedChunk (byte [] data, int index, int length) { writer.WriteVariableInt (length); writer.Write (data, index, length); @@ -258,8 +262,13 @@ namespace System.ServiceModel.Channels XmlBinaryReaderSession reader_session; int reader_session_items; + object read_lock = new object (); + object write_lock = new object (); + public Message ReadSizedMessage () { + lock (read_lock) { + // FIXME: implement full [MC-NMF]. int packetType; @@ -318,11 +327,15 @@ namespace System.ServiceModel.Channels benc.CurrentReaderSession = null; return msg; + + } } // FIXME: support timeout public Message ReadUnsizedMessage (TimeSpan timeout) { + lock (read_lock) { + // Encoding type 7 is expected if (EncodingRecord != EncodingBinary) throw new NotImplementedException (String.Format ("Message encoding {0:X} is not implemented yet", EncodingRecord)); @@ -347,6 +360,8 @@ namespace System.ServiceModel.Channels Message msg = Encoder.ReadMessage (ms, (int) ms.Length); return msg; + + } } byte [] eof_buffer = new byte [1]; @@ -354,6 +369,8 @@ namespace System.ServiceModel.Channels public void WriteSizedMessage (Message message) { + lock (write_lock) { + ResetWriteBuffer (); if (EncodingRecord != 8) @@ -395,11 +412,15 @@ namespace System.ServiceModel.Channels s.Write (buffer.GetBuffer (), 0, (int) buffer.Position); s.Flush (); + + } } // FIXME: support timeout public void WriteUnsizedMessage (Message message, TimeSpan timeout) { + lock (write_lock) { + ResetWriteBuffer (); if (EncodingRecord != EncodingBinary) @@ -414,19 +435,29 @@ namespace System.ServiceModel.Channels s.WriteByte (UnsizedMessageTerminator); // terminator s.Flush (); + + } } public void WriteEndRecord () { + lock (write_lock) { + s.WriteByte (EndRecord); // it is required s.Flush (); + + } } public void ReadEndRecord () { + lock (read_lock) { + int b; if ((b = s.ReadByte ()) != EndRecord) throw new ProtocolException (String.Format ("EndRecord message was expected, got {0:X}", b)); + + } } } } diff --git a/mcs/class/System.ServiceModel/Test/System.ServiceModel/CallbackBehaviorAttributeTest.cs b/mcs/class/System.ServiceModel/Test/System.ServiceModel/CallbackBehaviorAttributeTest.cs index 2455698998f..2bc1342b907 100644 --- a/mcs/class/System.ServiceModel/Test/System.ServiceModel/CallbackBehaviorAttributeTest.cs +++ b/mcs/class/System.ServiceModel/Test/System.ServiceModel/CallbackBehaviorAttributeTest.cs @@ -176,7 +176,7 @@ namespace MonoTests.System.ServiceModel proxy.SendMessage (); //Wait for callback - sort of hack, but better than using wait handle to possibly block tests. - Thread.Sleep (1000); + Thread.Sleep (2000); //Cleanup eventServiceHost.Close (); @@ -185,6 +185,36 @@ namespace MonoTests.System.ServiceModel Assert.IsTrue (CallbackReceived, "#2"); } + [Test] + public void CallbackExample2 () + { + //Start service and use net.tcp binding + ServiceHost eventServiceHost = new ServiceHost (typeof (GreetingsService2)); + NetTcpBinding tcpBindingpublish = new NetTcpBinding (); + tcpBindingpublish.Security.Mode = SecurityMode.None; + eventServiceHost.AddServiceEndpoint (typeof (IGreetings2), tcpBindingpublish, "net.tcp://localhost:8000/GreetingsService2"); + eventServiceHost.Open (); + + //Create client proxy + NetTcpBinding clientBinding = new NetTcpBinding (); + clientBinding.Security.Mode = SecurityMode.None; + EndpointAddress ep = new EndpointAddress ("net.tcp://localhost:8000/GreetingsService2"); + ClientCallback2 cb = new ClientCallback2 (); + IGreetings2 proxy = DuplexChannelFactory.CreateChannel (new InstanceContext (cb), clientBinding, ep); + + //Call service + proxy.SendMessage (); + + //Wait for callback - sort of hack, but better than using wait handle to possibly block tests. + Thread.Sleep (2000); + + //Cleanup + eventServiceHost.Close (); + + Assert.IsTrue (CallbackSent2, "#1"); + Assert.IsTrue (CallbackReceived2, "#2"); + } + public static bool CallbackSent, CallbackReceived; //Service implementation @@ -224,6 +254,46 @@ namespace MonoTests.System.ServiceModel [OperationContract (IsOneWay = true)] void ShowMessage (string message); } + + public static bool CallbackSent2, CallbackReceived2; + + //Service implementation + [ServiceBehavior (ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)] + public class GreetingsService2 : IGreetings2 + { + public void SendMessage () + { + //Make a callback + IGreetingsCallback2 clientCallback = OperationContext.Current.GetCallbackChannel (); + + clientCallback.ShowMessage ("Mono and WCF are GREAT!"); + CallbackBehaviorAttributeTest.CallbackSent2 = true; + } + } + + // Client callback interface implementation + [CallbackBehavior (ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)] + public class ClientCallback2 : IGreetingsCallback2 + { + public void ShowMessage (string message) + { + CallbackBehaviorAttributeTest.CallbackReceived2 = true; + } + } + + [ServiceContract (CallbackContract = typeof (IGreetingsCallback2))] + public interface IGreetings2 + { + [OperationContract (IsOneWay = false)] + void SendMessage (); + } + + [ServiceContract] + public interface IGreetingsCallback2 + { + [OperationContract (IsOneWay = false)] + void ShowMessage (string message); + } #endregion } } diff --git a/mcs/class/System.ServiceModel/Test/System.ServiceModel/ChangeLog b/mcs/class/System.ServiceModel/Test/System.ServiceModel/ChangeLog index fbd1a5b389c..19d50063544 100755 --- a/mcs/class/System.ServiceModel/Test/System.ServiceModel/ChangeLog +++ b/mcs/class/System.ServiceModel/Test/System.ServiceModel/ChangeLog @@ -1,3 +1,8 @@ +2010-06-15 Atsushi Enomoto + + * CallbackBehaviorAttributeTest.cs : added test for bug #567672 + ('IsOneWay=false' case). + 2010-06-04 Atsushi Enomoto * CallbackBehaviorAttributeTest.cs : test recent changes on operation -- 2.25.1