Merge pull request #15069 from muxi/prototype-cfstream

Implementation of CFStream
pull/14879/head
Muxi Yan 7 years ago committed by GitHub
commit d7728cda51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      BUILD
  2. 13
      build.yaml
  3. 18
      gRPC-Core.podspec
  4. 22
      gRPC-ProtoRPC.podspec
  5. 10
      gRPC.podspec
  6. 3
      include/grpc/impl/codegen/port_platform.h
  7. 4
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
  8. 183
      src/core/lib/iomgr/cfstream_handle.cc
  9. 80
      src/core/lib/iomgr/cfstream_handle.h
  10. 372
      src/core/lib/iomgr/endpoint_cfstream.cc
  11. 49
      src/core/lib/iomgr/endpoint_cfstream.h
  12. 52
      src/core/lib/iomgr/error_cfstream.cc
  13. 31
      src/core/lib/iomgr/error_cfstream.h
  14. 4
      src/core/lib/iomgr/ev_epoll1_linux.cc
  15. 4
      src/core/lib/iomgr/ev_epollex_linux.cc
  16. 2
      src/core/lib/iomgr/ev_epollsig_linux.cc
  17. 4
      src/core/lib/iomgr/ev_poll_posix.cc
  18. 4
      src/core/lib/iomgr/ev_posix.cc
  19. 4
      src/core/lib/iomgr/iomgr_posix.cc
  20. 13
      src/core/lib/iomgr/polling_entity.cc
  21. 39
      src/core/lib/iomgr/port.h
  22. 2
      src/core/lib/iomgr/resolve_address.h
  23. 2
      src/core/lib/iomgr/resolve_address_posix.cc
  24. 2
      src/core/lib/iomgr/sockaddr_posix.h
  25. 2
      src/core/lib/iomgr/socket_factory_posix.cc
  26. 2
      src/core/lib/iomgr/socket_utils_common_posix.cc
  27. 216
      src/core/lib/iomgr/tcp_client_cfstream.cc
  28. 2
      src/core/lib/iomgr/tcp_client_posix.cc
  29. 4
      src/core/lib/iomgr/tcp_posix.cc
  30. 4
      src/core/lib/iomgr/tcp_server_posix.cc
  31. 4
      src/core/lib/iomgr/tcp_server_utils_posix_common.cc
  32. 18
      src/core/lib/slice/slice_buffer.cc
  33. 3
      src/core/lib/transport/transport.cc
  34. 11
      src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
  35. 31
      src/objective-c/tests/Podfile
  36. 773
      src/objective-c/tests/Tests.xcodeproj/project.pbxproj
  37. 2
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
  38. 2
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsLocalCleartext.xcscheme
  39. 63
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsLocalCleartextCFStream.xcscheme
  40. 63
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsLocalSSLCFStream.xcscheme
  41. 2
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemote.xcscheme
  42. 61
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemoteCFStream.xcscheme
  43. 41
      src/objective-c/tests/run_tests.sh
  44. 18
      templates/gRPC-Core.podspec.template
  45. 22
      templates/gRPC-ProtoRPC.podspec.template
  46. 10
      templates/gRPC.podspec.template
  47. 201
      test/core/iomgr/ios/CFStreamTests/CFStreamClientTests.mm
  48. 344
      test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm
  49. 338
      test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/project.pbxproj
  50. 56
      test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests.xcscheme
  51. 61
      test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Asan.xcscheme
  52. 78
      test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Msan.xcscheme
  53. 60
      test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Tsan.xcscheme
  54. 22
      test/core/iomgr/ios/CFStreamTests/Info.plist
  55. 50
      test/core/iomgr/ios/CFStreamTests/Podfile
  56. 39
      test/core/iomgr/ios/CFStreamTests/build_tests.sh
  57. 67
      test/core/iomgr/ios/CFStreamTests/run_tests.sh
  58. 26
      tools/run_tests/generated/sources_and_headers.json
  59. 11
      tools/run_tests/run_tests.py
  60. 3
      tools/run_tests/sanity/core_banned_functions.py

19
BUILD

@ -1003,6 +1003,25 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "grpc_cfstream",
srcs = [
"src/core/lib/iomgr/cfstream_handle.cc",
"src/core/lib/iomgr/endpoint_cfstream.cc",
"src/core/lib/iomgr/error_cfstream.cc",
"src/core/lib/iomgr/tcp_client_cfstream.cc",
],
hdrs = [
"src/core/lib/iomgr/cfstream_handle.h",
"src/core/lib/iomgr/endpoint_cfstream.h",
"src/core/lib/iomgr/error_cfstream.h",
],
deps = [
":gpr_base",
":grpc_base",
],
)
grpc_cc_library(
name = "grpc_client_channel",
srcs = [

@ -536,6 +536,19 @@ filegroups:
uses:
- grpc_codegen
- grpc_trace_headers
- name: grpc_cfstream
headers:
- src/core/lib/iomgr/cfstream_handle.h
- src/core/lib/iomgr/endpoint_cfstream.h
- src/core/lib/iomgr/error_cfstream.h
src:
- src/core/lib/iomgr/cfstream_handle.cc
- src/core/lib/iomgr/endpoint_cfstream.cc
- src/core/lib/iomgr/error_cfstream.cc
- src/core/lib/iomgr/tcp_client_cfstream.cc
uses:
- grpc_base_headers
- gpr_base_headers
- name: grpc_client_authority_filter
headers:
- src/core/ext/filters/http/client_authority_filter.h

@ -1080,6 +1080,24 @@ Pod::Spec.new do |s|
'src/core/ext/filters/workarounds/workaround_utils.h'
end
s.subspec 'CFStream-Implementation' do |ss|
ss.header_mappings_dir = '.'
ss.dependency "#{s.name}/Implementation", version
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1'
}
ss.source_files = 'src/core/lib/iomgr/cfstream_handle.cc',
'src/core/lib/iomgr/endpoint_cfstream.cc',
'src/core/lib/iomgr/error_cfstream.cc',
'src/core/lib/iomgr/tcp_client_cfstream.cc',
'src/core/lib/iomgr/cfstream_handle.h',
'src/core/lib/iomgr/endpoint_cfstream.h',
'src/core/lib/iomgr/error_cfstream.h'
ss.private_header_files = 'src/core/lib/iomgr/cfstream_handle.h',
'src/core/lib/iomgr/endpoint_cfstream.h',
'src/core/lib/iomgr/error_cfstream.h'
end
s.subspec 'Cronet-Interface' do |ss|
ss.header_mappings_dir = 'include/grpc'
ss.source_files = 'include/grpc/grpc_cronet.h'

@ -41,12 +41,24 @@ Pod::Spec.new do |s|
s.header_dir = name
src_dir = 'src/objective-c/ProtoRPC'
s.source_files = "#{src_dir}/*.{h,m}"
s.header_mappings_dir = "#{src_dir}"
s.dependency 'gRPC', version
s.dependency 'gRPC-RxLibrary', version
s.dependency 'Protobuf', '~> 3.0'
s.subspec 'Main' do |ss|
ss.header_mappings_dir = "#{src_dir}"
ss.dependency 'gRPC', version
ss.dependency 'gRPC-RxLibrary', version
ss.dependency 'Protobuf', '~> 3.0'
ss.source_files = "#{src_dir}/*.{h,m}"
end
s.subspec 'CFStream' do |ss|
ss.dependency 'gRPC/CFStream', version
ss.dependency "#{s.name}/Main", version
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1'
}
end
s.pod_target_xcconfig = {
# This is needed by all pods that depend on Protobuf:
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1',

@ -63,6 +63,16 @@ Pod::Spec.new do |s|
ss.dependency 'gRPC-Core', version
end
# This subspec is mutually exclusive with the `Main` subspec
s.subspec 'CFStream' do |ss|
ss.dependency 'gRPC-Core/CFStream-Implementation', version
ss.dependency "#{s.name}/Main", version
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1'
}
end
s.subspec 'GID' do |ss|
ss.ios.deployment_target = '7.0'

@ -227,7 +227,10 @@
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 1
#define GPR_GETPID_IN_UNISTD_H 1
/* TODO(mxyan): Remove when CFStream becomes default */
#ifndef GRPC_CFSTREAM
#define GPR_SUPPORT_CHANNELS_FROM_FD 1
#endif
#ifdef _LP64
#define GPR_ARCH_64 1
#else /* _LP64 */

@ -18,7 +18,7 @@
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h"
#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET)
#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER)
#include <ares.h>
#include <sys/ioctl.h>
@ -348,4 +348,4 @@ void grpc_ares_ev_driver_start(grpc_ares_ev_driver* ev_driver) {
gpr_mu_unlock(&ev_driver->mu);
}
#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET) */
#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */

@ -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 */

@ -1237,12 +1237,12 @@ const grpc_event_engine_vtable* grpc_init_epoll1_linux(bool explicit_request) {
}
#else /* defined(GRPC_LINUX_EPOLL) */
#if defined(GRPC_POSIX_SOCKET)
#if defined(GRPC_POSIX_SOCKET_EV_EPOLL1)
#include "src/core/lib/iomgr/ev_epoll1_linux.h"
/* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return
* NULL */
const grpc_event_engine_vtable* grpc_init_epoll1_linux(bool explicit_request) {
return nullptr;
}
#endif /* defined(GRPC_POSIX_SOCKET) */
#endif /* defined(GRPC_POSIX_SOCKET_EV_EPOLL1) */
#endif /* !defined(GRPC_LINUX_EPOLL) */

@ -1556,7 +1556,7 @@ const grpc_event_engine_vtable* grpc_init_epollex_linux(
}
#else /* defined(GRPC_LINUX_EPOLL_CREATE1) */
#if defined(GRPC_POSIX_SOCKET)
#if defined(GRPC_POSIX_SOCKET_EV_EPOLLEX)
#include "src/core/lib/iomgr/ev_epollex_linux.h"
/* If GRPC_LINUX_EPOLL_CREATE1 is not defined, it means
epoll_create1 is not available. Return NULL */
@ -1564,6 +1564,6 @@ const grpc_event_engine_vtable* grpc_init_epollex_linux(
bool explicitly_requested) {
return nullptr;
}
#endif /* defined(GRPC_POSIX_SOCKET) */
#endif /* defined(GRPC_POSIX_SOCKET_EV_EPOLLEX) */
#endif /* !defined(GRPC_LINUX_EPOLL_CREATE1) */

@ -1721,7 +1721,7 @@ const grpc_event_engine_vtable* grpc_init_epollsig_linux(
}
#else /* defined(GRPC_LINUX_EPOLL_CREATE1) */
#if defined(GRPC_POSIX_SOCKET)
#if defined(GRPC_POSIX_SOCKET_EV_EPOLLSIG)
#include "src/core/lib/iomgr/ev_epollsig_linux.h"
/* If GRPC_LINUX_EPOLL_CREATE1 is not defined, it means
epoll_create1 is not available. Return NULL */

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#ifdef GRPC_POSIX_SOCKET_EV_POLL
#include "src/core/lib/iomgr/ev_poll_posix.h"
@ -1761,4 +1761,4 @@ const grpc_event_engine_vtable* grpc_init_poll_cv_posix(bool explicit_request) {
return &vtable;
}
#endif
#endif /* GRPC_POSIX_SOCKET_EV_POLL */

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#ifdef GRPC_POSIX_SOCKET_EV
#include "src/core/lib/iomgr/ev_posix.h"
@ -334,4 +334,4 @@ void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd) {
g_event_engine->pollset_set_del_fd(pollset_set, fd);
}
#endif // GRPC_POSIX_SOCKET
#endif // GRPC_POSIX_SOCKET_EV

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#ifdef GRPC_POSIX_SOCKET_IOMGR
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/iomgr/ev_posix.h"
@ -64,4 +64,4 @@ void grpc_set_default_iomgr_platform() {
grpc_set_iomgr_platform_vtable(&vtable);
}
#endif /* GRPC_POSIX_SOCKET */
#endif /* GRPC_POSIX_SOCKET_IOMGR */

@ -61,8 +61,11 @@ bool grpc_polling_entity_is_empty(const grpc_polling_entity* pollent) {
void grpc_polling_entity_add_to_pollset_set(grpc_polling_entity* pollent,
grpc_pollset_set* pss_dst) {
if (pollent->tag == GRPC_POLLS_POLLSET) {
GPR_ASSERT(pollent->pollent.pollset != nullptr);
grpc_pollset_set_add_pollset(pss_dst, pollent->pollent.pollset);
// CFStream does not use file destriptors. When CFStream is used, the fd
// pollset is possible to be null.
if (pollent->pollent.pollset != nullptr) {
grpc_pollset_set_add_pollset(pss_dst, pollent->pollent.pollset);
}
} else if (pollent->tag == GRPC_POLLS_POLLSET_SET) {
GPR_ASSERT(pollent->pollent.pollset_set != nullptr);
grpc_pollset_set_add_pollset_set(pss_dst, pollent->pollent.pollset_set);
@ -75,8 +78,14 @@ void grpc_polling_entity_add_to_pollset_set(grpc_polling_entity* pollent,
void grpc_polling_entity_del_from_pollset_set(grpc_polling_entity* pollent,
grpc_pollset_set* pss_dst) {
if (pollent->tag == GRPC_POLLS_POLLSET) {
#ifdef GRPC_CFSTREAM
if (pollent->pollent.pollset != nullptr) {
grpc_pollset_set_del_pollset(pss_dst, pollent->pollent.pollset);
}
#else
GPR_ASSERT(pollent->pollent.pollset != nullptr);
grpc_pollset_set_del_pollset(pss_dst, pollent->pollent.pollset);
#endif
} else if (pollent->tag == GRPC_POLLS_POLLSET_SET) {
GPR_ASSERT(pollent->pollent.pollset_set != nullptr);
grpc_pollset_set_del_pollset_set(pss_dst, pollent->pollent.pollset_set);

@ -97,7 +97,26 @@
#define GRPC_MSG_IOVLEN_TYPE int
#define GRPC_POSIX_FORK 1
#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1
#ifdef GRPC_CFSTREAM
#define GRPC_POSIX_SOCKET_IOMGR 1
#define GRPC_CFSTREAM_ENDPOINT 1
#define GRPC_CFSTREAM_CLIENT 1
#define GRPC_POSIX_SOCKET_ARES_EV_DRIVER 1
#define GRPC_POSIX_SOCKET_EV 1
#define GRPC_POSIX_SOCKET_EV_EPOLL1 1
#define GRPC_POSIX_SOCKET_EV_EPOLLEX 1
#define GRPC_POSIX_SOCKET_EV_EPOLLSIG 1
#define GRPC_POSIX_SOCKET_EV_POLL 1
#define GRPC_POSIX_SOCKET_RESOLVE_ADDRESS 1
#define GRPC_POSIX_SOCKET_SOCKADDR 1
#define GRPC_POSIX_SOCKET_SOCKET_FACTORY 1
#define GRPC_POSIX_SOCKET_TCP 1
#define GRPC_POSIX_SOCKET_TCP_SERVER 1
#define GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON 1
#define GRPC_POSIX_SOCKET_UTILS_COMMON 1
#else
#define GRPC_POSIX_SOCKET 1
#endif
#define GRPC_POSIX_SOCKETUTILS 1
#define GRPC_POSIX_SYSCONF 1
#define GRPC_POSIX_WAKEUP_FD 1
@ -131,12 +150,30 @@
#endif
#if defined(GRPC_POSIX_SOCKET) + defined(GRPC_WINSOCK_SOCKET) + \
defined(GRPC_CUSTOM_SOCKET) != \
defined(GRPC_CUSTOM_SOCKET) + defined(GRPC_CFSTREAM) != \
1
#error \
"Must define exactly one of GRPC_POSIX_SOCKET, GRPC_WINSOCK_SOCKET, GRPC_CUSTOM_SOCKET"
#endif
#ifdef GRPC_POSIX_SOCKET
#define GRPC_POSIX_SOCKET_ARES_EV_DRIVER 1
#define GRPC_POSIX_SOCKET_EV 1
#define GRPC_POSIX_SOCKET_EV_EPOLLEX 1
#define GRPC_POSIX_SOCKET_EV_EPOLLSIG 1
#define GRPC_POSIX_SOCKET_EV_POLL 1
#define GRPC_POSIX_SOCKET_EV_EPOLL1 1
#define GRPC_POSIX_SOCKET_IOMGR 1
#define GRPC_POSIX_SOCKET_RESOLVE_ADDRESS 1
#define GRPC_POSIX_SOCKET_SOCKADDR 1
#define GRPC_POSIX_SOCKET_SOCKET_FACTORY 1
#define GRPC_POSIX_SOCKET_TCP 1
#define GRPC_POSIX_SOCKET_TCP_CLIENT 1
#define GRPC_POSIX_SOCKET_TCP_SERVER 1
#define GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON 1
#define GRPC_POSIX_SOCKET_UTILS_COMMON 1
#endif
#if defined(GRPC_POSIX_HOST_NAME_MAX) && defined(GRPC_POSIX_SYSCONF)
#error "Cannot define both GRPC_POSIX_HOST_NAME_MAX and GRPC_POSIX_SYSCONF"
#endif

@ -33,7 +33,7 @@
#include <ws2tcpip.h>
#endif
#ifdef GRPC_POSIX_SOCKET
#if defined(GRPC_POSIX_SOCKET) || defined(GRPC_CFSTREAM)
#include <sys/socket.h>
#endif

@ -19,7 +19,7 @@
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#ifdef GRPC_POSIX_SOCKET_RESOLVE_ADDRESS
#include "src/core/lib/iomgr/sockaddr.h"

@ -23,7 +23,7 @@
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#ifdef GRPC_POSIX_SOCKET_SOCKADDR
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#ifdef GRPC_POSIX_SOCKET_SOCKET_FACTORY
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/useful.h"

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
#include "src/core/lib/iomgr/socket_utils.h"
#include "src/core/lib/iomgr/socket_utils_posix.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 */

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#ifdef GRPC_POSIX_SOCKET_TCP_CLIENT
#include "src/core/lib/iomgr/tcp_client_posix.h"

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#ifdef GRPC_POSIX_SOCKET_TCP
#include "src/core/lib/iomgr/network_status_tracker.h"
#include "src/core/lib/iomgr/tcp_posix.h"
@ -819,4 +819,4 @@ void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd,
TCP_UNREF(tcp, "destroy");
}
#endif
#endif /* GRPC_POSIX_SOCKET_TCP */

@ -25,7 +25,7 @@
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#ifdef GRPC_POSIX_SOCKET_TCP_SERVER
#include "src/core/lib/iomgr/tcp_server.h"
@ -559,4 +559,4 @@ grpc_tcp_server_vtable grpc_posix_tcp_server_vtable = {
tcp_server_shutdown_starting_add,
tcp_server_unref,
tcp_server_shutdown_listeners};
#endif
#endif /* GRPC_POSIX_SOCKET_TCP_SERVER */

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#ifdef GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON
#include "src/core/lib/iomgr/tcp_server_utils_posix.h"
@ -217,4 +217,4 @@ error:
return ret;
}
#endif /* GRPC_POSIX_SOCKET */
#endif /* GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON */

@ -333,14 +333,26 @@ void grpc_slice_buffer_trim_end(grpc_slice_buffer* sb, size_t n,
size_t slice_len = GRPC_SLICE_LENGTH(slice);
if (slice_len > n) {
sb->slices[idx] = grpc_slice_split_head(&slice, slice_len - n);
grpc_slice_buffer_add_indexed(garbage, slice);
if (garbage) {
grpc_slice_buffer_add_indexed(garbage, slice);
} else {
grpc_slice_unref_internal(slice);
}
return;
} else if (slice_len == n) {
grpc_slice_buffer_add_indexed(garbage, slice);
if (garbage) {
grpc_slice_buffer_add_indexed(garbage, slice);
} else {
grpc_slice_unref_internal(slice);
}
sb->count = idx;
return;
} else {
grpc_slice_buffer_add_indexed(garbage, slice);
if (garbage) {
grpc_slice_buffer_add_indexed(garbage, slice);
} else {
grpc_slice_unref_internal(slice);
}
n -= slice_len;
sb->count = idx;
}

@ -184,7 +184,8 @@ void grpc_transport_set_pops(grpc_transport* transport, grpc_stream* stream,
nullptr) {
transport->vtable->set_pollset_set(transport, stream, pollset_set);
} else {
abort();
// No-op for empty pollset. Empty pollset is possible when using
// non-fd-based event engines such as CFStream.
}
}

@ -20,6 +20,14 @@
#import <grpc/grpc.h>
#ifdef GRPC_CFSTREAM
const grpc_completion_queue_attributes kCompletionQueueAttr = {GRPC_CQ_CURRENT_VERSION,
GRPC_CQ_NEXT, GRPC_CQ_NON_POLLING};
#else
const grpc_completion_queue_attributes kCompletionQueueAttr = {
GRPC_CQ_CURRENT_VERSION, GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING};
#endif
@implementation GRPCCompletionQueue
+ (instancetype)completionQueue {
@ -33,7 +41,8 @@
- (instancetype)init {
if ((self = [super init])) {
_unmanagedQueue = grpc_completion_queue_create_for_next(NULL);
_unmanagedQueue = grpc_completion_queue_create(
grpc_completion_queue_factory_lookup(&kCompletionQueueAttr), &kCompletionQueueAttr, NULL);
// This is for the following block to capture the pointer by value (instead
// of retaining self and doing self->_unmanagedQueue). This is essential

@ -36,6 +36,27 @@ GRPC_LOCAL_SRC = '../../..'
end
end
%w(
InteropTestsRemoteCFStream
InteropTestsLocalSSLCFStream
InteropTestsLocalCleartextCFStream
).each do |target_name|
target target_name do
pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true
pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
pod 'gRPC/CFStream', :path => GRPC_LOCAL_SRC
pod 'gRPC-Core/CFStream-Implementation', :path => GRPC_LOCAL_SRC
pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC
pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC, :inhibit_warnings => true
pod 'RemoteTest', :path => "RemoteTestClient", :inhibit_warnings => true
end
end
%w(
CoreCronetEnd2EndTests
CronetUnitTests
@ -65,7 +86,7 @@ end
# TODO(jcanizales): Send a PR to Cocoapods to get rid of this need.
pre_install do |installer|
# This is the gRPC-Core podspec object, as initialized by its podspec file.
grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec
grpc_core_spec = installer.pod_targets.find{|t| t.name.start_with?('gRPC-Core')}.root_spec
# Copied from gRPC-Core.podspec, except for the adjusted src_root:
src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
@ -96,7 +117,11 @@ post_install do |installer|
# GPR_UNREACHABLE_CODE causes "Control may reach end of non-void
# function" warning
config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CRONET_WITH_PACKET_COALESCING=1'
if target.name.include?('CFStream')
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CFSTREAM=1'
else
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CRONET_WITH_PACKET_COALESCING=1'
end
end
end
@ -104,7 +129,7 @@ post_install do |installer|
# the test target 'InteropTestsRemoteWithCronet'
# Activate GRPCCall+InternalTests functions for the dedicated build configuration 'Test', which will
# be used by all test targets using it.
if target.name == 'gRPC'
if target.name == 'gRPC' || target.name.start_with?('gRPC.')
target.build_configurations.each do |config|
if config.name == 'Cronet'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_COMPILE_WITH_CRONET=1 GRPC_TEST_OBJC=1'

File diff suppressed because it is too large Load Diff

@ -26,6 +26,7 @@
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@ -66,6 +67,7 @@
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

@ -26,6 +26,7 @@
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@ -57,6 +58,7 @@
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

@ -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>

@ -26,6 +26,7 @@
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@ -60,6 +61,7 @@
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

@ -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>

@ -53,7 +53,7 @@ while [ $retries -lt 3 ]; do
out=$(xcodebuild \
-workspace Tests.xcworkspace \
-scheme AllTests \
-destination name="iPhone 6" \
-destination name="iPhone 8" \
HOST_PORT_LOCALSSL=localhost:5051 \
HOST_PORT_LOCAL=localhost:5050 \
HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \
@ -83,7 +83,7 @@ echo "TIME: $(date)"
xcodebuild \
-workspace Tests.xcworkspace \
-scheme CoreCronetEnd2EndTests \
-destination name="iPhone 6" \
-destination name="iPhone 8" \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
@ -113,7 +113,7 @@ echo "TIME: $(date)"
xcodebuild \
-workspace Tests.xcworkspace \
-scheme CronetUnitTests \
-destination name="iPhone 6" \
-destination name="iPhone 8" \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
@ -123,11 +123,44 @@ echo "TIME: $(date)"
xcodebuild \
-workspace Tests.xcworkspace \
-scheme InteropTestsRemoteWithCronet \
-destination name="iPhone 6" \
-destination name="iPhone 8" \
HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
echo "TIME: $(date)"
xcodebuild \
-workspace Tests.xcworkspace \
-scheme InteropTestsRemoteCFStream \
-destination name="iPhone 8" \
HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
echo "TIME: $(date)"
xcodebuild \
-workspace Tests.xcworkspace \
-scheme InteropTestsLocalCleartextCFStream \
-destination name="iPhone 8" \
HOST_PORT_LOCAL=localhost:5050 \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
echo "TIME: $(date)"
xcodebuild \
-workspace Tests.xcworkspace \
-scheme InteropTestsLocalSSLCFStream \
-destination name="iPhone 8" \
HOST_PORT_LOCALSSL=localhost:5051 \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
exit 0

@ -68,6 +68,14 @@
excl = grpc_private_files(libs)
return [file for file in out if not file in excl]
def cfstream_private_headers(libs):
out = grpc_lib_files(libs, ("grpc_cfstream",), ("own_headers",))
return out
def cfstream_private_files(libs):
out = grpc_lib_files(libs, ("grpc_cfstream",), ("own_src", "own_headers"))
return out
def ruby_multiline_list(files, indent):
return (',\n' + indent*' ').join('\'%s\'' % f for f in files)
%>
@ -175,6 +183,16 @@
ss.private_header_files = ${ruby_multiline_list(grpc_private_headers(libs), 30)}
end
s.subspec 'CFStream-Implementation' do |ss|
ss.header_mappings_dir = '.'
ss.dependency "#{s.name}/Implementation", version
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1'
}
ss.source_files = ${ruby_multiline_list(cfstream_private_files(filegroups), 22)}
ss.private_header_files = ${ruby_multiline_list(cfstream_private_headers(filegroups), 30)}
end
s.subspec 'Cronet-Interface' do |ss|
ss.header_mappings_dir = 'include/grpc'
ss.source_files = ${ruby_multiline_list(grpc_cronet_public_headers(libs), 22)}

@ -43,12 +43,24 @@
s.header_dir = name
src_dir = 'src/objective-c/ProtoRPC'
s.source_files = "#{src_dir}/*.{h,m}"
s.header_mappings_dir = "#{src_dir}"
s.dependency 'gRPC', version
s.dependency 'gRPC-RxLibrary', version
s.dependency 'Protobuf', '~> 3.0'
s.subspec 'Main' do |ss|
ss.header_mappings_dir = "#{src_dir}"
ss.dependency 'gRPC', version
ss.dependency 'gRPC-RxLibrary', version
ss.dependency 'Protobuf', '~> 3.0'
ss.source_files = "#{src_dir}/*.{h,m}"
end
s.subspec 'CFStream' do |ss|
ss.dependency 'gRPC/CFStream', version
ss.dependency "#{s.name}/Main", version
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1'
}
end
s.pod_target_xcconfig = {
# This is needed by all pods that depend on Protobuf:
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1',

@ -65,6 +65,16 @@
ss.dependency 'gRPC-Core', version
end
# This subspec is mutually exclusive with the `Main` subspec
s.subspec 'CFStream' do |ss|
ss.dependency 'gRPC-Core/CFStream-Implementation', version
ss.dependency "#{s.name}/Main", version
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1'
}
end
s.subspec 'GID' do |ss|
ss.ios.deployment_target = '7.0'

@ -0,0 +1,201 @@
/*
*
* 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.
*
*/
#import <XCTest/XCTest.h>
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_CFSTREAM
#include <netinet/in.h>
#include <grpc/impl/codegen/sync.h>
#include <grpc/support/sync.h>
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "test/core/util/test_config.h"
// static int g_connections_complete = 0;
static gpr_mu g_mu;
static int g_connections_complete = 0;
static grpc_endpoint* g_connecting = nullptr;
static void finish_connection() {
gpr_mu_lock(&g_mu);
g_connections_complete++;
gpr_mu_unlock(&g_mu);
}
static void must_succeed(void* arg, grpc_error* error) {
GPR_ASSERT(g_connecting != nullptr);
GPR_ASSERT(error == GRPC_ERROR_NONE);
grpc_endpoint_shutdown(g_connecting, GRPC_ERROR_CREATE_FROM_STATIC_STRING("must_succeed called"));
grpc_endpoint_destroy(g_connecting);
g_connecting = nullptr;
finish_connection();
}
static void must_fail(void* arg, grpc_error* error) {
GPR_ASSERT(g_connecting == nullptr);
GPR_ASSERT(error != GRPC_ERROR_NONE);
const char* error_str = grpc_error_string(error);
NSLog(@"%s", error_str);
finish_connection();
}
@interface CFStreamClientTests : XCTestCase
@end
@implementation CFStreamClientTests
+ (void)setUp {
grpc_init();
gpr_mu_init(&g_mu);
}
+ (void)tearDown {
grpc_shutdown();
}
- (void)testSucceeds {
grpc_resolved_address resolved_addr;
struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
int svr_fd;
int r;
int connections_complete_before;
grpc_closure done;
grpc_core::ExecCtx exec_ctx;
gpr_log(GPR_DEBUG, "test_succeeds");
memset(&resolved_addr, 0, sizeof(resolved_addr));
resolved_addr.len = sizeof(struct sockaddr_in);
addr->sin_family = AF_INET;
/* create a dummy server */
svr_fd = socket(AF_INET, SOCK_STREAM, 0);
GPR_ASSERT(svr_fd >= 0);
GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr.len));
GPR_ASSERT(0 == listen(svr_fd, 1));
gpr_mu_lock(&g_mu);
connections_complete_before = g_connections_complete;
gpr_mu_unlock(&g_mu);
/* connect to it */
GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr.len) == 0);
GRPC_CLOSURE_INIT(&done, must_succeed, nullptr, grpc_schedule_on_exec_ctx);
grpc_tcp_client_connect(&done, &g_connecting, nullptr, nullptr, &resolved_addr,
GRPC_MILLIS_INF_FUTURE);
/* await the connection */
do {
resolved_addr.len = sizeof(addr);
r = accept(svr_fd, reinterpret_cast<struct sockaddr*>(addr),
reinterpret_cast<socklen_t*>(&resolved_addr.len));
} while (r == -1 && errno == EINTR);
GPR_ASSERT(r >= 0);
close(r);
grpc_core::ExecCtx::Get()->Flush();
/* wait for the connection callback to finish */
gpr_mu_lock(&g_mu);
NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5];
while (connections_complete_before == g_connections_complete) {
gpr_mu_unlock(&g_mu);
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline];
gpr_mu_lock(&g_mu);
}
XCTAssertGreaterThan(g_connections_complete, connections_complete_before);
gpr_mu_unlock(&g_mu);
}
- (void)testFails {
grpc_core::ExecCtx exec_ctx;
grpc_resolved_address resolved_addr;
struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
int connections_complete_before;
grpc_closure done;
int svr_fd;
gpr_log(GPR_DEBUG, "test_fails");
memset(&resolved_addr, 0, sizeof(resolved_addr));
resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
addr->sin_family = AF_INET;
svr_fd = socket(AF_INET, SOCK_STREAM, 0);
GPR_ASSERT(svr_fd >= 0);
GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr*)addr, (socklen_t)resolved_addr.len));
GPR_ASSERT(0 == listen(svr_fd, 1));
GPR_ASSERT(getsockname(svr_fd, (struct sockaddr*)addr, (socklen_t*)&resolved_addr.len) == 0);
close(svr_fd);
gpr_mu_lock(&g_mu);
connections_complete_before = g_connections_complete;
gpr_mu_unlock(&g_mu);
/* connect to a broken address */
GRPC_CLOSURE_INIT(&done, must_fail, nullptr, grpc_schedule_on_exec_ctx);
grpc_tcp_client_connect(&done, &g_connecting, nullptr, nullptr, &resolved_addr,
GRPC_MILLIS_INF_FUTURE);
grpc_core::ExecCtx::Get()->Flush();
/* wait for the connection callback to finish */
gpr_mu_lock(&g_mu);
NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:5];
while (g_connections_complete == connections_complete_before) {
gpr_mu_unlock(&g_mu);
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline];
gpr_mu_lock(&g_mu);
}
XCTAssertGreaterThan(g_connections_complete, connections_complete_before);
gpr_mu_unlock(&g_mu);
}
@end
#else // GRPC_CFSTREAM
// Dummy test suite
@interface CFStreamClientTests : XCTestCase
@end
@implementation CFStreamClientTests
- (void)setUp {
[super setUp];
}
- (void)tearDown {
[super tearDown];
}
@end
#endif // GRPC_CFSTREAM

@ -0,0 +1,344 @@
/*
*
* 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.
*
*/
#import <XCTest/XCTest.h>
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_CFSTREAM
#include <netinet/in.h>
#include <grpc/impl/codegen/sync.h>
#include <grpc/support/sync.h>
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "test/core/util/test_config.h"
static const int kConnectTimeout = 5;
static const int kWriteTimeout = 5;
static const int kReadTimeout = 5;
static const int kBufferSize = 10000;
static const int kRunLoopTimeout = 1;
static void set_atm(void *arg, grpc_error *error) {
gpr_atm *p = static_cast<gpr_atm *>(arg);
gpr_atm_full_cas(p, -1, reinterpret_cast<gpr_atm>(error));
}
static void init_event_closure(grpc_closure *closure, gpr_atm *atm) {
*atm = -1;
GRPC_CLOSURE_INIT(closure, set_atm, static_cast<void *>(atm), grpc_schedule_on_exec_ctx);
}
static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const char *buffer,
size_t buffer_len) {
if (slices->length != buffer_len) {
return false;
}
for (int i = 0; i < slices->count; i++) {
grpc_slice slice = slices->slices[i];
if (0 != memcmp(buffer, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice))) {
return false;
}
buffer += GRPC_SLICE_LENGTH(slice);
}
return true;
}
@interface CFStreamEndpointTests : XCTestCase
@end
@implementation CFStreamEndpointTests {
grpc_endpoint *ep_;
int svr_fd_;
}
- (BOOL)waitForEvent:(gpr_atm *)event timeout:(int)timeout {
grpc_core::ExecCtx::Get()->Flush();
NSDate *deadline = [NSDate dateWithTimeIntervalSinceNow:kConnectTimeout];
while (gpr_atm_acq_load(event) == -1 && [deadline timeIntervalSinceNow] > 0) {
NSDate *deadline = [NSDate dateWithTimeIntervalSinceNow:kRunLoopTimeout];
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:deadline];
}
return (gpr_atm_acq_load(event) != -1);
}
+ (void)setUp {
grpc_init();
}
+ (void)tearDown {
grpc_shutdown();
}
- (void)setUp {
self.continueAfterFailure = NO;
// Set up CFStream connection before testing the endpoint
grpc_core::ExecCtx exec_ctx;
grpc_resolved_address resolved_addr;
struct sockaddr_in *addr = reinterpret_cast<struct sockaddr_in *>(resolved_addr.addr);
int svr_fd;
int r;
gpr_atm connected = -1;
grpc_closure done;
gpr_log(GPR_DEBUG, "test_succeeds");
memset(&resolved_addr, 0, sizeof(resolved_addr));
resolved_addr.len = sizeof(struct sockaddr_in);
addr->sin_family = AF_INET;
/* create a dummy server */
svr_fd = socket(AF_INET, SOCK_STREAM, 0);
XCTAssertGreaterThanOrEqual(svr_fd, 0);
XCTAssertEqual(bind(svr_fd, (struct sockaddr *)addr, (socklen_t)resolved_addr.len), 0);
XCTAssertEqual(listen(svr_fd, 1), 0);
/* connect to it */
XCTAssertEqual(getsockname(svr_fd, (struct sockaddr *)addr, (socklen_t *)&resolved_addr.len), 0);
init_event_closure(&done, &connected);
grpc_tcp_client_connect(&done, &ep_, nullptr, nullptr, &resolved_addr, GRPC_MILLIS_INF_FUTURE);
/* await the connection */
do {
resolved_addr.len = sizeof(addr);
r = accept(svr_fd, reinterpret_cast<struct sockaddr *>(addr),
reinterpret_cast<socklen_t *>(&resolved_addr.len));
} while (r == -1 && errno == EINTR);
XCTAssertGreaterThanOrEqual(r, 0);
svr_fd_ = r;
/* wait for the connection callback to finish */
XCTAssertEqual([self waitForEvent:&connected timeout:kConnectTimeout], YES);
XCTAssertEqual(reinterpret_cast<grpc_error *>(connected), GRPC_ERROR_NONE);
}
- (void)tearDown {
grpc_core::ExecCtx exec_ctx;
close(svr_fd_);
grpc_endpoint_destroy(ep_);
}
- (void)testReadWrite {
grpc_core::ExecCtx exec_ctx;
gpr_atm read;
grpc_closure read_done;
grpc_slice_buffer read_slices;
grpc_slice_buffer read_one_slice;
gpr_atm write;
grpc_closure write_done;
grpc_slice_buffer write_slices;
grpc_slice slice;
char write_buffer[kBufferSize];
char read_buffer[kBufferSize];
size_t recv_size = 0;
grpc_slice_buffer_init(&write_slices);
slice = grpc_slice_from_static_buffer(write_buffer, kBufferSize);
grpc_slice_buffer_add(&write_slices, slice);
init_event_closure(&write_done, &write);
grpc_endpoint_write(ep_, &write_slices, &write_done);
XCTAssertEqual([self waitForEvent:&write timeout:kWriteTimeout], YES);
XCTAssertEqual(reinterpret_cast<grpc_error *>(write), GRPC_ERROR_NONE);
while (recv_size < kBufferSize) {
ssize_t size = recv(svr_fd_, read_buffer, kBufferSize, 0);
XCTAssertGreaterThanOrEqual(size, 0);
recv_size += size;
}
XCTAssertEqual(recv_size, kBufferSize);
XCTAssertEqual(memcmp(read_buffer, write_buffer, kBufferSize), 0);
ssize_t send_size = send(svr_fd_, read_buffer, kBufferSize, 0);
XCTAssertGreaterThanOrEqual(send_size, 0);
grpc_slice_buffer_init(&read_slices);
grpc_slice_buffer_init(&read_one_slice);
while (read_slices.length < kBufferSize) {
init_event_closure(&read_done, &read);
grpc_endpoint_read(ep_, &read_one_slice, &read_done);
XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], YES);
XCTAssertEqual(reinterpret_cast<grpc_error *>(read), GRPC_ERROR_NONE);
grpc_slice_buffer_move_into(&read_one_slice, &read_slices);
XCTAssertLessThanOrEqual(read_slices.length, kBufferSize);
}
XCTAssertTrue(compare_slice_buffer_with_buffer(&read_slices, read_buffer, kBufferSize));
grpc_endpoint_shutdown(ep_, GRPC_ERROR_NONE);
grpc_slice_buffer_reset_and_unref(&read_slices);
grpc_slice_buffer_reset_and_unref(&write_slices);
grpc_slice_buffer_reset_and_unref(&read_one_slice);
}
- (void)testShutdownBeforeRead {
grpc_core::ExecCtx exec_ctx;
gpr_atm read;
grpc_closure read_done;
grpc_slice_buffer read_slices;
gpr_atm write;
grpc_closure write_done;
grpc_slice_buffer write_slices;
grpc_slice slice;
char write_buffer[kBufferSize];
char read_buffer[kBufferSize];
size_t recv_size = 0;
grpc_slice_buffer_init(&read_slices);
init_event_closure(&read_done, &read);
grpc_endpoint_read(ep_, &read_slices, &read_done);
grpc_slice_buffer_init(&write_slices);
slice = grpc_slice_from_static_buffer(write_buffer, kBufferSize);
grpc_slice_buffer_add(&write_slices, slice);
init_event_closure(&write_done, &write);
grpc_endpoint_write(ep_, &write_slices, &write_done);
XCTAssertEqual([self waitForEvent:&write timeout:kWriteTimeout], YES);
XCTAssertEqual(reinterpret_cast<grpc_error *>(write), GRPC_ERROR_NONE);
while (recv_size < kBufferSize) {
ssize_t size = recv(svr_fd_, read_buffer, kBufferSize, 0);
XCTAssertGreaterThanOrEqual(size, 0);
recv_size += size;
}
XCTAssertEqual(recv_size, kBufferSize);
XCTAssertEqual(memcmp(read_buffer, write_buffer, kBufferSize), 0);
XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], NO);
grpc_endpoint_shutdown(ep_, GRPC_ERROR_NONE);
grpc_core::ExecCtx::Get()->Flush();
XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], YES);
XCTAssertNotEqual(reinterpret_cast<grpc_error *>(read), GRPC_ERROR_NONE);
grpc_slice_buffer_reset_and_unref(&read_slices);
grpc_slice_buffer_reset_and_unref(&write_slices);
}
- (void)testRemoteClosed {
grpc_core::ExecCtx exec_ctx;
gpr_atm read;
grpc_closure read_done;
grpc_slice_buffer read_slices;
gpr_atm write;
grpc_closure write_done;
grpc_slice_buffer write_slices;
grpc_slice slice;
char write_buffer[kBufferSize];
char read_buffer[kBufferSize];
size_t recv_size = 0;
init_event_closure(&read_done, &read);
grpc_slice_buffer_init(&read_slices);
grpc_endpoint_read(ep_, &read_slices, &read_done);
grpc_slice_buffer_init(&write_slices);
slice = grpc_slice_from_static_buffer(write_buffer, kBufferSize);
grpc_slice_buffer_add(&write_slices, slice);
init_event_closure(&write_done, &write);
grpc_endpoint_write(ep_, &write_slices, &write_done);
XCTAssertEqual([self waitForEvent:&write timeout:kWriteTimeout], YES);
XCTAssertEqual(reinterpret_cast<grpc_error *>(write), GRPC_ERROR_NONE);
while (recv_size < kBufferSize) {
ssize_t size = recv(svr_fd_, read_buffer, kBufferSize, 0);
XCTAssertGreaterThanOrEqual(size, 0);
recv_size += size;
}
XCTAssertEqual(recv_size, kBufferSize);
XCTAssertEqual(memcmp(read_buffer, write_buffer, kBufferSize), 0);
close(svr_fd_);
XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], YES);
XCTAssertNotEqual(reinterpret_cast<grpc_error *>(read), GRPC_ERROR_NONE);
grpc_endpoint_shutdown(ep_, GRPC_ERROR_NONE);
grpc_slice_buffer_reset_and_unref(&read_slices);
grpc_slice_buffer_reset_and_unref(&write_slices);
}
- (void)testRemoteReset {
grpc_core::ExecCtx exec_ctx;
gpr_atm read;
grpc_closure read_done;
grpc_slice_buffer read_slices;
init_event_closure(&read_done, &read);
grpc_slice_buffer_init(&read_slices);
grpc_endpoint_read(ep_, &read_slices, &read_done);
struct linger so_linger;
so_linger.l_onoff = 1;
so_linger.l_linger = 0;
setsockopt(svr_fd_, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger));
close(svr_fd_);
XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], YES);
XCTAssertNotEqual(reinterpret_cast<grpc_error *>(read), GRPC_ERROR_NONE);
grpc_endpoint_shutdown(ep_, GRPC_ERROR_NONE);
grpc_slice_buffer_reset_and_unref(&read_slices);
}
@end
#else // GRPC_CFSTREAM
// Dummy test suite
@interface CFStreamEndpointTests : XCTestCase
@end
@implementation CFStreamEndpointTests
- (void)setUp {
[super setUp];
}
- (void)tearDown {
[super tearDown];
}
@end
#endif // GRPC_CFSTREAM

@ -0,0 +1,338 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 48;
objects = {
/* Begin PBXBuildFile section */
5E143B892069D72200715A6E /* CFStreamClientTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5E143B882069D72200715A6E /* CFStreamClientTests.mm */; };
5E143B8C206B5F9F00715A6E /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5E143B8A2069D72700715A6E /* Info.plist */; };
5E143B8E206C5B9A00715A6E /* CFStreamEndpointTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5E143B8D206C5B9A00715A6E /* CFStreamEndpointTests.mm */; };
604EA96D9CD477A8EA411BDF /* libPods-CFStreamTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AFFA154D492751CEAC05D591 /* libPods-CFStreamTests.a */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
5E143B792069D67300715A6E /* CFStreamTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CFStreamTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
5E143B882069D72200715A6E /* CFStreamClientTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CFStreamClientTests.mm; sourceTree = "<group>"; };
5E143B8A2069D72700715A6E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5E143B8D206C5B9A00715A6E /* CFStreamEndpointTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CFStreamEndpointTests.mm; sourceTree = "<group>"; };
8CB4409E07E180CCA59987DF /* Pods-CFStreamTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CFStreamTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CFStreamTests/Pods-CFStreamTests.release.xcconfig"; sourceTree = "<group>"; };
9E3FAF9DA6B98ED4FE6D6848 /* Pods-CFStreamTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CFStreamTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CFStreamTests/Pods-CFStreamTests.debug.xcconfig"; sourceTree = "<group>"; };
AFFA154D492751CEAC05D591 /* libPods-CFStreamTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CFStreamTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
5E143B762069D67300715A6E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
604EA96D9CD477A8EA411BDF /* libPods-CFStreamTests.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
5E143B582069D67300715A6E = {
isa = PBXGroup;
children = (
5E143B8D206C5B9A00715A6E /* CFStreamEndpointTests.mm */,
5E143B8A2069D72700715A6E /* Info.plist */,
5E143B882069D72200715A6E /* CFStreamClientTests.mm */,
5E143B622069D67300715A6E /* Products */,
A331D95F7F230B507FBF6D22 /* Pods */,
6AC36F6C5DB5CA8F717D1B67 /* Frameworks */,
);
sourceTree = "<group>";
};
5E143B622069D67300715A6E /* Products */ = {
isa = PBXGroup;
children = (
5E143B792069D67300715A6E /* CFStreamTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
6AC36F6C5DB5CA8F717D1B67 /* Frameworks */ = {
isa = PBXGroup;
children = (
AFFA154D492751CEAC05D591 /* libPods-CFStreamTests.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
A331D95F7F230B507FBF6D22 /* Pods */ = {
isa = PBXGroup;
children = (
9E3FAF9DA6B98ED4FE6D6848 /* Pods-CFStreamTests.debug.xcconfig */,
8CB4409E07E180CCA59987DF /* Pods-CFStreamTests.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
5E143B782069D67300715A6E /* CFStreamTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5E143B852069D67300715A6E /* Build configuration list for PBXNativeTarget "CFStreamTests" */;
buildPhases = (
4EBA55D3E23FC6C84596E3D5 /* [CP] Check Pods Manifest.lock */,
5E143B752069D67300715A6E /* Sources */,
5E143B762069D67300715A6E /* Frameworks */,
5E143B772069D67300715A6E /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = CFStreamTests;
productName = CFStreamTestsTests;
productReference = 5E143B792069D67300715A6E /* CFStreamTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
5E143B592069D67300715A6E /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0920;
ORGANIZATIONNAME = gRPC;
TargetAttributes = {
5E143B782069D67300715A6E = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 5E143B5C2069D67300715A6E /* Build configuration list for PBXProject "CFStreamTests" */;
compatibilityVersion = "Xcode 8.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 5E143B582069D67300715A6E;
productRefGroup = 5E143B622069D67300715A6E /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
5E143B782069D67300715A6E /* CFStreamTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
5E143B772069D67300715A6E /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5E143B8C206B5F9F00715A6E /* Info.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
4EBA55D3E23FC6C84596E3D5 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-CFStreamTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
5E143B752069D67300715A6E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5E143B892069D72200715A6E /* CFStreamClientTests.mm in Sources */,
5E143B8E206C5B9A00715A6E /* CFStreamEndpointTests.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
5E143B802069D67300715A6E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
5E143B812069D67300715A6E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
5E143B862069D67300715A6E /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9E3FAF9DA6B98ED4FE6D6848 /* Pods-CFStreamTests.debug.xcconfig */;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"COCOAPODS=1",
"$(inherited)",
"PB_FIELD_32BIT=1",
"PB_NO_PACKED_STRUCTS=1",
"GRPC_CFSTREAM=1",
);
INFOPLIST_FILE = Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CFStreamTestsTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = ../../../../..;
};
name = Debug;
};
5E143B872069D67300715A6E /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 8CB4409E07E180CCA59987DF /* Pods-CFStreamTests.release.xcconfig */;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CFStreamTestsTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = ../../../../..;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
5E143B5C2069D67300715A6E /* Build configuration list for PBXProject "CFStreamTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5E143B802069D67300715A6E /* Debug */,
5E143B812069D67300715A6E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
5E143B852069D67300715A6E /* Build configuration list for PBXNativeTarget "CFStreamTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5E143B862069D67300715A6E /* Debug */,
5E143B872069D67300715A6E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 5E143B592069D67300715A6E /* Project object */;
}

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E143B782069D67300715A6E"
BuildableName = "CFStreamTests.xctest"
BlueprintName = "CFStreamTests"
ReferencedContainer = "container:CFStreamTests.xcodeproj">
</BuildableReference>
</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>

@ -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 = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableAddressSanitizer = "YES"
enableASanStackUseAfterReturn = "YES"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E143B782069D67300715A6E"
BuildableName = "CFStreamTests.xctest"
BlueprintName = "CFStreamTests"
ReferencedContainer = "container:CFStreamTests.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES"
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,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E143B782069D67300715A6E"
BuildableName = "CFStreamTests.xctest"
BlueprintName = "CFStreamTests"
ReferencedContainer = "container:CFStreamTests.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<AdditionalOptions>
<AdditionalOption
key = "DYLD_INSERT_LIBRARIES"
value = "/usr/lib/libgmalloc.dylib"
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
key = "NSZombieEnabled"
value = "YES"
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
key = "MallocGuardEdges"
value = ""
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
key = "MallocScribble"
value = ""
isEnabled = "YES">
</AdditionalOption>
</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,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableThreadSanitizer = "YES"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E143B782069D67300715A6E"
BuildableName = "CFStreamTests.xctest"
BlueprintName = "CFStreamTests"
ReferencedContainer = "container:CFStreamTests.xcodeproj">
</BuildableReference>
</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"
stopOnEveryThreadSanitizerIssue = "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,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

@ -0,0 +1,50 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
install! 'cocoapods', :deterministic_uuids => false
# Location of gRPC's repo root relative to this file.
GRPC_LOCAL_SRC = '../../../../..'
# Install the dependencies in the main target plus all test targets.
target 'CFStreamTests' do
pod 'gRPC-Core/CFStream-Implementation', :path => GRPC_LOCAL_SRC
end
pre_install do |installer|
# This is the gRPC-Core podspec object, as initialized by its podspec file.
grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec
# Copied from gRPC-Core.podspec, except for the adjusted src_root:
src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
grpc_core_spec.pod_target_xcconfig = {
'GRPC_SRC_ROOT' => src_root,
'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
# If we don't set these two settings, `include/grpc/support/time.h` and
# `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
# build.
'USE_HEADERMAP' => 'NO',
'ALWAYS_SEARCH_USER_PATHS' => 'NO',
}
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'YES'
end
# CocoaPods creates duplicated library targets of gRPC-Core when the test targets include
# non-default subspecs of gRPC-Core. All of these library targets start with prefix 'gRPC-Core'
# and require the same error suppresion.
if target.name.start_with?('gRPC-Core')
target.build_configurations.each do |config|
# TODO(zyc): Remove this setting after the issue is resolved
# GPR_UNREACHABLE_CODE causes "Control may reach end of non-void
# function" warning
config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO'
end
end
end
end

@ -0,0 +1,39 @@
#!/bin/bash
# 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.
# Don't run this script standalone. Instead, run from the repository root:
# ./tools/run_tests/run_tests.py -l objc
set -e
# CocoaPods requires the terminal to be using UTF-8 encoding.
export LANG=en_US.UTF-8
cd "$(dirname "$0")"
hash pod 2>/dev/null || { echo >&2 "Cocoapods needs to be installed."; exit 1; }
hash xcodebuild 2>/dev/null || {
echo >&2 "XCode command-line tools need to be installed."
exit 1
}
# clean the directory
rm -rf Pods
rm -rf CFStreamTests.xcworkspace
rm -f Podfile.lock
echo "TIME: $(date)"
pod install

@ -0,0 +1,67 @@
#!/bin/bash
# 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.
# Don't run this script standalone. Instead, run from the repository root:
# ./tools/run_tests/run_tests.py -l objc
set -ev
cd "$(dirname "$0")"
echo "TIME: $(date)"
XCODEBUILD_FILTER='(^CompileC |^Ld |^ *[^ ]*clang |^ *cd |^ *export |^Libtool |^ *[^ ]*libtool |^CpHeader |^ *builtin-copy )'
xcodebuild \
-workspace CFStreamTests.xcworkspace \
-scheme CFStreamTests \
-destination name="iPhone 8" \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
echo "TIME: $(date)"
xcodebuild \
-workspace CFStreamTests.xcworkspace \
-scheme CFStreamTests_Asan \
-destination name="iPhone 8" \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
echo "TIME: $(date)"
xcodebuild \
-workspace CFStreamTests.xcworkspace \
-scheme CFStreamTests_Tsan \
-destination name="iPhone 8" \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
echo "TIME: $(date)"
xcodebuild \
-workspace CFStreamTests.xcworkspace \
-scheme CFStreamTests_Msan \
-destination name="iPhone 8" \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -

@ -9744,6 +9744,32 @@
"third_party": false,
"type": "filegroup"
},
{
"deps": [
"gpr",
"gpr_base_headers",
"grpc_base_headers"
],
"headers": [
"src/core/lib/iomgr/cfstream_handle.h",
"src/core/lib/iomgr/endpoint_cfstream.h",
"src/core/lib/iomgr/error_cfstream.h"
],
"is_filegroup": true,
"language": "c",
"name": "grpc_cfstream",
"src": [
"src/core/lib/iomgr/cfstream_handle.cc",
"src/core/lib/iomgr/cfstream_handle.h",
"src/core/lib/iomgr/endpoint_cfstream.cc",
"src/core/lib/iomgr/endpoint_cfstream.h",
"src/core/lib/iomgr/error_cfstream.cc",
"src/core/lib/iomgr/error_cfstream.h",
"src/core/lib/iomgr/tcp_client_cfstream.cc"
],
"third_party": false,
"type": "filegroup"
},
{
"deps": [
"gpr",

@ -1114,6 +1114,12 @@ class ObjCLanguage(object):
'SCHEME': 'SwiftSample',
'EXAMPLE_PATH': 'src/objective-c/examples/SwiftSample'
}),
self.config.job_spec(
['test/core/iomgr/ios/CFStreamTests/run_tests.sh'],
timeout_seconds=10 * 60,
shortname='cfstream-tests',
cpu_cost=1e6,
environ=_FORCE_ENVIRON_FOR_WRAPPERS),
]
def pre_build_steps(self):
@ -1126,7 +1132,10 @@ class ObjCLanguage(object):
return []
def build_steps(self):
return [['src/objective-c/tests/build_tests.sh']]
return [
['src/objective-c/tests/build_tests.sh'],
['test/core/iomgr/ios/CFStreamTests/build_tests.sh'],
]
def post_tests_steps(self):
return []

@ -30,7 +30,8 @@ BANNED_EXCEPT = {
['src/core/lib/slice/slice_buffer.cc'],
'grpc_slice_ref(': ['src/core/lib/slice/slice.cc'],
'grpc_slice_unref(': ['src/core/lib/slice/slice.cc'],
'grpc_error_create(': ['src/core/lib/iomgr/error.cc'],
'grpc_error_create(':
['src/core/lib/iomgr/error.cc', 'src/core/lib/iomgr/error_cfstream.cc'],
'grpc_error_ref(': ['src/core/lib/iomgr/error.cc'],
'grpc_error_unref(': ['src/core/lib/iomgr/error.cc'],
'grpc_os_error(': ['src/core/lib/iomgr/error.cc'],

Loading…
Cancel
Save