diff options
author | Aidan Skinner <aidan@apache.org> | 2009-12-22 20:59:57 +0000 |
---|---|---|
committer | Aidan Skinner <aidan@apache.org> | 2009-12-22 20:59:57 +0000 |
commit | 7f9ed6e2b0f36ecaaecddaf70c8647b1fa9d1db9 (patch) | |
tree | be9da793f2236f827a36cb9943f6393b1cc8e77a | |
parent | 3b02993425f0b3479fcb131b1d3bba9ce5eab3e4 (diff) | |
download | qpid-python-7f9ed6e2b0f36ecaaecddaf70c8647b1fa9d1db9.tar.gz |
QPID-2239: make sure the close() does not hand.
Also handle authentication failures properly, QPID-2240.
Patch by julien.lavigne
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@893315 13f79535-47bb-0310-9956-ffa450edef68
16 files changed, 199 insertions, 128 deletions
diff --git a/qpid/dotnet/client-010/client/client/Client.cs b/qpid/dotnet/client-010/client/client/Client.cs index 1b87a3d578..864cf65186 100644 --- a/qpid/dotnet/client-010/client/client/Client.cs +++ b/qpid/dotnet/client-010/client/client/Client.cs @@ -34,11 +34,18 @@ namespace org.apache.qpid.client private readonly Object _closeOK; private IClosedListener _closedListner; + public event EventHandler<ExceptionArgs> ExceptionRaised; + public event EventHandler ConnectionLost; public bool IsClosed { get { return _isClosed; } - set { _isClosed = value; } + set + { + _isClosed = value; + if(_isClosed && ConnectionLost != null) + ConnectionLost(this, EventArgs.Empty); + } } public Object CloseOk @@ -67,14 +74,20 @@ namespace org.apache.qpid.client { _log.Debug(String.Format("Client Connecting to host {0}; port {1}; virtualHost {2}; username {3}", host, port, virtualHost, username)); - ConnectionDelegate connectionDelegate = new ClientConnectionDelegate(this, username, password); + ClientConnectionDelegate connectionDelegate = new ClientConnectionDelegate(this, username, password); ManualResetEvent negotiationComplete = new ManualResetEvent(false); - connectionDelegate.setCondition(negotiationComplete); + connectionDelegate.SetCondition(negotiationComplete); connectionDelegate.VirtualHost = virtualHost; _conn = IoTransport.Connect(host, port, connectionDelegate); _conn.Send(new ProtocolHeader(1, 0, 10)); negotiationComplete.WaitOne(); + + if (connectionDelegate.Exception != null) + throw connectionDelegate.Exception; + + connectionDelegate.SetCondition(null); + } /// <summary> @@ -93,15 +106,20 @@ namespace org.apache.qpid.client { _log.Debug(String.Format("Client Connecting to host {0}; port {1}; virtualHost {2}; username {3}", host, port, virtualHost, username)); - _log.Debug(String.Format("SSL paramters: serverName: {0}; certPath: {1}; rejectUntrusted: {2}", serverName, certPath, rejectUntrusted)); - ConnectionDelegate connectionDelegate = new ClientConnectionDelegate(this, username, password); + _log.Debug(String.Format("SSL paramters: serverName: {0}; certPath: {1}; rejectUntrusted: {2}", serverName, certPath, rejectUntrusted)); + ClientConnectionDelegate connectionDelegate = new ClientConnectionDelegate(this, username, password); ManualResetEvent negotiationComplete = new ManualResetEvent(false); - connectionDelegate.setCondition(negotiationComplete); + connectionDelegate.SetCondition(negotiationComplete); connectionDelegate.VirtualHost = virtualHost; _conn = IoSSLTransport.Connect(host, port, serverName, certPath, rejectUntrusted, connectionDelegate); _conn.Send(new ProtocolHeader(1, 0, 10)); negotiationComplete.WaitOne(); + + if (connectionDelegate.Exception != null) + throw connectionDelegate.Exception; + + connectionDelegate.SetCondition(null); } public void Close() @@ -142,5 +160,11 @@ namespace org.apache.qpid.client } #endregion + + public void RaiseException(Exception exception) + { + if (ExceptionRaised != null) + ExceptionRaised(this, new ExceptionArgs(exception)); + } } } diff --git a/qpid/dotnet/client-010/client/client/ClientConnectionDelegate.cs b/qpid/dotnet/client-010/client/client/ClientConnectionDelegate.cs index fff65673bc..9999f5312d 100644 --- a/qpid/dotnet/client-010/client/client/ClientConnectionDelegate.cs +++ b/qpid/dotnet/client-010/client/client/ClientConnectionDelegate.cs @@ -33,6 +33,7 @@ namespace org.apache.qpid.client private readonly Client _client; private string _username; private string _password; + private Exception _exception; public ClientConnectionDelegate(Client client, string username, string pasword) { @@ -41,14 +42,24 @@ namespace org.apache.qpid.client _password = pasword; } + public Exception Exception + { + get { return _exception; } + } + public override SessionDelegate GetSessionDelegate() { return new ClientSessionDelegate(); } - public override void Exception(Exception t) + public override void RaiseException(Exception exception) { - throw t; + _exception = exception; + + if (_negotiationComplete != null) + _negotiationComplete.Set(); + else + _client.RaiseException(exception); } public override void ConnectionStart(Channel context, ConnectionStart mystruct) @@ -78,7 +89,7 @@ namespace org.apache.qpid.client catch (Exception e) { throw new SystemException("Error when closing client", e); - } + } } } @@ -86,12 +97,12 @@ namespace org.apache.qpid.client { base.ConnectionClose(context, connectionClose); ErrorCode errorCode = ErrorCode.GetErrorCode((int) connectionClose.GetReplyCode()); - if (_client.ClosedListener == null && errorCode.Code != (int) QpidErrorCode.NO_ERROR) - { - throw new Exception ("Server Closed the connection: Reason " + - connectionClose.GetReplyText()); - } - _client.ClosedListener.OnClosed(errorCode, connectionClose.GetReplyText(), null); + + if(_client.ClosedListener != null) + _client.ClosedListener.OnClosed(errorCode, connectionClose.GetReplyText(), null); + + if (errorCode.Code != (int)QpidErrorCode.NO_ERROR) + throw new Exception ("Server Closed the connection: Reason " + connectionClose.GetReplyText()); } } } diff --git a/qpid/dotnet/client-010/client/client/IClient.cs b/qpid/dotnet/client-010/client/client/IClient.cs index a9da74a840..6fe4a4d4b8 100644 --- a/qpid/dotnet/client-010/client/client/IClient.cs +++ b/qpid/dotnet/client-010/client/client/IClient.cs @@ -18,6 +18,7 @@ */ using System; +using org.apache.qpid.transport; namespace org.apache.qpid.client { @@ -49,13 +50,18 @@ namespace org.apache.qpid.client /// <returns>A newly created (suspended) session.</returns> IClientSession CreateSession(long expiryInSeconds); + + event EventHandler<ExceptionArgs> ExceptionRaised; + event EventHandler ConnectionLost; + /// <summary> - /// If the communication layer detects a serious problem with a connection, it - // informs the client's ClosedListener + /// If the broker sends a disconnect message, it will notify the ClosedListener /// </summary> /// IClosedListener ClosedListener { set; } + + bool IsClosed { get; set; } /// <summary> diff --git a/qpid/dotnet/client-010/client/transport/Channel.cs b/qpid/dotnet/client-010/client/transport/Channel.cs index 1742c05a3d..48ba707182 100644 --- a/qpid/dotnet/client-010/client/transport/Channel.cs +++ b/qpid/dotnet/client-010/client/transport/Channel.cs @@ -64,7 +64,7 @@ namespace org.apache.qpid.transport public void Init(Object v, ProtocolHeader hdr) { - _connection.ConnectionDelegate.init(this, hdr); + _connection.ConnectionDelegate.Init(this, hdr); } public void Control(Object v, Method method) @@ -171,4 +171,4 @@ namespace org.apache.qpid.transport return String.Format("{0}:{1}", _connection, _channel); } } -} +}
\ No newline at end of file diff --git a/qpid/dotnet/client-010/client/transport/ClientDelegate.cs b/qpid/dotnet/client-010/client/transport/ClientDelegate.cs index 865cc6df20..957324ad41 100644 --- a/qpid/dotnet/client-010/client/transport/ClientDelegate.cs +++ b/qpid/dotnet/client-010/client/transport/ClientDelegate.cs @@ -24,7 +24,7 @@ namespace org.apache.qpid.transport { abstract class ClientDelegate : ConnectionDelegate { - public override void init(Channel ch, ProtocolHeader hdr) + public override void Init(Channel ch, ProtocolHeader hdr) { if (hdr.Major != 0 && hdr.Minor != 10) { diff --git a/qpid/dotnet/client-010/client/transport/Connection.cs b/qpid/dotnet/client-010/client/transport/Connection.cs index bd1509384c..b97357a96b 100644 --- a/qpid/dotnet/client-010/client/transport/Connection.cs +++ b/qpid/dotnet/client-010/client/transport/Connection.cs @@ -130,7 +130,7 @@ namespace org.apache.qpid.transport public void On_ReceivedException(Object sender, ExceptionArgs arg) { - _connDdelegate.Exception(arg.Exception); + _connDdelegate.RaiseException(arg.Exception); } public void On_ReceivedClosed(Object sender, EventArgs arg) diff --git a/qpid/dotnet/client-010/client/transport/ConnectionDelegate.cs b/qpid/dotnet/client-010/client/transport/ConnectionDelegate.cs index 825909645d..5d491bc06f 100644 --- a/qpid/dotnet/client-010/client/transport/ConnectionDelegate.cs +++ b/qpid/dotnet/client-010/client/transport/ConnectionDelegate.cs @@ -35,20 +35,20 @@ namespace org.apache.qpid.transport private static readonly Logger log = Logger.Get(typeof(ConnectionDelegate)); private String _virtualHost; - private ManualResetEvent _negotiationComplete; + protected ManualResetEvent _negotiationComplete; public abstract SessionDelegate GetSessionDelegate(); - public abstract void Exception(Exception t); + public abstract void RaiseException(Exception t); public abstract void Closed(); - public void setCondition(ManualResetEvent negotiationComplete) + public void SetCondition(ManualResetEvent negotiationComplete) { _negotiationComplete = negotiationComplete; } - public virtual void init(Channel ch, ProtocolHeader hdr) + public virtual void Init(Channel ch, ProtocolHeader hdr) { ch.Connection.Send(new ProtocolHeader((byte)1, hdr.Major, hdr.Minor)); List<Object> plain = new List<Object>(); @@ -105,4 +105,4 @@ namespace org.apache.qpid.transport ch.ConnectionCloseOk(); } } -} +}
\ No newline at end of file diff --git a/qpid/dotnet/client-010/client/transport/network/Assembler.cs b/qpid/dotnet/client-010/client/transport/network/Assembler.cs index ac8f48567f..ff85f11c2f 100644 --- a/qpid/dotnet/client-010/client/transport/network/Assembler.cs +++ b/qpid/dotnet/client-010/client/transport/network/Assembler.cs @@ -42,8 +42,11 @@ namespace org.apache.qpid.transport.network // the event raised when a buffer is read from the wire public event EventHandler<ReceivedPayload<IProtocolEvent>> ReceivedEvent; - public event EventHandler<ExceptionArgs> ExceptionProcessing; - public event EventHandler HandlerClosed; + public event EventHandler Closed; + + + // Not in use : + public event EventHandler<ExceptionArgs> Exception; event EventHandler<ReceivedPayload<IProtocolEvent>> IReceiver<ReceivedPayload<IProtocolEvent>>.Received { @@ -63,42 +66,6 @@ namespace org.apache.qpid.transport.network } } - event EventHandler<ExceptionArgs> IReceiver<ReceivedPayload<IProtocolEvent>>.Exception - { - add - { - lock (m_objectLock) - { - ExceptionProcessing += value; - } - } - remove - { - lock (m_objectLock) - { - ExceptionProcessing -= value; - } - } - } - - event EventHandler IReceiver<ReceivedPayload<IProtocolEvent>>.Closed - { - add - { - lock (m_objectLock) - { - HandlerClosed += value; - } - } - remove - { - lock (m_objectLock) - { - HandlerClosed -= value; - } - } - } - public Assembler() { segments = new Dictionary<int, List<byte[]>>(); @@ -267,16 +234,21 @@ namespace org.apache.qpid.transport.network log.Debug("Assembler: protocol event:", protevent); ReceivedPayload<IProtocolEvent> payload = new ReceivedPayload<IProtocolEvent>(); payload.Payload = protevent; - if (ReceivedEvent != null) + + if (protevent is ConnectionCloseOk) { - ReceivedEvent(this, payload); + if (Closed != null) + Closed(this, EventArgs.Empty); } else { - log.Debug("No listener for event: {0}", protevent); + if (ReceivedEvent != null) + ReceivedEvent(this, payload); + else + log.Debug("No listener for event: {0}", protevent); } } #endregion } -} +}
\ No newline at end of file diff --git a/qpid/dotnet/client-010/client/transport/network/InputHandler.cs b/qpid/dotnet/client-010/client/transport/network/InputHandler.cs index 1872b9a111..c5d5f13727 100644 --- a/qpid/dotnet/client-010/client/transport/network/InputHandler.cs +++ b/qpid/dotnet/client-010/client/transport/network/InputHandler.cs @@ -44,7 +44,9 @@ namespace org.apache.qpid.transport.network // the event raised when a buffer is read from the wire public event EventHandler<ReceivedPayload<INetworkEvent>> ReceivedEvent; public event EventHandler<ExceptionArgs> ExceptionProcessing; - public event EventHandler HandlerClosed; + + // Not in used... This even is never raised in the code => the application will block on Close() until the timeout is reached + public event EventHandler Closed; event EventHandler<ReceivedPayload<INetworkEvent>> IReceiver<ReceivedPayload<INetworkEvent>>.Received { @@ -82,24 +84,6 @@ namespace org.apache.qpid.transport.network } } - event EventHandler IReceiver<ReceivedPayload<INetworkEvent>>.Closed - { - add - { - lock (m_objectLock) - { - HandlerClosed += value; - } - } - remove - { - lock (m_objectLock) - { - HandlerClosed -= value; - } - } - } - private State state; private MemoryStream input; private int needed; @@ -279,4 +263,4 @@ namespace org.apache.qpid.transport.network #endregion } -} +}
\ No newline at end of file diff --git a/qpid/dotnet/client-010/client/transport/network/io/IoReceiver.cs b/qpid/dotnet/client-010/client/transport/network/io/IoReceiver.cs index 97f8a7d3cd..b60444fa29 100644 --- a/qpid/dotnet/client-010/client/transport/network/io/IoReceiver.cs +++ b/qpid/dotnet/client-010/client/transport/network/io/IoReceiver.cs @@ -166,10 +166,6 @@ namespace org.apache.qpid.transport.network.io } log.Debug("Receiver thread terminating"); } - catch (IOException) - { - // IOException is thrown when the socket is Closed according to the docs - } catch (Exception t) { if (ExceptionReading != null) @@ -186,4 +182,4 @@ namespace org.apache.qpid.transport.network.io } } } -} +}
\ No newline at end of file diff --git a/qpid/dotnet/client-010/client/transport/network/io/IoSSLTransport.cs b/qpid/dotnet/client-010/client/transport/network/io/IoSSLTransport.cs index 82b42f2bfe..8b36693bc2 100644 --- a/qpid/dotnet/client-010/client/transport/network/io/IoSSLTransport.cs +++ b/qpid/dotnet/client-010/client/transport/network/io/IoSSLTransport.cs @@ -62,11 +62,9 @@ namespace org.apache.qpid.transport.network.io inputHandler.ReceivedEvent += assembler.On_ReceivedEvent; // Connection listen to asembler protocol event Receiver.Closed += Connection.On_ReceivedClosed; + assembler.Closed += Connection.On_ReceivedClosed; Receiver.Exception += Connection.On_ReceivedException; - inputHandler.HandlerClosed += Connection.On_ReceivedClosed; inputHandler.ExceptionProcessing += Connection.On_ReceivedException; - assembler.HandlerClosed += Connection.On_ReceivedClosed; - assembler.ExceptionProcessing += Connection.On_ReceivedException; assembler.ReceivedEvent += Connection.On_ReceivedEvent; } diff --git a/qpid/dotnet/client-010/client/transport/network/io/IoTransport.cs b/qpid/dotnet/client-010/client/transport/network/io/IoTransport.cs index af754ea57f..483e5428b8 100644 --- a/qpid/dotnet/client-010/client/transport/network/io/IoTransport.cs +++ b/qpid/dotnet/client-010/client/transport/network/io/IoTransport.cs @@ -65,11 +65,9 @@ namespace org.apache.qpid.transport.network.io inputHandler.ReceivedEvent += assembler.On_ReceivedEvent; // Connection listen to asembler protocol event Receiver.Closed += Connection.On_ReceivedClosed; + assembler.Closed += Connection.On_ReceivedClosed; Receiver.Exception += Connection.On_ReceivedException; - inputHandler.HandlerClosed += Connection.On_ReceivedClosed; inputHandler.ExceptionProcessing += Connection.On_ReceivedException; - assembler.HandlerClosed += Connection.On_ReceivedClosed; - assembler.ExceptionProcessing += Connection.On_ReceivedException; assembler.ReceivedEvent += Connection.On_ReceivedEvent; } @@ -140,4 +138,4 @@ namespace org.apache.qpid.transport.network.io #endregion } -} +}
\ No newline at end of file diff --git a/qpid/dotnet/client-010/test/Helpers/ConfigHelpers.cs b/qpid/dotnet/client-010/test/Helpers/ConfigHelpers.cs new file mode 100644 index 0000000000..92374b5c41 --- /dev/null +++ b/qpid/dotnet/client-010/test/Helpers/ConfigHelpers.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; +using log4net.Config; + +namespace test.Helpers +{ + class ConfigHelpers + { + public static Dictionary<string, string> LoadConfig() + { + Dictionary<string, string> properties = new Dictionary<string, string>(); + + XmlConfigurator.Configure(new FileInfo("/log.xml")); + // populate default properties + properties.Add("Username", "guest"); + properties.Add("Password", "guest"); + properties.Add("Host", "localhost"); + properties.Add("Port", "5672"); + properties.Add("VirtualHost", "test"); + //Read the test config file + XmlTextReader reader = new XmlTextReader(Environment.CurrentDirectory + "/Qpid Test.dll.config"); + while (reader.Read()) + { + // if node type is an element + if (reader.NodeType == XmlNodeType.Element && reader.Name.Equals("add")) + { + if (properties.ContainsKey(reader.GetAttribute("key"))) + { + properties[reader.GetAttribute("key")] = reader.GetAttribute("value"); + } + else + { + properties.Add(reader.GetAttribute("key"), reader.GetAttribute("value")); + } + } + } + + return properties; + } + } +} diff --git a/qpid/dotnet/client-010/test/Test.csproj b/qpid/dotnet/client-010/test/Test.csproj index b917e17b49..7bb6eaa999 100644 --- a/qpid/dotnet/client-010/test/Test.csproj +++ b/qpid/dotnet/client-010/test/Test.csproj @@ -47,6 +47,8 @@ <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> + <Compile Include="interop\ConnectionTests.cs" /> + <Compile Include="Helpers\ConfigHelpers.cs" /> <Compile Include="interop\Admin.cs" /> <Compile Include="interop\ApplicationHeaders.cs" /> <Compile Include="interop\Message.cs" /> @@ -77,4 +79,4 @@ <Target Name="AfterBuild"> </Target> --> -</Project> +</Project>
\ No newline at end of file diff --git a/qpid/dotnet/client-010/test/interop/ConnectionTests.cs b/qpid/dotnet/client-010/test/interop/ConnectionTests.cs new file mode 100644 index 0000000000..0c2ea8a648 --- /dev/null +++ b/qpid/dotnet/client-010/test/interop/ConnectionTests.cs @@ -0,0 +1,59 @@ +using System; +using System.Net.Sockets; +using NUnit.Framework; +using org.apache.qpid.client; +using test.Helpers; + +namespace test +{ + [TestFixture] + public class ConnectionTests + { + [SetUp] + public void Setup() + { + + } + + [Test] + [ExpectedException(typeof(Exception))] + public void should_raise_exception_in_calling_thread_on_authentification_failure() + { + var properties = ConfigHelpers.LoadConfig(); + + var client = new Client(); + client.Connect(properties["Host"], Convert.ToInt16(properties["Port"]), properties["VirtualHost"], + properties["Username"], "some silly password to make sure the authentification fail"); + } + + [Test] + [ExpectedException(typeof(Exception))] + public void should_raise_exception_in_calling_thread_on_authentification_failure_with_clodedListener() + { + var properties = ConfigHelpers.LoadConfig(); + + var client = new Client(); + client.ClosedListener = new FakeListener(); + client.Connect(properties["Host"], Convert.ToInt16(properties["Port"]), properties["VirtualHost"], + properties["Username"], "some silly password to make sure the authentification fail"); + } + + [Test] + public void should_not_block_on_close() + { + var properties = ConfigHelpers.LoadConfig(); + + var client = new Client(); + client.Connect(properties["Host"], Convert.ToInt16(properties["Port"]), properties["VirtualHost"], + properties["Username"], properties["Password"]); + client.Close(); + } + } + + public class FakeListener : IClosedListener + { + public void OnClosed(ErrorCode errorCode, string reason, Exception t) + { + } + } +} diff --git a/qpid/dotnet/client-010/test/interop/TestCase.cs b/qpid/dotnet/client-010/test/interop/TestCase.cs index 99f81d9ff7..867f082000 100644 --- a/qpid/dotnet/client-010/test/interop/TestCase.cs +++ b/qpid/dotnet/client-010/test/interop/TestCase.cs @@ -30,6 +30,7 @@ using NUnit.Framework; using org.apache.qpid.client; using org.apache.qpid.transport; using org.apache.qpid.transport.util; +using test.Helpers; namespace test.interop { @@ -43,35 +44,11 @@ namespace test.interop [TestFixtureSetUp] public void Init() { - XmlConfigurator.Configure(new FileInfo("/log.xml")); - // populate default properties - _properties.Add("Username", "guest"); - _properties.Add("Password", "guest"); - _properties.Add("Host", "localhost"); - _properties.Add("Port", "5672"); - _properties.Add("VirtualHost", "test"); - //Read the test config file - XmlTextReader reader = new XmlTextReader(Environment.CurrentDirectory + "/Qpid Test.dll.config"); - while (reader.Read()) - { - // if node type is an element - if (reader.NodeType == XmlNodeType.Element && reader.Name.Equals("add")) - { - if (_properties.ContainsKey(reader.GetAttribute("key"))) - { - _properties[reader.GetAttribute("key")] = reader.GetAttribute("value"); - } - else - { - _properties.Add(reader.GetAttribute("key"), reader.GetAttribute("value")); - } - - } - } + var properties = ConfigHelpers.LoadConfig(); // create a client and connect to the broker _client = new Client(); - _client.Connect(Properties["Host"], Convert.ToInt16(Properties["Port"]), Properties["VirtualHost"], - Properties["Username"], Properties["Password"]); + _client.Connect(properties["Host"], Convert.ToInt16(properties["Port"]), properties["VirtualHost"], + properties["Username"], properties["Password"]); } |