void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store, const char *key, const char *value) { if (store == NULL) return; store_ensure_capacity(store); store->entries[store->num_entries].key = gpr_slice_from_copied_string(key); store->entries[store->num_entries].value = gpr_slice_from_copied_string(value); store->num_entries++; }
static void test_add_to_empty_md_store(void) { grpc_credentials_md_store *store = grpc_credentials_md_store_create(0); const char *key_str = "hello"; const char *value_str = "there blah blah blah blah blah blah blah"; gpr_slice key = gpr_slice_from_copied_string(key_str); gpr_slice value = gpr_slice_from_copied_string(value_str); grpc_credentials_md_store_add(store, key, value); GPR_ASSERT(store->num_entries == 1); GPR_ASSERT(gpr_slice_cmp(key, store->entries[0].key) == 0); GPR_ASSERT(gpr_slice_cmp(value, store->entries[0].value) == 0); gpr_slice_unref(key); gpr_slice_unref(value); grpc_credentials_md_store_unref(store); }
static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { grpc_endpoint_test_fixture f = config.create_fixture(slice_size); gpr_slice_buffer incoming; gpr_slice s = gpr_slice_from_copied_string("hello world 12345678900987654321"); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; int n = 0; grpc_closure done_closure; gpr_log(GPR_INFO, "Start test left over"); gpr_slice_buffer_init(&incoming); grpc_closure_init(&done_closure, inc_call_ctr, &n); grpc_endpoint_read(&exec_ctx, f.client_ep, &incoming, &done_closure); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(n == 1); GPR_ASSERT(incoming.count == 1); GPR_ASSERT(0 == gpr_slice_cmp(s, incoming.slices[0])); grpc_endpoint_shutdown(&exec_ctx, f.client_ep); grpc_endpoint_shutdown(&exec_ctx, f.server_ep); grpc_endpoint_destroy(&exec_ctx, f.client_ep); grpc_endpoint_destroy(&exec_ctx, f.server_ep); grpc_exec_ctx_finish(&exec_ctx); gpr_slice_unref(s); gpr_slice_buffer_destroy(&incoming); clean_up(); }
static void test_send_messages_at_the_same_time() { grpc_op *op; gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world"); grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); prepare_test(1); op = g_state.ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message = request_payload; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message = tag(2); op->flags = 0; op->reserved = NULL; op++; GPR_ASSERT(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS == grpc_call_start_batch(g_state.call, g_state.ops, (size_t)(op - g_state.ops), tag(1), NULL)); grpc_byte_buffer_destroy(request_payload); cleanup_test(); }
static void test_fails(grpc_slice_split_mode split_mode, char *response) { grpc_httpcli_parser parser; gpr_slice input_slice = gpr_slice_from_copied_string(response); size_t num_slices; size_t i; gpr_slice *slices; int done = 0; grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices); gpr_slice_unref(input_slice); grpc_httpcli_parser_init(&parser); for (i = 0; i < num_slices; i++) { if (!done && !grpc_httpcli_parser_parse(&parser, slices[i])) { done = 1; } gpr_slice_unref(slices[i]); } if (!done && !grpc_httpcli_parser_eof(&parser)) { done = 1; } GPR_ASSERT(done); grpc_httpcli_parser_destroy(&parser); gpr_free(slices); }
static grpc_mdelem *client_recv_filter(void *user_data, grpc_mdelem *md) { client_recv_filter_args *a = user_data; if (md == GRPC_MDELEM_STATUS_200) { return NULL; } else if (md->key == GRPC_MDSTR_STATUS) { char *message_string; gpr_asprintf(&message_string, "Received http2 header with status: %s", grpc_mdstr_as_c_string(md->value)); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); grpc_call_element_send_cancel_with_message(a->exec_ctx, a->elem, GRPC_STATUS_CANCELLED, &message); return NULL; } else if (md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) { return NULL; } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) { const char *value_str = grpc_mdstr_as_c_string(md->value); if (strncmp(value_str, EXPECTED_CONTENT_TYPE, EXPECTED_CONTENT_TYPE_LENGTH) == 0 && (value_str[EXPECTED_CONTENT_TYPE_LENGTH] == '+' || value_str[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) { /* Although the C implementation doesn't (currently) generate them, any custom +-suffix is explicitly valid. */ /* TODO(klempner): We should consider preallocating common values such as +proto or +json, or at least stashing them if we see them. */ /* TODO(klempner): Should we be surfacing this to application code? */ } else { /* TODO(klempner): We're currently allowing this, but we shouldn't see it without a proxy so log for now. */ gpr_log(GPR_INFO, "Unexpected content-type '%s'", value_str); } return NULL; } return md; }
static void send_farewells(void *c, int success) { grpc_child_channel *channel = c; grpc_channel_element *lbelem = LINK_BACK_ELEM_FROM_CHANNEL(channel); lb_channel_data *chand = lbelem->channel_data; int send_goaway; grpc_channel_op op; gpr_mu_lock(&chand->mu); send_goaway = !chand->sent_goaway; chand->sent_goaway = 1; gpr_mu_unlock(&chand->mu); if (send_goaway) { op.type = GRPC_CHANNEL_GOAWAY; op.dir = GRPC_CALL_DOWN; op.data.goaway.status = GRPC_STATUS_OK; op.data.goaway.message = gpr_slice_from_copied_string("Client disconnect"); grpc_channel_next_op(lbelem, &op); } op.type = GRPC_CHANNEL_DISCONNECT; op.dir = GRPC_CALL_DOWN; grpc_channel_next_op(lbelem, &op); gpr_mu_lock(&chand->mu); chand->sending_farewell = 0; chand->sent_farewell = 1; maybe_destroy_channel(channel); gpr_mu_unlock(&chand->mu); }
static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_status_code status, const char *error_msg) { call_data *calld = elem->call_data; gpr_log(GPR_ERROR, "Client side authentication failure: %s", error_msg); gpr_slice error_slice = gpr_slice_from_copied_string(error_msg); grpc_transport_stream_op_add_close(&calld->op, status, &error_slice); grpc_call_next_op(exec_ctx, elem, &calld->op); }
static grpc_endpoint_test_fixture secure_endpoint_create_fixture_tcp_socketpair_leftover(size_t slice_size) { gpr_slice s = gpr_slice_from_copied_string("hello world 12345678900987654321"); grpc_endpoint_test_fixture f; f = secure_endpoint_create_fixture_tcp_socketpair(slice_size, &s, 1); return f; }
/* Constructor for channel_data */ static void init_channel_elem(grpc_channel_element *elem, const grpc_channel_args *args, grpc_mdctx *mdctx, int is_first, int is_last) { size_t i; size_t gettable_capacity = 0; /* grab pointers to our data from the channel element */ channel_data *channeld = elem->channel_data; /* The first and the last filters tend to be implemented differently to handle the case that there's no 'next' filter to call on the up or down path */ GPR_ASSERT(!is_first); GPR_ASSERT(!is_last); /* initialize members */ channeld->te_trailers = grpc_mdelem_from_strings(mdctx, "te", "trailers"); channeld->status_ok = grpc_mdelem_from_strings(mdctx, ":status", "200"); channeld->status_not_found = grpc_mdelem_from_strings(mdctx, ":status", "404"); channeld->method_post = grpc_mdelem_from_strings(mdctx, ":method", "POST"); channeld->http_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "http"); channeld->https_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "https"); channeld->grpc_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "grpc"); channeld->path_key = grpc_mdstr_from_string(mdctx, ":path"); channeld->authority_key = grpc_mdstr_from_string(mdctx, ":authority"); channeld->host_key = grpc_mdstr_from_string(mdctx, "host"); channeld->content_type = grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc"); channeld->mdctx = mdctx; /* initialize http download support */ channeld->gettable_count = 0; channeld->gettables = NULL; for (i = 0; i < args->num_args; i++) { if (0 == strcmp(args->args[i].key, GRPC_ARG_SERVE_OVER_HTTP)) { gettable *g; gpr_slice slice; grpc_http_server_page *p = args->args[i].value.pointer.p; if (channeld->gettable_count == gettable_capacity) { gettable_capacity = GPR_MAX(gettable_capacity * 3 / 2, gettable_capacity + 1); channeld->gettables = gpr_realloc(channeld->gettables, gettable_capacity * sizeof(gettable)); } g = &channeld->gettables[channeld->gettable_count++]; g->path = grpc_mdelem_from_strings(mdctx, ":path", p->path); g->content_type = grpc_mdelem_from_strings(mdctx, "content-type", p->content_type); slice = gpr_slice_from_copied_string(p->content); g->content = grpc_byte_buffer_create(&slice, 1); gpr_slice_unref(slice); } } }
static void test_dump_slice(void) { static const char *text = "HELLO WORLD!"; static const char *long_text = "It was a bright cold day in April, and the clocks were striking " "thirteen. Winston Smith, his chin nuzzled into his breast in an effort " "to escape the vile wind, slipped quickly through the glass doors of " "Victory Mansions, though not quickly enough to prevent a swirl of " "gritty dust from entering along with him."; LOG_TEST_NAME("test_dump_slice"); expect_slice_dump(gpr_slice_from_copied_string(text), GPR_DUMP_ASCII, text); expect_slice_dump(gpr_slice_from_copied_string(long_text), GPR_DUMP_ASCII, long_text); expect_slice_dump(gpr_slice_from_copied_buffer("\x01", 1), GPR_DUMP_HEX, "01"); expect_slice_dump(gpr_slice_from_copied_buffer("\x01", 1), GPR_DUMP_HEX | GPR_DUMP_ASCII, "01 '.'"); }
static void plugin_md_request_metadata_ready(void *request, const grpc_metadata *md, size_t num_md, grpc_status_code status, const char *error_details) { /* called from application code */ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request; if (status != GRPC_STATUS_OK) { if (error_details != NULL) { gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s", error_details); } r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR, error_details); } else { size_t i; bool seen_illegal_header = false; grpc_credentials_md *md_array = NULL; for (i = 0; i < num_md; i++) { if (!grpc_header_key_is_legal(md[i].key, strlen(md[i].key))) { gpr_log(GPR_ERROR, "Plugin added invalid metadata key: %s", md[i].key); seen_illegal_header = true; break; } else if (!grpc_is_binary_header(md[i].key, strlen(md[i].key)) && !grpc_header_nonbin_value_is_legal(md[i].value, md[i].value_length)) { gpr_log(GPR_ERROR, "Plugin added invalid metadata value."); seen_illegal_header = true; break; } } if (seen_illegal_header) { r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR, "Illegal metadata"); } else if (num_md > 0) { md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md)); for (i = 0; i < num_md; i++) { md_array[i].key = gpr_slice_from_copied_string(md[i].key); md_array[i].value = gpr_slice_from_copied_buffer(md[i].value, md[i].value_length); } r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK, NULL); for (i = 0; i < num_md; i++) { gpr_slice_unref(md_array[i].key); gpr_slice_unref(md_array[i].value); } gpr_free(md_array); } } gpr_free(r); grpc_exec_ctx_finish(&exec_ctx); }
static void test_bad_audience_claims_failure(void) { grpc_jwt_claims *claims; gpr_slice s = gpr_slice_from_copied_string(claims_without_time_constraint); grpc_json *json = grpc_json_parse_string_with_len( (char *)GPR_SLICE_START_PTR(s), GPR_SLICE_LENGTH(s)); GPR_ASSERT(json != NULL); claims = grpc_jwt_claims_from_json(json, s); GPR_ASSERT(claims != NULL); GPR_ASSERT(grpc_jwt_claims_check(claims, "https://bar.com") == GRPC_JWT_VERIFIER_BAD_AUDIENCE); grpc_jwt_claims_destroy(claims); }
static void reset_addr_and_set_magic_string(struct sockaddr **addr, size_t *addr_len, gpr_slice *connect_string) { struct sockaddr_in target; *connect_string = gpr_slice_from_copied_string(magic_connect_string); gpr_free(*addr); target.sin_family = AF_INET; target.sin_addr.s_addr = htonl(INADDR_LOOPBACK); target.sin_port = htons((uint16_t)server_port); *addr_len = sizeof(target); *addr = (struct sockaddr *)gpr_malloc(sizeof(target)); memcpy(*addr, &target, sizeof(target)); }
int byte_buffer_eq_string(grpc_byte_buffer *bb, const char *str) { grpc_byte_buffer_reader reader; grpc_byte_buffer *rbb; int res; grpc_byte_buffer_reader_init(&reader, bb); rbb = grpc_raw_byte_buffer_from_reader(&reader); res = byte_buffer_eq_slice(rbb, gpr_slice_from_copied_string(str)); grpc_byte_buffer_reader_destroy(&reader); grpc_byte_buffer_destroy(rbb); return res; }
/* Creates and returns a gpr_slice containing random alphanumeric characters. */ static gpr_slice generate_random_slice() { size_t i; static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; char *output; const size_t output_size = 1024 * 1024; output = gpr_malloc(output_size); for (i = 0; i < output_size - 1; ++i) { output[i] = chars[rand() % (int)(sizeof(chars) - 1)]; } output[output_size - 1] = '\0'; gpr_slice out = gpr_slice_from_copied_string(output); gpr_free(output); return out; }
static void maybe_start_some_streams( grpc_chttp2_transport_global *transport_global) { grpc_chttp2_stream_global *stream_global; /* start streams where we have free grpc_chttp2_stream ids and free * concurrency */ while (transport_global->next_stream_id <= MAX_CLIENT_STREAM_ID && transport_global->concurrent_stream_count < transport_global ->settings[GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] && grpc_chttp2_list_pop_waiting_for_concurrency(transport_global, &stream_global)) { GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_DEBUG, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d", transport_global->is_client ? "CLI" : "SVR", stream_global, transport_global->next_stream_id)); GPR_ASSERT(stream_global->id == 0); stream_global->id = transport_global->next_stream_id; transport_global->next_stream_id += 2; if (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID) { grpc_chttp2_add_incoming_goaway( transport_global, GRPC_CHTTP2_NO_ERROR, gpr_slice_from_copied_string("Exceeded sequence number limit")); } stream_global->outgoing_window = transport_global->settings[GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]; stream_global->incoming_window = transport_global->settings[GRPC_SENT_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]; grpc_chttp2_stream_map_add( &TRANSPORT_FROM_GLOBAL(transport_global)->new_stream_map, stream_global->id, STREAM_FROM_GLOBAL(stream_global)); stream_global->in_stream_map = 1; transport_global->concurrent_stream_count++; grpc_chttp2_list_add_incoming_window_updated(transport_global, stream_global); grpc_chttp2_list_add_writable_stream(transport_global, stream_global); } /* cancel out streams that will never be started */ while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID && grpc_chttp2_list_pop_waiting_for_concurrency(transport_global, &stream_global)) { cancel_from_api(transport_global, stream_global, GRPC_STATUS_UNAVAILABLE); } }
static void test_succeeds(grpc_slice_split_mode split_mode, char *response, int expect_status, char *expect_body, ...) { grpc_httpcli_parser parser; gpr_slice input_slice = gpr_slice_from_copied_string(response); size_t num_slices; size_t i; gpr_slice *slices; va_list args; grpc_split_slices(split_mode, &input_slice, 1, &slices, &num_slices); gpr_slice_unref(input_slice); grpc_httpcli_parser_init(&parser); for (i = 0; i < num_slices; i++) { GPR_ASSERT(grpc_httpcli_parser_parse(&parser, slices[i])); gpr_slice_unref(slices[i]); } GPR_ASSERT(grpc_httpcli_parser_eof(&parser)); GPR_ASSERT(expect_status == parser.r.status); if (expect_body != NULL) { GPR_ASSERT(strlen(expect_body) == parser.r.body_length); GPR_ASSERT(0 == memcmp(expect_body, parser.r.body, parser.r.body_length)); } else { GPR_ASSERT(parser.r.body_length == 0); } va_start(args, expect_body); i = 0; for (;;) { char *expect_key; char *expect_value; expect_key = va_arg(args, char *); if (!expect_key) break; GPR_ASSERT(i < parser.r.hdr_count); expect_value = va_arg(args, char *); GPR_ASSERT(expect_value); GPR_ASSERT(0 == strcmp(expect_key, parser.r.hdrs[i].key)); GPR_ASSERT(0 == strcmp(expect_value, parser.r.hdrs[i].value)); i++; } va_end(args); GPR_ASSERT(i == parser.r.hdr_count); grpc_httpcli_parser_destroy(&parser); gpr_free(slices); }
static void test_claims_success(void) { grpc_jwt_claims *claims; gpr_slice s = gpr_slice_from_copied_string(claims_without_time_constraint); grpc_json *json = grpc_json_parse_string_with_len( (char *)GPR_SLICE_START_PTR(s), GPR_SLICE_LENGTH(s)); GPR_ASSERT(json != NULL); claims = grpc_jwt_claims_from_json(json, s); GPR_ASSERT(claims != NULL); GPR_ASSERT(grpc_jwt_claims_json(claims) == json); GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), "https://foo.com") == 0); GPR_ASSERT(strcmp(grpc_jwt_claims_issuer(claims), "blah.foo.com") == 0); GPR_ASSERT(strcmp(grpc_jwt_claims_subject(claims), "*****@*****.**") == 0); GPR_ASSERT(strcmp(grpc_jwt_claims_id(claims), "jwtuniqueid") == 0); GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") == GRPC_JWT_VERIFIER_OK); grpc_jwt_claims_destroy(claims); }
void grpc_channel_destroy(grpc_channel *channel) { grpc_channel_op op; grpc_channel_element *elem; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); op.type = GRPC_CHANNEL_GOAWAY; op.dir = GRPC_CALL_DOWN; op.data.goaway.status = GRPC_STATUS_OK; op.data.goaway.message = gpr_slice_from_copied_string("Client disconnect"); elem->filter->channel_op(elem, NULL, &op); op.type = GRPC_CHANNEL_DISCONNECT; op.dir = GRPC_CALL_DOWN; elem->filter->channel_op(elem, NULL, &op); grpc_channel_internal_unref(channel); }
/* called from application code */ static void on_md_processing_done( void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md, const grpc_metadata *response_md, size_t num_response_md, grpc_status_code status, const char *error_details) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; /* TODO(jboeuf): Implement support for response_md. */ if (response_md != NULL && num_response_md > 0) { gpr_log(GPR_INFO, "response_md in auth metadata processing not supported for now. " "Ignoring..."); } if (status == GRPC_STATUS_OK) { calld->consumed_md = consumed_md; calld->num_consumed_md = num_consumed_md; grpc_metadata_batch_filter(calld->recv_initial_metadata, remove_consumed_md, elem); grpc_metadata_array_destroy(&calld->md); calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 1); } else { gpr_slice message; grpc_transport_stream_op close_op; memset(&close_op, 0, sizeof(close_op)); grpc_metadata_array_destroy(&calld->md); error_details = error_details != NULL ? error_details : "Authentication metadata processing failed."; message = gpr_slice_from_copied_string(error_details); calld->transport_op.send_initial_metadata = NULL; if (calld->transport_op.send_message != NULL) { grpc_byte_stream_destroy(calld->transport_op.send_message); calld->transport_op.send_message = NULL; } calld->transport_op.send_trailing_metadata = NULL; grpc_transport_stream_op_add_close(&close_op, status, &message); grpc_call_next_op(&exec_ctx, elem, &close_op); calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 0); } grpc_exec_ctx_finish(&exec_ctx); }
static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel, int send_goaway, grpc_error *send_disconnect) { grpc_transport_op op; struct shutdown_cleanup_args *sc; grpc_channel_element *elem; memset(&op, 0, sizeof(op)); op.send_goaway = send_goaway; sc = gpr_malloc(sizeof(*sc)); sc->slice = gpr_slice_from_copied_string("Server shutdown"); op.goaway_message = &sc->slice; op.goaway_status = GRPC_STATUS_OK; op.disconnect_with_error = send_disconnect; grpc_closure_init(&sc->closure, shutdown_cleanup, sc); op.on_consumed = &sc->closure; elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); elem->filter->start_transport_op(exec_ctx, elem, &op); }
static void test_read_none_compressed_slice(void) { gpr_slice slice; grpc_byte_buffer *buffer; grpc_byte_buffer_reader reader; gpr_slice first_slice, second_slice; int first_code, second_code; LOG_TEST("test_read_none_compressed_slice"); slice = gpr_slice_from_copied_string("test"); buffer = grpc_raw_byte_buffer_create(&slice, 1); gpr_slice_unref(slice); grpc_byte_buffer_reader_init(&reader, buffer); first_code = grpc_byte_buffer_reader_next(&reader, &first_slice); GPR_ASSERT(first_code != 0); GPR_ASSERT(memcmp(GPR_SLICE_START_PTR(first_slice), "test", 4) == 0); gpr_slice_unref(first_slice); second_code = grpc_byte_buffer_reader_next(&reader, &second_slice); GPR_ASSERT(second_code == 0); grpc_byte_buffer_destroy(buffer); }
static void on_md_processing_done(void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md, int success) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; if (success) { calld->consumed_md = consumed_md; calld->num_consumed_md = num_consumed_md; grpc_metadata_batch_filter(&calld->md_op->data.metadata, remove_consumed_md, elem); calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success); } else { gpr_slice message = gpr_slice_from_copied_string( "Authentication metadata processing failed."); grpc_sopb_reset(calld->recv_ops); grpc_transport_stream_op_add_close(&calld->transport_op, GRPC_STATUS_UNAUTHENTICATED, &message); grpc_call_next_op(elem, &calld->transport_op); } }
// Callback to connect to the backend server specified by the HTTP // CONNECT request. static void on_server_connect_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { proxy_connection* conn = arg; if (error != GRPC_ERROR_NONE) { // TODO(roth): Technically, in this case, we should handle the error // by returning an HTTP response to the client indicating that the // connection failed. However, for the purposes of this test code, // it's fine to pretend this is a client-side error, which will // cause the client connection to be dropped. proxy_connection_failed(exec_ctx, conn, true /* is_client */, "HTTP proxy server connect", error); return; } // We've established a connection, so send back a 200 response code to // the client. // The write callback inherits our reference to conn. gpr_slice slice = gpr_slice_from_copied_string("HTTP/1.0 200 connected\r\n\r\n"); gpr_slice_buffer_add(&conn->client_write_buffer, slice); grpc_endpoint_write(exec_ctx, conn->client_endpoint, &conn->client_write_buffer, &conn->on_write_response_done); }
static void plugin_md_request_metadata_ready(void *request, const grpc_metadata *md, size_t num_md, grpc_status_code status, const char *error_details) { /* called from application code */ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request; if (status != GRPC_STATUS_OK) { if (error_details != NULL) { gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s", error_details); } r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR); } else { size_t i; grpc_credentials_md *md_array = NULL; if (num_md > 0) { md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md)); for (i = 0; i < num_md; i++) { md_array[i].key = gpr_slice_from_copied_string(md[i].key); md_array[i].value = gpr_slice_from_copied_buffer(md[i].value, md[i].value_length); } } r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK); if (md_array != NULL) { for (i = 0; i < num_md; i++) { gpr_slice_unref(md_array[i].key); gpr_slice_unref(md_array[i].value); } gpr_free(md_array); } } gpr_free(r); grpc_exec_ctx_finish(&exec_ctx); }
// Start transport stream op. static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op* op) { call_data* calld = elem->call_data; // Check max send message size. if (op->send_message != NULL && calld->max_send_size >= 0 && op->send_message->length > (size_t)calld->max_send_size) { char* message_string; gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %d)", op->send_message->length, calld->max_send_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); grpc_call_element_send_close_with_message( exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message); } // Inject callback for receiving a message. if (op->recv_message_ready != NULL) { calld->next_recv_message_ready = op->recv_message_ready; calld->recv_message = op->recv_message; op->recv_message_ready = &calld->recv_message_ready; } // Chain to the next filter. grpc_call_next_op(exec_ctx, elem, op); }
static void finish_shutdown_channel(void *p, int success) { shutdown_channel_args *sca = p; grpc_channel_op op; if (sca->send_goaway) { op.type = GRPC_CHANNEL_GOAWAY; op.dir = GRPC_CALL_DOWN; op.data.goaway.status = GRPC_STATUS_OK; op.data.goaway.message = gpr_slice_from_copied_string("Server shutdown"); channel_op(grpc_channel_stack_element( grpc_channel_get_channel_stack(sca->chand->channel), 0), NULL, &op); } if (sca->send_disconnect) { op.type = GRPC_CHANNEL_DISCONNECT; op.dir = GRPC_CALL_DOWN; channel_op(grpc_channel_stack_element( grpc_channel_get_channel_stack(sca->chand->channel), 0), NULL, &op); } GRPC_CHANNEL_INTERNAL_UNREF(sca->chand->channel, "shutdown"); gpr_free(sca); }
static void test_expired_claims_failure(void) { grpc_jwt_claims *claims; gpr_slice s = gpr_slice_from_copied_string(expired_claims); grpc_json *json = grpc_json_parse_string_with_len( (char *)GPR_SLICE_START_PTR(s), GPR_SLICE_LENGTH(s)); gpr_timespec exp_iat = {100, 0, GPR_CLOCK_REALTIME}; gpr_timespec exp_exp = {120, 0, GPR_CLOCK_REALTIME}; gpr_timespec exp_nbf = {60, 0, GPR_CLOCK_REALTIME}; GPR_ASSERT(json != NULL); claims = grpc_jwt_claims_from_json(json, s); GPR_ASSERT(claims != NULL); GPR_ASSERT(grpc_jwt_claims_json(claims) == json); GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), "https://foo.com") == 0); GPR_ASSERT(strcmp(grpc_jwt_claims_issuer(claims), "blah.foo.com") == 0); GPR_ASSERT(strcmp(grpc_jwt_claims_subject(claims), "*****@*****.**") == 0); GPR_ASSERT(strcmp(grpc_jwt_claims_id(claims), "jwtuniqueid") == 0); GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_issued_at(claims), exp_iat) == 0); GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_expires_at(claims), exp_exp) == 0); GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_not_before(claims), exp_nbf) == 0); GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") == GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE); grpc_jwt_claims_destroy(claims); }
static void init_transport(grpc_chttp2_transport *t, grpc_transport_setup_callback setup, void *arg, const grpc_channel_args *channel_args, grpc_endpoint *ep, gpr_slice *slices, size_t nslices, grpc_mdctx *mdctx, int is_client) { size_t i; int j; grpc_transport_setup_result sr; GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) == GRPC_CHTTP2_CLIENT_CONNECT_STRLEN); memset(t, 0, sizeof(*t)); t->base.vtable = &vtable; t->ep = ep; /* one ref is for destroy, the other for when ep becomes NULL */ gpr_ref_init(&t->refs, 2); gpr_mu_init(&t->mu); grpc_mdctx_ref(mdctx); t->metadata_context = mdctx; t->endpoint_reading = 1; t->global.error_state = GRPC_CHTTP2_ERROR_STATE_NONE; t->global.next_stream_id = is_client ? 1 : 2; t->global.is_client = is_client; t->global.outgoing_window = DEFAULT_WINDOW; t->global.incoming_window = DEFAULT_WINDOW; t->global.connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET; t->global.ping_counter = 1; t->global.pings.next = t->global.pings.prev = &t->global.pings; t->parsing.is_client = is_client; t->parsing.str_grpc_timeout = grpc_mdstr_from_string(t->metadata_context, "grpc-timeout"); t->parsing.deframe_state = is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0; t->writing.is_client = is_client; gpr_slice_buffer_init(&t->global.qbuf); gpr_slice_buffer_init(&t->writing.outbuf); grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor, mdctx); grpc_iomgr_closure_init(&t->writing_action, writing_action, t); grpc_iomgr_closure_init(&t->reading_action, reading_action, t); gpr_slice_buffer_init(&t->parsing.qbuf); grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser); grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser, t->metadata_context); grpc_iomgr_closure_init(&t->channel_callback.notify_closed, notify_closed, t); if (is_client) { gpr_slice_buffer_add( &t->global.qbuf, gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING)); } /* 8 is a random stab in the dark as to a good initial size: it's small enough that it shouldn't waste memory for infrequently used connections, yet large enough that the exponential growth should happen nicely when it's needed. TODO(ctiller): tune this */ grpc_chttp2_stream_map_init(&t->parsing_stream_map, 8); grpc_chttp2_stream_map_init(&t->new_stream_map, 8); /* copy in initial settings to all setting sets */ for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) { t->parsing.settings[i] = grpc_chttp2_settings_parameters[i].default_value; for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) { t->global.settings[j][i] = grpc_chttp2_settings_parameters[i].default_value; } } t->global.dirtied_local_settings = 1; /* Hack: it's common for implementations to assume 65536 bytes initial send window -- this should by rights be 0 */ t->global.force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; t->global.sent_local_settings = 0; /* configure http2 the way we like it */ if (is_client) { push_setting(t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0); push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0); } push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW); if (channel_args) { for (i = 0; i < channel_args->num_args; i++) { if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_MAX_CONCURRENT_STREAMS)) { if (is_client) { gpr_log(GPR_ERROR, "%s: is ignored on the client", GRPC_ARG_MAX_CONCURRENT_STREAMS); } else if (channel_args->args[i].type != GRPC_ARG_INTEGER) { gpr_log(GPR_ERROR, "%s: must be an integer", GRPC_ARG_MAX_CONCURRENT_STREAMS); } else { push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, channel_args->args[i].value.integer); } } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) { if (channel_args->args[i].type != GRPC_ARG_INTEGER) { gpr_log(GPR_ERROR, "%s: must be an integer", GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER); } else if ((t->global.next_stream_id & 1) != (channel_args->args[i].value.integer & 1)) { gpr_log(GPR_ERROR, "%s: low bit must be %d on %s", GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER, t->global.next_stream_id & 1, is_client ? "client" : "server"); } else { t->global.next_stream_id = channel_args->args[i].value.integer; } } } } gpr_mu_lock(&t->mu); t->channel_callback.executing = 1; REF_TRANSPORT(t, "init"); /* matches unref at end of this function */ gpr_mu_unlock(&t->mu); sr = setup(arg, &t->base, t->metadata_context); lock(t); t->channel_callback.cb = sr.callbacks; t->channel_callback.cb_user_data = sr.user_data; t->channel_callback.executing = 0; unlock(t); REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */ recv_data(t, slices, nslices, GRPC_ENDPOINT_CB_OK); UNREF_TRANSPORT(t, "init"); }