static gpr_slice compute_default_pem_root_certs_once(void) { gpr_slice result = gpr_empty_slice(); /* First try to load the roots from the environment. */ char *default_root_certs_path = gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); if (default_root_certs_path != NULL) { result = gpr_load_file(default_root_certs_path, 0, NULL); gpr_free(default_root_certs_path); } /* Try overridden roots if needed. */ grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL; if (GPR_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != NULL) { char *pem_root_certs = NULL; ovrd_res = ssl_roots_override_cb(&pem_root_certs); if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) { GPR_ASSERT(pem_root_certs != NULL); result = gpr_slice_new(pem_root_certs, strlen(pem_root_certs), gpr_free); } } /* Fall back to installed certs if needed. */ if (GPR_SLICE_IS_EMPTY(result) && ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) { result = gpr_load_file(installed_roots_path, 0, NULL); } return result; }
gpr_slice grpc_httpcli_format_connect_request( const grpc_httpcli_request *request) { gpr_strvec out; gpr_strvec_init(&out); gpr_strvec_add(&out, gpr_strdup("CONNECT ")); fill_common_header(request, &out, false); gpr_strvec_add(&out, gpr_strdup("\r\n")); size_t flat_len; char *flat = gpr_strvec_flatten(&out, &flat_len); gpr_strvec_destroy(&out); return gpr_slice_new(flat, flat_len, gpr_free); }
static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory, grpc_resolver_args* args) { if (0 != strcmp(args->uri->authority, "")) { gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme", args->uri->scheme); return NULL; } // Get lb_enabled arg. Anything other than "0" is interpreted as true. const char* lb_enabled_qpart = grpc_uri_get_query_arg(args->uri, "lb_enabled"); const bool lb_enabled = lb_enabled_qpart != NULL && strcmp("0", lb_enabled_qpart) != 0; // Construct addresses. gpr_slice path_slice = gpr_slice_new(args->uri->path, strlen(args->uri->path), do_nothing); gpr_slice_buffer path_parts; gpr_slice_buffer_init(&path_parts); gpr_slice_split(path_slice, ",", &path_parts); grpc_lb_addresses* addresses = grpc_lb_addresses_create(path_parts.count); bool errors_found = false; for (size_t i = 0; i < addresses->num_addresses; i++) { grpc_uri ith_uri = *args->uri; char* part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII); ith_uri.path = part_str; if (!parse_ipv4( &ith_uri, (struct sockaddr_storage*)(&addresses->addresses[i].address.addr), &addresses->addresses[i].address.len)) { errors_found = true; } gpr_free(part_str); addresses->addresses[i].is_balancer = lb_enabled; if (errors_found) break; } gpr_slice_buffer_destroy(&path_parts); gpr_slice_unref(path_slice); if (errors_found) { grpc_lb_addresses_destroy(addresses, NULL /* user_data_destroy */); return NULL; } // Instantiate resolver. fake_resolver* r = gpr_malloc(sizeof(fake_resolver)); memset(r, 0, sizeof(*r)); r->target_name = gpr_strdup(args->uri->path); r->addresses = addresses; r->lb_policy_name = gpr_strdup(grpc_uri_get_query_arg(args->uri, "lb_policy")); gpr_mu_init(&r->mu); grpc_resolver_init(&r->base, &fake_resolver_vtable); return &r->base; }
gpr_slice gpr_load_file(const char *filename, int add_null_terminator, int *success) { unsigned char *contents = NULL; size_t contents_size = 0; char *error_msg = NULL; gpr_slice result = gpr_empty_slice(); FILE *file; size_t bytes_read = 0; GRPC_SCHEDULING_START_BLOCKING_REGION; file = fopen(filename, "rb"); if (file == NULL) { gpr_asprintf(&error_msg, "Could not open file %s (error = %s).", filename, strerror(errno)); GPR_ASSERT(error_msg != NULL); goto end; } fseek(file, 0, SEEK_END); /* Converting to size_t on the assumption that it will not fail */ contents_size = (size_t)ftell(file); fseek(file, 0, SEEK_SET); contents = gpr_malloc(contents_size + (add_null_terminator ? 1 : 0)); bytes_read = fread(contents, 1, contents_size, file); if (bytes_read < contents_size) { GPR_ASSERT(ferror(file)); gpr_asprintf(&error_msg, "Error %s occured while reading file %s.", strerror(errno), filename); GPR_ASSERT(error_msg != NULL); goto end; } if (success != NULL) *success = 1; if (add_null_terminator) { contents[contents_size++] = 0; } result = gpr_slice_new(contents, contents_size, gpr_free); end: if (error_msg != NULL) { gpr_log(GPR_ERROR, "%s", error_msg); gpr_free(error_msg); if (success != NULL) *success = 0; } if (file != NULL) fclose(file); GRPC_SCHEDULING_END_BLOCKING_REGION; return result; }
static grpc_resolver *sockaddr_create(grpc_resolver_args *args, int parse(grpc_uri *uri, struct sockaddr_storage *dst, size_t *len)) { if (0 != strcmp(args->uri->authority, "")) { gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme", args->uri->scheme); return NULL; } /* Construct addresses. */ gpr_slice path_slice = gpr_slice_new(args->uri->path, strlen(args->uri->path), do_nothing); gpr_slice_buffer path_parts; gpr_slice_buffer_init(&path_parts); gpr_slice_split(path_slice, ",", &path_parts); grpc_lb_addresses *addresses = grpc_lb_addresses_create(path_parts.count); bool errors_found = false; for (size_t i = 0; i < addresses->num_addresses; i++) { grpc_uri ith_uri = *args->uri; char *part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII); ith_uri.path = part_str; if (!parse( &ith_uri, (struct sockaddr_storage *)(&addresses->addresses[i].address.addr), &addresses->addresses[i].address.len)) { errors_found = true; } gpr_free(part_str); if (errors_found) break; } gpr_slice_buffer_destroy(&path_parts); gpr_slice_unref(path_slice); if (errors_found) { grpc_lb_addresses_destroy(addresses, NULL /* user_data_destroy */); return NULL; } /* Instantiate resolver. */ sockaddr_resolver *r = gpr_malloc(sizeof(sockaddr_resolver)); memset(r, 0, sizeof(*r)); r->target_name = gpr_strdup(args->uri->path); r->addresses = addresses; gpr_mu_init(&r->mu); grpc_resolver_init(&r->base, &sockaddr_resolver_vtable); return &r->base; }
gpr_slice grpc_httpcli_format_post_request(const grpc_httpcli_request *request, const char *body_bytes, size_t body_size) { gpr_strvec out; char *tmp; size_t out_len; size_t i; gpr_strvec_init(&out); gpr_strvec_add(&out, gpr_strdup("POST ")); fill_common_header(request, &out); if (body_bytes) { uint8_t has_content_type = 0; for (i = 0; i < request->http.hdr_count; i++) { if (strcmp(request->http.hdrs[i].key, "Content-Type") == 0) { has_content_type = 1; break; } } if (!has_content_type) { gpr_strvec_add(&out, gpr_strdup("Content-Type: text/plain\r\n")); } gpr_asprintf(&tmp, "Content-Length: %lu\r\n", (unsigned long)body_size); gpr_strvec_add(&out, tmp); } gpr_strvec_add(&out, gpr_strdup("\r\n")); tmp = gpr_strvec_flatten(&out, &out_len); gpr_strvec_destroy(&out); if (body_bytes) { tmp = gpr_realloc(tmp, out_len + body_size); memcpy(tmp + out_len, body_bytes, body_size); out_len += body_size; } return gpr_slice_new(tmp, out_len, gpr_free); }
void test_connect(const char *server_host, const char *client_host, int port, int expect_ok) { char *client_hostport; char *server_hostport; grpc_channel *client; grpc_server *server; grpc_completion_queue *cq; grpc_call *c; grpc_call *s; cq_verifier *cqv; gpr_timespec deadline; int got_port; grpc_op ops[6]; grpc_op *op; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; grpc_status_code status; grpc_call_error error; char *details = NULL; size_t details_capacity = 0; int was_cancelled = 2; grpc_call_details call_details; char *peer; int picked_port = 0; if (port == 0) { port = grpc_pick_unused_port_or_die(); picked_port = 1; } gpr_join_host_port(&server_hostport, server_host, port); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); /* Create server. */ cq = grpc_completion_queue_create(NULL); server = grpc_server_create(NULL, NULL); grpc_server_register_completion_queue(server, cq, NULL); GPR_ASSERT((got_port = grpc_server_add_insecure_http2_port( server, server_hostport)) > 0); if (port == 0) { port = got_port; } else { GPR_ASSERT(port == got_port); } grpc_server_start(server); cqv = cq_verifier_create(cq); /* Create client. */ if (client_host[0] == 'i') { /* for ipv4:/ipv6: addresses, concatenate the port to each of the parts */ size_t i; gpr_slice uri_slice; gpr_slice_buffer uri_parts; char **hosts_with_port; uri_slice = gpr_slice_new((char *)client_host, strlen(client_host), do_nothing); gpr_slice_buffer_init(&uri_parts); gpr_slice_split(uri_slice, ",", &uri_parts); hosts_with_port = gpr_malloc(sizeof(char *) * uri_parts.count); for (i = 0; i < uri_parts.count; i++) { char *uri_part_str = gpr_dump_slice(uri_parts.slices[i], GPR_DUMP_ASCII); gpr_asprintf(&hosts_with_port[i], "%s:%d", uri_part_str, port); gpr_free(uri_part_str); } client_hostport = gpr_strjoin_sep((const char **)hosts_with_port, uri_parts.count, ",", NULL); for (i = 0; i < uri_parts.count; i++) { gpr_free(hosts_with_port[i]); } gpr_free(hosts_with_port); gpr_slice_buffer_destroy(&uri_parts); gpr_slice_unref(uri_slice); } else { gpr_join_host_port(&client_hostport, client_host, port); } client = grpc_insecure_channel_create(client_hostport, NULL, NULL); gpr_log(GPR_INFO, "Testing with server=%s client=%s (expecting %s)", server_hostport, client_hostport, expect_ok ? "success" : "failure"); gpr_free(client_hostport); gpr_free(server_hostport); if (expect_ok) { /* Normal deadline, shouldn't be reached. */ deadline = ms_from_now(60000); } else { /* Give up faster when failure is expected. BUG: Setting this to 1000 reveals a memory leak (b/18608927). */ deadline = ms_from_now(1500); } /* Send a trivial request. */ c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/foo", "foo.test.google.fr", deadline, NULL); GPR_ASSERT(c); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = expect_ok ? GRPC_INITIAL_METADATA_WAIT_FOR_READY : 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata = &initial_metadata_recv; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; op->data.recv_status_on_client.status_details = &details; op->data.recv_status_on_client.status_details_capacity = &details_capacity; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); GPR_ASSERT(GRPC_CALL_OK == error); if (expect_ok) { /* Check for a successful request. */ error = grpc_server_request_call(server, &s, &call_details, &request_metadata_recv, cq, cq, tag(101)); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(101), 1); cq_verify(cqv); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; op++; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->data.send_status_from_server.trailing_metadata_count = 0; op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; op->data.send_status_from_server.status_details = "xyz"; op->flags = 0; op++; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->data.recv_close_on_server.cancelled = &was_cancelled; op->flags = 0; op++; error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(102), 1); CQ_EXPECT_COMPLETION(cqv, tag(1), 1); cq_verify(cqv); peer = grpc_call_get_peer(c); gpr_log(GPR_DEBUG, "got peer: '%s'", peer); gpr_free(peer); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 1); grpc_call_destroy(s); } else { /* Check for a failed connection. */ CQ_EXPECT_COMPLETION(cqv, tag(1), 1); cq_verify(cqv); GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); } grpc_call_destroy(c); cq_verifier_destroy(cqv); /* Destroy client. */ grpc_channel_destroy(client); /* Destroy server. */ grpc_server_shutdown_and_notify(server, cq, tag(1000)); GPR_ASSERT(grpc_completion_queue_pluck( cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) .type == GRPC_OP_COMPLETE); grpc_server_destroy(server); grpc_completion_queue_shutdown(cq); drain_cq(cq); grpc_completion_queue_destroy(cq); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); gpr_free(details); if (picked_port) { grpc_recycle_unused_port(port); } }
grpc_error *grpc_chttp2_goaway_parser_parse(grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport *t, grpc_chttp2_stream *s, gpr_slice slice, int is_last) { uint8_t *const beg = GPR_SLICE_START_PTR(slice); uint8_t *const end = GPR_SLICE_END_PTR(slice); uint8_t *cur = beg; grpc_chttp2_goaway_parser *p = parser; switch (p->state) { case GRPC_CHTTP2_GOAWAY_LSI0: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_LSI0; return GRPC_ERROR_NONE; } p->last_stream_id = ((uint32_t)*cur) << 24; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_LSI1: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_LSI1; return GRPC_ERROR_NONE; } p->last_stream_id |= ((uint32_t)*cur) << 16; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_LSI2: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_LSI2; return GRPC_ERROR_NONE; } p->last_stream_id |= ((uint32_t)*cur) << 8; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_LSI3: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_LSI3; return GRPC_ERROR_NONE; } p->last_stream_id |= ((uint32_t)*cur); ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_ERR0: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_ERR0; return GRPC_ERROR_NONE; } p->error_code = ((uint32_t)*cur) << 24; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_ERR1: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_ERR1; return GRPC_ERROR_NONE; } p->error_code |= ((uint32_t)*cur) << 16; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_ERR2: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_ERR2; return GRPC_ERROR_NONE; } p->error_code |= ((uint32_t)*cur) << 8; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_ERR3: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_ERR3; return GRPC_ERROR_NONE; } p->error_code |= ((uint32_t)*cur); ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_DEBUG: if (end != cur) memcpy(p->debug_data + p->debug_pos, cur, (size_t)(end - cur)); GPR_ASSERT((size_t)(end - cur) < UINT32_MAX - p->debug_pos); p->debug_pos += (uint32_t)(end - cur); p->state = GRPC_CHTTP2_GOAWAY_DEBUG; if (is_last) { grpc_chttp2_add_incoming_goaway( exec_ctx, t, (uint32_t)p->error_code, gpr_slice_new(p->debug_data, p->debug_length, gpr_free)); p->debug_data = NULL; } return GRPC_ERROR_NONE; } GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here")); }
grpc_chttp2_parse_error grpc_chttp2_goaway_parser_parse( grpc_exec_ctx *exec_ctx, void *parser, grpc_chttp2_transport_parsing *transport_parsing, grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) { uint8_t *const beg = GPR_SLICE_START_PTR(slice); uint8_t *const end = GPR_SLICE_END_PTR(slice); uint8_t *cur = beg; grpc_chttp2_goaway_parser *p = parser; switch (p->state) { case GRPC_CHTTP2_GOAWAY_LSI0: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_LSI0; return GRPC_CHTTP2_PARSE_OK; } p->last_stream_id = ((uint32_t)*cur) << 24; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_LSI1: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_LSI1; return GRPC_CHTTP2_PARSE_OK; } p->last_stream_id |= ((uint32_t)*cur) << 16; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_LSI2: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_LSI2; return GRPC_CHTTP2_PARSE_OK; } p->last_stream_id |= ((uint32_t)*cur) << 8; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_LSI3: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_LSI3; return GRPC_CHTTP2_PARSE_OK; } p->last_stream_id |= ((uint32_t)*cur); ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_ERR0: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_ERR0; return GRPC_CHTTP2_PARSE_OK; } p->error_code = ((uint32_t)*cur) << 24; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_ERR1: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_ERR1; return GRPC_CHTTP2_PARSE_OK; } p->error_code |= ((uint32_t)*cur) << 16; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_ERR2: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_ERR2; return GRPC_CHTTP2_PARSE_OK; } p->error_code |= ((uint32_t)*cur) << 8; ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_ERR3: if (cur == end) { p->state = GRPC_CHTTP2_GOAWAY_ERR3; return GRPC_CHTTP2_PARSE_OK; } p->error_code |= ((uint32_t)*cur); ++cur; /* fallthrough */ case GRPC_CHTTP2_GOAWAY_DEBUG: if (end != cur) memcpy(p->debug_data + p->debug_pos, cur, (size_t)(end - cur)); GPR_ASSERT((size_t)(end - cur) < UINT32_MAX - p->debug_pos); p->debug_pos += (uint32_t)(end - cur); p->state = GRPC_CHTTP2_GOAWAY_DEBUG; if (is_last) { transport_parsing->goaway_received = 1; transport_parsing->goaway_last_stream_index = p->last_stream_id; gpr_slice_unref(transport_parsing->goaway_text); transport_parsing->goaway_error = (grpc_status_code)p->error_code; transport_parsing->goaway_text = gpr_slice_new(p->debug_data, p->debug_length, gpr_free); p->debug_data = NULL; } return GRPC_CHTTP2_PARSE_OK; } GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR); }
static grpc_resolver *sockaddr_create( grpc_resolver_args *args, const char *default_lb_policy_name, int parse(grpc_uri *uri, struct sockaddr_storage *dst, size_t *len)) { size_t i; int errors_found = 0; /* GPR_FALSE */ sockaddr_resolver *r; gpr_slice path_slice; gpr_slice_buffer path_parts; if (0 != strcmp(args->uri->authority, "")) { gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme", args->uri->scheme); return NULL; } r = gpr_malloc(sizeof(sockaddr_resolver)); memset(r, 0, sizeof(*r)); r->lb_policy_name = NULL; if (0 != strcmp(args->uri->query, "")) { gpr_slice query_slice; gpr_slice_buffer query_parts; query_slice = gpr_slice_new(args->uri->query, strlen(args->uri->query), do_nothing); gpr_slice_buffer_init(&query_parts); gpr_slice_split(query_slice, "=", &query_parts); GPR_ASSERT(query_parts.count == 2); if (0 == gpr_slice_str_cmp(query_parts.slices[0], "lb_policy")) { r->lb_policy_name = gpr_dump_slice(query_parts.slices[1], GPR_DUMP_ASCII); } gpr_slice_buffer_destroy(&query_parts); gpr_slice_unref(query_slice); } if (r->lb_policy_name == NULL) { r->lb_policy_name = gpr_strdup(default_lb_policy_name); } path_slice = gpr_slice_new(args->uri->path, strlen(args->uri->path), do_nothing); gpr_slice_buffer_init(&path_parts); gpr_slice_split(path_slice, ",", &path_parts); r->num_addrs = path_parts.count; r->addrs = gpr_malloc(sizeof(struct sockaddr_storage) * r->num_addrs); r->addrs_len = gpr_malloc(sizeof(*r->addrs_len) * r->num_addrs); for (i = 0; i < r->num_addrs; i++) { grpc_uri ith_uri = *args->uri; char *part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII); ith_uri.path = part_str; if (!parse(&ith_uri, &r->addrs[i], &r->addrs_len[i])) { errors_found = 1; /* GPR_TRUE */ } gpr_free(part_str); if (errors_found) break; } gpr_slice_buffer_destroy(&path_parts); gpr_slice_unref(path_slice); if (errors_found) { gpr_free(r->lb_policy_name); gpr_free(r->addrs); gpr_free(r->addrs_len); gpr_free(r); return NULL; } gpr_ref_init(&r->refs, 1); gpr_mu_init(&r->mu); grpc_resolver_init(&r->base, &sockaddr_resolver_vtable); r->subchannel_factory = args->subchannel_factory; grpc_subchannel_factory_ref(r->subchannel_factory); return &r->base; }
static grpc_resolver *sockaddr_create( grpc_resolver_args *args, const char *default_lb_policy_name, int parse(grpc_uri *uri, struct sockaddr_storage *dst, size_t *len)) { bool errors_found = false; sockaddr_resolver *r; gpr_slice path_slice; gpr_slice_buffer path_parts; if (0 != strcmp(args->uri->authority, "")) { gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme", args->uri->scheme); return NULL; } r = gpr_malloc(sizeof(sockaddr_resolver)); memset(r, 0, sizeof(*r)); r->lb_policy_name = gpr_strdup(grpc_uri_get_query_arg(args->uri, "lb_policy")); const char *lb_enabled_qpart = grpc_uri_get_query_arg(args->uri, "lb_enabled"); /* anything other than "0" is interpreted as true */ const bool lb_enabled = (lb_enabled_qpart != NULL && (strcmp("0", lb_enabled_qpart) != 0)); if (r->lb_policy_name != NULL && strcmp("grpclb", r->lb_policy_name) == 0 && !lb_enabled) { /* we want grpclb but the "resolved" addresses aren't LB enabled. Bail * out, as this is meant mostly for tests. */ gpr_log(GPR_ERROR, "Requested 'grpclb' LB policy but resolved addresses don't " "support load balancing."); abort(); } if (r->lb_policy_name == NULL) { r->lb_policy_name = gpr_strdup(default_lb_policy_name); } path_slice = gpr_slice_new(args->uri->path, strlen(args->uri->path), do_nothing); gpr_slice_buffer_init(&path_parts); gpr_slice_split(path_slice, ",", &path_parts); r->addresses = grpc_lb_addresses_create(path_parts.count); for (size_t i = 0; i < r->addresses->num_addresses; i++) { grpc_uri ith_uri = *args->uri; char *part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII); ith_uri.path = part_str; if (!parse(&ith_uri, (struct sockaddr_storage *)(&r->addresses->addresses[i] .address.addr), &r->addresses->addresses[i].address.len)) { errors_found = true; } gpr_free(part_str); r->addresses->addresses[i].is_balancer = lb_enabled; if (errors_found) break; } r->target_name = gpr_strdup(args->uri->path); gpr_slice_buffer_destroy(&path_parts); gpr_slice_unref(path_slice); if (errors_found) { gpr_free(r->lb_policy_name); gpr_free(r->target_name); grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */); gpr_free(r); return NULL; } gpr_ref_init(&r->refs, 1); gpr_mu_init(&r->mu); grpc_resolver_init(&r->base, &sockaddr_resolver_vtable); return &r->base; }