Enclose sin6_scope_id in uri

pull/9839/head
Yuchen Zeng 8 years ago
parent dfa88e95c5
commit aa76d3d3b6
  1. 26
      src/core/ext/client_channel/parse_address.c
  2. 28
      src/core/ext/client_channel/uri_parser.c
  3. 12
      src/core/lib/iomgr/sockaddr_utils.c
  4. 3
      src/core/lib/iomgr/tcp_client_posix.c
  5. 2
      test/core/client_channel/uri_parser_test.c
  6. 16
      test/core/iomgr/sockaddr_utils_test.c
  7. 1
      test/core/slice/percent_encoding_test.c

@ -44,6 +44,7 @@
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/support/string.h"
#ifdef GRPC_HAVE_UNIX_SOCKET
@ -119,9 +120,28 @@ int parse_ipv6(grpc_uri *uri, grpc_resolved_address *resolved_addr) {
memset(in6, 0, sizeof(*in6));
resolved_addr->len = sizeof(*in6);
in6->sin6_family = AF_INET6;
if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host);
goto done;
char *host_end = (char *)gpr_memrchr(host, '%', strlen(host));
if (host_end != NULL) {
size_t host_without_scope_len = (size_t)(host_end - host);
char host_without_scope[host_without_scope_len + 1];
strncpy(host_without_scope, host, host_without_scope_len);
host_without_scope[host_without_scope_len] = '\0';
if (inet_pton(AF_INET6, host_without_scope, &in6->sin6_addr) == 0) {
gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host_without_scope);
goto done;
}
if (gpr_parse_bytes_to_uint32(host_end + 1,
strlen(host) - host_without_scope_len - 1,
&in6->sin6_scope_id) == 0) {
gpr_log(GPR_ERROR, "invalid ipv6 scope id: '%s'", host_end + 1);
goto done;
}
} else {
if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host);
goto done;
}
}
if (port != NULL) {

@ -42,6 +42,7 @@
#include <grpc/support/port_platform.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/support/string.h"
/** a size_t default value... maps to all 1's */
@ -68,11 +69,16 @@ static grpc_uri *bad_uri(const char *uri_text, size_t pos, const char *section,
return NULL;
}
/** Returns a copy of \a src[begin, end) */
static char *copy_component(const char *src, size_t begin, size_t end) {
char *out = gpr_malloc(end - begin + 1);
memcpy(out, src + begin, end - begin);
out[end - begin] = 0;
/** Returns a copy of percent decoded \a src[begin, end) */
static char *decode_and_copy_component(const char *src, size_t begin,
size_t end) {
grpc_slice component =
grpc_slice_from_copied_buffer(src + begin, end - begin);
grpc_slice decoded_component =
grpc_permissive_percent_decode_slice(component);
char *out = grpc_slice_to_c_string(decoded_component);
grpc_slice_unref(component);
grpc_slice_unref(decoded_component);
return out;
}
@ -264,11 +270,13 @@ grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) {
uri = gpr_malloc(sizeof(*uri));
memset(uri, 0, sizeof(*uri));
uri->scheme = copy_component(uri_text, scheme_begin, scheme_end);
uri->authority = copy_component(uri_text, authority_begin, authority_end);
uri->path = copy_component(uri_text, path_begin, path_end);
uri->query = copy_component(uri_text, query_begin, query_end);
uri->fragment = copy_component(uri_text, fragment_begin, fragment_end);
uri->scheme = decode_and_copy_component(uri_text, scheme_begin, scheme_end);
uri->authority =
decode_and_copy_component(uri_text, authority_begin, authority_end);
uri->path = decode_and_copy_component(uri_text, path_begin, path_end);
uri->query = decode_and_copy_component(uri_text, query_begin, query_end);
uri->fragment =
decode_and_copy_component(uri_text, fragment_begin, fragment_end);
parse_query_parts(uri);
return uri;

@ -162,6 +162,7 @@ int grpc_sockaddr_to_string(char **out,
char ntop_buf[INET6_ADDRSTRLEN];
const void *ip = NULL;
int port;
uint32_t sin6_scope_id = 0;
int ret;
*out = NULL;
@ -177,10 +178,19 @@ int grpc_sockaddr_to_string(char **out,
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
ip = &addr6->sin6_addr;
port = ntohs(addr6->sin6_port);
sin6_scope_id = addr6->sin6_scope_id;
}
if (ip != NULL &&
grpc_inet_ntop(addr->sa_family, ip, ntop_buf, sizeof(ntop_buf)) != NULL) {
ret = gpr_join_host_port(out, ntop_buf, port);
if (sin6_scope_id != 0) {
char *host_with_scope;
/* Enclose sin6_scope_id with the format defined in RFC 6784 section 2. */
gpr_asprintf(&host_with_scope, "%s%%25%" PRIu32, ntop_buf, sin6_scope_id);
ret = gpr_join_host_port(out, host_with_scope, port);
gpr_free(host_with_scope);
} else {
ret = gpr_join_host_port(out, ntop_buf, port);
}
} else {
ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family);
}

@ -37,6 +37,9 @@
#include "src/core/lib/iomgr/tcp_client_posix.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/socket_utils_posix.h"
#include <errno.h>
#include <netinet/in.h>
#include <string.h>

@ -142,6 +142,8 @@ int main(int argc, char **argv) {
test_succeeds("http:?legit#twice", "http", "", "", "legit", "twice");
test_succeeds("http://foo?bar#lol?", "http", "foo", "", "bar", "lol?");
test_succeeds("http://foo?bar#lol?/", "http", "foo", "", "bar", "lol?/");
test_succeeds("ipv6:[2001:db8::1%252]:12345", "ipv6", "",
"[2001:db8::1%2]:12345", "", "");
test_fails("xyz");
test_fails("http:?dangling-pct-%0");

@ -70,6 +70,12 @@ static grpc_resolved_address make_addr6(const uint8_t *data, size_t data_len) {
return resolved_addr6;
}
static void set_addr6_scope_id(grpc_resolved_address *addr, uint32_t scope_id) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr->addr;
GPR_ASSERT(addr6->sin6_family == AF_INET6);
addr6->sin6_scope_id = scope_id;
}
static const uint8_t kMapped[] = {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0xff, 0xff, 192, 0, 2, 1};
@ -222,6 +228,16 @@ static void test_sockaddr_to_string(void) {
expect_sockaddr_str("[2001:db8::1]:12345", &input6, 1);
expect_sockaddr_uri("ipv6:[2001:db8::1]:12345", &input6);
set_addr6_scope_id(&input6, 2);
expect_sockaddr_str("[2001:db8::1%252]:12345", &input6, 0);
expect_sockaddr_str("[2001:db8::1%252]:12345", &input6, 1);
expect_sockaddr_uri("ipv6:[2001:db8::1%252]:12345", &input6);
set_addr6_scope_id(&input6, 101);
expect_sockaddr_str("[2001:db8::1%25101]:12345", &input6, 0);
expect_sockaddr_str("[2001:db8::1%25101]:12345", &input6, 1);
expect_sockaddr_uri("ipv6:[2001:db8::1%25101]:12345", &input6);
input6 = make_addr6(kMapped, sizeof(kMapped));
expect_sockaddr_str("[::ffff:192.0.2.1]:12345", &input6, 0);
expect_sockaddr_str("192.0.2.1:12345", &input6, 1);

@ -146,6 +146,7 @@ int main(int argc, char **argv) {
TEST_VECTOR("\x0f", "%0F", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("\xff", "%FF", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("\xee", "%EE", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("%2", "%252", grpc_url_percent_encoding_unreserved_bytes);
TEST_NONCONFORMANT_VECTOR("%", "%",
grpc_url_percent_encoding_unreserved_bytes);
TEST_NONCONFORMANT_VECTOR("%A", "%A",

Loading…
Cancel
Save