mirror of https://github.com/grpc/grpc.git
commit
dddf207932
211 changed files with 6261 additions and 1572 deletions
@ -0,0 +1,15 @@ |
||||
/.bundle/ |
||||
/.yardoc |
||||
/Gemfile.lock |
||||
/_yardoc/ |
||||
/coverage/ |
||||
/doc/ |
||||
/pkg/ |
||||
/spec/reports/ |
||||
/tmp/ |
||||
*.bundle |
||||
*.so |
||||
*.o |
||||
*.a |
||||
mkmf.log |
||||
vendor |
@ -0,0 +1,4 @@ |
||||
source 'https://rubygems.org/' |
||||
|
||||
gem 'grpc', '~> 1.0' |
||||
gem 'googleauth', '>= 0.5.1', '< 0.7' |
@ -0,0 +1,183 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
#ifdef GRPC_CFSTREAM |
||||
#import <CoreFoundation/CoreFoundation.h> |
||||
#import "src/core/lib/iomgr/cfstream_handle.h" |
||||
|
||||
#include <grpc/support/atm.h> |
||||
#include <grpc/support/sync.h> |
||||
|
||||
#include "src/core/lib/debug/trace.h" |
||||
#include "src/core/lib/iomgr/closure.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
|
||||
extern grpc_core::TraceFlag grpc_tcp_trace; |
||||
|
||||
void* CFStreamHandle::Retain(void* info) { |
||||
CFStreamHandle* handle = static_cast<CFStreamHandle*>(info); |
||||
CFSTREAM_HANDLE_REF(handle, "retain"); |
||||
return info; |
||||
} |
||||
|
||||
void CFStreamHandle::Release(void* info) { |
||||
CFStreamHandle* handle = static_cast<CFStreamHandle*>(info); |
||||
CFSTREAM_HANDLE_UNREF(handle, "release"); |
||||
} |
||||
|
||||
CFStreamHandle* CFStreamHandle::CreateStreamHandle( |
||||
CFReadStreamRef read_stream, CFWriteStreamRef write_stream) { |
||||
return new CFStreamHandle(read_stream, write_stream); |
||||
} |
||||
|
||||
void CFStreamHandle::ReadCallback(CFReadStreamRef stream, |
||||
CFStreamEventType type, |
||||
void* client_callback_info) { |
||||
CFStreamHandle* handle = static_cast<CFStreamHandle*>(client_callback_info); |
||||
CFSTREAM_HANDLE_REF(handle, "read callback"); |
||||
dispatch_async( |
||||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ |
||||
grpc_core::ExecCtx exec_ctx; |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, "CFStream ReadCallback (%p, %p, %lu, %p)", handle, |
||||
stream, type, client_callback_info); |
||||
} |
||||
switch (type) { |
||||
case kCFStreamEventOpenCompleted: |
||||
handle->open_event_.SetReady(); |
||||
break; |
||||
case kCFStreamEventHasBytesAvailable: |
||||
case kCFStreamEventEndEncountered: |
||||
handle->read_event_.SetReady(); |
||||
break; |
||||
case kCFStreamEventErrorOccurred: |
||||
handle->open_event_.SetReady(); |
||||
handle->read_event_.SetReady(); |
||||
break; |
||||
default: |
||||
GPR_UNREACHABLE_CODE(return ); |
||||
} |
||||
CFSTREAM_HANDLE_UNREF(handle, "read callback"); |
||||
}); |
||||
} |
||||
void CFStreamHandle::WriteCallback(CFWriteStreamRef stream, |
||||
CFStreamEventType type, |
||||
void* clientCallBackInfo) { |
||||
CFStreamHandle* handle = static_cast<CFStreamHandle*>(clientCallBackInfo); |
||||
CFSTREAM_HANDLE_REF(handle, "write callback"); |
||||
dispatch_async( |
||||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ |
||||
grpc_core::ExecCtx exec_ctx; |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, "CFStream WriteCallback (%p, %p, %lu, %p)", handle, |
||||
stream, type, clientCallBackInfo); |
||||
} |
||||
switch (type) { |
||||
case kCFStreamEventOpenCompleted: |
||||
handle->open_event_.SetReady(); |
||||
break; |
||||
case kCFStreamEventCanAcceptBytes: |
||||
case kCFStreamEventEndEncountered: |
||||
handle->write_event_.SetReady(); |
||||
break; |
||||
case kCFStreamEventErrorOccurred: |
||||
handle->open_event_.SetReady(); |
||||
handle->write_event_.SetReady(); |
||||
break; |
||||
default: |
||||
GPR_UNREACHABLE_CODE(return ); |
||||
} |
||||
CFSTREAM_HANDLE_UNREF(handle, "write callback"); |
||||
}); |
||||
} |
||||
|
||||
CFStreamHandle::CFStreamHandle(CFReadStreamRef read_stream, |
||||
CFWriteStreamRef write_stream) { |
||||
gpr_ref_init(&refcount_, 1); |
||||
open_event_.InitEvent(); |
||||
read_event_.InitEvent(); |
||||
write_event_.InitEvent(); |
||||
CFStreamClientContext ctx = {0, static_cast<void*>(this), nil, nil, nil}; |
||||
CFReadStreamSetClient( |
||||
read_stream, |
||||
kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | |
||||
kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, |
||||
CFStreamHandle::ReadCallback, &ctx); |
||||
CFWriteStreamSetClient( |
||||
write_stream, |
||||
kCFStreamEventOpenCompleted | kCFStreamEventCanAcceptBytes | |
||||
kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, |
||||
CFStreamHandle::WriteCallback, &ctx); |
||||
CFReadStreamScheduleWithRunLoop(read_stream, CFRunLoopGetMain(), |
||||
kCFRunLoopCommonModes); |
||||
CFWriteStreamScheduleWithRunLoop(write_stream, CFRunLoopGetMain(), |
||||
kCFRunLoopCommonModes); |
||||
} |
||||
|
||||
CFStreamHandle::~CFStreamHandle() { |
||||
open_event_.DestroyEvent(); |
||||
read_event_.DestroyEvent(); |
||||
write_event_.DestroyEvent(); |
||||
} |
||||
|
||||
void CFStreamHandle::NotifyOnOpen(grpc_closure* closure) { |
||||
open_event_.NotifyOn(closure); |
||||
} |
||||
|
||||
void CFStreamHandle::NotifyOnRead(grpc_closure* closure) { |
||||
read_event_.NotifyOn(closure); |
||||
} |
||||
|
||||
void CFStreamHandle::NotifyOnWrite(grpc_closure* closure) { |
||||
write_event_.NotifyOn(closure); |
||||
} |
||||
|
||||
void CFStreamHandle::Shutdown(grpc_error* error) { |
||||
open_event_.SetShutdown(GRPC_ERROR_REF(error)); |
||||
read_event_.SetShutdown(GRPC_ERROR_REF(error)); |
||||
write_event_.SetShutdown(GRPC_ERROR_REF(error)); |
||||
GRPC_ERROR_UNREF(error); |
||||
} |
||||
|
||||
void CFStreamHandle::Ref(const char* file, int line, const char* reason) { |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_atm val = gpr_atm_no_barrier_load(&refcount_.count); |
||||
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, |
||||
"CFStream Handle ref %p : %s %" PRIdPTR " -> %" PRIdPTR, this, |
||||
reason, val, val + 1); |
||||
} |
||||
gpr_ref(&refcount_); |
||||
} |
||||
|
||||
void CFStreamHandle::Unref(const char* file, int line, const char* reason) { |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_atm val = gpr_atm_no_barrier_load(&refcount_.count); |
||||
gpr_log(GPR_ERROR, |
||||
"CFStream Handle unref %p : %s %" PRIdPTR " -> %" PRIdPTR, this, |
||||
reason, val, val - 1); |
||||
} |
||||
if (gpr_unref(&refcount_)) { |
||||
delete this; |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,80 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
/* The CFStream handle acts as an event synchronization entity for
|
||||
* read/write/open/error/eos events happening on CFStream streams. */ |
||||
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_CFSTREAM_HANDLE_H |
||||
#define GRPC_CORE_LIB_IOMGR_CFSTREAM_HANDLE_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
#ifdef GRPC_CFSTREAM |
||||
#import <CoreFoundation/CoreFoundation.h> |
||||
|
||||
#include "src/core/lib/iomgr/closure.h" |
||||
#include "src/core/lib/iomgr/lockfree_event.h" |
||||
|
||||
class CFStreamHandle final { |
||||
public: |
||||
static CFStreamHandle* CreateStreamHandle(CFReadStreamRef read_stream, |
||||
CFWriteStreamRef write_stream); |
||||
~CFStreamHandle(); |
||||
CFStreamHandle(const CFReadStreamRef& ref) = delete; |
||||
CFStreamHandle(CFReadStreamRef&& ref) = delete; |
||||
CFStreamHandle& operator=(const CFStreamHandle& rhs) = delete; |
||||
|
||||
void NotifyOnOpen(grpc_closure* closure); |
||||
void NotifyOnRead(grpc_closure* closure); |
||||
void NotifyOnWrite(grpc_closure* closure); |
||||
void Shutdown(grpc_error* error); |
||||
|
||||
void Ref(const char* file = "", int line = 0, const char* reason = nullptr); |
||||
void Unref(const char* file = "", int line = 0, const char* reason = nullptr); |
||||
|
||||
private: |
||||
CFStreamHandle(CFReadStreamRef read_stream, CFWriteStreamRef write_stream); |
||||
static void ReadCallback(CFReadStreamRef stream, CFStreamEventType type, |
||||
void* client_callback_info); |
||||
static void WriteCallback(CFWriteStreamRef stream, CFStreamEventType type, |
||||
void* client_callback_info); |
||||
static void* Retain(void* info); |
||||
static void Release(void* info); |
||||
|
||||
grpc_core::LockfreeEvent open_event_; |
||||
grpc_core::LockfreeEvent read_event_; |
||||
grpc_core::LockfreeEvent write_event_; |
||||
|
||||
gpr_refcount refcount_; |
||||
}; |
||||
|
||||
#ifdef DEBUG |
||||
#define CFSTREAM_HANDLE_REF(handle, reason) \ |
||||
(handle)->Ref(__FILE__, __LINE__, (reason)) |
||||
#define CFSTREAM_HANDLE_UNREF(handle, reason) \ |
||||
(handle)->Unref(__FILE__, __LINE__, (reason)) |
||||
#else |
||||
#define CFSTREAM_HANDLE_REF(handle, reason) (handle)->Ref() |
||||
#define CFSTREAM_HANDLE_UNREF(handle, reason) (handle)->Unref() |
||||
#endif |
||||
|
||||
#endif |
||||
|
||||
#endif /* GRPC_CORE_LIB_IOMGR_CFSTREAM_HANDLE_H */ |
@ -0,0 +1,372 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
#ifdef GRPC_CFSTREAM_ENDPOINT |
||||
|
||||
#import <CoreFoundation/CoreFoundation.h> |
||||
#import "src/core/lib/iomgr/endpoint_cfstream.h" |
||||
|
||||
#include <grpc/slice_buffer.h> |
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/lib/gpr/string.h" |
||||
#include "src/core/lib/iomgr/cfstream_handle.h" |
||||
#include "src/core/lib/iomgr/closure.h" |
||||
#include "src/core/lib/iomgr/endpoint.h" |
||||
#include "src/core/lib/iomgr/error_cfstream.h" |
||||
#include "src/core/lib/slice/slice_internal.h" |
||||
#include "src/core/lib/slice/slice_string_helpers.h" |
||||
|
||||
extern grpc_core::TraceFlag grpc_tcp_trace; |
||||
|
||||
typedef struct { |
||||
grpc_endpoint base; |
||||
gpr_refcount refcount; |
||||
|
||||
CFReadStreamRef read_stream; |
||||
CFWriteStreamRef write_stream; |
||||
CFStreamHandle* stream_sync; |
||||
|
||||
grpc_closure* read_cb; |
||||
grpc_closure* write_cb; |
||||
grpc_slice_buffer* read_slices; |
||||
grpc_slice_buffer* write_slices; |
||||
|
||||
grpc_closure read_action; |
||||
grpc_closure write_action; |
||||
|
||||
char* peer_string; |
||||
grpc_resource_user* resource_user; |
||||
grpc_resource_user_slice_allocator slice_allocator; |
||||
} CFStreamEndpoint; |
||||
|
||||
static void CFStreamFree(CFStreamEndpoint* ep) { |
||||
grpc_resource_user_unref(ep->resource_user); |
||||
CFRelease(ep->read_stream); |
||||
CFRelease(ep->write_stream); |
||||
CFSTREAM_HANDLE_UNREF(ep->stream_sync, "free"); |
||||
gpr_free(ep->peer_string); |
||||
gpr_free(ep); |
||||
} |
||||
|
||||
#ifndef NDEBUG |
||||
#define EP_REF(ep, reason) CFStreamRef((ep), (reason), __FILE__, __LINE__) |
||||
#define EP_UNREF(ep, reason) CFStreamUnref((ep), (reason), __FILE__, __LINE__) |
||||
static void CFStreamUnref(CFStreamEndpoint* ep, const char* reason, |
||||
const char* file, int line) { |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_atm val = gpr_atm_no_barrier_load(&ep->refcount.count); |
||||
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, |
||||
"CFStream endpoint unref %p : %s %" PRIdPTR " -> %" PRIdPTR, ep, |
||||
reason, val, val - 1); |
||||
} |
||||
if (gpr_unref(&ep->refcount)) { |
||||
CFStreamFree(ep); |
||||
} |
||||
} |
||||
static void CFStreamRef(CFStreamEndpoint* ep, const char* reason, |
||||
const char* file, int line) { |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_atm val = gpr_atm_no_barrier_load(&ep->refcount.count); |
||||
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, |
||||
"CFStream endpoint ref %p : %s %" PRIdPTR " -> %" PRIdPTR, ep, |
||||
reason, val, val + 1); |
||||
} |
||||
gpr_ref(&ep->refcount); |
||||
} |
||||
#else |
||||
#define EP_REF(ep, reason) CFStreamRef((ep)) |
||||
#define EP_UNREF(ep, reason) CFStreamUnref((ep)) |
||||
static void CFStreamUnref(CFStreamEndpoint* ep) { |
||||
if (gpr_unref(&ep->refcount)) { |
||||
CFStreamFree(ep); |
||||
} |
||||
} |
||||
static void CFStreamRef(CFStreamEndpoint* ep) { gpr_ref(&ep->refcount); } |
||||
#endif |
||||
|
||||
static grpc_error* CFStreamAnnotateError(grpc_error* src_error, |
||||
CFStreamEndpoint* ep) { |
||||
return grpc_error_set_str( |
||||
grpc_error_set_int(src_error, GRPC_ERROR_INT_GRPC_STATUS, |
||||
GRPC_STATUS_UNAVAILABLE), |
||||
GRPC_ERROR_STR_TARGET_ADDRESS, |
||||
grpc_slice_from_copied_string(ep->peer_string)); |
||||
} |
||||
|
||||
static void CallReadCb(CFStreamEndpoint* ep, grpc_error* error) { |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, "CFStream endpoint:%p call_read_cb %p %p:%p", ep, |
||||
ep->read_cb, ep->read_cb->cb, ep->read_cb->cb_arg); |
||||
size_t i; |
||||
const char* str = grpc_error_string(error); |
||||
gpr_log(GPR_DEBUG, "read: error=%s", str); |
||||
|
||||
for (i = 0; i < ep->read_slices->count; i++) { |
||||
char* dump = grpc_dump_slice(ep->read_slices->slices[i], |
||||
GPR_DUMP_HEX | GPR_DUMP_ASCII); |
||||
gpr_log(GPR_DEBUG, "READ %p (peer=%s): %s", ep, ep->peer_string, dump); |
||||
gpr_free(dump); |
||||
} |
||||
} |
||||
grpc_closure* cb = ep->read_cb; |
||||
ep->read_cb = nullptr; |
||||
ep->read_slices = nullptr; |
||||
GRPC_CLOSURE_SCHED(cb, error); |
||||
} |
||||
|
||||
static void CallWriteCb(CFStreamEndpoint* ep, grpc_error* error) { |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, "CFStream endpoint:%p call_write_cb %p %p:%p", ep, |
||||
ep->write_cb, ep->write_cb->cb, ep->write_cb->cb_arg); |
||||
const char* str = grpc_error_string(error); |
||||
gpr_log(GPR_DEBUG, "write: error=%s", str); |
||||
} |
||||
grpc_closure* cb = ep->write_cb; |
||||
ep->write_cb = nullptr; |
||||
ep->write_slices = nullptr; |
||||
GRPC_CLOSURE_SCHED(cb, error); |
||||
} |
||||
|
||||
static void ReadAction(void* arg, grpc_error* error) { |
||||
CFStreamEndpoint* ep = static_cast<CFStreamEndpoint*>(arg); |
||||
GPR_ASSERT(ep->read_cb != nullptr); |
||||
if (error) { |
||||
grpc_slice_buffer_reset_and_unref_internal(ep->read_slices); |
||||
CallReadCb(ep, GRPC_ERROR_REF(error)); |
||||
EP_UNREF(ep, "read"); |
||||
return; |
||||
} |
||||
|
||||
GPR_ASSERT(ep->read_slices->count == 1); |
||||
grpc_slice slice = ep->read_slices->slices[0]; |
||||
size_t len = GRPC_SLICE_LENGTH(slice); |
||||
CFIndex read_size = |
||||
CFReadStreamRead(ep->read_stream, GRPC_SLICE_START_PTR(slice), len); |
||||
if (read_size == -1) { |
||||
grpc_slice_buffer_reset_and_unref_internal(ep->read_slices); |
||||
CFErrorRef stream_error = CFReadStreamCopyError(ep->read_stream); |
||||
if (stream_error != nullptr) { |
||||
error = CFStreamAnnotateError( |
||||
GRPC_ERROR_CREATE_FROM_CFERROR(stream_error, "Read error"), ep); |
||||
CFRelease(stream_error); |
||||
} else { |
||||
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Read error"); |
||||
} |
||||
CallReadCb(ep, error); |
||||
EP_UNREF(ep, "read"); |
||||
} else if (read_size == 0) { |
||||
grpc_slice_buffer_reset_and_unref_internal(ep->read_slices); |
||||
CallReadCb(ep, |
||||
CFStreamAnnotateError( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Socket closed"), ep)); |
||||
EP_UNREF(ep, "read"); |
||||
} else { |
||||
if (read_size < len) { |
||||
grpc_slice_buffer_trim_end(ep->read_slices, len - read_size, nullptr); |
||||
} |
||||
CallReadCb(ep, GRPC_ERROR_NONE); |
||||
EP_UNREF(ep, "read"); |
||||
} |
||||
} |
||||
|
||||
static void WriteAction(void* arg, grpc_error* error) { |
||||
CFStreamEndpoint* ep = static_cast<CFStreamEndpoint*>(arg); |
||||
GPR_ASSERT(ep->write_cb != nullptr); |
||||
if (error) { |
||||
grpc_slice_buffer_reset_and_unref_internal(ep->write_slices); |
||||
CallWriteCb(ep, GRPC_ERROR_REF(error)); |
||||
EP_UNREF(ep, "write"); |
||||
return; |
||||
} |
||||
|
||||
grpc_slice slice = grpc_slice_buffer_take_first(ep->write_slices); |
||||
size_t slice_len = GRPC_SLICE_LENGTH(slice); |
||||
CFIndex write_size = CFWriteStreamWrite( |
||||
ep->write_stream, GRPC_SLICE_START_PTR(slice), slice_len); |
||||
if (write_size == -1) { |
||||
grpc_slice_buffer_reset_and_unref_internal(ep->write_slices); |
||||
CFErrorRef stream_error = CFWriteStreamCopyError(ep->write_stream); |
||||
if (stream_error != nullptr) { |
||||
error = CFStreamAnnotateError( |
||||
GRPC_ERROR_CREATE_FROM_CFERROR(stream_error, "write failed."), ep); |
||||
CFRelease(stream_error); |
||||
} else { |
||||
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("write failed."); |
||||
} |
||||
CallWriteCb(ep, error); |
||||
EP_UNREF(ep, "write"); |
||||
} else { |
||||
if (write_size < GRPC_SLICE_LENGTH(slice)) { |
||||
grpc_slice_buffer_undo_take_first( |
||||
ep->write_slices, grpc_slice_sub(slice, write_size, slice_len)); |
||||
} |
||||
if (ep->write_slices->length > 0) { |
||||
ep->stream_sync->NotifyOnWrite(&ep->write_action); |
||||
} else { |
||||
CallWriteCb(ep, GRPC_ERROR_NONE); |
||||
EP_UNREF(ep, "write"); |
||||
} |
||||
|
||||
if (grpc_tcp_trace.enabled()) { |
||||
grpc_slice trace_slice = grpc_slice_sub(slice, 0, write_size); |
||||
char* dump = grpc_dump_slice(trace_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); |
||||
gpr_log(GPR_DEBUG, "WRITE %p (peer=%s): %s", ep, ep->peer_string, dump); |
||||
gpr_free(dump); |
||||
grpc_slice_unref_internal(trace_slice); |
||||
} |
||||
} |
||||
grpc_slice_unref_internal(slice); |
||||
} |
||||
|
||||
static void CFStreamReadAllocationDone(void* arg, grpc_error* error) { |
||||
CFStreamEndpoint* ep = static_cast<CFStreamEndpoint*>(arg); |
||||
if (error == GRPC_ERROR_NONE) { |
||||
ep->stream_sync->NotifyOnRead(&ep->read_action); |
||||
} else { |
||||
grpc_slice_buffer_reset_and_unref_internal(ep->read_slices); |
||||
CallReadCb(ep, error); |
||||
EP_UNREF(ep, "read"); |
||||
} |
||||
} |
||||
|
||||
static void CFStreamRead(grpc_endpoint* ep, grpc_slice_buffer* slices, |
||||
grpc_closure* cb) { |
||||
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep); |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, "CFStream endpoint:%p read (%p, %p) length:%zu", ep_impl, |
||||
slices, cb, slices->length); |
||||
} |
||||
GPR_ASSERT(ep_impl->read_cb == nullptr); |
||||
ep_impl->read_cb = cb; |
||||
ep_impl->read_slices = slices; |
||||
grpc_slice_buffer_reset_and_unref_internal(slices); |
||||
grpc_resource_user_alloc_slices(&ep_impl->slice_allocator, |
||||
GRPC_TCP_DEFAULT_READ_SLICE_SIZE, 1, |
||||
ep_impl->read_slices); |
||||
EP_REF(ep_impl, "read"); |
||||
} |
||||
|
||||
static void CFStreamWrite(grpc_endpoint* ep, grpc_slice_buffer* slices, |
||||
grpc_closure* cb) { |
||||
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep); |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, "CFStream endpoint:%p write (%p, %p) length:%zu", |
||||
ep_impl, slices, cb, slices->length); |
||||
} |
||||
GPR_ASSERT(ep_impl->write_cb == nullptr); |
||||
ep_impl->write_cb = cb; |
||||
ep_impl->write_slices = slices; |
||||
EP_REF(ep_impl, "write"); |
||||
ep_impl->stream_sync->NotifyOnWrite(&ep_impl->write_action); |
||||
} |
||||
|
||||
void CFStreamShutdown(grpc_endpoint* ep, grpc_error* why) { |
||||
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep); |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, "CFStream endpoint:%p shutdown (%p)", ep_impl, why); |
||||
} |
||||
CFReadStreamClose(ep_impl->read_stream); |
||||
CFWriteStreamClose(ep_impl->write_stream); |
||||
ep_impl->stream_sync->Shutdown(why); |
||||
grpc_resource_user_shutdown(ep_impl->resource_user); |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, "CFStream endpoint:%p shutdown DONE (%p)", ep_impl, why); |
||||
} |
||||
} |
||||
|
||||
void CFStreamDestroy(grpc_endpoint* ep) { |
||||
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep); |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, "CFStream endpoint:%p destroy", ep_impl); |
||||
} |
||||
EP_UNREF(ep_impl, "destroy"); |
||||
} |
||||
|
||||
grpc_resource_user* CFStreamGetResourceUser(grpc_endpoint* ep) { |
||||
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep); |
||||
return ep_impl->resource_user; |
||||
} |
||||
|
||||
char* CFStreamGetPeer(grpc_endpoint* ep) { |
||||
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep); |
||||
return gpr_strdup(ep_impl->peer_string); |
||||
} |
||||
|
||||
int CFStreamGetFD(grpc_endpoint* ep) { return 0; } |
||||
|
||||
void CFStreamAddToPollset(grpc_endpoint* ep, grpc_pollset* pollset) {} |
||||
void CFStreamAddToPollsetSet(grpc_endpoint* ep, grpc_pollset_set* pollset) {} |
||||
void CFStreamDeleteFromPollsetSet(grpc_endpoint* ep, |
||||
grpc_pollset_set* pollset) {} |
||||
|
||||
static const grpc_endpoint_vtable vtable = {CFStreamRead, |
||||
CFStreamWrite, |
||||
CFStreamAddToPollset, |
||||
CFStreamAddToPollsetSet, |
||||
CFStreamDeleteFromPollsetSet, |
||||
CFStreamShutdown, |
||||
CFStreamDestroy, |
||||
CFStreamGetResourceUser, |
||||
CFStreamGetPeer, |
||||
CFStreamGetFD}; |
||||
|
||||
grpc_endpoint* grpc_cfstream_endpoint_create( |
||||
CFReadStreamRef read_stream, CFWriteStreamRef write_stream, |
||||
const char* peer_string, grpc_resource_quota* resource_quota, |
||||
CFStreamHandle* stream_sync) { |
||||
CFStreamEndpoint* ep_impl = |
||||
static_cast<CFStreamEndpoint*>(gpr_malloc(sizeof(CFStreamEndpoint))); |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, |
||||
"CFStream endpoint:%p create readStream:%p writeStream: %p", |
||||
ep_impl, read_stream, write_stream); |
||||
} |
||||
ep_impl->base.vtable = &vtable; |
||||
gpr_ref_init(&ep_impl->refcount, 1); |
||||
ep_impl->read_stream = read_stream; |
||||
ep_impl->write_stream = write_stream; |
||||
CFRetain(read_stream); |
||||
CFRetain(write_stream); |
||||
ep_impl->stream_sync = stream_sync; |
||||
CFSTREAM_HANDLE_REF(ep_impl->stream_sync, "endpoint create"); |
||||
|
||||
ep_impl->peer_string = gpr_strdup(peer_string); |
||||
ep_impl->read_cb = nil; |
||||
ep_impl->write_cb = nil; |
||||
ep_impl->read_slices = nil; |
||||
ep_impl->write_slices = nil; |
||||
GRPC_CLOSURE_INIT(&ep_impl->read_action, ReadAction, |
||||
static_cast<void*>(ep_impl), grpc_schedule_on_exec_ctx); |
||||
GRPC_CLOSURE_INIT(&ep_impl->write_action, WriteAction, |
||||
static_cast<void*>(ep_impl), grpc_schedule_on_exec_ctx); |
||||
ep_impl->resource_user = |
||||
grpc_resource_user_create(resource_quota, peer_string); |
||||
grpc_resource_user_slice_allocator_init(&ep_impl->slice_allocator, |
||||
ep_impl->resource_user, |
||||
CFStreamReadAllocationDone, ep_impl); |
||||
|
||||
return &ep_impl->base; |
||||
} |
||||
|
||||
#endif /* GRPC_CFSTREAM_ENDPOINT */ |
@ -0,0 +1,49 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_ENDPOINT_CFSTREAM_H |
||||
#define GRPC_CORE_LIB_IOMGR_ENDPOINT_CFSTREAM_H |
||||
/*
|
||||
Low level TCP "bottom half" implementation, for use by transports built on |
||||
top of a TCP connection. |
||||
|
||||
Note that this file does not (yet) include APIs for creating the socket in |
||||
the first place. |
||||
|
||||
All calls passing slice transfer ownership of a slice refcount unless |
||||
otherwise specified. |
||||
*/ |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GRPC_CFSTREAM |
||||
|
||||
#import <CoreFoundation/CoreFoundation.h> |
||||
|
||||
#include "src/core/lib/debug/trace.h" |
||||
#include "src/core/lib/iomgr/cfstream_handle.h" |
||||
#include "src/core/lib/iomgr/endpoint.h" |
||||
|
||||
grpc_endpoint* grpc_cfstream_endpoint_create( |
||||
CFReadStreamRef read_stream, CFWriteStreamRef write_stream, |
||||
const char* peer_string, grpc_resource_quota* resource_quota, |
||||
CFStreamHandle* stream_sync); |
||||
|
||||
#endif /* GRPC_CFSTREAM */ |
||||
|
||||
#endif /* GRPC_CORE_LIB_IOMGR_ENDPOINT_CFSTREAM_H */ |
@ -0,0 +1,52 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#ifdef GRPC_CFSTREAM |
||||
#include <CoreFoundation/CoreFoundation.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/lib/iomgr/error.h" |
||||
|
||||
#define MAX_ERROR_DESCRIPTION 256 |
||||
|
||||
grpc_error* grpc_error_create_from_cferror(const char* file, int line, |
||||
void* arg, const char* custom_desc) { |
||||
CFErrorRef error = static_cast<CFErrorRef>(arg); |
||||
char buf_domain[MAX_ERROR_DESCRIPTION]; |
||||
char buf_desc[MAX_ERROR_DESCRIPTION]; |
||||
char* error_msg; |
||||
CFErrorDomain domain = CFErrorGetDomain((error)); |
||||
CFIndex code = CFErrorGetCode((error)); |
||||
CFStringRef desc = CFErrorCopyDescription((error)); |
||||
CFStringGetCString(domain, buf_domain, MAX_ERROR_DESCRIPTION, |
||||
kCFStringEncodingUTF8); |
||||
CFStringGetCString(desc, buf_desc, MAX_ERROR_DESCRIPTION, |
||||
kCFStringEncodingUTF8); |
||||
gpr_asprintf(&error_msg, "%s (error domain:%s, code:%ld, description:%s)", |
||||
custom_desc, buf_domain, code, buf_desc); |
||||
CFRelease(desc); |
||||
grpc_error* return_error = grpc_error_create( |
||||
file, line, grpc_slice_from_copied_string(error_msg), NULL, 0); |
||||
gpr_free(error_msg); |
||||
return return_error; |
||||
} |
||||
#endif /* GRPC_CFSTREAM */ |
@ -0,0 +1,31 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_ERROR_CFSTREAM_H |
||||
#define GRPC_CORE_LIB_IOMGR_ERROR_CFSTREAM_H |
||||
|
||||
#ifdef GRPC_CFSTREAM |
||||
// Create an error from Apple Core Foundation CFError object
|
||||
#define GRPC_ERROR_CREATE_FROM_CFERROR(error, desc) \ |
||||
grpc_error_create_from_cferror(__FILE__, __LINE__, \
|
||||
static_cast<void*>((error)), (desc)) |
||||
grpc_error* grpc_error_create_from_cferror(const char* file, int line, |
||||
void* arg, const char* desc); |
||||
#endif /* GRPC_CFSTREAM */ |
||||
|
||||
#endif /* GRPC_CORE_LIB_IOMGR_ERROR_CFSTREAM_H */ |
@ -0,0 +1,216 @@ |
||||
|
||||
/*
|
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
#ifdef GRPC_CFSTREAM_CLIENT |
||||
|
||||
#include <CoreFoundation/CoreFoundation.h> |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/sync.h> |
||||
|
||||
#include <netinet/in.h> |
||||
|
||||
#include "src/core/lib/channel/channel_args.h" |
||||
#include "src/core/lib/gpr/host_port.h" |
||||
#include "src/core/lib/iomgr/cfstream_handle.h" |
||||
#include "src/core/lib/iomgr/closure.h" |
||||
#include "src/core/lib/iomgr/endpoint_cfstream.h" |
||||
#include "src/core/lib/iomgr/error.h" |
||||
#include "src/core/lib/iomgr/error_cfstream.h" |
||||
#include "src/core/lib/iomgr/sockaddr_utils.h" |
||||
#include "src/core/lib/iomgr/tcp_client.h" |
||||
#include "src/core/lib/iomgr/timer.h" |
||||
|
||||
extern grpc_core::TraceFlag grpc_tcp_trace; |
||||
|
||||
typedef struct CFStreamConnect { |
||||
gpr_mu mu; |
||||
gpr_refcount refcount; |
||||
|
||||
CFReadStreamRef read_stream; |
||||
CFWriteStreamRef write_stream; |
||||
CFStreamHandle* stream_sync; |
||||
|
||||
grpc_timer alarm; |
||||
grpc_closure on_alarm; |
||||
grpc_closure on_open; |
||||
|
||||
bool read_stream_open; |
||||
bool write_stream_open; |
||||
bool failed; |
||||
|
||||
grpc_closure* closure; |
||||
grpc_endpoint** endpoint; |
||||
int refs; |
||||
char* addr_name; |
||||
grpc_resource_quota* resource_quota; |
||||
} CFStreamConnect; |
||||
|
||||
static void CFStreamConnectCleanup(CFStreamConnect* connect) { |
||||
grpc_resource_quota_unref_internal(connect->resource_quota); |
||||
CFSTREAM_HANDLE_UNREF(connect->stream_sync, "async connect clean up"); |
||||
CFRelease(connect->read_stream); |
||||
CFRelease(connect->write_stream); |
||||
gpr_mu_destroy(&connect->mu); |
||||
gpr_free(connect->addr_name); |
||||
gpr_free(connect); |
||||
} |
||||
|
||||
static void OnAlarm(void* arg, grpc_error* error) { |
||||
CFStreamConnect* connect = static_cast<CFStreamConnect*>(arg); |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, "CLIENT_CONNECT :%p OnAlarm, error:%p", connect, error); |
||||
} |
||||
gpr_mu_lock(&connect->mu); |
||||
grpc_closure* closure = connect->closure; |
||||
connect->closure = nil; |
||||
const bool done = (--connect->refs == 0); |
||||
gpr_mu_unlock(&connect->mu); |
||||
// Only schedule a callback once, by either OnAlarm or OnOpen. The
|
||||
// first one issues callback while the second one does cleanup.
|
||||
if (done) { |
||||
CFStreamConnectCleanup(connect); |
||||
} else { |
||||
grpc_error* error = |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING("connect() timed out"); |
||||
GRPC_CLOSURE_SCHED(closure, error); |
||||
} |
||||
} |
||||
|
||||
static void OnOpen(void* arg, grpc_error* error) { |
||||
CFStreamConnect* connect = static_cast<CFStreamConnect*>(arg); |
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, "CLIENT_CONNECT :%p OnOpen, error:%p", connect, error); |
||||
} |
||||
gpr_mu_lock(&connect->mu); |
||||
grpc_timer_cancel(&connect->alarm); |
||||
grpc_closure* closure = connect->closure; |
||||
connect->closure = nil; |
||||
|
||||
bool done = (--connect->refs == 0); |
||||
grpc_endpoint** endpoint = connect->endpoint; |
||||
|
||||
// Only schedule a callback once, by either OnAlarm or OnOpen. The
|
||||
// first one issues callback while the second one does cleanup.
|
||||
if (done) { |
||||
gpr_mu_unlock(&connect->mu); |
||||
CFStreamConnectCleanup(connect); |
||||
} else { |
||||
if (error == GRPC_ERROR_NONE) { |
||||
CFErrorRef stream_error = CFReadStreamCopyError(connect->read_stream); |
||||
if (stream_error == NULL) { |
||||
stream_error = CFWriteStreamCopyError(connect->write_stream); |
||||
} |
||||
if (stream_error) { |
||||
error = GRPC_ERROR_CREATE_FROM_CFERROR(stream_error, "connect() error"); |
||||
CFRelease(stream_error); |
||||
} |
||||
if (error == GRPC_ERROR_NONE) { |
||||
*endpoint = grpc_cfstream_endpoint_create( |
||||
connect->read_stream, connect->write_stream, connect->addr_name, |
||||
connect->resource_quota, connect->stream_sync); |
||||
} |
||||
} else { |
||||
GRPC_ERROR_REF(error); |
||||
} |
||||
gpr_mu_unlock(&connect->mu); |
||||
GRPC_CLOSURE_SCHED(closure, error); |
||||
} |
||||
} |
||||
|
||||
static void ParseResolvedAddress(const grpc_resolved_address* addr, |
||||
CFStringRef* host, int* port) { |
||||
char *host_port, *host_string, *port_string; |
||||
grpc_sockaddr_to_string(&host_port, addr, 1); |
||||
gpr_split_host_port(host_port, &host_string, &port_string); |
||||
*host = CFStringCreateWithCString(NULL, host_string, kCFStringEncodingUTF8); |
||||
gpr_free(host_string); |
||||
gpr_free(port_string); |
||||
gpr_free(host_port); |
||||
*port = grpc_sockaddr_get_port(addr); |
||||
} |
||||
|
||||
static void CFStreamClientConnect(grpc_closure* closure, grpc_endpoint** ep, |
||||
grpc_pollset_set* interested_parties, |
||||
const grpc_channel_args* channel_args, |
||||
const grpc_resolved_address* resolved_addr, |
||||
grpc_millis deadline) { |
||||
CFStreamConnect* connect; |
||||
|
||||
connect = (CFStreamConnect*)gpr_zalloc(sizeof(CFStreamConnect)); |
||||
connect->closure = closure; |
||||
connect->endpoint = ep; |
||||
connect->addr_name = grpc_sockaddr_to_uri(resolved_addr); |
||||
// connect->resource_quota = resource_quota;
|
||||
connect->refs = 2; // One for the connect operation, one for the timer.
|
||||
gpr_ref_init(&connect->refcount, 1); |
||||
gpr_mu_init(&connect->mu); |
||||
|
||||
if (grpc_tcp_trace.enabled()) { |
||||
gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting", |
||||
connect->addr_name); |
||||
} |
||||
|
||||
grpc_resource_quota* resource_quota = grpc_resource_quota_create(NULL); |
||||
if (channel_args != NULL) { |
||||
for (size_t i = 0; i < channel_args->num_args; i++) { |
||||
if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) { |
||||
grpc_resource_quota_unref_internal(resource_quota); |
||||
resource_quota = grpc_resource_quota_ref_internal( |
||||
(grpc_resource_quota*)channel_args->args[i].value.pointer.p); |
||||
} |
||||
} |
||||
} |
||||
connect->resource_quota = resource_quota; |
||||
|
||||
CFReadStreamRef read_stream; |
||||
CFWriteStreamRef write_stream; |
||||
|
||||
CFStringRef host; |
||||
int port; |
||||
ParseResolvedAddress(resolved_addr, &host, &port); |
||||
CFStreamCreatePairWithSocketToHost(NULL, host, port, &read_stream, |
||||
&write_stream); |
||||
CFRelease(host); |
||||
connect->read_stream = read_stream; |
||||
connect->write_stream = write_stream; |
||||
connect->stream_sync = |
||||
CFStreamHandle::CreateStreamHandle(read_stream, write_stream); |
||||
GRPC_CLOSURE_INIT(&connect->on_open, OnOpen, static_cast<void*>(connect), |
||||
grpc_schedule_on_exec_ctx); |
||||
connect->stream_sync->NotifyOnOpen(&connect->on_open); |
||||
GRPC_CLOSURE_INIT(&connect->on_alarm, OnAlarm, connect, |
||||
grpc_schedule_on_exec_ctx); |
||||
gpr_mu_lock(&connect->mu); |
||||
CFReadStreamOpen(read_stream); |
||||
CFWriteStreamOpen(write_stream); |
||||
grpc_timer_init(&connect->alarm, deadline, &connect->on_alarm); |
||||
gpr_mu_unlock(&connect->mu); |
||||
} |
||||
|
||||
grpc_tcp_client_vtable grpc_posix_tcp_client_vtable = {CFStreamClientConnect}; |
||||
|
||||
#endif /* GRPC_CFSTREAM_CLIENT */ |
@ -0,0 +1,25 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<package> |
||||
<metadata> |
||||
<id>Grpc.Core.NativeDebug</id> |
||||
<title>Grpc.Core: Native Debug Symbols</title> |
||||
<summary>Debug symbols for the native library contained in Grpc.Core</summary> |
||||
<description>Currently contains grpc_csharp_ext.pdb</description> |
||||
<version>$version$</version> |
||||
<authors>Google Inc.</authors> |
||||
<owners>grpc-packages</owners> |
||||
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> |
||||
<projectUrl>https://github.com/grpc/grpc</projectUrl> |
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance> |
||||
<releaseNotes>Release $version$</releaseNotes> |
||||
<copyright>Copyright 2015, Google Inc.</copyright> |
||||
<tags>gRPC RPC Protocol HTTP/2</tags> |
||||
</metadata> |
||||
<files> |
||||
<!-- forward slashes in src path enable building on Linux --> |
||||
<file src="nativelibs/csharp_ext_windows_x86/grpc_csharp_ext.dll" target="runtimes/win/native/grpc_csharp_ext.x86.dll" /> |
||||
<file src="nativelibs/csharp_ext_windows_x86/grpc_csharp_ext.pdb" target="runtimes/win/native/grpc_csharp_ext.x86.pdb" /> |
||||
<file src="nativelibs/csharp_ext_windows_x64/grpc_csharp_ext.dll" target="runtimes/win/native/grpc_csharp_ext.x64.dll" /> |
||||
<file src="nativelibs/csharp_ext_windows_x64/grpc_csharp_ext.pdb" target="runtimes/win/native/grpc_csharp_ext.x64.pdb" /> |
||||
</files> |
||||
</package> |
@ -0,0 +1,38 @@ |
||||
// <auto-generated> |
||||
// Generated by the protocol buffer compiler. DO NOT EDIT! |
||||
// source: src/proto/grpc/testing/empty_service.proto |
||||
// </auto-generated> |
||||
#pragma warning disable 1591, 0612, 3021 |
||||
#region Designer generated code |
||||
|
||||
using pb = global::Google.Protobuf; |
||||
using pbc = global::Google.Protobuf.Collections; |
||||
using pbr = global::Google.Protobuf.Reflection; |
||||
using scg = global::System.Collections.Generic; |
||||
namespace Grpc.Testing { |
||||
|
||||
/// <summary>Holder for reflection information generated from src/proto/grpc/testing/empty_service.proto</summary> |
||||
public static partial class EmptyServiceReflection { |
||||
|
||||
#region Descriptor |
||||
/// <summary>File descriptor for src/proto/grpc/testing/empty_service.proto</summary> |
||||
public static pbr::FileDescriptor Descriptor { |
||||
get { return descriptor; } |
||||
} |
||||
private static pbr::FileDescriptor descriptor; |
||||
|
||||
static EmptyServiceReflection() { |
||||
byte[] descriptorData = global::System.Convert.FromBase64String( |
||||
string.Concat( |
||||
"CipzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2VtcHR5X3NlcnZpY2UucHJvdG8S", |
||||
"DGdycGMudGVzdGluZzIOCgxFbXB0eVNlcnZpY2ViBnByb3RvMw==")); |
||||
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, |
||||
new pbr::FileDescriptor[] { }, |
||||
new pbr::GeneratedClrTypeInfo(null, null)); |
||||
} |
||||
#endregion |
||||
|
||||
} |
||||
} |
||||
|
||||
#endregion Designer generated code |
@ -0,0 +1,85 @@ |
||||
// <auto-generated> |
||||
// Generated by the protocol buffer compiler. DO NOT EDIT! |
||||
// source: src/proto/grpc/testing/empty_service.proto |
||||
// </auto-generated> |
||||
// Original file comments: |
||||
// Copyright 2018 gRPC authors. |
||||
// |
||||
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||
// you may not use this file except in compliance with the License. |
||||
// You may obtain a copy of the License at |
||||
// |
||||
// http://www.apache.org/licenses/LICENSE-2.0 |
||||
// |
||||
// Unless required by applicable law or agreed to in writing, software |
||||
// distributed under the License is distributed on an "AS IS" BASIS, |
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
// See the License for the specific language governing permissions and |
||||
// limitations under the License. |
||||
// |
||||
#pragma warning disable 0414, 1591 |
||||
#region Designer generated code |
||||
|
||||
using grpc = global::Grpc.Core; |
||||
|
||||
namespace Grpc.Testing { |
||||
/// <summary> |
||||
/// A service that has zero methods. |
||||
/// See https://github.com/grpc/grpc/issues/15574 |
||||
/// </summary> |
||||
public static partial class EmptyService |
||||
{ |
||||
static readonly string __ServiceName = "grpc.testing.EmptyService"; |
||||
|
||||
|
||||
/// <summary>Service descriptor</summary> |
||||
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor |
||||
{ |
||||
get { return global::Grpc.Testing.EmptyServiceReflection.Descriptor.Services[0]; } |
||||
} |
||||
|
||||
/// <summary>Base class for server-side implementations of EmptyService</summary> |
||||
public abstract partial class EmptyServiceBase |
||||
{ |
||||
} |
||||
|
||||
/// <summary>Client for EmptyService</summary> |
||||
public partial class EmptyServiceClient : grpc::ClientBase<EmptyServiceClient> |
||||
{ |
||||
/// <summary>Creates a new client for EmptyService</summary> |
||||
/// <param name="channel">The channel to use to make remote calls.</param> |
||||
public EmptyServiceClient(grpc::Channel channel) : base(channel) |
||||
{ |
||||
} |
||||
/// <summary>Creates a new client for EmptyService that uses a custom <c>CallInvoker</c>.</summary> |
||||
/// <param name="callInvoker">The callInvoker to use to make remote calls.</param> |
||||
public EmptyServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) |
||||
{ |
||||
} |
||||
/// <summary>Protected parameterless constructor to allow creation of test doubles.</summary> |
||||
protected EmptyServiceClient() : base() |
||||
{ |
||||
} |
||||
/// <summary>Protected constructor to allow creation of configured clients.</summary> |
||||
/// <param name="configuration">The client configuration.</param> |
||||
protected EmptyServiceClient(ClientBaseConfiguration configuration) : base(configuration) |
||||
{ |
||||
} |
||||
|
||||
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary> |
||||
protected override EmptyServiceClient NewInstance(ClientBaseConfiguration configuration) |
||||
{ |
||||
return new EmptyServiceClient(configuration); |
||||
} |
||||
} |
||||
|
||||
/// <summary>Creates service definition that can be registered with a server</summary> |
||||
/// <param name="serviceImpl">An object implementing the server-side handling logic.</param> |
||||
public static grpc::ServerServiceDefinition BindService(EmptyServiceBase serviceImpl) |
||||
{ |
||||
return grpc::ServerServiceDefinition.CreateBuilder().Build(); |
||||
} |
||||
|
||||
} |
||||
} |
||||
#endregion |
@ -1,30 +0,0 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2017 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#import "GRPCCall.h" |
||||
|
||||
@interface GRPCCall (MobileLog) |
||||
// Set the object to be passed down along channel stack with channel arg
|
||||
// GRPC_ARG_MOBILE_LOG_CONFIG. The setting may be used by custom channel
|
||||
// filters for metrics logging.
|
||||
+ (void)setLogConfig:(id)logConfig; |
||||
|
||||
// Obtain the object to be passed down along channel stack with channel arg
|
||||
// GRPC_ARG_MOBILE_LOG_CONFIG.
|
||||
+ (id)logConfig; |
||||
@end |
@ -1,33 +0,0 @@ |
||||
/* |
||||
* |
||||
* Copyright 2017 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#import "GRPCCall+MobileLog.h" |
||||
|
||||
static id globalLogConfig = nil; |
||||
|
||||
@implementation GRPCCall (MobileLog) |
||||
|
||||
+ (void)setLogConfig:(id)logConfig { |
||||
globalLogConfig = logConfig; |
||||
} |
||||
|
||||
+ (id)logConfig { |
||||
return globalLogConfig; |
||||
} |
||||
|
||||
@end |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,63 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<Scheme |
||||
LastUpgradeVersion = "0920" |
||||
version = "1.3"> |
||||
<BuildAction |
||||
parallelizeBuildables = "YES" |
||||
buildImplicitDependencies = "YES"> |
||||
</BuildAction> |
||||
<TestAction |
||||
buildConfiguration = "Test" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
language = "" |
||||
shouldUseLaunchSchemeArgsEnv = "YES"> |
||||
<Testables> |
||||
<TestableReference |
||||
skipped = "NO"> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5EC5E4302081856B000EF4AD" |
||||
BuildableName = "InteropTestsLocalCleartextCFStream.xctest" |
||||
BlueprintName = "InteropTestsLocalCleartextCFStream" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
<SkippedTests> |
||||
<Test |
||||
Identifier = "InteropTests"> |
||||
</Test> |
||||
</SkippedTests> |
||||
</TestableReference> |
||||
</Testables> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</TestAction> |
||||
<LaunchAction |
||||
buildConfiguration = "Debug" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
language = "" |
||||
launchStyle = "0" |
||||
useCustomWorkingDirectory = "NO" |
||||
ignoresPersistentStateOnLaunch = "NO" |
||||
debugDocumentVersioning = "YES" |
||||
debugServiceExtension = "internal" |
||||
allowLocationSimulation = "YES"> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</LaunchAction> |
||||
<ProfileAction |
||||
buildConfiguration = "Release" |
||||
shouldUseLaunchSchemeArgsEnv = "YES" |
||||
savedToolIdentifier = "" |
||||
useCustomWorkingDirectory = "NO" |
||||
debugDocumentVersioning = "YES"> |
||||
</ProfileAction> |
||||
<AnalyzeAction |
||||
buildConfiguration = "Debug"> |
||||
</AnalyzeAction> |
||||
<ArchiveAction |
||||
buildConfiguration = "Release" |
||||
revealArchiveInOrganizer = "YES"> |
||||
</ArchiveAction> |
||||
</Scheme> |
@ -0,0 +1,63 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<Scheme |
||||
LastUpgradeVersion = "0920" |
||||
version = "1.3"> |
||||
<BuildAction |
||||
parallelizeBuildables = "YES" |
||||
buildImplicitDependencies = "YES"> |
||||
</BuildAction> |
||||
<TestAction |
||||
buildConfiguration = "Test" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
language = "" |
||||
shouldUseLaunchSchemeArgsEnv = "YES"> |
||||
<Testables> |
||||
<TestableReference |
||||
skipped = "NO"> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5EC5E441208185CE000EF4AD" |
||||
BuildableName = "InteropTestsLocalSSLCFStream.xctest" |
||||
BlueprintName = "InteropTestsLocalSSLCFStream" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
<SkippedTests> |
||||
<Test |
||||
Identifier = "InteropTests"> |
||||
</Test> |
||||
</SkippedTests> |
||||
</TestableReference> |
||||
</Testables> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</TestAction> |
||||
<LaunchAction |
||||
buildConfiguration = "Debug" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
language = "" |
||||
launchStyle = "0" |
||||
useCustomWorkingDirectory = "NO" |
||||
ignoresPersistentStateOnLaunch = "NO" |
||||
debugDocumentVersioning = "YES" |
||||
debugServiceExtension = "internal" |
||||
allowLocationSimulation = "YES"> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</LaunchAction> |
||||
<ProfileAction |
||||
buildConfiguration = "Release" |
||||
shouldUseLaunchSchemeArgsEnv = "YES" |
||||
savedToolIdentifier = "" |
||||
useCustomWorkingDirectory = "NO" |
||||
debugDocumentVersioning = "YES"> |
||||
</ProfileAction> |
||||
<AnalyzeAction |
||||
buildConfiguration = "Debug"> |
||||
</AnalyzeAction> |
||||
<ArchiveAction |
||||
buildConfiguration = "Release" |
||||
revealArchiveInOrganizer = "YES"> |
||||
</ArchiveAction> |
||||
</Scheme> |
@ -0,0 +1,61 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<Scheme |
||||
LastUpgradeVersion = "0920" |
||||
version = "1.3"> |
||||
<BuildAction |
||||
parallelizeBuildables = "YES" |
||||
buildImplicitDependencies = "YES"> |
||||
</BuildAction> |
||||
<TestAction |
||||
buildConfiguration = "Test" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
shouldUseLaunchSchemeArgsEnv = "YES"> |
||||
<Testables> |
||||
<TestableReference |
||||
skipped = "NO"> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5EC5E420208177CC000EF4AD" |
||||
BuildableName = "InteropTestsRemoteCFStream.xctest" |
||||
BlueprintName = "InteropTestsRemoteCFStream" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
<SkippedTests> |
||||
<Test |
||||
Identifier = "InteropTests"> |
||||
</Test> |
||||
</SkippedTests> |
||||
</TestableReference> |
||||
</Testables> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</TestAction> |
||||
<LaunchAction |
||||
buildConfiguration = "Debug" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
launchStyle = "0" |
||||
useCustomWorkingDirectory = "NO" |
||||
ignoresPersistentStateOnLaunch = "NO" |
||||
debugDocumentVersioning = "YES" |
||||
debugServiceExtension = "internal" |
||||
allowLocationSimulation = "YES"> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</LaunchAction> |
||||
<ProfileAction |
||||
buildConfiguration = "Release" |
||||
shouldUseLaunchSchemeArgsEnv = "YES" |
||||
savedToolIdentifier = "" |
||||
useCustomWorkingDirectory = "NO" |
||||
debugDocumentVersioning = "YES"> |
||||
</ProfileAction> |
||||
<AnalyzeAction |
||||
buildConfiguration = "Debug"> |
||||
</AnalyzeAction> |
||||
<ArchiveAction |
||||
buildConfiguration = "Release" |
||||
revealArchiveInOrganizer = "YES"> |
||||
</ArchiveAction> |
||||
</Scheme> |
@ -1,78 +0,0 @@ |
||||
#!/usr/bin/python |
||||
# Copyright 2018 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
# This script analyzes link map file generated by Xcode. It calculates and |
||||
# prints out the sizes of each dependent library and the total sizes of the |
||||
# symbols. |
||||
# The script takes one parameter, which is the path to the link map file. |
||||
|
||||
import sys |
||||
import re |
||||
|
||||
table_tag = {} |
||||
state = "start" |
||||
|
||||
table_stats_symbol = {} |
||||
table_stats_dead = {} |
||||
section_total_size = 0 |
||||
symbol_total_size = 0 |
||||
|
||||
|
||||
file_import = sys.argv[1] |
||||
lines = list(open(file_import)) |
||||
for line in lines: |
||||
line_stripped = line[:-1] |
||||
if "# Object files:" == line_stripped: |
||||
state = "object" |
||||
continue |
||||
elif "# Sections:" == line_stripped: |
||||
state = "section" |
||||
continue |
||||
elif "# Symbols:" == line_stripped: |
||||
state = "symbol" |
||||
continue |
||||
elif "# Dead Stripped Symbols:" == line_stripped: |
||||
state = "dead" |
||||
continue |
||||
|
||||
if state == "object": |
||||
segs = re.search('(\[ *[0-9]*\]) (.*)', line_stripped) |
||||
table_tag[segs.group(1)] = segs.group(2) |
||||
|
||||
if state == "section": |
||||
if len(line_stripped) == 0 or line_stripped[0] == '#': |
||||
continue |
||||
segs = re.search('^(.+?)\s+(.+?)\s+.*', line_stripped) |
||||
section_total_size += int(segs.group(2), 16) |
||||
|
||||
if state == "symbol": |
||||
if len(line_stripped) == 0 or line_stripped[0] == '#': |
||||
continue |
||||
segs = re.search('^.+?\s+(.+?)\s+(\[.+?\]).*', line_stripped) |
||||
target = table_tag[segs.group(2)] |
||||
target_stripped = re.search('^(.*?)(\(.+?\))?$', target).group(1) |
||||
size = int(segs.group(1), 16) |
||||
if not target_stripped in table_stats_symbol: |
||||
table_stats_symbol[target_stripped] = 0 |
||||
table_stats_symbol[target_stripped] += size |
||||
|
||||
print("Sections total size: %d" % section_total_size) |
||||
|
||||
for target in table_stats_symbol: |
||||
print(target) |
||||
print(table_stats_symbol[target]) |
||||
symbol_total_size += table_stats_symbol[target] |
||||
|
||||
print("Symbols total size: %d" % symbol_total_size) |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue