2010-05-28 Atsushi Enomoto <atsushi@ximian.com>
authorAtsushi Eno <atsushieno@gmail.com>
Tue, 15 Jun 2010 05:45:38 +0000 (05:45 -0000)
committerAtsushi Eno <atsushieno@gmail.com>
Tue, 15 Jun 2010 05:45:38 +0000 (05:45 -0000)
* 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

mcs/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog
mcs/class/System.ServiceModel/System.ServiceModel.Channels/TcpBinaryFrameManager.cs
mcs/class/System.ServiceModel/Test/System.ServiceModel/CallbackBehaviorAttributeTest.cs
mcs/class/System.ServiceModel/Test/System.ServiceModel/ChangeLog

index 9380749489ee7764377d04fb1b60c0c8b2ceced7..e5a137dbbdd1fc8c2fe968caa32d78b6880ccb2c 100755 (executable)
@@ -1,3 +1,8 @@
+2010-05-28  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * TcpBinaryFrameManager.cs : lock read and write respectively.
+         Finally fixed bug #567672 ('IsOneWay=false' case).
+
 2010-05-28  Atsushi Enomoto  <atsushi@ximian.com>
 
        * DirectionalAction.cs : remove old code from winfx beta.
index 466719e25afbcab04b3586f95f6bdbd5f93eaad9..42ada3193824f018c00ddc686e86aa1ddcb67cb5 100644 (file)
@@ -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));
+
+                       }
                }
        }
 }
index 2455698998feacb6f4e06bf73e48f3f8334a212c..2bc1342b9074dfbfa3293b236b4c34c8afdd4841 100644 (file)
@@ -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<IGreetings2>.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<IGreetingsCallback2> ();
+
+                               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
        }
 }
index fbd1a5b389ca54f72ce33a7945657fb6d0408052..19d50063544f83c1af18494657c7957f17b2aa3c 100755 (executable)
@@ -1,3 +1,8 @@
+2010-06-15  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * CallbackBehaviorAttributeTest.cs : added test for bug #567672
+         ('IsOneWay=false' case).
+
 2010-06-04  Atsushi Enomoto  <atsushi@ximian.com>
 
        * CallbackBehaviorAttributeTest.cs : test recent changes on operation