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; }
static void init_default_pem_root_certs(void) { /* 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) { default_pem_root_certs = gpr_empty_slice(); } else { default_pem_root_certs = gpr_load_file(default_root_certs_path, 0, NULL); gpr_free(default_root_certs_path); } /* Fall back to installed certs if needed. */ if (GPR_SLICE_IS_EMPTY(default_pem_root_certs)) { default_pem_root_certs = gpr_load_file(installed_roots_path, 0, NULL); } }
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; }
grpc_error *grpc_load_file(const char *filename, int add_null_terminator, grpc_slice *output) { unsigned char *contents = NULL; size_t contents_size = 0; grpc_slice result = gpr_empty_slice(); FILE *file; size_t bytes_read = 0; grpc_error *error = GRPC_ERROR_NONE; GRPC_SCHEDULING_START_BLOCKING_REGION; file = fopen(filename, "rb"); if (file == NULL) { error = GRPC_OS_ERROR(errno, "fopen"); 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) { error = GRPC_OS_ERROR(errno, "fread"); GPR_ASSERT(ferror(file)); goto end; } if (add_null_terminator) { contents[contents_size++] = 0; } result = grpc_slice_new(contents, contents_size, gpr_free); end: *output = result; if (file != NULL) fclose(file); if (error != GRPC_ERROR_NONE) { grpc_error *error_out = grpc_error_set_str( GRPC_ERROR_CREATE_REFERENCING("Failed to load file", &error, 1), GRPC_ERROR_STR_FILENAME, filename); GRPC_ERROR_UNREF(error); error = error_out; } GRPC_SCHEDULING_END_BLOCKING_REGION; return error; }
/* Takes ownership of creds_path if not NULL. */ static grpc_call_credentials *create_default_creds_from_path(char *creds_path) { grpc_json *json = NULL; grpc_auth_json_key key; grpc_auth_refresh_token token; grpc_call_credentials *result = NULL; gpr_slice creds_data = gpr_empty_slice(); int file_ok = 0; if (creds_path == NULL) goto end; creds_data = gpr_load_file(creds_path, 0, &file_ok); if (!file_ok) goto end; json = grpc_json_parse_string_with_len( (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data)); if (json == NULL) goto end; /* First, try an auth json key. */ key = grpc_auth_json_key_create_from_json(json); if (grpc_auth_json_key_is_valid(&key)) { result = grpc_service_account_jwt_access_credentials_create_from_auth_json_key( key, grpc_max_auth_token_lifetime()); goto end; } /* Then try a refresh token if the auth json key was invalid. */ token = grpc_auth_refresh_token_create_from_json(json); if (grpc_auth_refresh_token_is_valid(&token)) { result = grpc_refresh_token_credentials_create_from_auth_refresh_token(token); goto end; } end: if (creds_path != NULL) gpr_free(creds_path); gpr_slice_unref(creds_data); if (json != NULL) grpc_json_destroy(json); return result; }
grpc_error *grpc_chttp2_perform_read( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, gpr_slice slice) { uint8_t *beg = GPR_SLICE_START_PTR(slice); uint8_t *end = GPR_SLICE_END_PTR(slice); uint8_t *cur = beg; grpc_error *err; if (cur == end) return GRPC_ERROR_NONE; switch (transport_parsing->deframe_state) { case GRPC_DTS_CLIENT_PREFIX_0: case GRPC_DTS_CLIENT_PREFIX_1: case GRPC_DTS_CLIENT_PREFIX_2: case GRPC_DTS_CLIENT_PREFIX_3: case GRPC_DTS_CLIENT_PREFIX_4: case GRPC_DTS_CLIENT_PREFIX_5: case GRPC_DTS_CLIENT_PREFIX_6: case GRPC_DTS_CLIENT_PREFIX_7: case GRPC_DTS_CLIENT_PREFIX_8: case GRPC_DTS_CLIENT_PREFIX_9: case GRPC_DTS_CLIENT_PREFIX_10: case GRPC_DTS_CLIENT_PREFIX_11: case GRPC_DTS_CLIENT_PREFIX_12: case GRPC_DTS_CLIENT_PREFIX_13: case GRPC_DTS_CLIENT_PREFIX_14: case GRPC_DTS_CLIENT_PREFIX_15: case GRPC_DTS_CLIENT_PREFIX_16: case GRPC_DTS_CLIENT_PREFIX_17: case GRPC_DTS_CLIENT_PREFIX_18: case GRPC_DTS_CLIENT_PREFIX_19: case GRPC_DTS_CLIENT_PREFIX_20: case GRPC_DTS_CLIENT_PREFIX_21: case GRPC_DTS_CLIENT_PREFIX_22: case GRPC_DTS_CLIENT_PREFIX_23: while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) { if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing ->deframe_state]) { char *msg; gpr_asprintf( &msg, "Connect string mismatch: expected '%c' (%d) got '%c' (%d) " "at byte %d", GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing ->deframe_state], (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING [transport_parsing->deframe_state], *cur, (int)*cur, transport_parsing->deframe_state); err = GRPC_ERROR_CREATE(msg); gpr_free(msg); return err; } ++cur; ++transport_parsing->deframe_state; } if (cur == end) { return GRPC_ERROR_NONE; } /* fallthrough */ dts_fh_0: case GRPC_DTS_FH_0: GPR_ASSERT(cur < end); transport_parsing->incoming_frame_size = ((uint32_t)*cur) << 16; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_1; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_1: GPR_ASSERT(cur < end); transport_parsing->incoming_frame_size |= ((uint32_t)*cur) << 8; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_2; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_2: GPR_ASSERT(cur < end); transport_parsing->incoming_frame_size |= *cur; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_3; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_3: GPR_ASSERT(cur < end); transport_parsing->incoming_frame_type = *cur; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_4; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_4: GPR_ASSERT(cur < end); transport_parsing->incoming_frame_flags = *cur; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_5; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_5: GPR_ASSERT(cur < end); transport_parsing->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_6; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_6: GPR_ASSERT(cur < end); transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 16; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_7; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_7: GPR_ASSERT(cur < end); transport_parsing->incoming_stream_id |= ((uint32_t)*cur) << 8; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_8; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_8: GPR_ASSERT(cur < end); transport_parsing->incoming_stream_id |= ((uint32_t)*cur); transport_parsing->deframe_state = GRPC_DTS_FRAME; err = init_frame_parser(exec_ctx, transport_parsing); if (err != GRPC_ERROR_NONE) { return err; } if (transport_parsing->incoming_stream_id != 0 && transport_parsing->incoming_stream_id > transport_parsing->last_incoming_stream_id) { transport_parsing->last_incoming_stream_id = transport_parsing->incoming_stream_id; } if (transport_parsing->incoming_frame_size == 0) { err = parse_frame_slice(exec_ctx, transport_parsing, gpr_empty_slice(), 1); if (err != GRPC_ERROR_NONE) { return err; } transport_parsing->incoming_stream = NULL; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_0; return GRPC_ERROR_NONE; } goto dts_fh_0; /* loop */ } else if (transport_parsing->incoming_frame_size > transport_parsing->max_frame_size) { char *msg; gpr_asprintf(&msg, "Frame size %d is larger than max frame size %d", transport_parsing->incoming_frame_size, transport_parsing->max_frame_size); err = GRPC_ERROR_CREATE(msg); gpr_free(msg); return err; } if (++cur == end) { return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FRAME: GPR_ASSERT(cur < end); if ((uint32_t)(end - cur) == transport_parsing->incoming_frame_size) { err = parse_frame_slice(exec_ctx, transport_parsing, gpr_slice_sub_no_ref(slice, (size_t)(cur - beg), (size_t)(end - beg)), 1); if (err != GRPC_ERROR_NONE) { return err; } transport_parsing->deframe_state = GRPC_DTS_FH_0; transport_parsing->incoming_stream = NULL; return GRPC_ERROR_NONE; } else if ((uint32_t)(end - cur) > transport_parsing->incoming_frame_size) { size_t cur_offset = (size_t)(cur - beg); err = parse_frame_slice( exec_ctx, transport_parsing, gpr_slice_sub_no_ref( slice, cur_offset, cur_offset + transport_parsing->incoming_frame_size), 1); if (err != GRPC_ERROR_NONE) { return err; } cur += transport_parsing->incoming_frame_size; transport_parsing->incoming_stream = NULL; goto dts_fh_0; /* loop */ } else { err = parse_frame_slice(exec_ctx, transport_parsing, gpr_slice_sub_no_ref(slice, (size_t)(cur - beg), (size_t)(end - beg)), 0); if (err != GRPC_ERROR_NONE) { return err; } transport_parsing->incoming_frame_size -= (uint32_t)(end - cur); return GRPC_ERROR_NONE; } GPR_UNREACHABLE_CODE(return 0); } GPR_UNREACHABLE_CODE(return 0); }
void grpc_chttp2_publish_reads( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_parsing *transport_parsing) { grpc_chttp2_stream_global *stream_global; grpc_chttp2_stream_parsing *stream_parsing; int was_zero; int is_zero; /* transport_parsing->last_incoming_stream_id is used as last-grpc_chttp2_stream-id when sending GOAWAY frame. https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8 says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream ID. So, since we don't have server pushed streams, client should send GOAWAY last-grpc_chttp2_stream-id=0 in this case. */ if (!transport_parsing->is_client) { transport_global->last_incoming_stream_id = transport_parsing->last_incoming_stream_id; } /* update global settings */ if (transport_parsing->settings_updated) { memcpy(transport_global->settings[GRPC_PEER_SETTINGS], transport_parsing->settings, sizeof(transport_parsing->settings)); transport_parsing->settings_updated = 0; } /* update settings based on ack if received */ if (transport_parsing->settings_ack_received) { memcpy(transport_global->settings[GRPC_ACKED_SETTINGS], transport_global->settings[GRPC_SENT_SETTINGS], GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t)); transport_parsing->settings_ack_received = 0; transport_global->sent_local_settings = 0; } /* move goaway to the global state if we received one (it will be published later */ if (transport_parsing->goaway_received) { grpc_chttp2_add_incoming_goaway(exec_ctx, transport_global, (uint32_t)transport_parsing->goaway_error, transport_parsing->goaway_text); transport_parsing->goaway_text = gpr_empty_slice(); transport_parsing->goaway_received = 0; } /* propagate flow control tokens to global state */ was_zero = transport_global->outgoing_window <= 0; GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("parsed", transport_global, outgoing_window, transport_parsing, outgoing_window); is_zero = transport_global->outgoing_window <= 0; if (was_zero && !is_zero) { while (grpc_chttp2_list_pop_stalled_by_transport(transport_global, &stream_global)) { grpc_chttp2_become_writable(transport_global, stream_global); } } if (transport_parsing->incoming_window < transport_global->connection_window_target * 3 / 4) { int64_t announce_bytes = transport_global->connection_window_target - transport_parsing->incoming_window; GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_global, announce_incoming_window, announce_bytes); GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", transport_parsing, incoming_window, announce_bytes); } /* for each stream that saw an update, fixup global state */ while (grpc_chttp2_list_pop_parsing_seen_stream( transport_global, transport_parsing, &stream_global, &stream_parsing)) { if (stream_parsing->seen_error) { stream_global->seen_error = true; stream_global->exceeded_metadata_size = stream_parsing->exceeded_metadata_size; grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } /* flush stats to global stream state */ grpc_transport_move_stats(&stream_parsing->stats, &stream_global->stats); /* update outgoing flow control window */ was_zero = stream_global->outgoing_window <= 0; GRPC_CHTTP2_FLOW_MOVE_STREAM("parsed", transport_global, stream_global, outgoing_window, stream_parsing, outgoing_window); is_zero = stream_global->outgoing_window <= 0; if (was_zero && !is_zero) { grpc_chttp2_become_writable(transport_global, stream_global); } stream_global->max_recv_bytes -= (uint32_t)GPR_MIN( stream_global->max_recv_bytes, stream_parsing->received_bytes); stream_parsing->received_bytes = 0; /* publish incoming stream ops */ if (stream_global->incoming_frames.tail != NULL) { stream_global->incoming_frames.tail->is_tail = 0; } if (stream_parsing->data_parser.incoming_frames.head != NULL) { grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } grpc_chttp2_incoming_frame_queue_merge( &stream_global->incoming_frames, &stream_parsing->data_parser.incoming_frames); if (stream_global->incoming_frames.tail != NULL) { stream_global->incoming_frames.tail->is_tail = 1; } if (!stream_global->published_initial_metadata && stream_parsing->got_metadata_on_parse[0]) { stream_parsing->got_metadata_on_parse[0] = 0; stream_global->published_initial_metadata = 1; GPR_SWAP(grpc_chttp2_incoming_metadata_buffer, stream_parsing->metadata_buffer[0], stream_global->received_initial_metadata); grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } if (!stream_global->published_trailing_metadata && stream_parsing->got_metadata_on_parse[1]) { stream_parsing->got_metadata_on_parse[1] = 0; stream_global->published_trailing_metadata = 1; GPR_SWAP(grpc_chttp2_incoming_metadata_buffer, stream_parsing->metadata_buffer[1], stream_global->received_trailing_metadata); grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } if (stream_parsing->forced_close_error != GRPC_ERROR_NONE) { intptr_t reason; bool has_reason = grpc_error_get_int(stream_parsing->forced_close_error, GRPC_ERROR_INT_HTTP2_ERROR, &reason); if (has_reason && reason != GRPC_CHTTP2_NO_ERROR) { grpc_status_code status_code = has_reason ? grpc_chttp2_http2_error_to_grpc_status( (grpc_chttp2_error_code)reason, stream_global->deadline) : GRPC_STATUS_INTERNAL; const char *status_details = grpc_error_string(stream_parsing->forced_close_error); gpr_slice slice_details = gpr_slice_from_copied_string(status_details); grpc_error_free_string(status_details); grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status_code, &slice_details); } grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1, 1, stream_parsing->forced_close_error); } if (stream_parsing->received_close) { grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1, 0, GRPC_ERROR_NONE); } } }
void grpc_chttp2_publish_reads( grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_parsing *transport_parsing) { grpc_chttp2_stream_global *stream_global; grpc_chttp2_stream_parsing *stream_parsing; /* transport_parsing->last_incoming_stream_id is used as last-grpc_chttp2_stream-id when sending GOAWAY frame. https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8 says that last-grpc_chttp2_stream-id is peer-initiated grpc_chttp2_stream ID. So, since we don't have server pushed streams, client should send GOAWAY last-grpc_chttp2_stream-id=0 in this case. */ if (!transport_parsing->is_client) { transport_global->last_incoming_stream_id = transport_parsing->incoming_stream_id; } /* copy parsing qbuf to global qbuf */ gpr_slice_buffer_move_into(&transport_parsing->qbuf, &transport_global->qbuf); /* update global settings */ if (transport_parsing->settings_updated) { memcpy(transport_global->settings[GRPC_PEER_SETTINGS], transport_parsing->settings, sizeof(transport_parsing->settings)); transport_parsing->settings_updated = 0; } /* update settings based on ack if received */ if (transport_parsing->settings_ack_received) { memcpy(transport_global->settings[GRPC_ACKED_SETTINGS], transport_global->settings[GRPC_SENT_SETTINGS], GRPC_CHTTP2_NUM_SETTINGS * sizeof(gpr_uint32)); transport_parsing->settings_ack_received = 0; } /* move goaway to the global state if we received one (it will be published later */ if (transport_parsing->goaway_received) { grpc_chttp2_add_incoming_goaway(transport_global, transport_parsing->goaway_error, transport_parsing->goaway_text); transport_parsing->goaway_text = gpr_empty_slice(); transport_parsing->goaway_received = 0; } /* propagate flow control tokens to global state */ if (transport_parsing->outgoing_window_update) { GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT( "parsed", transport_global, outgoing_window, transport_parsing->outgoing_window_update); GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT( "parsed", transport_parsing, outgoing_window_update, -(gpr_int64)transport_parsing->outgoing_window_update); transport_global->outgoing_window += transport_parsing->outgoing_window_update; transport_parsing->outgoing_window_update = 0; } if (transport_parsing->incoming_window_delta) { GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT( "parsed", transport_global, incoming_window, -(gpr_int64)transport_parsing->incoming_window_delta); GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT( "parsed", transport_parsing, incoming_window_delta, -(gpr_int64)transport_parsing->incoming_window_delta); transport_global->incoming_window -= transport_parsing->incoming_window_delta; transport_parsing->incoming_window_delta = 0; } /* for each stream that saw an update, fixup global state */ while (grpc_chttp2_list_pop_parsing_seen_stream( transport_global, transport_parsing, &stream_global, &stream_parsing)) { /* update incoming flow control window */ if (stream_parsing->incoming_window_delta) { GRPC_CHTTP2_FLOWCTL_TRACE_STREAM( "parsed", transport_parsing, stream_global, incoming_window, -(gpr_int64)stream_parsing->incoming_window_delta); GRPC_CHTTP2_FLOWCTL_TRACE_STREAM( "parsed", transport_parsing, stream_parsing, incoming_window_delta, -(gpr_int64)stream_parsing->incoming_window_delta); GRPC_CHTTP2_FLOWCTL_TRACE_STREAM( "parsed", transport_parsing, stream_global, max_recv_bytes, -(gpr_int64)stream_parsing->incoming_window_delta); stream_global->incoming_window -= stream_parsing->incoming_window_delta; GPR_ASSERT(stream_global->max_recv_bytes >= stream_parsing->incoming_window_delta); stream_global->max_recv_bytes -= stream_parsing->incoming_window_delta; stream_parsing->incoming_window_delta = 0; grpc_chttp2_list_add_writable_window_update_stream(transport_global, stream_global); } /* update outgoing flow control window */ if (stream_parsing->outgoing_window_update) { int was_zero = stream_global->outgoing_window <= 0; int is_zero; GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("parsed", transport_parsing, stream_global, outgoing_window, stream_parsing->outgoing_window_update); GRPC_CHTTP2_FLOWCTL_TRACE_STREAM( "parsed", transport_parsing, stream_parsing, outgoing_window_update, -(gpr_int64)stream_parsing->outgoing_window_update); stream_global->outgoing_window += stream_parsing->outgoing_window_update; stream_parsing->outgoing_window_update = 0; is_zero = stream_global->outgoing_window <= 0; if (was_zero && !is_zero) { grpc_chttp2_list_add_writable_stream(transport_global, stream_global); } } /* updating closed status */ if (stream_parsing->received_close) { stream_global->read_closed = 1; grpc_chttp2_list_add_read_write_state_changed(transport_global, stream_global); } if (stream_parsing->saw_rst_stream) { stream_global->cancelled = 1; stream_global->cancelled_status = grpc_chttp2_http2_error_to_grpc_status( stream_parsing->rst_stream_reason); if (stream_parsing->rst_stream_reason == GRPC_CHTTP2_NO_ERROR) { stream_global->published_cancelled = 1; } grpc_chttp2_list_add_read_write_state_changed(transport_global, stream_global); } /* publish incoming stream ops */ if (stream_parsing->data_parser.incoming_sopb.nops > 0) { grpc_incoming_metadata_buffer_move_to_referencing_sopb( &stream_parsing->incoming_metadata, &stream_global->incoming_metadata, &stream_parsing->data_parser.incoming_sopb); grpc_sopb_move_to(&stream_parsing->data_parser.incoming_sopb, &stream_global->incoming_sopb); grpc_chttp2_list_add_read_write_state_changed(transport_global, stream_global); } } }
int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing, gpr_slice slice) { gpr_uint8 *beg = GPR_SLICE_START_PTR(slice); gpr_uint8 *end = GPR_SLICE_END_PTR(slice); gpr_uint8 *cur = beg; if (cur == end) return 1; switch (transport_parsing->deframe_state) { case GRPC_DTS_CLIENT_PREFIX_0: case GRPC_DTS_CLIENT_PREFIX_1: case GRPC_DTS_CLIENT_PREFIX_2: case GRPC_DTS_CLIENT_PREFIX_3: case GRPC_DTS_CLIENT_PREFIX_4: case GRPC_DTS_CLIENT_PREFIX_5: case GRPC_DTS_CLIENT_PREFIX_6: case GRPC_DTS_CLIENT_PREFIX_7: case GRPC_DTS_CLIENT_PREFIX_8: case GRPC_DTS_CLIENT_PREFIX_9: case GRPC_DTS_CLIENT_PREFIX_10: case GRPC_DTS_CLIENT_PREFIX_11: case GRPC_DTS_CLIENT_PREFIX_12: case GRPC_DTS_CLIENT_PREFIX_13: case GRPC_DTS_CLIENT_PREFIX_14: case GRPC_DTS_CLIENT_PREFIX_15: case GRPC_DTS_CLIENT_PREFIX_16: case GRPC_DTS_CLIENT_PREFIX_17: case GRPC_DTS_CLIENT_PREFIX_18: case GRPC_DTS_CLIENT_PREFIX_19: case GRPC_DTS_CLIENT_PREFIX_20: case GRPC_DTS_CLIENT_PREFIX_21: case GRPC_DTS_CLIENT_PREFIX_22: case GRPC_DTS_CLIENT_PREFIX_23: while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) { if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing ->deframe_state]) { gpr_log(GPR_INFO, "Connect string mismatch: expected '%c' (%d) got '%c' (%d) " "at byte %d", GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing ->deframe_state], (int)(gpr_uint8)GRPC_CHTTP2_CLIENT_CONNECT_STRING [transport_parsing->deframe_state], *cur, (int)*cur, transport_parsing->deframe_state); return 0; } ++cur; ++transport_parsing->deframe_state; } if (cur == end) { return 1; } /* fallthrough */ dts_fh_0: case GRPC_DTS_FH_0: GPR_ASSERT(cur < end); transport_parsing->incoming_frame_size = ((gpr_uint32)*cur) << 16; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_1; return 1; } /* fallthrough */ case GRPC_DTS_FH_1: GPR_ASSERT(cur < end); transport_parsing->incoming_frame_size |= ((gpr_uint32)*cur) << 8; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_2; return 1; } /* fallthrough */ case GRPC_DTS_FH_2: GPR_ASSERT(cur < end); transport_parsing->incoming_frame_size |= *cur; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_3; return 1; } /* fallthrough */ case GRPC_DTS_FH_3: GPR_ASSERT(cur < end); transport_parsing->incoming_frame_type = *cur; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_4; return 1; } /* fallthrough */ case GRPC_DTS_FH_4: GPR_ASSERT(cur < end); transport_parsing->incoming_frame_flags = *cur; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_5; return 1; } /* fallthrough */ case GRPC_DTS_FH_5: GPR_ASSERT(cur < end); transport_parsing->incoming_stream_id = (((gpr_uint32)*cur) & 0x7f) << 24; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_6; return 1; } /* fallthrough */ case GRPC_DTS_FH_6: GPR_ASSERT(cur < end); transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 16; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_7; return 1; } /* fallthrough */ case GRPC_DTS_FH_7: GPR_ASSERT(cur < end); transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 8; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_8; return 1; } /* fallthrough */ case GRPC_DTS_FH_8: GPR_ASSERT(cur < end); transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur); transport_parsing->deframe_state = GRPC_DTS_FRAME; if (!init_frame_parser(transport_parsing)) { return 0; } if (transport_parsing->incoming_stream_id) { transport_parsing->last_incoming_stream_id = transport_parsing->incoming_stream_id; } if (transport_parsing->incoming_frame_size == 0) { if (!parse_frame_slice(transport_parsing, gpr_empty_slice(), 1)) { return 0; } transport_parsing->incoming_stream = NULL; if (++cur == end) { transport_parsing->deframe_state = GRPC_DTS_FH_0; return 1; } goto dts_fh_0; /* loop */ } if (++cur == end) { return 1; } /* fallthrough */ case GRPC_DTS_FRAME: GPR_ASSERT(cur < end); if ((gpr_uint32)(end - cur) == transport_parsing->incoming_frame_size) { if (!parse_frame_slice( transport_parsing, gpr_slice_sub_no_ref(slice, cur - beg, end - beg), 1)) { return 0; } transport_parsing->deframe_state = GRPC_DTS_FH_0; transport_parsing->incoming_stream = NULL; return 1; } else if ((gpr_uint32)(end - cur) > transport_parsing->incoming_frame_size) { if (!parse_frame_slice( transport_parsing, gpr_slice_sub_no_ref( slice, cur - beg, cur + transport_parsing->incoming_frame_size - beg), 1)) { return 0; } cur += transport_parsing->incoming_frame_size; transport_parsing->incoming_stream = NULL; goto dts_fh_0; /* loop */ } else { if (!parse_frame_slice( transport_parsing, gpr_slice_sub_no_ref(slice, cur - beg, end - beg), 0)) { return 0; } transport_parsing->incoming_frame_size -= (end - cur); return 1; } gpr_log(GPR_ERROR, "should never reach here"); abort(); } gpr_log(GPR_ERROR, "should never reach here"); abort(); return 0; }
/* Takes ownership of creds_path if not NULL. */ static grpc_error *create_default_creds_from_path( char *creds_path, grpc_call_credentials **creds) { grpc_json *json = NULL; grpc_auth_json_key key; grpc_auth_refresh_token token; grpc_call_credentials *result = NULL; gpr_slice creds_data = gpr_empty_slice(); grpc_error *error = GRPC_ERROR_NONE; if (creds_path == NULL) { error = GRPC_ERROR_CREATE("creds_path unset"); goto end; } error = grpc_load_file(creds_path, 0, &creds_data); if (error != GRPC_ERROR_NONE) { goto end; } json = grpc_json_parse_string_with_len( (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data)); if (json == NULL) { char *dump = gpr_dump_slice(creds_data, GPR_DUMP_HEX | GPR_DUMP_ASCII); error = grpc_error_set_str(GRPC_ERROR_CREATE("Failed to parse JSON"), GRPC_ERROR_STR_RAW_BYTES, dump); gpr_free(dump); goto end; } /* First, try an auth json key. */ key = grpc_auth_json_key_create_from_json(json); if (grpc_auth_json_key_is_valid(&key)) { result = grpc_service_account_jwt_access_credentials_create_from_auth_json_key( key, grpc_max_auth_token_lifetime()); if (result == NULL) { error = GRPC_ERROR_CREATE( "grpc_service_account_jwt_access_credentials_create_from_auth_json_" "key failed"); } goto end; } /* Then try a refresh token if the auth json key was invalid. */ token = grpc_auth_refresh_token_create_from_json(json); if (grpc_auth_refresh_token_is_valid(&token)) { result = grpc_refresh_token_credentials_create_from_auth_refresh_token(token); if (result == NULL) { error = GRPC_ERROR_CREATE( "grpc_refresh_token_credentials_create_from_auth_refresh_token " "failed"); } goto end; } end: GPR_ASSERT((result == NULL) + (error == GRPC_ERROR_NONE) == 1); if (creds_path != NULL) gpr_free(creds_path); gpr_slice_unref(creds_data); if (json != NULL) grpc_json_destroy(json); *creds = result; return error; }