| 
					
				 | 
			
			
				@@ -63,21 +63,31 @@ class CallHook; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 class CompletionQueue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 extern CoreCodegenInterface* g_core_codegen_interface; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const char kBinaryErrorDetailsKey[] = "grpc-status-details-bin"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // TODO(yangg) if the map is changed before we send, the pointers will be a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // mess. Make sure it does not happen. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 inline grpc_metadata* FillMetadataArray( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const std::multimap<grpc::string, grpc::string>& metadata) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (metadata.empty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const std::multimap<grpc::string, grpc::string>& metadata, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    size_t* metadata_count, const grpc::string& optional_error_details) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  *metadata_count = metadata.size() + (optional_error_details.empty() ? 0 : 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (*metadata_count == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return nullptr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_metadata* metadata_array = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       (grpc_metadata*)(g_core_codegen_interface->gpr_malloc( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          metadata.size() * sizeof(grpc_metadata))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          (*metadata_count) * sizeof(grpc_metadata))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t i = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     metadata_array[i].key = SliceReferencingString(iter->first); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     metadata_array[i].value = SliceReferencingString(iter->second); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!optional_error_details.empty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    metadata_array[i].key = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        g_core_codegen_interface->grpc_slice_from_static_buffer( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            kBinaryErrorDetailsKey, sizeof(kBinaryErrorDetailsKey) - 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    metadata_array[i].value = SliceReferencingString(optional_error_details); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return metadata_array; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -216,8 +226,8 @@ class CallOpSendInitialMetadata { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     maybe_compression_level_.is_set = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     send_ = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     flags_ = flags; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    initial_metadata_count_ = metadata.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    initial_metadata_ = FillMetadataArray(metadata); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    initial_metadata_ = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        FillMetadataArray(metadata, &initial_metadata_count_, ""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   void set_compression_level(grpc_compression_level level) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -454,11 +464,12 @@ class CallOpServerSendStatus { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   void ServerSendStatus( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const std::multimap<grpc::string, grpc::string>& trailing_metadata, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const Status& status) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    trailing_metadata_count_ = trailing_metadata.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    trailing_metadata_ = FillMetadataArray(trailing_metadata); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    send_error_details_ = status.error_details(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    trailing_metadata_ = FillMetadataArray( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        trailing_metadata, &trailing_metadata_count_, send_error_details_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     send_status_available_ = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     send_status_code_ = static_cast<grpc_status_code>(GetCanonicalCode(status)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    send_status_details_ = status.error_message(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    send_error_message_ = status.error_message(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  protected: 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -470,9 +481,9 @@ class CallOpServerSendStatus { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         trailing_metadata_count_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     op->data.send_status_from_server.trailing_metadata = trailing_metadata_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     op->data.send_status_from_server.status = send_status_code_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    status_details_slice_ = SliceReferencingString(send_status_details_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    error_message_slice_ = SliceReferencingString(send_error_message_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     op->data.send_status_from_server.status_details = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        send_status_details_.empty() ? nullptr : &status_details_slice_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        send_error_message_.empty() ? nullptr : &error_message_slice_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     op->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -486,10 +497,11 @@ class CallOpServerSendStatus { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   bool send_status_available_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_status_code send_status_code_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc::string send_status_details_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc::string send_error_details_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc::string send_error_message_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t trailing_metadata_count_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_metadata* trailing_metadata_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_slice status_details_slice_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_slice error_message_slice_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 class CallOpRecvInitialMetadata { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -528,7 +540,7 @@ class CallOpClientRecvStatus { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   void ClientRecvStatus(ClientContext* context, Status* status) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     metadata_map_ = &context->trailing_metadata_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     recv_status_ = status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    status_details_ = g_core_codegen_interface->grpc_empty_slice(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    error_message_ = g_core_codegen_interface->grpc_empty_slice(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  protected: 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -538,7 +550,7 @@ class CallOpClientRecvStatus { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     op->data.recv_status_on_client.trailing_metadata = metadata_map_->arr(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     op->data.recv_status_on_client.status = &status_code_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    op->data.recv_status_on_client.status_details = &status_details_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    op->data.recv_status_on_client.status_details = &error_message_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     op->flags = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     op->reserved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -546,10 +558,17 @@ class CallOpClientRecvStatus { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   void FinishOp(bool* status) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (recv_status_ == nullptr) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     metadata_map_->FillMap(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc::string binary_error_details; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    auto iter = metadata_map_->map()->find(kBinaryErrorDetailsKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (iter != metadata_map_->map()->end()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      binary_error_details = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          grpc::string(iter->second.begin(), iter->second.length()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     *recv_status_ = Status(static_cast<StatusCode>(status_code_), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           grpc::string(GRPC_SLICE_START_PTR(status_details_), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                        GRPC_SLICE_END_PTR(status_details_))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    g_core_codegen_interface->grpc_slice_unref(status_details_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           grpc::string(GRPC_SLICE_START_PTR(error_message_), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        GRPC_SLICE_END_PTR(error_message_)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           binary_error_details); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    g_core_codegen_interface->grpc_slice_unref(error_message_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     recv_status_ = nullptr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -557,7 +576,7 @@ class CallOpClientRecvStatus { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MetadataMap* metadata_map_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   Status* recv_status_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_status_code status_code_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_slice status_details_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_slice error_message_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /// An abstract collection of CallOpSet's, to be used whenever 
			 |