Skip to content

Commit 5b925d5

Browse files
author
Alexandru Scvortov
committed
merge bug24440 into default (add amqp URL support to C client)
2 parents fe142c3 + f743d96 commit 5b925d5

File tree

10 files changed

+750
-176
lines changed

10 files changed

+750
-176
lines changed

.hgignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
^(|librabbitmq/|tests/|examples/|tools/|tools/doc/)Makefile(\.in)?$
2222
^tests/test_tables$
23+
^tests/test_parse_url$
2324
^examples/amqp_sendstring$
2425
^examples/amqp_exchange_declare$
2526
^examples/amqp_listen$

librabbitmq/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ if USE_MSINTTYPES
1313
AM_CFLAGS += -I$(top_srcdir)/msinttypes
1414
endif
1515

16-
librabbitmq_la_SOURCES = amqp_mem.c amqp_table.c amqp_connection.c amqp_socket.c amqp_api.c $(PLATFORM_DIR)/socket.c
16+
librabbitmq_la_SOURCES = amqp_mem.c amqp_table.c amqp_connection.c amqp_socket.c amqp_api.c amqp_url.c $(PLATFORM_DIR)/socket.c
1717
librabbitmq_la_LDFLAGS = -no-undefined
1818
librabbitmq_la_LIBADD = $(EXTRA_LIBS)
1919
nodist_librabbitmq_la_SOURCES = amqp_framing.c

librabbitmq/amqp.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,19 @@ RABBITMQ_EXPORT int amqp_encode_table(amqp_bytes_t encoded,
396396
amqp_table_t *input,
397397
size_t *offset);
398398

399+
struct amqp_connection_info {
400+
char *user;
401+
char *password;
402+
char *host;
403+
char *vhost;
404+
int port;
405+
};
406+
407+
RABBITMQ_EXPORT void amqp_default_connection_info(
408+
struct amqp_connection_info *parsed);
409+
RABBITMQ_EXPORT int amqp_parse_url(char *url,
410+
struct amqp_connection_info *parsed);
411+
399412
#ifdef __cplusplus
400413
}
401414
#endif

librabbitmq/amqp_api.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ static const char *client_error_strings[ERROR_MAX] = {
5858
"unknown host", /* ERROR_GETHOSTBYNAME_FAILED */
5959
"incompatible AMQP version", /* ERROR_INCOMPATIBLE_AMQP_VERSION */
6060
"connection closed unexpectedly", /* ERROR_CONNECTION_CLOSED */
61+
"could not parse AMQP URL", /* ERROR_BAD_AMQP_URL */
6162
};
6263

6364
char *amqp_error_string(int err)

librabbitmq/amqp_private.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@
6060
#define ERROR_GETHOSTBYNAME_FAILED 5
6161
#define ERROR_INCOMPATIBLE_AMQP_VERSION 6
6262
#define ERROR_CONNECTION_CLOSED 7
63-
#define ERROR_MAX 7
63+
#define ERROR_BAD_AMQP_URL 8
64+
#define ERROR_MAX 8
6465

6566
extern char *amqp_os_error_string(int err);
6667

librabbitmq/amqp_url.c

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
/*
2+
* ***** BEGIN LICENSE BLOCK *****
3+
* Version: MPL 1.1/GPL 2.0
4+
*
5+
* The contents of this file are subject to the Mozilla Public License
6+
* Version 1.1 (the "License"); you may not use this file except in
7+
* compliance with the License. You may obtain a copy of the License
8+
* at http://www.mozilla.org/MPL/
9+
*
10+
* Software distributed under the License is distributed on an "AS IS"
11+
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
12+
* the License for the specific language governing rights and
13+
* limitations under the License.
14+
*
15+
* The Original Code is librabbitmq.
16+
*
17+
* The Initial Developer of the Original Code is VMware, Inc.
18+
* Portions created by VMware are Copyright (c) 2007-2011 VMware, Inc.
19+
*
20+
* Portions created by Tony Garnock-Jones are Copyright (c) 2009-2010
21+
* VMware, Inc. and Tony Garnock-Jones.
22+
*
23+
* All rights reserved.
24+
*
25+
* Alternatively, the contents of this file may be used under the terms
26+
* of the GNU General Public License Version 2 or later (the "GPL"), in
27+
* which case the provisions of the GPL are applicable instead of those
28+
* above. If you wish to allow use of your version of this file only
29+
* under the terms of the GPL, and not to allow others to use your
30+
* version of this file under the terms of the MPL, indicate your
31+
* decision by deleting the provisions above and replace them with the
32+
* notice and other provisions required by the GPL. If you do not
33+
* delete the provisions above, a recipient may use your version of
34+
* this file under the terms of any one of the MPL or the GPL.
35+
*
36+
* ***** END LICENSE BLOCK *****
37+
*/
38+
39+
#include <string.h>
40+
#include <stdio.h>
41+
#include <stdlib.h>
42+
#include <stdint.h>
43+
44+
#include "amqp.h"
45+
#include "amqp_framing.h"
46+
#include "amqp_private.h"
47+
48+
void amqp_default_connection_info(struct amqp_connection_info *ci)
49+
{
50+
/* Apply defaults */
51+
ci->user = "guest";
52+
ci->password = "guest";
53+
ci->host = "localhost";
54+
ci->port = 5672;
55+
ci->vhost = "/";
56+
}
57+
58+
/* Scan for the next delimiter, handling percent-encodings on the way. */
59+
static char find_delim(char **pp, int colon_and_at_sign_are_delims)
60+
{
61+
char *from = *pp;
62+
char *to = from;
63+
64+
for (;;) {
65+
char ch = *from++;
66+
67+
switch (ch) {
68+
case ':':
69+
case '@':
70+
if (!colon_and_at_sign_are_delims) {
71+
*to++ = ch;
72+
break;
73+
}
74+
75+
/* fall through */
76+
case 0:
77+
case '/':
78+
case '?':
79+
case '#':
80+
case '[':
81+
case ']':
82+
*to = 0;
83+
*pp = from;
84+
return ch;
85+
86+
case '%': {
87+
unsigned int val;
88+
int chars;
89+
int res = sscanf(from, "%2x%n", &val, &chars);
90+
91+
if (res == EOF || res < 1 || chars != 2)
92+
/* Return a surprising delimiter to
93+
force an error. */
94+
return '%';
95+
96+
*to++ = val;
97+
from += 2;
98+
break;
99+
}
100+
101+
default:
102+
*to++ = ch;
103+
break;
104+
}
105+
}
106+
}
107+
108+
/* Parse an AMQP URL into its component parts. */
109+
int amqp_parse_url(char *url, struct amqp_connection_info *parsed)
110+
{
111+
int res = -ERROR_BAD_AMQP_URL;
112+
char delim;
113+
char *start;
114+
char *host;
115+
char *port = NULL;
116+
117+
/* check the prefix */
118+
if (strncmp(url, "amqp://", 7))
119+
goto out;
120+
121+
host = start = url += 7;
122+
delim = find_delim(&url, 1);
123+
124+
if (delim == ':') {
125+
/* The colon could be introducing the port or the
126+
password part of the userinfo. We don't know yet,
127+
so stash the preceding component. */
128+
port = start = url;
129+
delim = find_delim(&url, 1);
130+
}
131+
132+
if (delim == '@') {
133+
/* What might have been the host and port were in fact
134+
the username and password */
135+
parsed->user = host;
136+
if (port)
137+
parsed->password = port;
138+
139+
port = NULL;
140+
host = start = url;
141+
delim = find_delim(&url, 1);
142+
}
143+
144+
if (delim == '[') {
145+
/* IPv6 address. The bracket should be the first
146+
character in the host. */
147+
if (host != start || *host != 0)
148+
goto out;
149+
150+
start = url;
151+
delim = find_delim(&url, 0);
152+
153+
if (delim != ']')
154+
goto out;
155+
156+
parsed->host = start;
157+
start = url;
158+
delim = find_delim(&url, 1);
159+
160+
/* Closing bracket should be the last character in the
161+
host. */
162+
if (*start != 0)
163+
goto out;
164+
}
165+
else {
166+
/* If we haven't seen the host yet, this is it. */
167+
if (*host != 0)
168+
parsed->host = host;
169+
}
170+
171+
if (delim == ':') {
172+
port = start = url;
173+
delim = find_delim(&url, 1);
174+
}
175+
176+
if (port) {
177+
char *end;
178+
long portnum = strtol(port, &end, 10);
179+
180+
if (port == end || *end != 0 || portnum < 0 || portnum > 65535)
181+
goto out;
182+
183+
parsed->port = portnum;
184+
}
185+
186+
if (delim == '/') {
187+
start = url;
188+
delim = find_delim(&url, 1);
189+
190+
if (delim != 0)
191+
goto out;
192+
193+
parsed->vhost = start;
194+
res = 0;
195+
}
196+
else if (delim == 0) {
197+
res = 0;
198+
}
199+
200+
/* Any other delimiter is bad, and we will return
201+
ERROR_BAD_AMQP_URL. */
202+
203+
out:
204+
return res;
205+
}

tests/Makefile.am

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
noinst_PROGRAMS = test_tables
1+
check_PROGRAMS = test_tables test_parse_url
2+
TESTS = $(check_PROGRAMS)
3+
EXTRA_DIST = test_tables.expected
24

35
AM_CFLAGS = -I$(top_srcdir)/librabbitmq
46

0 commit comments

Comments
 (0)