diff options
-rw-r--r-- | librabbitmq/amqp.h | 2 | ||||
-rw-r--r-- | librabbitmq/amqp_url.c | 37 | ||||
-rw-r--r-- | tests/test_parse_url.c | 111 | ||||
-rw-r--r-- | tools/common.c | 68 |
4 files changed, 149 insertions, 69 deletions
diff --git a/librabbitmq/amqp.h b/librabbitmq/amqp.h index d1bfe4e..825e9ff 100644 --- a/librabbitmq/amqp.h +++ b/librabbitmq/amqp.h @@ -124,6 +124,7 @@ struct iovec; # define AMQP_CALL #endif +#include <stdbool.h> #include <stddef.h> #include <stdint.h> @@ -569,6 +570,7 @@ struct amqp_connection_info { char *host; char *vhost; int port; + bool ssl; }; AMQP_PUBLIC_FUNCTION diff --git a/librabbitmq/amqp_url.c b/librabbitmq/amqp_url.c index 277b5a6..72a4126 100644 --- a/librabbitmq/amqp_url.c +++ b/librabbitmq/amqp_url.c @@ -52,6 +52,7 @@ void amqp_default_connection_info(struct amqp_connection_info *ci) ci->host = "localhost"; ci->port = 5672; ci->vhost = "/"; + ci->ssl = false; } /* Scan for the next delimiter, handling percent-encodings on the way. */ @@ -116,11 +117,16 @@ int amqp_parse_url(char *url, struct amqp_connection_info *parsed) char *port = NULL; /* check the prefix */ - if (strncmp(url, "amqp://", 7)) { + if (!strncmp(url, "amqp://", 7)) { + /* do nothing */ + } else if (!strncmp(url, "amqps://", 8)) { + parsed->port = 5671; + parsed->ssl = true; + } else { goto out; } - host = start = url += 7; + host = start = url += (parsed->ssl ? 8 : 7); delim = find_delim(&url, 1); if (delim == ':') { @@ -135,9 +141,8 @@ int amqp_parse_url(char *url, struct amqp_connection_info *parsed) /* What might have been the host and port were in fact the username and password */ parsed->user = host; - if (port) { + if (port) parsed->password = port; - } port = NULL; host = start = url; @@ -147,16 +152,14 @@ int amqp_parse_url(char *url, struct amqp_connection_info *parsed) if (delim == '[') { /* IPv6 address. The bracket should be the first character in the host. */ - if (host != start || *host != 0) { + if (host != start || *host != 0) goto out; - } start = url; delim = find_delim(&url, 0); - if (delim != ']') { + if (delim != ']') goto out; - } parsed->host = start; start = url; @@ -164,14 +167,13 @@ int amqp_parse_url(char *url, struct amqp_connection_info *parsed) /* Closing bracket should be the last character in the host. */ - if (*start != 0) { + if (*start != 0) goto out; - } - } else { + } + else { /* If we haven't seen the host yet, this is it. */ - if (*host != 0) { + if (*host != 0) parsed->host = host; - } } if (delim == ':') { @@ -183,9 +185,8 @@ int amqp_parse_url(char *url, struct amqp_connection_info *parsed) char *end; long portnum = strtol(port, &end, 10); - if (port == end || *end != 0 || portnum < 0 || portnum > 65535) { + if (port == end || *end != 0 || portnum < 0 || portnum > 65535) goto out; - } parsed->port = portnum; } @@ -194,13 +195,13 @@ int amqp_parse_url(char *url, struct amqp_connection_info *parsed) start = url; delim = find_delim(&url, 1); - if (delim != 0) { + if (delim != 0) goto out; - } parsed->vhost = start; res = 0; - } else if (delim == 0) { + } + else if (delim == 0) { res = 0; } diff --git a/tests/test_parse_url.c b/tests/test_parse_url.c index b816cd8..241cf8c 100644 --- a/tests/test_parse_url.c +++ b/tests/test_parse_url.c @@ -111,62 +111,143 @@ int main(void) { /* From the spec */ parse_success("amqp://user:pass@host:10000/vhost", "user", "pass", - "host", 10000, "vhost"); + "host", 10000, "vhost"); + parse_success("amqps://user:pass@host:10000/vhost", "user", "pass", + "host", 10000, "vhost"); + parse_success("amqp://user%61:%61pass@ho%61st:10000/v%2fhost", - "usera", "apass", "hoast", 10000, "v/host"); + "usera", "apass", "hoast", 10000, "v/host"); + parse_success("amqps://user%61:%61pass@ho%61st:10000/v%2fhost", + "usera", "apass", "hoast", 10000, "v/host"); + parse_success("amqp://", "guest", "guest", "localhost", 5672, "/"); + parse_success("amqps://", "guest", "guest", "localhost", 5671, "/"); + parse_success("amqp://:@/", "", "", "localhost", 5672, ""); + parse_success("amqps://:@/", "", "", "localhost", 5671, ""); + parse_success("amqp://user@", "user", "guest", "localhost", 5672, "/"); + parse_success("amqps://user@", "user", "guest", "localhost", 5671, "/"); + parse_success("amqp://user:pass@", "user", "pass", - "localhost", 5672, "/"); + "localhost", 5672, "/"); + parse_success("amqps://user:pass@", "user", "pass", + "localhost", 5671, "/"); + parse_success("amqp://host", "guest", "guest", "host", 5672, "/"); + parse_success("amqps://host", "guest", "guest", "host", 5671, "/"); + parse_success("amqp://:10000", "guest", "guest", "localhost", 10000, - "/"); + "/"); + parse_success("amqps://:10000", "guest", "guest", "localhost", 10000, + "/"); + parse_success("amqp:///vhost", "guest", "guest", "localhost", 5672, - "vhost"); + "vhost"); + parse_success("amqps:///vhost", "guest", "guest", "localhost", 5671, + "vhost"); + parse_success("amqp://host/", "guest", "guest", "host", 5672, ""); + parse_success("amqps://host/", "guest", "guest", "host", 5671, ""); + parse_success("amqp://host/%2f", "guest", "guest", "host", 5672, "/"); + parse_success("amqps://host/%2f", "guest", "guest", "host", 5671, "/"); + parse_success("amqp://[::1]", "guest", "guest", "::1", 5672, "/"); + parse_success("amqps://[::1]", "guest", "guest", "::1", 5671, "/"); /* Various other success cases */ parse_success("amqp://host:100", "guest", "guest", "host", 100, "/"); + parse_success("amqps://host:100", "guest", "guest", "host", 100, "/"); + parse_success("amqp://[::1]:100", "guest", "guest", "::1", 100, "/"); + parse_success("amqps://[::1]:100", "guest", "guest", "::1", 100, "/"); parse_success("amqp://host/blah", "guest", "guest", - "host", 5672, "blah"); + "host", 5672, "blah"); + parse_success("amqps://host/blah", "guest", "guest", + "host", 5671, "blah"); + parse_success("amqp://host:100/blah", "guest", "guest", - "host", 100, "blah"); + "host", 100, "blah"); + parse_success("amqps://host:100/blah", "guest", "guest", + "host", 100, "blah"); + parse_success("amqp://:100/blah", "guest", "guest", - "localhost", 100, "blah"); + "localhost", 100, "blah"); + parse_success("amqps://:100/blah", "guest", "guest", + "localhost", 100, "blah"); + parse_success("amqp://[::1]/blah", "guest", "guest", - "::1", 5672, "blah"); + "::1", 5672, "blah"); + parse_success("amqps://[::1]/blah", "guest", "guest", + "::1", 5671, "blah"); + parse_success("amqp://[::1]:100/blah", "guest", "guest", - "::1", 100, "blah"); + "::1", 100, "blah"); + parse_success("amqps://[::1]:100/blah", "guest", "guest", + "::1", 100, "blah"); parse_success("amqp://user:pass@host", "user", "pass", - "host", 5672, "/"); + "host", 5672, "/"); + parse_success("amqps://user:pass@host", "user", "pass", + "host", 5671, "/"); + parse_success("amqp://user:pass@host:100", "user", "pass", - "host", 100, "/"); + "host", 100, "/"); + parse_success("amqps://user:pass@host:100", "user", "pass", + "host", 100, "/"); + parse_success("amqp://user:pass@:100", "user", "pass", - "localhost", 100, "/"); + "localhost", 100, "/"); + parse_success("amqps://user:pass@:100", "user", "pass", + "localhost", 100, "/"); + parse_success("amqp://user:pass@[::1]", "user", "pass", - "::1", 5672, "/"); + "::1", 5672, "/"); + parse_success("amqps://user:pass@[::1]", "user", "pass", + "::1", 5671, "/"); + parse_success("amqp://user:pass@[::1]:100", "user", "pass", - "::1", 100, "/"); + "::1", 100, "/"); + parse_success("amqps://user:pass@[::1]:100", "user", "pass", + "::1", 100, "/"); /* Various failure cases */ parse_fail("http://www.rabbitmq.com"); + parse_fail("amqp://foo:bar:baz"); + parse_fail("amqps://foo:bar:baz"); + + parse_fail("amqp://foo[::1]"); + parse_fail("amqps://foo[::1]"); + parse_fail("amqp://foo[::1]"); + parse_fail("amqps://foo[::1]"); + parse_fail("amqp://foo:[::1]"); + parse_fail("amqps://foo:[::1]"); + parse_fail("amqp://[::1]foo"); + parse_fail("amqps://[::1]foo"); + parse_fail("amqp://foo:1000xyz"); + parse_fail("amqps://foo:1000xyz"); + parse_fail("amqp://foo:1000000"); + parse_fail("amqps://foo:1000000"); + parse_fail("amqp://foo/bar/baz"); + parse_fail("amqps://foo/bar/baz"); parse_fail("amqp://foo%1"); + parse_fail("amqps://foo%1"); + parse_fail("amqp://foo%1x"); + parse_fail("amqps://foo%1x"); + parse_fail("amqp://foo%xy"); + parse_fail("amqps://foo%xy"); return 0; } diff --git a/tools/common.c b/tools/common.c index 43b74be..b0f534c 100644 --- a/tools/common.c +++ b/tools/common.c @@ -236,10 +236,9 @@ static void init_connection_info(struct amqp_connection_info *ci) if (amqp_server) { char *colon; - if (ci->host) { + if (ci->host) die("both --server and --url options specify" " server host"); - } /* parse the server string into a hostname and a port */ colon = strchr(amqp_server, ':'); @@ -252,86 +251,83 @@ static void init_connection_info(struct amqp_connection_info *ci) --url now allows connection options to be specificied concisely. */ fprintf(stderr, "Specifying the port number with" - " --server is deprecated\n"); + " --server is deprecated\n"); host_len = colon - amqp_server; ci->host = malloc(host_len + 1); memcpy(ci->host, amqp_server, host_len); ci->host[host_len] = 0; - if (ci->port >= 0) { + if (ci->port >= 0) die("both --server and --url options specify" " server port"); - } - if (amqp_port >= 0) { + if (amqp_port >= 0) die("both --server and --port options specify" " server port"); - } ci->port = strtol(colon+1, &port_end, 10); if (ci->port < 0 || ci->port > 65535 || port_end == colon+1 - || *port_end != 0) { + || *port_end != 0) die("bad server port number in '%s'", amqp_server); - } + } + + if (amqp_ssl && !ci->ssl) { + die("the --ssl option specifies an SSL connection" + " but the --server option does not"); } } if (amqp_port >= 0) { - if (ci->port >= 0) { + if (ci->port >= 0) die("both --port and --url options specify" " server port"); - } ci->port = amqp_port; } if (amqp_username) { - if (ci->user) { + if (ci->user) die("both --username and --url options specify" " AMQP username"); - } ci->user = amqp_username; } if (amqp_password) { - if (ci->password) { + if (ci->password) die("both --password and --url options specify" " AMQP password"); - } ci->password = amqp_password; } if (amqp_vhost) { - if (ci->vhost) { + if (ci->vhost) die("both --vhost and --url options specify" " AMQP vhost"); - } ci->vhost = amqp_vhost; } + if (amqp_ssl) { + ci->ssl = true; + } + amqp_default_connection_info(&defaults); - if (!ci->user) { + if (!ci->user) ci->user = defaults.user; - } - if (!ci->password) { + if (!ci->password) ci->password = defaults.password; - } - if (!ci->host) { + if (!ci->host) ci->host = defaults.host; - } - if (ci->port < 0) { + if (ci->port < 0) ci->port = defaults.port; - } - if (!ci->vhost) { + if (!ci->vhost) ci->vhost = defaults.vhost; - } } amqp_connection_state_t make_connection(void) @@ -342,24 +338,24 @@ amqp_connection_state_t make_connection(void) init_connection_info(&ci); conn = amqp_new_connection(); + if (ci.ssl) { #ifdef WITH_SSL - if (amqp_ssl) { s = amqp_open_ssl_socket(conn, ci.host, ci.port, amqp_cacert, - amqp_key, amqp_cert); - } else + amqp_key, amqp_cert); +#else + die("librabbitmq was not built with SSL/TLS support"); #endif - { + } else { s = amqp_open_socket(ci.host, ci.port); amqp_set_sockfd(conn, s); } die_amqp_error(s, "opening socket to %s:%d", ci.host, ci.port); die_rpc(amqp_login(conn, ci.vhost, 0, 131072, 0, - AMQP_SASL_METHOD_PLAIN, - ci.user, ci.password), - "logging in to AMQP server"); - if (!amqp_channel_open(conn, 1)) { + AMQP_SASL_METHOD_PLAIN, + ci.user, ci.password), + "logging in to AMQP server"); + if (!amqp_channel_open(conn, 1)) die_rpc(amqp_get_rpc_reply(conn), "opening channel"); - } return conn; } |