Skip to content

Commit 93d534d

Browse files
author
Steve Powell
committed
Merge default in.
2 parents 2ba3900 + 140f562 commit 93d534d

File tree

22 files changed

+330
-92
lines changed

22 files changed

+330
-92
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ ensure-deliverables: rabbit-vsn
3434
file ${RELEASE_DIR}/${NAME_VSN}.msm
3535

3636
ensure-prerequisites: rabbit-vsn
37-
dpkg -L htmldoc plotutils transfig graphviz docbook-utils > /dev/null
37+
[ -f "/etc/debian_version" ] && dpkg -L htmldoc plotutils transfig graphviz docbook-utils || true > /dev/null
3838

3939
ensure-release-dir: rabbit-vsn
4040
touch ${RELEASE_DIR}/

docs/wikipages/data.ApiOverview.txt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ The core API interfaces and classes are
2626

2727
Other useful interfaces and classes include:
2828

29-
- [code ConnectionParameters]: configures a [code ConnectionFactory]
3029
- [code QueueingBasicConsumer]: receives messages delivered from the server
3130
- [code Protocols]: support class for choosing an AMQP protocol variant
3231

@@ -117,7 +116,7 @@ of the shell environment variable scanned.)
117116

118117
** Connecting to a broker
119118

120-
The following code connects to an AMQP broker:
119+
The following two code snippets connect to an AMQP broker:
121120

122121
@code java
123122
ConnectionFactory factory = new ConnectionFactory();
@@ -129,6 +128,16 @@ The following code connects to an AMQP broker:
129128
factory.Port = AmqpTcpEndpoint.UseDefaultPort;
130129
IConnection conn = factory.CreateConnection();
131130

131+
@code java
132+
ConnectionFactory factory = new ConnectionFactory();
133+
factory.Uri = "amqp://user:pass@hostName:port/vhost";
134+
IConnection conn = factory.CreateConnection();
135+
136+
Since the .NET client uses a stricter interpretation of the AMQP URI
137+
spec than the other clients, care must be taken when using URIs. In
138+
particular, the host part must not be omitted and virtual hosts with
139+
empty names are not addressable.
140+
132141
All factory properties have default values. The default value for a property will be used if the property remains unassigned prior to creating a connection:
133142
- username: [code "guest"]
134143
- password: [code "guest"]

projects/client/RabbitMQ.Client/src/client/api/AuthMechanism.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@
4141

4242
namespace RabbitMQ.Client
4343
{
44-
/// A pluggable authentication mechanism.
44+
///<summary>A pluggable authentication mechanism.</summary>
4545
public interface AuthMechanism {
46-
/// Handle one round of challenge-response
46+
///<summary>Handle one round of challenge-response</summary>
4747
byte[] handleChallenge(byte[] challenge, ConnectionFactory factory);
4848
}
49-
}
49+
}

projects/client/RabbitMQ.Client/src/client/api/AuthMechanismFactory.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@
4242
namespace RabbitMQ.Client
4343
{
4444
public interface AuthMechanismFactory {
45-
/// Return a new authentication mechanism implementation
45+
///<summary>Return a new authentication mechanism implementation</summary>
4646
AuthMechanism GetInstance();
4747

48-
/// The name of the authentication mechanism, as negotiated on the wire
48+
///<summary>The name of the authentication mechanism, as negotiated on the wire</summary>
4949
string Name { get; }
5050
}
51-
}
51+
}

projects/client/RabbitMQ.Client/src/client/api/ConnectionFactory.cs

Lines changed: 82 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
using System;
4242
using System.IO;
4343
using System.Net;
44+
using System.Net.Security;
4445
using System.Net.Sockets;
4546
using System.Collections;
4647

@@ -76,17 +77,24 @@ namespace RabbitMQ.Client
7677
/// conn.Close(Constants.ReplySuccess, "Closing the connection");
7778
///</code></example>
7879
///<para>
79-
/// Please see also the API overview and tutorial in the User Guide.
80+
///The same example, written more compactly with AMQP URIs:
8081
///</para>
82+
///<example><code>
83+
/// ConnectionFactory factory = new ConnectionFactory();
84+
/// factory.Uri = "amqp://localhost";
85+
/// IConnection conn = factory.CreateConnection();
86+
/// ...
87+
///</code></example>
8188
///<para>
82-
/// Some of the static methods described below take, as a
83-
/// convenience, a System.Uri instance representing an AMQP server
84-
/// address. The use of Uri here is not standardised - Uri is
85-
/// simply a convenient container for internet-address-like
86-
/// components. In particular, the Uri "Scheme" property is
87-
/// ignored: only the "Host" and "Port" properties are extracted.
89+
/// Please see also the API overview and tutorial in the User Guide.
8890
///</para>
89-
///</remarks>
91+
///<para>
92+
///Note that the Uri property takes a string representation of an
93+
///AMQP URI. Omitted URI parts will take default values. The
94+
///host part of the URI cannot be omitted and URIs of the form
95+
///"amqp://foo/" (note the trailling slash) also represent the
96+
///default virtual host. The latter issue means that virtual
97+
///hosts with an empty name are not addressable. </para></remarks>
9098
public class ConnectionFactory
9199
{
92100
/// <summary>Default user name (value: "guest")</summary>
@@ -152,6 +160,7 @@ public class ConnectionFactory
152160
///<summary>The AMQP protocol to be used</summary>
153161
public IProtocol Protocol = Protocols.FromEnvironment();
154162

163+
///<summary>The AMQP connection target</summary>
155164
public AmqpTcpEndpoint Endpoint
156165
{
157166
get
@@ -167,21 +176,16 @@ public AmqpTcpEndpoint Endpoint
167176
}
168177
}
169178

170-
public String Address
179+
///<summary>Set connection parameters using the amqp or amqps scheme</summary>
180+
public Uri uri
171181
{
172-
get
173-
{
174-
String result = HostName;
175-
if(Port != AmqpTcpEndpoint.UseDefaultPort)
176-
{
177-
result += (":" + Port);
178-
}
179-
return result;
180-
}
181-
set
182-
{
183-
Endpoint = AmqpTcpEndpoint.Parse(Protocol, value);
184-
}
182+
set { SetUri(value); }
183+
}
184+
185+
///<summary>Set connection parameters using the amqp or amqps scheme</summary>
186+
public String Uri
187+
{
188+
set { SetUri(new Uri(value, UriKind.Absolute)); }
185189
}
186190

187191
///<summary>Construct a fresh instance, with all fields set to
@@ -332,5 +336,61 @@ public AuthMechanismFactory AuthMechanismFactory(string[] mechs) {
332336

333337
return null;
334338
}
339+
340+
341+
private void SetUri(Uri uri)
342+
{
343+
Endpoint = new AmqpTcpEndpoint();
344+
345+
if ("amqp".CompareTo(uri.Scheme.ToLower()) == 0) {
346+
// nothing special to do
347+
} else if ("amqps".CompareTo(uri.Scheme.ToLower()) == 0) {
348+
Ssl.Enabled = true;
349+
Ssl.AcceptablePolicyErrors =
350+
SslPolicyErrors.RemoteCertificateNameMismatch;
351+
Port = AmqpTcpEndpoint.DefaultAmqpSslPort;
352+
} else {
353+
throw new ArgumentException("Wrong scheme in AMQP URI: " +
354+
uri.Scheme);
355+
}
356+
string host = uri.Host;
357+
if (!String.IsNullOrEmpty(host)) {
358+
HostName = host;
359+
}
360+
Ssl.ServerName = HostName;
361+
362+
int port = uri.Port;
363+
if (port != -1) {
364+
Port = port;
365+
}
366+
367+
string userInfo = uri.UserInfo;
368+
if (!String.IsNullOrEmpty(userInfo)) {
369+
string[] userPass = userInfo.Split(':');
370+
if (userPass.Length > 2) {
371+
throw new ArgumentException("Bad user info in AMQP " +
372+
"URI: " + userInfo);
373+
}
374+
UserName = UriDecode(userPass[0]);
375+
if (userPass.Length == 2) {
376+
Password = UriDecode(userPass[1]);
377+
}
378+
}
379+
380+
/* C# automatically changes URIs into a canonical form
381+
that has at least the path segment "/". */
382+
if (uri.Segments.Length > 2) {
383+
throw new ArgumentException("Multiple segments in " +
384+
"path of AMQP URI: " +
385+
String.Join(", ", uri.Segments));
386+
} else if (uri.Segments.Length == 2) {
387+
VirtualHost = UriDecode(uri.Segments[1]);
388+
}
389+
}
390+
391+
//<summary>Unescape a string, protecting '+'.</summary>
392+
private string UriDecode(string uri) {
393+
return System.Uri.UnescapeDataString(uri.Replace("+", "%2B"));
394+
}
335395
}
336396
}

projects/client/RabbitMQ.Client/src/client/api/IModel.cs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -317,26 +317,28 @@ uint QueueDelete(string queue,
317317
[AmqpUnsupported("RabbitMQ.Client.Framing.v0_9")]
318318
void ConfirmSelect();
319319

320-
//<summary>Wait until all published messages have been confirmed.
321-
//<remarks>
322-
//Waits until all messages published since the last call have
323-
//been either ack'd or nack'd by the broker. Returns whether
324-
//all the messages were ack'd (and none were nack'd). Note,
325-
//when called on a non-Confirm channel, returns true
326-
//immediately.
327-
//</remarks>
320+
///<summary>Wait until all published messages have been confirmed.
321+
///</summary>
322+
///<remarks>
323+
///Waits until all messages published since the last call have
324+
///been either ack'd or nack'd by the broker. Returns whether
325+
///all the messages were ack'd (and none were nack'd). Note,
326+
///when called on a non-Confirm channel, returns true
327+
///immediately.
328+
///</remarks>
328329
[AmqpMethodDoNotImplement(null)]
329330
[AmqpUnsupported("RabbitMQ.Client.Framing.v0_8qpid")]
330331
[AmqpUnsupported("RabbitMQ.Client.Framing.v0_8")]
331332
[AmqpUnsupported("RabbitMQ.Client.Framing.v0_9")]
332333
bool WaitForConfirms();
333334

334-
//<summary>Wait until all published messages have been confirmed.
335-
//<remarks>
336-
//Waits until all messages published since the last call have
337-
//been ack'd by the broker. If a nack is received, throws an
338-
//OperationInterrupedException exception immediately.
339-
//</remarks>
335+
///<summary>Wait until all published messages have been confirmed.
336+
///</summary>
337+
///<remarks>
338+
///Waits until all messages published since the last call have
339+
///been ack'd by the broker. If a nack is received, throws an
340+
///OperationInterrupedException exception immediately.
341+
///</remarks>
340342
[AmqpMethodDoNotImplement(null)]
341343
[AmqpUnsupported("RabbitMQ.Client.Framing.v0_8qpid")]
342344
[AmqpUnsupported("RabbitMQ.Client.Framing.v0_8")]

projects/client/RabbitMQ.Client/src/client/events/BasicNackEventArgs.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ public bool Multiple
7070
set { m_multiple = value; }
7171
}
7272

73-
//<summary>Clients should ignore this field.</summary>
73+
///<summary>Ignore</summary>
74+
///<remarks>Clients should ignore this field.</remarks>
7475
public bool Requeue
7576
{
7677
get { return m_requeue; }

projects/client/RabbitMQ.Client/src/client/impl/ConnectionBase.cs

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,6 @@ public abstract class ConnectionBase : IConnection
6969
///complete (milliseconds)</summary>
7070
public static int HandshakeTimeout = 10000;
7171

72-
///<summary>Timeout used while waiting for a
73-
///connection.close-ok reply to a connection.close request
74-
///(milliseconds)</summary>
75-
public static int ConnectionCloseTimeout = 10000;
76-
7772
public ConnectionFactory m_factory;
7873
public IFrameHandler m_frameHandler;
7974
public uint m_frameMax = 0;
@@ -630,15 +625,14 @@ public void MainLoop()
630625
"Unexpected Exception",
631626
ex));
632627
}
633-
634-
// If allowed for clean shutdown
635-
// Run main loop for a limited amount of time (as defined
636-
// by ConnectionCloseTimeout).
628+
629+
// If allowed for clean shutdown, run main loop until the
630+
// connection closes.
637631
if (shutdownCleanly)
638632
{
639633
ClosingLoop();
640634
}
641-
635+
642636
FinishClose();
643637

644638
m_appContinuation.Set();
@@ -742,16 +736,10 @@ public void ClosingLoop()
742736
{
743737
try
744738
{
745-
m_frameHandler.Timeout = ConnectionCloseTimeout;
746-
DateTime startTimeout = DateTime.Now;
739+
m_frameHandler.Timeout = 0;
747740
// Wait for response/socket closure or timeout
748741
while (!m_closed)
749742
{
750-
if ((DateTime.Now - startTimeout).TotalMilliseconds >= ConnectionCloseTimeout)
751-
{
752-
LogCloseError("Timeout, when waiting for server's response on close", null);
753-
break;
754-
}
755743
MainLoopIteration();
756744
}
757745
}

projects/client/RabbitMQ.Client/src/client/impl/SocketFrameHandler_0_9.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,12 @@ namespace RabbitMQ.Client.Impl
4949
{
5050
public class SocketFrameHandler_0_9 : IFrameHandler
5151
{
52-
public const int WSAEWOULDBLOCK = 10035;
52+
public const int WSAEWOULDBLOCK = 10035;
5353
// ^^ System.Net.Sockets.SocketError doesn't exist in .NET 1.1
5454

55+
// Timeout in seconds to wait for a clean socket close.
56+
public const int SOCKET_CLOSING_TIMEOUT = 1;
57+
5558
public AmqpTcpEndpoint m_endpoint;
5659
public TcpClient m_socket;
5760
public NetworkBinaryReader m_reader;
@@ -147,6 +150,7 @@ public void WriteFrame(Frame frame)
147150

148151
public void Close()
149152
{
153+
m_socket.LingerState = new LingerOption(true, SOCKET_CLOSING_TIMEOUT);
150154
m_socket.Close();
151155
}
152156
}

0 commit comments

Comments
 (0)