/* tcp read callback */ static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, int success) { size_t i; int keep_reading = 0; grpc_chttp2_transport *t = tp; lock(t); i = 0; GPR_ASSERT(!t->parsing_active); if (!t->closed) { t->parsing_active = 1; /* merge stream lists */ grpc_chttp2_stream_map_move_into(&t->new_stream_map, &t->parsing_stream_map); grpc_chttp2_prepare_to_read(&t->global, &t->parsing); gpr_mu_unlock(&t->mu); for (; i < t->read_buffer.count && grpc_chttp2_perform_read(exec_ctx, &t->parsing, t->read_buffer.slices[i]); i++) ; gpr_mu_lock(&t->mu); if (i != t->read_buffer.count) { drop_connection(exec_ctx, t); } /* merge stream lists */ grpc_chttp2_stream_map_move_into(&t->new_stream_map, &t->parsing_stream_map); t->global.concurrent_stream_count = (gpr_uint32)grpc_chttp2_stream_map_size(&t->parsing_stream_map); if (t->parsing.initial_window_update != 0) { grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, update_global_window, t); t->parsing.initial_window_update = 0; } /* handle higher level things */ grpc_chttp2_publish_reads(exec_ctx, &t->global, &t->parsing); t->parsing_active = 0; } if (!success || i != t->read_buffer.count) { drop_connection(exec_ctx, t); read_error_locked(exec_ctx, t); } else if (!t->closed) { keep_reading = 1; REF_TRANSPORT(t, "keep_reading"); prevent_endpoint_shutdown(t); } gpr_slice_buffer_reset_and_unref(&t->read_buffer); unlock(exec_ctx, t); if (keep_reading) { grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer, &t->recv_data); allow_endpoint_shutdown_unlocked(exec_ctx, t); UNREF_TRANSPORT(exec_ctx, t, "keep_reading"); } else { UNREF_TRANSPORT(exec_ctx, t, "recv_data"); } }
/* tcp read callback */ static void recv_data(void *tp, gpr_slice *slices, size_t nslices, grpc_endpoint_cb_status error) { grpc_chttp2_transport *t = tp; size_t i; int unref = 0; switch (error) { case GRPC_ENDPOINT_CB_SHUTDOWN: case GRPC_ENDPOINT_CB_EOF: case GRPC_ENDPOINT_CB_ERROR: lock(t); drop_connection(t); read_error_locked(t); unlock(t); unref = 1; for (i = 0; i < nslices; i++) gpr_slice_unref(slices[i]); break; case GRPC_ENDPOINT_CB_OK: lock(t); i = 0; GPR_ASSERT(!t->parsing_active); if (t->global.error_state == GRPC_CHTTP2_ERROR_STATE_NONE) { t->parsing_active = 1; /* merge stream lists */ grpc_chttp2_stream_map_move_into(&t->new_stream_map, &t->parsing_stream_map); grpc_chttp2_prepare_to_read(&t->global, &t->parsing); gpr_mu_unlock(&t->mu); for (; i < nslices && grpc_chttp2_perform_read(&t->parsing, slices[i]); i++) { gpr_slice_unref(slices[i]); } gpr_mu_lock(&t->mu); if (i != nslices) { drop_connection(t); } /* merge stream lists */ grpc_chttp2_stream_map_move_into(&t->new_stream_map, &t->parsing_stream_map); t->global.concurrent_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map); if (t->parsing.initial_window_update != 0) { grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, update_global_window, t); } /* handle higher level things */ grpc_chttp2_publish_reads(&t->global, &t->parsing); t->parsing_active = 0; } if (i == nslices) { grpc_chttp2_schedule_closure(&t->global, &t->reading_action, 1); } else { read_error_locked(t); unref = 1; } unlock(t); for (; i < nslices; i++) gpr_slice_unref(slices[i]); break; } if (unref) { UNREF_TRANSPORT(t, "recv_data"); } }
/* tcp read callback */ static int recv_data_loop(grpc_chttp2_transport *t, int *success) { size_t i; int keep_reading = 0; lock(t); i = 0; GPR_ASSERT(!t->parsing_active); if (!t->closed) { t->parsing_active = 1; /* merge stream lists */ grpc_chttp2_stream_map_move_into(&t->new_stream_map, &t->parsing_stream_map); grpc_chttp2_prepare_to_read(&t->global, &t->parsing); gpr_mu_unlock(&t->mu); for (; i < t->read_buffer.count && grpc_chttp2_perform_read(&t->parsing, t->read_buffer.slices[i]); i++) ; gpr_mu_lock(&t->mu); if (i != t->read_buffer.count) { drop_connection(t); } /* merge stream lists */ grpc_chttp2_stream_map_move_into(&t->new_stream_map, &t->parsing_stream_map); t->global.concurrent_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map); if (t->parsing.initial_window_update != 0) { grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, update_global_window, t); t->parsing.initial_window_update = 0; } /* handle higher level things */ grpc_chttp2_publish_reads(&t->global, &t->parsing); t->parsing_active = 0; } if (!*success || i != t->read_buffer.count) { drop_connection(t); read_error_locked(t); } else if (!t->closed) { keep_reading = 1; REF_TRANSPORT(t, "keep_reading"); prevent_endpoint_shutdown(t); } gpr_slice_buffer_reset_and_unref(&t->read_buffer); unlock(t); if (keep_reading) { int ret = -1; switch (grpc_endpoint_read(t->ep, &t->read_buffer, &t->recv_data)) { case GRPC_ENDPOINT_DONE: *success = 1; ret = 1; break; case GRPC_ENDPOINT_ERROR: *success = 0; ret = 1; break; case GRPC_ENDPOINT_PENDING: ret = 0; break; } allow_endpoint_shutdown_unlocked(t); UNREF_TRANSPORT(t, "keep_reading"); return ret; } else { UNREF_TRANSPORT(t, "recv_data"); return 0; } gpr_log(GPR_ERROR, "should never reach here"); abort(); }