diff --git a/BUILD b/BUILD index 934146f57e0..8a827ff54e1 100644 --- a/BUILD +++ b/BUILD @@ -1259,3 +1259,21 @@ objc_bundle_library( name = "gRPCCertificates", resources = ["etc/roots.pem"], ) + +proto_objc_rpc_path = objc_path + "/ProtoRPC" + +objc_library( + name = "proto_objc_rpc", + hdrs = glob([ + proto_objc_rpc_path + "/*.h", + ]), + srcs = glob([ + proto_objc_rpc_path + "/*.m", + ]), + includes = [objc_path], + deps = [ + ":grpc_client", + ":rx_library", + "//external:protobuf_objc", + ], +) diff --git a/Makefile b/Makefile index 195793342c6..e6029f48107 100644 --- a/Makefile +++ b/Makefile @@ -331,6 +331,8 @@ HOST_LDLIBS = $(LDLIBS) # These are automatically computed variables. # There shouldn't be any need to change anything from now on. +HAS_PKG_CONFIG = $(shell command -v pkg-config >/dev/null 2>&1 && echo true || echo false) + ifeq ($(SYSTEM),MINGW32) SHARED_EXT = dll endif @@ -355,6 +357,13 @@ ifeq ($(SYSTEM),Darwin) OPENSSL_REQUIRES_DL = true endif +ifeq ($(HAS_PKG_CONFIG),true) +OPENSSL_ALPN_CHECK_CMD = pkg-config --atleast-version=1.0.2 openssl +ZLIB_CHECK_CMD = pkg-config --exists zlib +PERFTOOLS_CHECK_CMD = pkg-config --exists profiler +PROTOBUF_CHECK_CMD = pkg-config --atleast-version=3.0.0-alpha-3 protobuf +else # HAS_PKG_CONFIG + ifeq ($(SYSTEM),MINGW32) OPENSSL_LIBS = ssl32 eay32 else @@ -365,15 +374,18 @@ OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/ope ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS) PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/perftools.c -lprofiler $(LDFLAGS) PROTOBUF_CHECK_CMD = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS) -PROTOC_CHECK_CMD = which protoc > /dev/null -PROTOC_CHECK_VERSION_CMD = protoc --version | grep -q libprotoc.3 -DTRACE_CHECK_CMD = which dtrace > /dev/null -SYSTEMTAP_HEADERS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/systemtap.c $(LDFLAGS) ifeq ($(OPENSSL_REQUIRES_DL),true) OPENSSL_ALPN_CHECK_CMD += -ldl endif +endif # HAS_PKG_CONFIG + +PROTOC_CHECK_CMD = which protoc > /dev/null +PROTOC_CHECK_VERSION_CMD = protoc --version | grep -q libprotoc.3 +DTRACE_CHECK_CMD = which dtrace > /dev/null +SYSTEMTAP_HEADERS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/systemtap.c $(LDFLAGS) + ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) HAS_SYSTEM_PERFTOOLS = $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_SYSTEM_PERFTOOLS),true) @@ -442,9 +454,33 @@ LDFLAGS += -L$(LIBDIR)/$(CONFIG)/zlib else DEP_MISSING += zlib endif +else +ifeq ($(HAS_PKG_CONFIG),true) +CPPFLAGS += $(shell pkg-config --cflags zlib) +LDFLAGS += $(shell pkg-config --libs-only-L zlib) +endif endif -ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),false) +OPENSSL_PKG_CONFIG = false + +ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true) +ifeq ($(HAS_PKG_CONFIG),true) +OPENSSL_PKG_CONFIG = true +CPPFLAGS := $(shell pkg-config --cflags openssl) $(CPPFLAGS) +LDFLAGS_OPENSSL_PKG_CONFIG = $(shell pkg-config --libs-only-L openssl) +ifeq ($(SYSTEM),Linux) +ifneq ($(LDFLAGS_OPENSSL_PKG_CONFIG),) +LDFLAGS_OPENSSL_PKG_CONFIG += $(shell pkg-config --libs-only-L openssl | sed s/L/Wl,-rpath,/) +endif +endif +LDFLAGS := $(LDFLAGS_OPENSSL_PKG_CONFIG) $(LDFLAGS) +else +LIBS_SECURE = $(OPENSSL_LIBS) +ifeq ($(OPENSSL_REQUIRES_DL),true) +LIBS_SECURE += dl +endif +endif +else ifeq ($(HAS_EMBEDDED_OPENSSL_ALPN),true) OPENSSL_DEP = $(LIBDIR)/$(CONFIG)/openssl/libssl.a OPENSSL_MERGE_LIBS += $(LIBDIR)/$(CONFIG)/openssl/libssl.a $(LIBDIR)/$(CONFIG)/openssl/libcrypto.a @@ -457,16 +493,28 @@ endif else NO_SECURE = true endif -else -LIBS_SECURE = $(OPENSSL_LIBS) -ifeq ($(OPENSSL_REQUIRES_DL),true) -LIBS_SECURE += dl -endif endif +ifeq ($(OPENSSL_PKG_CONFIG),true) +LDLIBS_SECURE += $(shell pkg-config --libs-only-l openssl) +else LDLIBS_SECURE += $(addprefix -l, $(LIBS_SECURE)) +endif + +PROTOBUF_PKG_CONFIG = false -ifeq ($(HAS_SYSTEM_PROTOBUF),false) +ifeq ($(HAS_SYSTEM_PROTOBUF),true) +ifeq ($(HAS_PKG_CONFIG),true) +PROTOBUF_PKG_CONFIG = true +CPPFLAGS := $(shell pkg-config --cflags protobuf) $(CPPFLAGS) +LDFLAGS_PROTOBUF_PKG_CONFIG = $(shell pkg-config --libs-only-L protobuf) +ifeq ($(SYSTEM),Linux) +ifneq ($(LDFLAGS_PROTOBUF_PKG_CONFIG),) +LDFLAGS_PROTOBUF_PKG_CONFIG += $(shell pkg-config --libs-only-L protobuf | sed s/L/Wl,-rpath,/) +endif +endif +endif +else ifeq ($(HAS_EMBEDDED_PROTOBUF),true) PROTOBUF_DEP = $(LIBDIR)/$(CONFIG)/protobuf/libprotobuf.a CPPFLAGS := -Ithird_party/protobuf/src $(CPPFLAGS) @@ -475,15 +523,19 @@ PROTOC = $(BINDIR)/$(CONFIG)/protobuf/protoc else NO_PROTOBUF = true endif -else endif LIBS_PROTOBUF = protobuf LIBS_PROTOC = protoc protobuf -LDLIBS_PROTOBUF += $(addprefix -l, $(LIBS_PROTOBUF)) HOST_LDLIBS_PROTOC += $(addprefix -l, $(LIBS_PROTOC)) +ifeq ($(PROTOBUF_PKG_CONFIG),true) +LDLIBS_PROTOBUF += $(shell pkg-config --libs-only-l protobuf) +else +LDLIBS_PROTOBUF += $(addprefix -l, $(LIBS_PROTOBUF)) +endif + ifeq ($(MAKECMDGOALS),clean) NO_DEPS = true endif diff --git a/src/core/security/security_connector.c b/src/core/security/security_connector.c index 5512bb177a9..34cb0395a24 100644 --- a/src/core/security/security_connector.c +++ b/src/core/security/security_connector.c @@ -196,12 +196,12 @@ typedef struct { static void fake_channel_destroy(grpc_security_connector *sc) { grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc; grpc_credentials_unref(c->request_metadata_creds); - grpc_auth_context_unref(sc->auth_context); + GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector"); gpr_free(sc); } static void fake_server_destroy(grpc_security_connector *sc) { - grpc_auth_context_unref(sc->auth_context); + GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector"); gpr_free(sc); } @@ -242,7 +242,7 @@ static grpc_security_status fake_check_peer(grpc_security_connector *sc, status = GRPC_SECURITY_ERROR; goto end; } - grpc_auth_context_unref(sc->auth_context); + GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector"); sc->auth_context = grpc_auth_context_create(NULL, 1); sc->auth_context->properties[0] = grpc_auth_property_init_from_cstring( GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, @@ -323,7 +323,7 @@ static void ssl_channel_destroy(grpc_security_connector *sc) { if (c->target_name != NULL) gpr_free(c->target_name); if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name); tsi_peer_destruct(&c->peer); - grpc_auth_context_unref(sc->auth_context); + GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector"); gpr_free(sc); } @@ -333,7 +333,7 @@ static void ssl_server_destroy(grpc_security_connector *sc) { if (c->handshaker_factory != NULL) { tsi_ssl_handshaker_factory_destroy(c->handshaker_factory); } - grpc_auth_context_unref(sc->auth_context); + GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector"); gpr_free(sc); } @@ -437,6 +437,9 @@ static grpc_security_status ssl_check_peer(grpc_security_connector *sc, gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name); return GRPC_SECURITY_ERROR; } + if (sc->auth_context != NULL) { + GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector"); + } sc->auth_context = tsi_ssl_peer_to_auth_context(peer); return GRPC_SECURITY_OK; } diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c index 9aba1e7f910..4d56549f9b6 100644 --- a/src/core/security/security_context.c +++ b/src/core/security/security_context.c @@ -89,7 +89,7 @@ grpc_client_security_context *grpc_client_security_context_create(void) { void grpc_client_security_context_destroy(void *ctx) { grpc_client_security_context *c = (grpc_client_security_context *)ctx; grpc_credentials_unref(c->creds); - grpc_auth_context_unref(c->auth_context); + GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "client_security_context"); gpr_free(ctx); } @@ -104,7 +104,7 @@ grpc_server_security_context *grpc_server_security_context_create(void) { void grpc_server_security_context_destroy(void *ctx) { grpc_server_security_context *c = (grpc_server_security_context *)ctx; - grpc_auth_context_unref(c->auth_context); + GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "server_security_context"); gpr_free(ctx); } @@ -120,21 +120,40 @@ grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained, memset(ctx->properties, 0, property_count * sizeof(grpc_auth_property)); ctx->property_count = property_count; gpr_ref_init(&ctx->refcount, 1); - if (chained != NULL) ctx->chained = grpc_auth_context_ref(chained); + if (chained != NULL) ctx->chained = GRPC_AUTH_CONTEXT_REF(chained, "chained"); return ctx; } +#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG +grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx, + const char *file, int line, + const char *reason) { + if (ctx == NULL) return NULL; + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "AUTH_CONTEXT:%p ref %d -> %d %s", ctx, (int)ctx->refcount.count, + (int)ctx->refcount.count + 1, reason); +#else grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx) { if (ctx == NULL) return NULL; +#endif gpr_ref(&ctx->refcount); return ctx; } +#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG +void grpc_auth_context_unref(grpc_auth_context *ctx, const char *file, int line, + const char *reason) { + if (ctx == NULL) return; + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "AUTH_CONTEXT:%p unref %d -> %d %s", ctx, (int)ctx->refcount.count, + (int)ctx->refcount.count - 1, reason); +#else void grpc_auth_context_unref(grpc_auth_context *ctx) { if (ctx == NULL) return; +#endif if (gpr_unref(&ctx->refcount)) { size_t i; - grpc_auth_context_unref(ctx->chained); + GRPC_AUTH_CONTEXT_UNREF(ctx->chained, "chained"); if (ctx->properties != NULL) { for (i = 0; i < ctx->property_count; i++) { grpc_auth_property_reset(&ctx->properties[i]); @@ -223,8 +242,8 @@ grpc_auth_property grpc_auth_property_init(const char *name, const char *value, } void grpc_auth_property_reset(grpc_auth_property *property) { - if (property->name != NULL) gpr_free(property->name); - if (property->value != NULL) gpr_free(property->value); + gpr_free(property->name); + gpr_free(property->value); memset(property, 0, sizeof(grpc_auth_property)); } diff --git a/src/core/security/security_context.h b/src/core/security/security_context.h index d8909cd6f1e..20c4390898a 100644 --- a/src/core/security/security_context.h +++ b/src/core/security/security_context.h @@ -55,9 +55,22 @@ grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained, size_t property_count); /* Refcounting. */ -grpc_auth_context *grpc_auth_context_ref( - grpc_auth_context *ctx); -void grpc_auth_context_unref(grpc_auth_context *ctx); +#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG +#define GRPC_AUTH_CONTEXT_REF(p, r) \ + grpc_auth_context_ref((p), __FILE__, __LINE__, (r)) +#define GRPC_AUTH_CONTEXT_UNREF(p, r) \ + grpc_auth_context_unref((p), __FILE__, __LINE__, (r)) +grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy, + const char *file, int line, + const char *reason); +void grpc_auth_context_unref(grpc_auth_context *policy, const char *file, + int line, const char *reason); +#else +#define GRPC_AUTH_CONTEXT_REF(p, r) grpc_auth_context_ref((p)) +#define GRPC_AUTH_CONTEXT_UNREF(p, r) grpc_auth_context_unref((p)) +grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy); +void grpc_auth_context_unref(grpc_auth_context *policy); +#endif grpc_auth_property grpc_auth_property_init_from_cstring(const char *name, const char *value); diff --git a/src/core/security/server_auth_filter.c b/src/core/security/server_auth_filter.c index b19160b8ed5..b8639287a5d 100644 --- a/src/core/security/server_auth_filter.c +++ b/src/core/security/server_auth_filter.c @@ -82,9 +82,13 @@ static void init_call_elem(grpc_call_element *elem, /* Create a security context for the call and reference the auth context from the channel. */ + if (initial_op->context[GRPC_CONTEXT_SECURITY].value != NULL) { + initial_op->context[GRPC_CONTEXT_SECURITY].destroy( + initial_op->context[GRPC_CONTEXT_SECURITY].value); + } server_ctx = grpc_server_security_context_create(); - server_ctx->auth_context = - grpc_auth_context_ref(chand->security_connector->auth_context); + server_ctx->auth_context = GRPC_AUTH_CONTEXT_REF( + chand->security_connector->auth_context, "server_security_context"); initial_op->context[GRPC_CONTEXT_SECURITY].value = server_ctx; initial_op->context[GRPC_CONTEXT_SECURITY].destroy = grpc_server_security_context_destroy; diff --git a/src/core/transport/chttp2/incoming_metadata.c b/src/core/transport/chttp2/incoming_metadata.c index e81927ab200..a4b7174329b 100644 --- a/src/core/transport/chttp2/incoming_metadata.c +++ b/src/core/transport/chttp2/incoming_metadata.c @@ -47,6 +47,10 @@ void grpc_chttp2_incoming_metadata_buffer_init( void grpc_chttp2_incoming_metadata_buffer_destroy( grpc_chttp2_incoming_metadata_buffer *buffer) { + size_t i; + for (i = 0; i < buffer->count; i++) { + grpc_mdelem_unref(buffer->elems[i].md); + } gpr_free(buffer->elems); } diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 94659a6bdf9..f9389697179 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -50,8 +50,6 @@ #include #include -/* #define REFCOUNTING_DEBUG */ - #define DEFAULT_WINDOW 65535 #define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024) #define MAX_WINDOW 0x7fffffffu @@ -436,6 +434,8 @@ static void destroy_stream(grpc_transport *gt, grpc_stream *gs) { grpc_chttp2_data_parser_destroy(&s->parsing.data_parser); grpc_chttp2_incoming_metadata_buffer_destroy(&s->parsing.incoming_metadata); grpc_chttp2_incoming_metadata_buffer_destroy(&s->global.incoming_metadata); + grpc_chttp2_incoming_metadata_live_op_buffer_end( + &s->global.outstanding_metadata); UNREF_TRANSPORT(t, "stream"); } @@ -859,11 +859,22 @@ static void update_global_window(void *args, gpr_uint32 id, void *stream) { stream_global->outgoing_window += t->parsing.initial_window_update; } +static void read_error_locked(grpc_chttp2_transport *t) { + t->endpoint_reading = 0; + if (!t->writing_active && t->ep) { + grpc_endpoint_destroy(t->ep); + t->ep = NULL; + /* safe as we still have a ref for read */ + UNREF_TRANSPORT(t, "disconnect"); + } +} + /* 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: @@ -871,15 +882,9 @@ static void recv_data(void *tp, gpr_slice *slices, size_t nslices, case GRPC_ENDPOINT_CB_ERROR: lock(t); drop_connection(t); - t->endpoint_reading = 0; - if (!t->writing_active && t->ep) { - grpc_endpoint_destroy(t->ep); - t->ep = NULL; - UNREF_TRANSPORT( - t, "disconnect"); /* safe as we still have a ref for read */ - } + read_error_locked(t); unlock(t); - UNREF_TRANSPORT(t, "recv_data"); + unref = 1; for (i = 0; i < nslices; i++) gpr_slice_unref(slices[i]); break; case GRPC_ENDPOINT_CB_OK: @@ -915,15 +920,22 @@ static void recv_data(void *tp, gpr_slice *slices, size_t nslices, } 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"); + } } static void reading_action(void *pt, int iomgr_success_ignored) { grpc_chttp2_transport *t = pt; + gpr_log(GPR_DEBUG, "reading_action"); grpc_endpoint_notify_on_read(t->ep, recv_data, t); } diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c index e75b449e129..c80d67823f5 100644 --- a/src/core/transport/metadata.c +++ b/src/core/transport/metadata.c @@ -120,7 +120,7 @@ static void unlock(grpc_mdctx *ctx) { if (ctx->refs == 0) { /* uncomment if you're having trouble diagnosing an mdelem leak to make things clearer (slows down destruction a lot, however) */ - /* gc_mdtab(ctx); */ + gc_mdtab(ctx); if (ctx->mdtab_count && ctx->mdtab_count == ctx->mdtab_free) { discard_metadata(ctx); } diff --git a/src/core/transport/transport.c b/src/core/transport/transport.c index 2f85a8557da..39d7b701f2c 100644 --- a/src/core/transport/transport.c +++ b/src/core/transport/transport.c @@ -112,8 +112,8 @@ void grpc_transport_op_add_cancellation(grpc_transport_op *op, grpc_mdstr *message) { if (op->cancel_with_status == GRPC_STATUS_OK) { op->cancel_with_status = status; - op->cancel_message = message; - } else if (message) { + } + if (message) { grpc_mdstr_unref(message); } } diff --git a/src/core/transport/transport.h b/src/core/transport/transport.h index 0a5b31a60a8..a2c41c47af0 100644 --- a/src/core/transport/transport.h +++ b/src/core/transport/transport.h @@ -77,7 +77,6 @@ typedef struct grpc_transport_op { grpc_pollset *bind_pollset; grpc_status_code cancel_with_status; - grpc_mdstr *cancel_message; /* Indexes correspond to grpc_context_index enum values */ grpc_call_context_element *context; diff --git a/src/core/transport/transport_op_string.c b/src/core/transport/transport_op_string.c index 5c4edb006aa..a408b757904 100644 --- a/src/core/transport/transport_op_string.c +++ b/src/core/transport/transport_op_string.c @@ -144,11 +144,6 @@ char *grpc_transport_op_string(grpc_transport_op *op) { first = 0; gpr_asprintf(&tmp, "CANCEL:%d", op->cancel_with_status); gpr_strvec_add(&b, tmp); - if (op->cancel_message) { - gpr_asprintf(&tmp, ";msg='%s'", - grpc_mdstr_as_c_string(op->cancel_message)); - gpr_strvec_add(&b, tmp); - } } out = gpr_strvec_flatten(&b, NULL); diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 39120344156..4da646d7b45 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -33,7 +33,7 @@ #import "ProtoRPC.h" -#import +#import #import #import #import @@ -66,6 +66,8 @@ // A writer that serializes the proto messages to send. id bytesWriter = [[[GRXWriter alloc] initWithWriter:requestsWriter] map:^id(GPBMessage *proto) { + // TODO(jcanizales): Fail with an understandable error message if the requestsWriter isn't + // sending GPBMessages. return [proto data]; }]; if ((self = [super initWithHost:host method:method requestsWriter:bytesWriter])) { diff --git a/src/python/src/grpc/_adapter/_c/types.h b/src/python/src/grpc/_adapter/_c/types.h index e189ae25660..3449f0643f7 100644 --- a/src/python/src/grpc/_adapter/_c/types.h +++ b/src/python/src/grpc/_adapter/_c/types.h @@ -241,10 +241,10 @@ double pygrpc_cast_gpr_timespec_to_double(gpr_timespec timespec); gpr_timespec pygrpc_cast_double_to_gpr_timespec(double seconds); /* Returns true on success, false on failure. */ -int pygrpc_cast_pylist_to_send_metadata( - PyObject *pylist, grpc_metadata **metadata, size_t *count); +int pygrpc_cast_pyseq_to_send_metadata( + PyObject *pyseq, grpc_metadata **metadata, size_t *count); /* Returns a metadata array as a Python object on success, else NULL. */ -PyObject *pygrpc_cast_metadata_array_to_pylist(grpc_metadata_array metadata); +PyObject *pygrpc_cast_metadata_array_to_pyseq(grpc_metadata_array metadata); /* Transliterate from a list of python channel arguments (2-tuples of string and string|integer|None) to a grpc_channel_args object. The strings placed diff --git a/src/python/src/grpc/_adapter/_c/utility.c b/src/python/src/grpc/_adapter/_c/utility.c index a433f26d769..480a720c21f 100644 --- a/src/python/src/grpc/_adapter/_c/utility.c +++ b/src/python/src/grpc/_adapter/_c/utility.c @@ -32,6 +32,7 @@ */ #include +#include #define PY_SSIZE_T_CLEAN #include @@ -118,7 +119,7 @@ PyObject *pygrpc_consume_event(grpc_event event) { tag->request_call_details.method, tag->request_call_details.host, pygrpc_cast_gpr_timespec_to_double(tag->request_call_details.deadline), GRPC_OP_RECV_INITIAL_METADATA, - pygrpc_cast_metadata_array_to_pylist(tag->request_metadata), Py_None, + pygrpc_cast_metadata_array_to_pyseq(tag->request_metadata), Py_None, Py_None, Py_None, Py_None, event.success ? Py_True : Py_False); } else { @@ -172,7 +173,7 @@ int pygrpc_produce_op(PyObject *op, grpc_op *result) { c_op.flags = 0; switch (type) { case GRPC_OP_SEND_INITIAL_METADATA: - if (!pygrpc_cast_pylist_to_send_metadata( + if (!pygrpc_cast_pyseq_to_send_metadata( PyTuple_GetItem(op, INITIAL_METADATA_INDEX), &c_op.data.send_initial_metadata.metadata, &c_op.data.send_initial_metadata.count)) { @@ -190,7 +191,7 @@ int pygrpc_produce_op(PyObject *op, grpc_op *result) { /* Don't need to fill in any other fields. */ break; case GRPC_OP_SEND_STATUS_FROM_SERVER: - if (!pygrpc_cast_pylist_to_send_metadata( + if (!pygrpc_cast_pyseq_to_send_metadata( PyTuple_GetItem(op, TRAILING_METADATA_INDEX), &c_op.data.send_status_from_server.trailing_metadata, &c_op.data.send_status_from_server.trailing_metadata_count)) { @@ -247,8 +248,16 @@ int pygrpc_produce_op(PyObject *op, grpc_op *result) { } void pygrpc_discard_op(grpc_op op) { + size_t i; switch(op.op) { case GRPC_OP_SEND_INITIAL_METADATA: + /* Whenever we produce send-metadata, we allocate new strings (to handle + arbitrary sequence input as opposed to just lists or just tuples). We + thus must free those elements. */ + for (i = 0; i < op.data.send_initial_metadata.count; ++i) { + gpr_free((void *)op.data.send_initial_metadata.metadata[i].key); + gpr_free((void *)op.data.send_initial_metadata.metadata[i].value); + } gpr_free(op.data.send_initial_metadata.metadata); break; case GRPC_OP_SEND_MESSAGE: @@ -258,6 +267,16 @@ void pygrpc_discard_op(grpc_op op) { /* Don't need to free any fields. */ break; case GRPC_OP_SEND_STATUS_FROM_SERVER: + /* Whenever we produce send-metadata, we allocate new strings (to handle + arbitrary sequence input as opposed to just lists or just tuples). We + thus must free those elements. */ + for (i = 0; i < op.data.send_status_from_server.trailing_metadata_count; + ++i) { + gpr_free( + (void *)op.data.send_status_from_server.trailing_metadata[i].key); + gpr_free( + (void *)op.data.send_status_from_server.trailing_metadata[i].value); + } gpr_free(op.data.send_status_from_server.trailing_metadata); gpr_free((char *)op.data.send_status_from_server.status_details); break; @@ -419,31 +438,41 @@ void pygrpc_discard_channel_args(grpc_channel_args args) { gpr_free(args.args); } -int pygrpc_cast_pylist_to_send_metadata( - PyObject *pylist, grpc_metadata **metadata, size_t *count) { +int pygrpc_cast_pyseq_to_send_metadata( + PyObject *pyseq, grpc_metadata **metadata, size_t *count) { size_t i; Py_ssize_t value_length; - *count = PyList_Size(pylist); + char *key; + char *value; + if (!PySequence_Check(pyseq)) { + return 0; + } + *count = PySequence_Size(pyseq); *metadata = gpr_malloc(sizeof(grpc_metadata) * *count); for (i = 0; i < *count; ++i) { - if (!PyArg_ParseTuple( - PyList_GetItem(pylist, i), "ss#", - &(*metadata)[i].key, &(*metadata)[i].value, &value_length)) { + PyObject *item = PySequence_GetItem(pyseq, i); + if (!PyArg_ParseTuple(item, "ss#", &key, &value, &value_length)) { + Py_DECREF(item); gpr_free(*metadata); *count = 0; *metadata = NULL; return 0; + } else { + (*metadata)[i].key = gpr_strdup(key); + (*metadata)[i].value = gpr_malloc(value_length); + memcpy((void *)(*metadata)[i].value, value, value_length); + Py_DECREF(item); } (*metadata)[i].value_length = value_length; } return 1; } -PyObject *pygrpc_cast_metadata_array_to_pylist(grpc_metadata_array metadata) { - PyObject *result = PyList_New(metadata.count); +PyObject *pygrpc_cast_metadata_array_to_pyseq(grpc_metadata_array metadata) { + PyObject *result = PyTuple_New(metadata.count); size_t i; for (i = 0; i < metadata.count; ++i) { - PyList_SetItem( + PyTuple_SetItem( result, i, Py_BuildValue( "ss#", metadata.metadata[i].key, metadata.metadata[i].value, (Py_ssize_t)metadata.metadata[i].value_length)); diff --git a/src/python/src/grpc/_adapter/_intermediary_low.py b/src/python/src/grpc/_adapter/_intermediary_low.py index 6b96aef1d34..3c7f0a26197 100644 --- a/src/python/src/grpc/_adapter/_intermediary_low.py +++ b/src/python/src/grpc/_adapter/_intermediary_low.py @@ -144,10 +144,11 @@ class Call(object): self._metadata.append((key, value)) def premetadata(self): - return self._internal.start_batch([ + result = self._internal.start_batch([ _types.OpArgs.send_initial_metadata(self._metadata) ], _IGNORE_ME_TAG) self._metadata = [] + return result def read(self, tag): return self._internal.start_batch([ diff --git a/src/python/src/grpc/_adapter/_intermediary_low_test.py b/src/python/src/grpc/_adapter/_intermediary_low_test.py index 1a9b0c69f3c..27a5b82e9c4 100644 --- a/src/python/src/grpc/_adapter/_intermediary_low_test.py +++ b/src/python/src/grpc/_adapter/_intermediary_low_test.py @@ -282,6 +282,9 @@ class EchoTest(unittest.TestCase): self.assertIn(server_trailing_binary_metadata_key, metadata) self.assertEqual(server_trailing_binary_metadata_value, metadata[server_trailing_binary_metadata_key]) + self.assertSetEqual(set(key for key, _ in finish_accepted.metadata), + set((server_trailing_metadata_key, + server_trailing_binary_metadata_key,))) server_timeout_none_event = self.server_completion_queue.get(0) self.assertIsNone(server_timeout_none_event) diff --git a/templates/BUILD.template b/templates/BUILD.template index 4d2bf7db283..dffdc1dddde 100644 --- a/templates/BUILD.template +++ b/templates/BUILD.template @@ -205,3 +205,21 @@ objc_bundle_library( name = "gRPCCertificates", resources = ["etc/roots.pem"], ) + +proto_objc_rpc_path = objc_path + "/ProtoRPC" + +objc_library( + name = "proto_objc_rpc", + hdrs = glob([ + proto_objc_rpc_path + "/*.h", + ]), + srcs = glob([ + proto_objc_rpc_path + "/*.m", + ]), + includes = [objc_path], + deps = [ + ":grpc_client", + ":rx_library", + "//external:protobuf_objc", + ], +) diff --git a/templates/Makefile.template b/templates/Makefile.template index ebe207f1918..3b04d7d0415 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -345,6 +345,8 @@ HOST_LDLIBS = $(LDLIBS) # These are automatically computed variables. # There shouldn't be any need to change anything from now on. +HAS_PKG_CONFIG = $(shell command -v pkg-config >/dev/null 2>&1 && echo true || echo false) + ifeq ($(SYSTEM),MINGW32) SHARED_EXT = dll endif @@ -369,6 +371,13 @@ ifeq ($(SYSTEM),Darwin) OPENSSL_REQUIRES_DL = true endif +ifeq ($(HAS_PKG_CONFIG),true) +OPENSSL_ALPN_CHECK_CMD = pkg-config --atleast-version=1.0.2 openssl +ZLIB_CHECK_CMD = pkg-config --exists zlib +PERFTOOLS_CHECK_CMD = pkg-config --exists profiler +PROTOBUF_CHECK_CMD = pkg-config --atleast-version=3.0.0-alpha-3 protobuf +else # HAS_PKG_CONFIG + ifeq ($(SYSTEM),MINGW32) OPENSSL_LIBS = ssl32 eay32 else @@ -379,15 +388,18 @@ OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/ope ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS) PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/perftools.c -lprofiler $(LDFLAGS) PROTOBUF_CHECK_CMD = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS) -PROTOC_CHECK_CMD = which protoc > /dev/null -PROTOC_CHECK_VERSION_CMD = protoc --version | grep -q libprotoc.3 -DTRACE_CHECK_CMD = which dtrace > /dev/null -SYSTEMTAP_HEADERS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/systemtap.c $(LDFLAGS) ifeq ($(OPENSSL_REQUIRES_DL),true) OPENSSL_ALPN_CHECK_CMD += -ldl endif +endif # HAS_PKG_CONFIG + +PROTOC_CHECK_CMD = which protoc > /dev/null +PROTOC_CHECK_VERSION_CMD = protoc --version | grep -q libprotoc.3 +DTRACE_CHECK_CMD = which dtrace > /dev/null +SYSTEMTAP_HEADERS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/systemtap.c $(LDFLAGS) + ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) HAS_SYSTEM_PERFTOOLS = $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_SYSTEM_PERFTOOLS),true) @@ -456,9 +468,33 @@ LDFLAGS += -L$(LIBDIR)/$(CONFIG)/zlib else DEP_MISSING += zlib endif +else +ifeq ($(HAS_PKG_CONFIG),true) +CPPFLAGS += $(shell pkg-config --cflags zlib) +LDFLAGS += $(shell pkg-config --libs-only-L zlib) +endif endif -ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),false) +OPENSSL_PKG_CONFIG = false + +ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true) +ifeq ($(HAS_PKG_CONFIG),true) +OPENSSL_PKG_CONFIG = true +CPPFLAGS := $(shell pkg-config --cflags openssl) $(CPPFLAGS) +LDFLAGS_OPENSSL_PKG_CONFIG = $(shell pkg-config --libs-only-L openssl) +ifeq ($(SYSTEM),Linux) +ifneq ($(LDFLAGS_OPENSSL_PKG_CONFIG),) +LDFLAGS_OPENSSL_PKG_CONFIG += $(shell pkg-config --libs-only-L openssl | sed s/L/Wl,-rpath,/) +endif +endif +LDFLAGS := $(LDFLAGS_OPENSSL_PKG_CONFIG) $(LDFLAGS) +else +LIBS_SECURE = $(OPENSSL_LIBS) +ifeq ($(OPENSSL_REQUIRES_DL),true) +LIBS_SECURE += dl +endif +endif +else ifeq ($(HAS_EMBEDDED_OPENSSL_ALPN),true) OPENSSL_DEP = $(LIBDIR)/$(CONFIG)/openssl/libssl.a OPENSSL_MERGE_LIBS += $(LIBDIR)/$(CONFIG)/openssl/libssl.a $(LIBDIR)/$(CONFIG)/openssl/libcrypto.a @@ -471,16 +507,28 @@ endif else NO_SECURE = true endif -else -LIBS_SECURE = $(OPENSSL_LIBS) -ifeq ($(OPENSSL_REQUIRES_DL),true) -LIBS_SECURE += dl -endif endif +ifeq ($(OPENSSL_PKG_CONFIG),true) +LDLIBS_SECURE += $(shell pkg-config --libs-only-l openssl) +else LDLIBS_SECURE += $(addprefix -l, $(LIBS_SECURE)) +endif + +PROTOBUF_PKG_CONFIG = false -ifeq ($(HAS_SYSTEM_PROTOBUF),false) +ifeq ($(HAS_SYSTEM_PROTOBUF),true) +ifeq ($(HAS_PKG_CONFIG),true) +PROTOBUF_PKG_CONFIG = true +CPPFLAGS := $(shell pkg-config --cflags protobuf) $(CPPFLAGS) +LDFLAGS_PROTOBUF_PKG_CONFIG = $(shell pkg-config --libs-only-L protobuf) +ifeq ($(SYSTEM),Linux) +ifneq ($(LDFLAGS_PROTOBUF_PKG_CONFIG),) +LDFLAGS_PROTOBUF_PKG_CONFIG += $(shell pkg-config --libs-only-L protobuf | sed s/L/Wl,-rpath,/) +endif +endif +endif +else ifeq ($(HAS_EMBEDDED_PROTOBUF),true) PROTOBUF_DEP = $(LIBDIR)/$(CONFIG)/protobuf/libprotobuf.a CPPFLAGS := -Ithird_party/protobuf/src $(CPPFLAGS) @@ -489,15 +537,19 @@ PROTOC = $(BINDIR)/$(CONFIG)/protobuf/protoc else NO_PROTOBUF = true endif -else endif LIBS_PROTOBUF = protobuf LIBS_PROTOC = protoc protobuf -LDLIBS_PROTOBUF += $(addprefix -l, $(LIBS_PROTOBUF)) HOST_LDLIBS_PROTOC += $(addprefix -l, $(LIBS_PROTOC)) +ifeq ($(PROTOBUF_PKG_CONFIG),true) +LDLIBS_PROTOBUF += $(shell pkg-config --libs-only-l protobuf) +else +LDLIBS_PROTOBUF += $(addprefix -l, $(LIBS_PROTOBUF)) +endif + ifeq ($(MAKECMDGOALS),clean) NO_DEPS = true endif diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c index e9adcf34c79..5b836fefc38 100644 --- a/test/core/bad_client/bad_client.c +++ b/test/core/bad_client/bad_client.c @@ -41,6 +41,7 @@ #include "src/core/support/string.h" #include "src/core/transport/chttp2_transport.h" +#include #include #include @@ -89,6 +90,8 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, /* Add a debug log */ gpr_log(GPR_INFO, "TEST: %s", hex); + gpr_free(hex); + /* Init grpc */ grpc_init(); diff --git a/test/core/end2end/tests/request_with_flags.c b/test/core/end2end/tests/request_with_flags.c index fac06023282..fb55a6512f6 100644 --- a/test/core/end2end/tests/request_with_flags.c +++ b/test/core/end2end/tests/request_with_flags.c @@ -105,7 +105,7 @@ static void test_invoke_request_with_flags( gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world"); grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - gpr_timespec deadline = five_seconds_time(); + gpr_timespec deadline = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100); grpc_end2end_test_fixture f = begin_test(config, "test_invoke_request_with_flags", NULL, NULL); cq_verifier *cqv = cq_verifier_create(f.cq); @@ -156,6 +156,11 @@ static void test_invoke_request_with_flags( expectation = call_start_batch_expected_result; GPR_ASSERT(expectation == grpc_call_start_batch(c, ops, op - ops, tag(1))); + if (expectation == GRPC_CALL_OK) { + cq_expect_completion(cqv, tag(1), 1); + cq_verify(cqv); + } + gpr_free(details); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); diff --git a/test/core/security/auth_context_test.c b/test/core/security/auth_context_test.c index 2fb0c01f6f2..2b12551a069 100644 --- a/test/core/security/auth_context_test.c +++ b/test/core/security/auth_context_test.c @@ -52,7 +52,7 @@ static void test_empty_context(void) { GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); it = grpc_auth_context_find_properties_by_name(ctx, "foo"); GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); - grpc_auth_context_unref(ctx); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); } static void test_simple_context(void) { @@ -86,7 +86,7 @@ static void test_simple_context(void) { GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &ctx->properties[1]); GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); - grpc_auth_context_unref(ctx); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); } static void test_chained_context(void) { @@ -96,7 +96,7 @@ static void test_chained_context(void) { size_t i; gpr_log(GPR_INFO, "test_chained_context"); - grpc_auth_context_unref(chained); + GRPC_AUTH_CONTEXT_UNREF(chained, "chained"); chained->properties[0] = grpc_auth_property_init_from_cstring("name", "padapo"); chained->properties[1] = grpc_auth_property_init_from_cstring("foo", "baz"); @@ -129,7 +129,7 @@ static void test_chained_context(void) { GPR_ASSERT(grpc_auth_property_iterator_next(&it) == &chained->properties[0]); GPR_ASSERT(grpc_auth_property_iterator_next(&it) == NULL); - grpc_auth_context_unref(ctx); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); } diff --git a/test/core/security/security_connector_test.c b/test/core/security/security_connector_test.c index 4ad8beb7270..b37fd7213df 100644 --- a/test/core/security/security_connector_test.c +++ b/test/core/security/security_connector_test.c @@ -73,7 +73,7 @@ static void test_unauthenticated_ssl_peer(void) { GPR_ASSERT(check_transport_security_type(ctx)); tsi_peer_destruct(&peer); - grpc_auth_context_unref(ctx); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); } static int check_identity(const grpc_auth_context *ctx, @@ -145,7 +145,7 @@ static void test_cn_only_ssl_peer_to_auth_context(void) { GPR_ASSERT(check_x509_cn(ctx, expected_cn)); tsi_peer_destruct(&peer); - grpc_auth_context_unref(ctx); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); } static void test_cn_and_one_san_ssl_peer_to_auth_context(void) { @@ -171,7 +171,7 @@ static void test_cn_and_one_san_ssl_peer_to_auth_context(void) { GPR_ASSERT(check_x509_cn(ctx, expected_cn)); tsi_peer_destruct(&peer); - grpc_auth_context_unref(ctx); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); } static void test_cn_and_multiple_sans_ssl_peer_to_auth_context(void) { @@ -202,7 +202,7 @@ static void test_cn_and_multiple_sans_ssl_peer_to_auth_context(void) { GPR_ASSERT(check_x509_cn(ctx, expected_cn)); tsi_peer_destruct(&peer); - grpc_auth_context_unref(ctx); + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); } static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context( @@ -238,8 +238,7 @@ static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context( GPR_ASSERT(check_x509_cn(ctx, expected_cn)); tsi_peer_destruct(&peer); - grpc_auth_context_unref(ctx); - + GRPC_AUTH_CONTEXT_UNREF(ctx, "test"); } int main(int argc, char **argv) {