#ifndef GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_H
#define GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_H
#include <grpc/support/port_platform.h>
#include <stddef.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gpr/arena.h"
#include "src/core/lib/iomgr/call_combiner.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/transport/transport.h"
typedef struct grpc_channel_element grpc_channel_element;
typedef struct grpc_call_element grpc_call_element;
typedef struct grpc_channel_stack grpc_channel_stack;
typedef struct grpc_call_stack grpc_call_stack;
typedef struct {
grpc_channel_stack* channel_stack;
const grpc_channel_args* channel_args;
grpc_transport* optional_transport;
int is_first;
int is_last;
} grpc_channel_element_args;
typedef struct {
grpc_call_stack* call_stack;
const void* server_transport_data;
grpc_call_context_element* context;
grpc_slice path;
gpr_timespec start_time;
grpc_millis deadline;
gpr_arena* arena;
grpc_call_combiner* call_combiner;
} grpc_call_element_args;
typedef struct {
grpc_transport_stream_stats transport_stream_stats;
gpr_timespec latency;
} grpc_call_stats;
struct grpc_call_final_info {
grpc_call_stats stats;
grpc_status_code final_status = GRPC_STATUS_OK;
const char* error_string = nullptr;
};
typedef struct {
void (*start_transport_stream_op_batch)(grpc_call_element* elem,
grpc_transport_stream_op_batch* op);
void (*start_transport_op)(grpc_channel_element* elem, grpc_transport_op* op);
size_t sizeof_call_data;
grpc_error* (*init_call_elem)(grpc_call_element* elem,
const grpc_call_element_args* args);
void (*set_pollset_or_pollset_set)(grpc_call_element* elem,
grpc_polling_entity* pollent);
void (*destroy_call_elem)(grpc_call_element* elem,
const grpc_call_final_info* final_info,
grpc_closure* then_schedule_closure);
size_t sizeof_channel_data;
grpc_error* (*init_channel_elem)(grpc_channel_element* elem,
grpc_channel_element_args* args);
void (*destroy_channel_elem)(grpc_channel_element* elem);
void (*get_channel_info)(grpc_channel_element* elem,
const grpc_channel_info* channel_info);
const char* name;
} grpc_channel_filter;
struct grpc_channel_element {
const grpc_channel_filter* filter;
void* channel_data;
};
struct grpc_call_element {
const grpc_channel_filter* filter;
void* channel_data;
void* call_data;
};
struct grpc_channel_stack {
grpc_stream_refcount refcount;
size_t count;
size_t call_stack_size;
};
struct grpc_call_stack {
grpc_stream_refcount refcount;
size_t count;
};
grpc_channel_element* grpc_channel_stack_element(grpc_channel_stack* stack,
size_t i);
grpc_channel_element* grpc_channel_stack_last_element(
grpc_channel_stack* stack);
grpc_call_element* grpc_call_stack_element(grpc_call_stack* stack, size_t i);
size_t grpc_channel_stack_size(const grpc_channel_filter** filters,
size_t filter_count);
grpc_error* grpc_channel_stack_init(
int initial_refs, grpc_iomgr_cb_func destroy, void* destroy_arg,
const grpc_channel_filter** filters, size_t filter_count,
const grpc_channel_args* args, grpc_transport* optional_transport,
const char* name, grpc_channel_stack* stack);
void grpc_channel_stack_destroy(grpc_channel_stack* stack);
grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack,
int initial_refs, grpc_iomgr_cb_func destroy,
void* destroy_arg,
const grpc_call_element_args* elem_args);
void grpc_call_stack_set_pollset_or_pollset_set(grpc_call_stack* call_stack,
grpc_polling_entity* pollent);
#ifndef NDEBUG
#define GRPC_CALL_STACK_REF(call_stack, reason) \
grpc_stream_ref(&(call_stack)->refcount, reason)
#define GRPC_CALL_STACK_UNREF(call_stack, reason) \
grpc_stream_unref(&(call_stack)->refcount, reason)
#define GRPC_CHANNEL_STACK_REF(channel_stack, reason) \
grpc_stream_ref(&(channel_stack)->refcount, reason)
#define GRPC_CHANNEL_STACK_UNREF(channel_stack, reason) \
grpc_stream_unref(&(channel_stack)->refcount, reason)
#else
#define GRPC_CALL_STACK_REF(call_stack, reason) \
grpc_stream_ref(&(call_stack)->refcount)
#define GRPC_CALL_STACK_UNREF(call_stack, reason) \
grpc_stream_unref(&(call_stack)->refcount)
#define GRPC_CHANNEL_STACK_REF(channel_stack, reason) \
grpc_stream_ref(&(channel_stack)->refcount)
#define GRPC_CHANNEL_STACK_UNREF(channel_stack, reason) \
grpc_stream_unref(&(channel_stack)->refcount)
#endif
void grpc_call_stack_destroy(grpc_call_stack* stack,
const grpc_call_final_info* final_info,
grpc_closure* then_schedule_closure);
void grpc_call_stack_ignore_set_pollset_or_pollset_set(
grpc_call_element* elem, grpc_polling_entity* pollent);
void grpc_call_next_op(grpc_call_element* elem,
grpc_transport_stream_op_batch* op);
void grpc_channel_next_op(grpc_channel_element* elem, grpc_transport_op* op);
void grpc_channel_next_get_info(grpc_channel_element* elem,
const grpc_channel_info* channel_info);
grpc_channel_stack* grpc_channel_stack_from_top_element(
grpc_channel_element* elem);
grpc_call_stack* grpc_call_stack_from_top_element(grpc_call_element* elem);
void grpc_call_log_op(const char* file, int line, gpr_log_severity severity,
grpc_call_element* elem,
grpc_transport_stream_op_batch* op);
extern grpc_core::TraceFlag grpc_trace_channel;
#define GRPC_CALL_LOG_OP(sev, elem, op) \
if (grpc_trace_channel.enabled()) grpc_call_log_op(sev, elem, op)
#endif