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