1 /* 2 * 3 * Copyright 2015-2016 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #ifndef GRPC_GRPC_H 20 #define GRPC_GRPC_H 21 22 #include <grpc/support/port_platform.h> 23 24 #include <grpc/status.h> 25 26 #include <grpc/byte_buffer.h> 27 #include <grpc/impl/codegen/connectivity_state.h> 28 #include <grpc/impl/codegen/grpc_types.h> 29 #include <grpc/impl/codegen/propagation_bits.h> 30 #include <grpc/slice.h> 31 #include <grpc/support/time.h> 32 #include <stddef.h> 33 34 #ifdef __cplusplus 35 extern "C" { 36 #endif 37 38 /*! \mainpage GRPC Core 39 * 40 * The GRPC Core library is a low-level library designed to be wrapped by higher 41 * level libraries. The top-level API is provided in grpc.h. Security related 42 * functionality lives in grpc_security.h. 43 */ 44 45 GRPCAPI void grpc_metadata_array_init(grpc_metadata_array* array); 46 GRPCAPI void grpc_metadata_array_destroy(grpc_metadata_array* array); 47 48 GRPCAPI void grpc_call_details_init(grpc_call_details* details); 49 GRPCAPI void grpc_call_details_destroy(grpc_call_details* details); 50 51 /** Registers a plugin to be initialized and destroyed with the library. 52 53 The \a init and \a destroy functions will be invoked as part of 54 \a grpc_init() and \a grpc_shutdown(), respectively. 55 Note that these functions can be invoked an arbitrary number of times 56 (and hence so will \a init and \a destroy). 57 It is safe to pass NULL to either argument. Plugins are destroyed in 58 the reverse order they were initialized. */ 59 GRPCAPI void grpc_register_plugin(void (*init)(void), void (*destroy)(void)); 60 61 /** Initialize the grpc library. 62 63 After it's called, a matching invocation to grpc_shutdown() is expected. 64 65 It is not safe to call any other grpc functions before calling this. 66 (To avoid overhead, little checking is done, and some things may work. We 67 do not warrant that they will continue to do so in future revisions of this 68 library). */ 69 GRPCAPI void grpc_init(void); 70 71 /** Shut down the grpc library. 72 73 Before it's called, there should haven been a matching invocation to 74 grpc_init(). 75 76 The last call to grpc_shutdown will initiate cleaning up of grpc library 77 internals, which can happen in another thread. Once the clean-up is done, 78 no memory is used by grpc, nor are any instructions executing within the 79 grpc library. Prior to calling, all application owned grpc objects must 80 have been destroyed. */ 81 GRPCAPI void grpc_shutdown(void); 82 83 /** EXPERIMENTAL. Returns 1 if the grpc library has been initialized. 84 TODO(ericgribkoff) Decide if this should be promoted to non-experimental as 85 part of stabilizing the fork support API, as tracked in 86 https://github.com/grpc/grpc/issues/15334 */ 87 GRPCAPI int grpc_is_initialized(void); 88 89 /** DEPRECATED. Recommend to use grpc_shutdown only */ 90 GRPCAPI void grpc_shutdown_blocking(void); 91 92 /** Return a string representing the current version of grpc */ 93 GRPCAPI const char* grpc_version_string(void); 94 95 /** Return a string specifying what the 'g' in gRPC stands for */ 96 GRPCAPI const char* grpc_g_stands_for(void); 97 98 /** Returns the completion queue factory based on the attributes. MAY return a 99 NULL if no factory can be found */ 100 GRPCAPI const grpc_completion_queue_factory* 101 grpc_completion_queue_factory_lookup( 102 const grpc_completion_queue_attributes* attributes); 103 104 /** Helper function to create a completion queue with grpc_cq_completion_type 105 of GRPC_CQ_NEXT and grpc_cq_polling_type of GRPC_CQ_DEFAULT_POLLING */ 106 GRPCAPI grpc_completion_queue* grpc_completion_queue_create_for_next( 107 void* reserved); 108 109 /** Helper function to create a completion queue with grpc_cq_completion_type 110 of GRPC_CQ_PLUCK and grpc_cq_polling_type of GRPC_CQ_DEFAULT_POLLING */ 111 GRPCAPI grpc_completion_queue* grpc_completion_queue_create_for_pluck( 112 void* reserved); 113 114 /** Helper function to create a completion queue with grpc_cq_completion_type 115 of GRPC_CQ_CALLBACK and grpc_cq_polling_type of GRPC_CQ_DEFAULT_POLLING. 116 This function is experimental. */ 117 GRPCAPI grpc_completion_queue* grpc_completion_queue_create_for_callback( 118 grpc_experimental_completion_queue_functor* shutdown_callback, 119 void* reserved); 120 121 /** Create a completion queue */ 122 GRPCAPI grpc_completion_queue* grpc_completion_queue_create( 123 const grpc_completion_queue_factory* factory, 124 const grpc_completion_queue_attributes* attributes, void* reserved); 125 126 /** Blocks until an event is available, the completion queue is being shut down, 127 or deadline is reached. 128 129 Returns a grpc_event with type GRPC_QUEUE_TIMEOUT on timeout, 130 otherwise a grpc_event describing the event that occurred. 131 132 Callers must not call grpc_completion_queue_next and 133 grpc_completion_queue_pluck simultaneously on the same completion queue. */ 134 GRPCAPI grpc_event grpc_completion_queue_next(grpc_completion_queue* cq, 135 gpr_timespec deadline, 136 void* reserved); 137 138 /** Blocks until an event with tag 'tag' is available, the completion queue is 139 being shutdown or deadline is reached. 140 141 Returns a grpc_event with type GRPC_QUEUE_TIMEOUT on timeout, 142 otherwise a grpc_event describing the event that occurred. 143 144 Callers must not call grpc_completion_queue_next and 145 grpc_completion_queue_pluck simultaneously on the same completion queue. 146 147 Completion queues support a maximum of GRPC_MAX_COMPLETION_QUEUE_PLUCKERS 148 concurrently executing plucks at any time. */ 149 GRPCAPI grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq, 150 void* tag, gpr_timespec deadline, 151 void* reserved); 152 153 /** Maximum number of outstanding grpc_completion_queue_pluck executions per 154 completion queue */ 155 #define GRPC_MAX_COMPLETION_QUEUE_PLUCKERS 6 156 157 /** Begin destruction of a completion queue. Once all possible events are 158 drained then grpc_completion_queue_next will start to produce 159 GRPC_QUEUE_SHUTDOWN events only. At that point it's safe to call 160 grpc_completion_queue_destroy. 161 162 After calling this function applications should ensure that no 163 NEW work is added to be published on this completion queue. */ 164 GRPCAPI void grpc_completion_queue_shutdown(grpc_completion_queue* cq); 165 166 /** Destroy a completion queue. The caller must ensure that the queue is 167 drained and no threads are executing grpc_completion_queue_next */ 168 GRPCAPI void grpc_completion_queue_destroy(grpc_completion_queue* cq); 169 170 /*********** EXPERIMENTAL API ************/ 171 /** Initializes a thread local cache for \a cq. 172 * grpc_flush_cq_tls_cache() MUST be called on the same thread, 173 * with the same cq. 174 */ 175 GRPCAPI void grpc_completion_queue_thread_local_cache_init( 176 grpc_completion_queue* cq); 177 178 /*********** EXPERIMENTAL API ************/ 179 /** Flushes the thread local cache for \a cq. 180 * Returns 1 if there was contents in the cache. If there was an event 181 * in \a cq tls cache, its tag is placed in tag, and ok is set to the 182 * event success. 183 */ 184 GRPCAPI int grpc_completion_queue_thread_local_cache_flush( 185 grpc_completion_queue* cq, void** tag, int* ok); 186 187 /** Check the connectivity state of a channel. */ 188 GRPCAPI grpc_connectivity_state grpc_channel_check_connectivity_state( 189 grpc_channel* channel, int try_to_connect); 190 191 /** Number of active "external connectivity state watchers" attached to a 192 * channel. 193 * Useful for testing. **/ 194 GRPCAPI int grpc_channel_num_external_connectivity_watchers( 195 grpc_channel* channel); 196 197 /** Watch for a change in connectivity state. 198 Once the channel connectivity state is different from last_observed_state, 199 tag will be enqueued on cq with success=1. 200 If deadline expires BEFORE the state is changed, tag will be enqueued on cq 201 with success=0. */ 202 GRPCAPI void grpc_channel_watch_connectivity_state( 203 grpc_channel* channel, grpc_connectivity_state last_observed_state, 204 gpr_timespec deadline, grpc_completion_queue* cq, void* tag); 205 206 /** Check whether a grpc channel supports connectivity watcher */ 207 GRPCAPI int grpc_channel_support_connectivity_watcher(grpc_channel* channel); 208 209 /** Create a call given a grpc_channel, in order to call 'method'. All 210 completions are sent to 'completion_queue'. 'method' and 'host' need only 211 live through the invocation of this function. 212 If parent_call is non-NULL, it must be a server-side call. It will be used 213 to propagate properties from the server call to this new client call, 214 depending on the value of \a propagation_mask (see propagation_bits.h for 215 possible values). */ 216 GRPCAPI grpc_call* grpc_channel_create_call( 217 grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask, 218 grpc_completion_queue* completion_queue, grpc_slice method, 219 const grpc_slice* host, gpr_timespec deadline, void* reserved); 220 221 /** Pre-register a method/host pair on a channel. 222 method and host are not owned and must remain alive while the channel is 223 alive. */ 224 GRPCAPI void* grpc_channel_register_call(grpc_channel* channel, 225 const char* method, const char* host, 226 void* reserved); 227 228 /** Create a call given a handle returned from grpc_channel_register_call. 229 \sa grpc_channel_create_call. */ 230 GRPCAPI grpc_call* grpc_channel_create_registered_call( 231 grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask, 232 grpc_completion_queue* completion_queue, void* registered_call_handle, 233 gpr_timespec deadline, void* reserved); 234 235 /** Allocate memory in the grpc_call arena: this memory is automatically 236 discarded at call completion */ 237 GRPCAPI void* grpc_call_arena_alloc(grpc_call* call, size_t size); 238 239 /** Start a batch of operations defined in the array ops; when complete, post a 240 completion of type 'tag' to the completion queue bound to the call. 241 The order of ops specified in the batch has no significance. 242 Only one operation of each type can be active at once in any given 243 batch. 244 If a call to grpc_call_start_batch returns GRPC_CALL_OK you must call 245 grpc_completion_queue_next or grpc_completion_queue_pluck on the completion 246 queue associated with 'call' for work to be performed. If a call to 247 grpc_call_start_batch returns any value other than GRPC_CALL_OK it is 248 guaranteed that no state associated with 'call' is changed and it is not 249 appropriate to call grpc_completion_queue_next or 250 grpc_completion_queue_pluck consequent to the failed grpc_call_start_batch 251 call. 252 If a call to grpc_call_start_batch with an empty batch returns 253 GRPC_CALL_OK, the tag is put in the completion queue immediately. 254 THREAD SAFETY: access to grpc_call_start_batch in multi-threaded environment 255 needs to be synchronized. As an optimization, you may synchronize batches 256 containing just send operations independently from batches containing just 257 receive operations. Access to grpc_call_start_batch with an empty batch is 258 thread-compatible. */ 259 GRPCAPI grpc_call_error grpc_call_start_batch(grpc_call* call, 260 const grpc_op* ops, size_t nops, 261 void* tag, void* reserved); 262 263 /** Returns a newly allocated string representing the endpoint to which this 264 call is communicating with. The string is in the uri format accepted by 265 grpc_channel_create. 266 The returned string should be disposed of with gpr_free(). 267 268 WARNING: this value is never authenticated or subject to any security 269 related code. It must not be used for any authentication related 270 functionality. Instead, use grpc_auth_context. */ 271 GRPCAPI char* grpc_call_get_peer(grpc_call* call); 272 273 struct census_context; 274 275 /** Set census context for a call; Must be called before first call to 276 grpc_call_start_batch(). */ 277 GRPCAPI void grpc_census_call_set_context(grpc_call* call, 278 struct census_context* context); 279 280 /** Retrieve the calls current census context. */ 281 GRPCAPI struct census_context* grpc_census_call_get_context(grpc_call* call); 282 283 /** Return a newly allocated string representing the target a channel was 284 created for. */ 285 GRPCAPI char* grpc_channel_get_target(grpc_channel* channel); 286 287 /** Request info about the channel. 288 \a channel_info indicates what information is being requested and 289 how that information will be returned. 290 \a channel_info is owned by the caller. */ 291 GRPCAPI void grpc_channel_get_info(grpc_channel* channel, 292 const grpc_channel_info* channel_info); 293 294 /** EXPERIMENTAL. Resets the channel's connect backoff. 295 TODO(roth): When we see whether this proves useful, either promote 296 to non-experimental or remove it. */ 297 GRPCAPI void grpc_channel_reset_connect_backoff(grpc_channel* channel); 298 299 /** Create a client channel to 'target'. Additional channel level configuration 300 MAY be provided by grpc_channel_args, though the expectation is that most 301 clients will want to simply pass NULL. The user data in 'args' need only 302 live through the invocation of this function. However, if any args of the 303 'pointer' type are passed, then the referenced vtable must be maintained 304 by the caller until grpc_channel_destroy terminates. See grpc_channel_args 305 definition for more on this. */ 306 GRPCAPI grpc_channel* grpc_insecure_channel_create( 307 const char* target, const grpc_channel_args* args, void* reserved); 308 309 /** Create a lame client: this client fails every operation attempted on it. */ 310 GRPCAPI grpc_channel* grpc_lame_client_channel_create( 311 const char* target, grpc_status_code error_code, const char* error_message); 312 313 /** Close and destroy a grpc channel */ 314 GRPCAPI void grpc_channel_destroy(grpc_channel* channel); 315 316 /** Error handling for grpc_call 317 Most grpc_call functions return a grpc_error. If the error is not GRPC_OK 318 then the operation failed due to some unsatisfied precondition. 319 If a grpc_call fails, it's guaranteed that no change to the call state 320 has been made. */ 321 322 /** Cancel an RPC. 323 Can be called multiple times, from any thread. 324 THREAD-SAFETY grpc_call_cancel and grpc_call_cancel_with_status 325 are thread-safe, and can be called at any point before grpc_call_unref 326 is called.*/ 327 GRPCAPI grpc_call_error grpc_call_cancel(grpc_call* call, void* reserved); 328 329 /** Cancel an RPC. 330 Can be called multiple times, from any thread. 331 If a status has not been received for the call, set it to the status code 332 and description passed in. 333 Importantly, this function does not send status nor description to the 334 remote endpoint. 335 Note that \a description doesn't need be a static string. 336 It doesn't need to be alive after the call to 337 grpc_call_cancel_with_status completes. 338 */ 339 GRPCAPI grpc_call_error grpc_call_cancel_with_status(grpc_call* call, 340 grpc_status_code status, 341 const char* description, 342 void* reserved); 343 344 /** Ref a call. 345 THREAD SAFETY: grpc_call_ref is thread-compatible */ 346 GRPCAPI void grpc_call_ref(grpc_call* call); 347 348 /** Unref a call. 349 THREAD SAFETY: grpc_call_unref is thread-compatible */ 350 GRPCAPI void grpc_call_unref(grpc_call* call); 351 352 /** Request notification of a new call. 353 Once a call is received, a notification tagged with \a tag_new is added to 354 \a cq_for_notification. \a call, \a details and \a request_metadata are 355 updated with the appropriate call information. \a cq_bound_to_call is bound 356 to \a call, and batch operation notifications for that call will be posted 357 to \a cq_bound_to_call. 358 Note that \a cq_for_notification must have been registered to the server via 359 \a grpc_server_register_completion_queue. */ 360 GRPCAPI grpc_call_error grpc_server_request_call( 361 grpc_server* server, grpc_call** call, grpc_call_details* details, 362 grpc_metadata_array* request_metadata, 363 grpc_completion_queue* cq_bound_to_call, 364 grpc_completion_queue* cq_for_notification, void* tag_new); 365 366 /** How to handle payloads for a registered method */ 367 typedef enum { 368 /** Don't try to read the payload */ 369 GRPC_SRM_PAYLOAD_NONE, 370 /** Read the initial payload as a byte buffer */ 371 GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER 372 } grpc_server_register_method_payload_handling; 373 374 /** Registers a method in the server. 375 Methods to this (host, method) pair will not be reported by 376 grpc_server_request_call, but instead be reported by 377 grpc_server_request_registered_call when passed the appropriate 378 registered_method (as returned by this function). 379 Must be called before grpc_server_start. 380 Returns NULL on failure. */ 381 GRPCAPI void* grpc_server_register_method( 382 grpc_server* server, const char* method, const char* host, 383 grpc_server_register_method_payload_handling payload_handling, 384 uint32_t flags); 385 386 /** Request notification of a new pre-registered call. 'cq_for_notification' 387 must have been registered to the server via 388 grpc_server_register_completion_queue. */ 389 GRPCAPI grpc_call_error grpc_server_request_registered_call( 390 grpc_server* server, void* registered_method, grpc_call** call, 391 gpr_timespec* deadline, grpc_metadata_array* request_metadata, 392 grpc_byte_buffer** optional_payload, 393 grpc_completion_queue* cq_bound_to_call, 394 grpc_completion_queue* cq_for_notification, void* tag_new); 395 396 /** Create a server. Additional configuration for each incoming channel can 397 be specified with args. If no additional configuration is needed, args can 398 be NULL. The user data in 'args' need only live through the invocation of 399 this function. However, if any args of the 'pointer' type are passed, then 400 the referenced vtable must be maintained by the caller until 401 grpc_server_destroy terminates. See grpc_channel_args definition for more 402 on this. */ 403 GRPCAPI grpc_server* grpc_server_create(const grpc_channel_args* args, 404 void* reserved); 405 406 /** Register a completion queue with the server. Must be done for any 407 notification completion queue that is passed to grpc_server_request_*_call 408 and to grpc_server_shutdown_and_notify. Must be performed prior to 409 grpc_server_start. */ 410 GRPCAPI void grpc_server_register_completion_queue(grpc_server* server, 411 grpc_completion_queue* cq, 412 void* reserved); 413 414 typedef struct grpc_server_config_fetcher grpc_server_config_fetcher; 415 416 /** EXPERIMENTAL. Creates an xDS config fetcher. */ 417 GRPCAPI grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create(); 418 419 /** EXPERIMENTAL. Destroys a config fetcher. */ 420 GRPCAPI void grpc_server_config_fetcher_destroy( 421 grpc_server_config_fetcher* config_fetcher); 422 423 /** EXPERIMENTAL. Sets the server's config fetcher. Takes ownership. 424 Must be called before adding ports */ 425 GRPCAPI void grpc_server_set_config_fetcher( 426 grpc_server* server, grpc_server_config_fetcher* config_fetcher); 427 428 /** Add a HTTP2 over plaintext over tcp listener. 429 Returns bound port number on success, 0 on failure. 430 REQUIRES: server not started */ 431 GRPCAPI int grpc_server_add_insecure_http2_port(grpc_server* server, 432 const char* addr); 433 434 /** Start a server - tells all listeners to start listening */ 435 GRPCAPI void grpc_server_start(grpc_server* server); 436 437 /** Begin shutting down a server. 438 After completion, no new calls or connections will be admitted. 439 Existing calls will be allowed to complete. 440 Send a GRPC_OP_COMPLETE event when there are no more calls being serviced. 441 Shutdown is idempotent, and all tags will be notified at once if multiple 442 grpc_server_shutdown_and_notify calls are made. 'cq' must have been 443 registered to this server via grpc_server_register_completion_queue. */ 444 GRPCAPI void grpc_server_shutdown_and_notify(grpc_server* server, 445 grpc_completion_queue* cq, 446 void* tag); 447 448 /** Cancel all in-progress calls. 449 Only usable after shutdown. */ 450 GRPCAPI void grpc_server_cancel_all_calls(grpc_server* server); 451 452 /** Destroy a server. 453 Shutdown must have completed beforehand (i.e. all tags generated by 454 grpc_server_shutdown_and_notify must have been received, and at least 455 one call to grpc_server_shutdown_and_notify must have been made). */ 456 GRPCAPI void grpc_server_destroy(grpc_server* server); 457 458 /** Enable or disable a tracer. 459 460 Tracers (usually controlled by the environment variable GRPC_TRACE) 461 allow printf-style debugging on GRPC internals, and are useful for 462 tracking down problems in the field. 463 464 Use of this function is not strictly thread-safe, but the 465 thread-safety issues raised by it should not be of concern. */ 466 GRPCAPI int grpc_tracer_set_enabled(const char* name, int enabled); 467 468 /** Check whether a metadata key is legal (will be accepted by core) */ 469 GRPCAPI int grpc_header_key_is_legal(grpc_slice slice); 470 471 /** Check whether a non-binary metadata value is legal (will be accepted by 472 core) */ 473 GRPCAPI int grpc_header_nonbin_value_is_legal(grpc_slice slice); 474 475 /** Check whether a metadata key corresponds to a binary value */ 476 GRPCAPI int grpc_is_binary_header(grpc_slice slice); 477 478 /** Convert grpc_call_error values to a string */ 479 GRPCAPI const char* grpc_call_error_to_string(grpc_call_error error); 480 481 /** Create a buffer pool */ 482 GRPCAPI grpc_resource_quota* grpc_resource_quota_create(const char* trace_name); 483 484 /** Add a reference to a buffer pool */ 485 GRPCAPI void grpc_resource_quota_ref(grpc_resource_quota* resource_quota); 486 487 /** Drop a reference to a buffer pool */ 488 GRPCAPI void grpc_resource_quota_unref(grpc_resource_quota* resource_quota); 489 490 /** Update the size of a buffer pool */ 491 GRPCAPI void grpc_resource_quota_resize(grpc_resource_quota* resource_quota, 492 size_t new_size); 493 494 /** Update the size of the maximum number of threads allowed */ 495 GRPCAPI void grpc_resource_quota_set_max_threads( 496 grpc_resource_quota* resource_quota, int new_max_threads); 497 498 /** Fetch a vtable for a grpc_channel_arg that points to a grpc_resource_quota 499 */ 500 GRPCAPI const grpc_arg_pointer_vtable* grpc_resource_quota_arg_vtable(void); 501 502 /************* CHANNELZ API *************/ 503 /** Channelz is under active development. The following APIs will see some 504 churn as the feature is implemented. This comment will be removed once 505 channelz is officially supported, and these APIs become stable. For now 506 you may track the progress by following this github issue: 507 https://github.com/grpc/grpc/issues/15340 508 509 the following APIs return allocated JSON strings that match the response 510 objects from the channelz proto, found here: 511 https://github.com/grpc/grpc/blob/master/src/proto/grpc/channelz/channelz.proto. 512 513 For easy conversion to protobuf, The JSON is formatted according to: 514 https://developers.google.com/protocol-buffers/docs/proto3#json. */ 515 516 /* Gets all root channels (i.e. channels the application has directly 517 created). This does not include subchannels nor non-top level channels. 518 The returned string is allocated and must be freed by the application. */ 519 GRPCAPI char* grpc_channelz_get_top_channels(intptr_t start_channel_id); 520 521 /* Gets all servers that exist in the process. */ 522 GRPCAPI char* grpc_channelz_get_servers(intptr_t start_server_id); 523 524 /* Returns a single Server, or else a NOT_FOUND code. */ 525 GRPCAPI char* grpc_channelz_get_server(intptr_t server_id); 526 527 /* Gets all server sockets that exist in the server. */ 528 GRPCAPI char* grpc_channelz_get_server_sockets(intptr_t server_id, 529 intptr_t start_socket_id, 530 intptr_t max_results); 531 532 /* Returns a single Channel, or else a NOT_FOUND code. The returned string 533 is allocated and must be freed by the application. */ 534 GRPCAPI char* grpc_channelz_get_channel(intptr_t channel_id); 535 536 /* Returns a single Subchannel, or else a NOT_FOUND code. The returned string 537 is allocated and must be freed by the application. */ 538 GRPCAPI char* grpc_channelz_get_subchannel(intptr_t subchannel_id); 539 540 /* Returns a single Socket, or else a NOT_FOUND code. The returned string 541 is allocated and must be freed by the application. */ 542 GRPCAPI char* grpc_channelz_get_socket(intptr_t socket_id); 543 544 #ifdef __cplusplus 545 } 546 #endif 547 548 #endif /* GRPC_GRPC_H */ 549