|  | @@ -178,6 +178,7 @@ struct grpc_call {
 | 
	
		
			
				|  |  |    gpr_uint8 received_metadata;
 | 
	
		
			
				|  |  |    gpr_uint8 have_read;
 | 
	
		
			
				|  |  |    gpr_uint8 have_alarm;
 | 
	
		
			
				|  |  | +  gpr_uint8 got_status_code;
 | 
	
		
			
				|  |  |    /* The current outstanding read message tag (only valid if have_read == 1) */
 | 
	
		
			
				|  |  |    void *read_tag;
 | 
	
		
			
				|  |  |    void *metadata_tag;
 | 
	
	
		
			
				|  | @@ -225,6 +226,7 @@ grpc_call *grpc_call_create(grpc_channel *channel,
 | 
	
		
			
				|  |  |    call->have_write = 0;
 | 
	
		
			
				|  |  |    call->have_alarm = 0;
 | 
	
		
			
				|  |  |    call->received_metadata = 0;
 | 
	
		
			
				|  |  | +  call->got_status_code = 0;
 | 
	
		
			
				|  |  |    call->status_code =
 | 
	
		
			
				|  |  |        server_transport_data != NULL ? GRPC_STATUS_OK : GRPC_STATUS_UNKNOWN;
 | 
	
		
			
				|  |  |    call->status_details = NULL;
 | 
	
	
		
			
				|  | @@ -268,6 +270,19 @@ void grpc_call_destroy(grpc_call *c) {
 | 
	
		
			
				|  |  |    grpc_call_internal_unref(c);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static void maybe_set_status_code(grpc_call *call, gpr_uint32 status) {
 | 
	
		
			
				|  |  | +  if (!call->got_status_code) {
 | 
	
		
			
				|  |  | +    call->status_code = status;
 | 
	
		
			
				|  |  | +    call->got_status_code = 1;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void maybe_set_status_details(grpc_call *call, grpc_mdstr *status) {
 | 
	
		
			
				|  |  | +  if (!call->status_details) {
 | 
	
		
			
				|  |  | +    call->status_details = grpc_mdstr_ref(status);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  grpc_call_error grpc_call_cancel(grpc_call *c) {
 | 
	
		
			
				|  |  |    grpc_call_element *elem;
 | 
	
		
			
				|  |  |    grpc_call_op op;
 | 
	
	
		
			
				|  | @@ -284,6 +299,21 @@ grpc_call_error grpc_call_cancel(grpc_call *c) {
 | 
	
		
			
				|  |  |    return GRPC_CALL_OK;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
 | 
	
		
			
				|  |  | +                                             grpc_status_code status,
 | 
	
		
			
				|  |  | +                                             const char *description) {
 | 
	
		
			
				|  |  | +  grpc_mdstr *details =
 | 
	
		
			
				|  |  | +      description ? grpc_mdstr_from_string(c->metadata_context, description)
 | 
	
		
			
				|  |  | +                  : NULL;
 | 
	
		
			
				|  |  | +  gpr_mu_lock(&c->read_mu);
 | 
	
		
			
				|  |  | +  maybe_set_status_code(c, status);
 | 
	
		
			
				|  |  | +  if (details) {
 | 
	
		
			
				|  |  | +    maybe_set_status_details(c, details);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  gpr_mu_unlock(&c->read_mu);
 | 
	
		
			
				|  |  | +  return grpc_call_cancel(c);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void grpc_call_execute_op(grpc_call *call, grpc_call_op *op) {
 | 
	
		
			
				|  |  |    grpc_call_element *elem;
 | 
	
		
			
				|  |  |    GPR_ASSERT(op->dir == GRPC_CALL_DOWN);
 | 
	
	
		
			
				|  | @@ -799,15 +829,14 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_call_op *op) {
 | 
	
		
			
				|  |  |    grpc_call *call = CALL_FROM_TOP_ELEM(elem);
 | 
	
		
			
				|  |  |    grpc_mdelem *md = op->data.metadata;
 | 
	
		
			
				|  |  |    grpc_mdstr *key = md->key;
 | 
	
		
			
				|  |  | +  gpr_log(GPR_DEBUG, "call %p got metadata %s %s", call,
 | 
	
		
			
				|  |  | +          grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value));
 | 
	
		
			
				|  |  |    if (key == grpc_channel_get_status_string(call->channel)) {
 | 
	
		
			
				|  |  | -    call->status_code = decode_status(md);
 | 
	
		
			
				|  |  | +    maybe_set_status_code(call, decode_status(md));
 | 
	
		
			
				|  |  |      grpc_mdelem_unref(md);
 | 
	
		
			
				|  |  |      op->done_cb(op->user_data, GRPC_OP_OK);
 | 
	
		
			
				|  |  |    } else if (key == grpc_channel_get_message_string(call->channel)) {
 | 
	
		
			
				|  |  | -    if (call->status_details) {
 | 
	
		
			
				|  |  | -      grpc_mdstr_unref(call->status_details);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    call->status_details = grpc_mdstr_ref(md->value);
 | 
	
		
			
				|  |  | +    maybe_set_status_details(call, md->value);
 | 
	
		
			
				|  |  |      grpc_mdelem_unref(md);
 | 
	
		
			
				|  |  |      op->done_cb(op->user_data, GRPC_OP_OK);
 | 
	
		
			
				|  |  |    } else {
 |