mirror of https://github.com/grpc/grpc.git
commit
5810b53df3
240 changed files with 4852 additions and 2169 deletions
@ -0,0 +1,66 @@ |
||||
Pod::Spec.new do |s| |
||||
s.name = "HelloWorld" |
||||
s.version = "0.0.1" |
||||
s.license = "Apache License, Version 2.0" |
||||
s.authors = { 'gRPC contributors' => 'grpc-io@googlegroups.com' } |
||||
s.homepage = "https://grpc.io/" |
||||
s.summary = "HelloWorld example" |
||||
s.source = { :git => 'https://github.com/grpc/grpc.git' } |
||||
|
||||
s.ios.deployment_target = "7.1" |
||||
s.osx.deployment_target = "10.9" |
||||
|
||||
# Base directory where the .proto files are. |
||||
src = "../../protos" |
||||
|
||||
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. |
||||
s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0" |
||||
|
||||
# Pods directory corresponding to this app's Podfile, relative to the location of this podspec. |
||||
pods_root = 'Pods' |
||||
|
||||
# Path where Cocoapods downloads protoc and the gRPC plugin. |
||||
protoc_dir = "#{pods_root}/!ProtoCompiler" |
||||
protoc = "#{protoc_dir}/protoc" |
||||
plugin = "#{pods_root}/!ProtoCompiler-gRPCPlugin/grpc_objective_c_plugin" |
||||
|
||||
# Directory where the generated files will be placed. |
||||
dir = "#{pods_root}/#{s.name}" |
||||
|
||||
s.prepare_command = <<-CMD |
||||
mkdir -p #{dir} |
||||
#{protoc} \ |
||||
--plugin=protoc-gen-grpc=#{plugin} \ |
||||
--objc_out=#{dir} \ |
||||
--grpc_out=#{dir} \ |
||||
-I #{src} \ |
||||
-I #{protoc_dir} \ |
||||
#{src}/helloworld.proto |
||||
CMD |
||||
|
||||
# Files generated by protoc |
||||
s.subspec "Messages" do |ms| |
||||
ms.source_files = "#{dir}/*.pbobjc.{h,m}", "#{dir}/**/*.pbobjc.{h,m}" |
||||
ms.header_mappings_dir = dir |
||||
ms.requires_arc = false |
||||
# The generated files depend on the protobuf runtime. |
||||
ms.dependency "Protobuf" |
||||
end |
||||
|
||||
# Files generated by the gRPC plugin |
||||
s.subspec "Services" do |ss| |
||||
ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}" |
||||
ss.header_mappings_dir = dir |
||||
ss.requires_arc = true |
||||
# The generated files depend on the gRPC runtime, and on the files generated by protoc. |
||||
ss.dependency "gRPC-ProtoRPC" |
||||
ss.dependency "#{s.name}/Messages" |
||||
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', |
||||
# This is needed by all pods that depend on gRPC-RxLibrary: |
||||
'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES', |
||||
} |
||||
end |
@ -0,0 +1,399 @@ |
||||
// !$*UTF8*$! |
||||
{ |
||||
archiveVersion = 1; |
||||
classes = { |
||||
}; |
||||
objectVersion = 50; |
||||
objects = { |
||||
|
||||
/* Begin PBXBuildFile section */ |
||||
5EF711A4215174880077496F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EF711A3215174880077496F /* AppDelegate.m */; }; |
||||
5EF711A7215174880077496F /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EF711A6215174880077496F /* ViewController.m */; }; |
||||
5EF711A9215174890077496F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5EF711A8215174890077496F /* Assets.xcassets */; }; |
||||
5EF711AC215174890077496F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5EF711AA215174890077496F /* Main.storyboard */; }; |
||||
5EF711AF215174890077496F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EF711AE215174890077496F /* main.m */; }; |
||||
827B966E84F6A63FD0F3F6BC /* libPods-HelloWorld.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 369D887F6054EBA486218C69 /* libPods-HelloWorld.a */; }; |
||||
/* End PBXBuildFile section */ |
||||
|
||||
/* Begin PBXFileReference section */ |
||||
2AAF8E8BA7DBFD2D3886AA25 /* Pods-HelloWorld.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld.release.xcconfig"; path = "Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld.release.xcconfig"; sourceTree = "<group>"; }; |
||||
369D887F6054EBA486218C69 /* libPods-HelloWorld.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HelloWorld.a"; sourceTree = BUILT_PRODUCTS_DIR; }; |
||||
5EF7119F215174870077496F /* HelloWorld.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloWorld.app; sourceTree = BUILT_PRODUCTS_DIR; }; |
||||
5EF711A2215174880077496F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; }; |
||||
5EF711A3215174880077496F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; }; |
||||
5EF711A5215174880077496F /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; }; |
||||
5EF711A6215174880077496F /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; }; |
||||
5EF711A8215174890077496F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; |
||||
5EF711AB215174890077496F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; |
||||
5EF711AD215174890077496F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; |
||||
5EF711AE215174890077496F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; }; |
||||
5EF711B0215174890077496F /* HelloWorld.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = HelloWorld.entitlements; sourceTree = "<group>"; }; |
||||
CA4699782F6344C8E67C9FEE /* Pods-HelloWorld.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld.debug.xcconfig"; path = "Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld.debug.xcconfig"; sourceTree = "<group>"; }; |
||||
/* End PBXFileReference section */ |
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */ |
||||
5EF7119C215174870077496F /* Frameworks */ = { |
||||
isa = PBXFrameworksBuildPhase; |
||||
buildActionMask = 2147483647; |
||||
files = ( |
||||
827B966E84F6A63FD0F3F6BC /* libPods-HelloWorld.a in Frameworks */, |
||||
); |
||||
runOnlyForDeploymentPostprocessing = 0; |
||||
}; |
||||
/* End PBXFrameworksBuildPhase section */ |
||||
|
||||
/* Begin PBXGroup section */ |
||||
5EF71196215174870077496F = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
5EF711AE215174890077496F /* main.m */, |
||||
5EF711A1215174870077496F /* HelloWorld */, |
||||
5EF711A0215174870077496F /* Products */, |
||||
8D3EFBB796129582177142C4 /* Pods */, |
||||
A986548CB5622AF6CC3ECCCE /* Frameworks */, |
||||
); |
||||
sourceTree = "<group>"; |
||||
}; |
||||
5EF711A0215174870077496F /* Products */ = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
5EF7119F215174870077496F /* HelloWorld.app */, |
||||
); |
||||
name = Products; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
5EF711A1215174870077496F /* HelloWorld */ = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
5EF711A2215174880077496F /* AppDelegate.h */, |
||||
5EF711A3215174880077496F /* AppDelegate.m */, |
||||
5EF711A5215174880077496F /* ViewController.h */, |
||||
5EF711A6215174880077496F /* ViewController.m */, |
||||
5EF711A8215174890077496F /* Assets.xcassets */, |
||||
5EF711AA215174890077496F /* Main.storyboard */, |
||||
5EF711AD215174890077496F /* Info.plist */, |
||||
5EF711B0215174890077496F /* HelloWorld.entitlements */, |
||||
); |
||||
path = HelloWorld; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
8D3EFBB796129582177142C4 /* Pods */ = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
CA4699782F6344C8E67C9FEE /* Pods-HelloWorld.debug.xcconfig */, |
||||
2AAF8E8BA7DBFD2D3886AA25 /* Pods-HelloWorld.release.xcconfig */, |
||||
); |
||||
name = Pods; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
A986548CB5622AF6CC3ECCCE /* Frameworks */ = { |
||||
isa = PBXGroup; |
||||
children = ( |
||||
369D887F6054EBA486218C69 /* libPods-HelloWorld.a */, |
||||
); |
||||
name = Frameworks; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
/* End PBXGroup section */ |
||||
|
||||
/* Begin PBXNativeTarget section */ |
||||
5EF7119E215174870077496F /* HelloWorld */ = { |
||||
isa = PBXNativeTarget; |
||||
buildConfigurationList = 5EF711B3215174890077496F /* Build configuration list for PBXNativeTarget "HelloWorld" */; |
||||
buildPhases = ( |
||||
3694AEA482289A5BDD5EA5A4 /* [CP] Check Pods Manifest.lock */, |
||||
5EF7119B215174870077496F /* Sources */, |
||||
5EF7119C215174870077496F /* Frameworks */, |
||||
5EF7119D215174870077496F /* Resources */, |
||||
DF5241368CCEAA9DC73E7EA8 /* [CP] Copy Pods Resources */, |
||||
); |
||||
buildRules = ( |
||||
); |
||||
dependencies = ( |
||||
); |
||||
name = HelloWorld; |
||||
productName = HelloWorld; |
||||
productReference = 5EF7119F215174870077496F /* HelloWorld.app */; |
||||
productType = "com.apple.product-type.application"; |
||||
}; |
||||
/* End PBXNativeTarget section */ |
||||
|
||||
/* Begin PBXProject section */ |
||||
5EF71197215174870077496F /* Project object */ = { |
||||
isa = PBXProject; |
||||
attributes = { |
||||
LastUpgradeCheck = 0930; |
||||
ORGANIZATIONNAME = gRPC; |
||||
TargetAttributes = { |
||||
5EF7119E215174870077496F = { |
||||
CreatedOnToolsVersion = 9.3; |
||||
SystemCapabilities = { |
||||
com.apple.Sandbox = { |
||||
enabled = 0; |
||||
}; |
||||
}; |
||||
}; |
||||
}; |
||||
}; |
||||
buildConfigurationList = 5EF7119A215174870077496F /* Build configuration list for PBXProject "HelloWorld" */; |
||||
compatibilityVersion = "Xcode 9.3"; |
||||
developmentRegion = en; |
||||
hasScannedForEncodings = 0; |
||||
knownRegions = ( |
||||
en, |
||||
Base, |
||||
); |
||||
mainGroup = 5EF71196215174870077496F; |
||||
productRefGroup = 5EF711A0215174870077496F /* Products */; |
||||
projectDirPath = ""; |
||||
projectRoot = ""; |
||||
targets = ( |
||||
5EF7119E215174870077496F /* HelloWorld */, |
||||
); |
||||
}; |
||||
/* End PBXProject section */ |
||||
|
||||
/* Begin PBXResourcesBuildPhase section */ |
||||
5EF7119D215174870077496F /* Resources */ = { |
||||
isa = PBXResourcesBuildPhase; |
||||
buildActionMask = 2147483647; |
||||
files = ( |
||||
5EF711A9215174890077496F /* Assets.xcassets in Resources */, |
||||
5EF711AC215174890077496F /* Main.storyboard in Resources */, |
||||
); |
||||
runOnlyForDeploymentPostprocessing = 0; |
||||
}; |
||||
/* End PBXResourcesBuildPhase section */ |
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */ |
||||
3694AEA482289A5BDD5EA5A4 /* [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-HelloWorld-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; |
||||
}; |
||||
DF5241368CCEAA9DC73E7EA8 /* [CP] Copy Pods Resources */ = { |
||||
isa = PBXShellScriptBuildPhase; |
||||
buildActionMask = 2147483647; |
||||
files = ( |
||||
); |
||||
inputPaths = ( |
||||
"${SRCROOT}/Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-resources.sh", |
||||
"${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", |
||||
); |
||||
name = "[CP] Copy Pods Resources"; |
||||
outputPaths = ( |
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle", |
||||
); |
||||
runOnlyForDeploymentPostprocessing = 0; |
||||
shellPath = /bin/sh; |
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-resources.sh\"\n"; |
||||
showEnvVarsInLog = 0; |
||||
}; |
||||
/* End PBXShellScriptBuildPhase section */ |
||||
|
||||
/* Begin PBXSourcesBuildPhase section */ |
||||
5EF7119B215174870077496F /* Sources */ = { |
||||
isa = PBXSourcesBuildPhase; |
||||
buildActionMask = 2147483647; |
||||
files = ( |
||||
5EF711A7215174880077496F /* ViewController.m in Sources */, |
||||
5EF711AF215174890077496F /* main.m in Sources */, |
||||
5EF711A4215174880077496F /* AppDelegate.m in Sources */, |
||||
); |
||||
runOnlyForDeploymentPostprocessing = 0; |
||||
}; |
||||
/* End PBXSourcesBuildPhase section */ |
||||
|
||||
/* Begin PBXVariantGroup section */ |
||||
5EF711AA215174890077496F /* Main.storyboard */ = { |
||||
isa = PBXVariantGroup; |
||||
children = ( |
||||
5EF711AB215174890077496F /* Base */, |
||||
); |
||||
name = Main.storyboard; |
||||
sourceTree = "<group>"; |
||||
}; |
||||
/* End PBXVariantGroup section */ |
||||
|
||||
/* Begin XCBuildConfiguration section */ |
||||
5EF711B1215174890077496F /* 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_ENABLE_OBJC_WEAK = YES; |
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; |
||||
CLANG_WARN_BOOL_CONVERSION = YES; |
||||
CLANG_WARN_COMMA = YES; |
||||
CLANG_WARN_CONSTANT_CONVERSION = YES; |
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = 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 = "-"; |
||||
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; |
||||
MACOSX_DEPLOYMENT_TARGET = 10.13; |
||||
MTL_ENABLE_DEBUG_INFO = YES; |
||||
ONLY_ACTIVE_ARCH = YES; |
||||
SDKROOT = macosx; |
||||
}; |
||||
name = Debug; |
||||
}; |
||||
5EF711B2215174890077496F /* 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_ENABLE_OBJC_WEAK = YES; |
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; |
||||
CLANG_WARN_BOOL_CONVERSION = YES; |
||||
CLANG_WARN_COMMA = YES; |
||||
CLANG_WARN_CONSTANT_CONVERSION = YES; |
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = 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 = "-"; |
||||
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; |
||||
MACOSX_DEPLOYMENT_TARGET = 10.13; |
||||
MTL_ENABLE_DEBUG_INFO = NO; |
||||
SDKROOT = macosx; |
||||
}; |
||||
name = Release; |
||||
}; |
||||
5EF711B4215174890077496F /* Debug */ = { |
||||
isa = XCBuildConfiguration; |
||||
baseConfigurationReference = CA4699782F6344C8E67C9FEE /* Pods-HelloWorld.debug.xcconfig */; |
||||
buildSettings = { |
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
||||
CODE_SIGN_STYLE = Automatic; |
||||
COMBINE_HIDPI_IMAGES = YES; |
||||
INFOPLIST_FILE = HelloWorld/Info.plist; |
||||
LD_RUNPATH_SEARCH_PATHS = ( |
||||
"$(inherited)", |
||||
"@executable_path/../Frameworks", |
||||
); |
||||
PRODUCT_BUNDLE_IDENTIFIER = io.grpc.HelloWorld; |
||||
PRODUCT_NAME = "$(TARGET_NAME)"; |
||||
}; |
||||
name = Debug; |
||||
}; |
||||
5EF711B5215174890077496F /* Release */ = { |
||||
isa = XCBuildConfiguration; |
||||
baseConfigurationReference = 2AAF8E8BA7DBFD2D3886AA25 /* Pods-HelloWorld.release.xcconfig */; |
||||
buildSettings = { |
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
||||
CODE_SIGN_STYLE = Automatic; |
||||
COMBINE_HIDPI_IMAGES = YES; |
||||
INFOPLIST_FILE = HelloWorld/Info.plist; |
||||
LD_RUNPATH_SEARCH_PATHS = ( |
||||
"$(inherited)", |
||||
"@executable_path/../Frameworks", |
||||
); |
||||
PRODUCT_BUNDLE_IDENTIFIER = io.grpc.HelloWorld; |
||||
PRODUCT_NAME = "$(TARGET_NAME)"; |
||||
}; |
||||
name = Release; |
||||
}; |
||||
/* End XCBuildConfiguration section */ |
||||
|
||||
/* Begin XCConfigurationList section */ |
||||
5EF7119A215174870077496F /* Build configuration list for PBXProject "HelloWorld" */ = { |
||||
isa = XCConfigurationList; |
||||
buildConfigurations = ( |
||||
5EF711B1215174890077496F /* Debug */, |
||||
5EF711B2215174890077496F /* Release */, |
||||
); |
||||
defaultConfigurationIsVisible = 0; |
||||
defaultConfigurationName = Release; |
||||
}; |
||||
5EF711B3215174890077496F /* Build configuration list for PBXNativeTarget "HelloWorld" */ = { |
||||
isa = XCConfigurationList; |
||||
buildConfigurations = ( |
||||
5EF711B4215174890077496F /* Debug */, |
||||
5EF711B5215174890077496F /* Release */, |
||||
); |
||||
defaultConfigurationIsVisible = 0; |
||||
defaultConfigurationName = Release; |
||||
}; |
||||
/* End XCConfigurationList section */ |
||||
}; |
||||
rootObject = 5EF71197215174870077496F /* Project object */; |
||||
} |
@ -0,0 +1,25 @@ |
||||
/*
|
||||
* |
||||
* 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 <Cocoa/Cocoa.h> |
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate> |
||||
|
||||
|
||||
@end |
||||
|
@ -0,0 +1,58 @@ |
||||
{ |
||||
"images" : [ |
||||
{ |
||||
"idiom" : "mac", |
||||
"size" : "16x16", |
||||
"scale" : "1x" |
||||
}, |
||||
{ |
||||
"idiom" : "mac", |
||||
"size" : "16x16", |
||||
"scale" : "2x" |
||||
}, |
||||
{ |
||||
"idiom" : "mac", |
||||
"size" : "32x32", |
||||
"scale" : "1x" |
||||
}, |
||||
{ |
||||
"idiom" : "mac", |
||||
"size" : "32x32", |
||||
"scale" : "2x" |
||||
}, |
||||
{ |
||||
"idiom" : "mac", |
||||
"size" : "128x128", |
||||
"scale" : "1x" |
||||
}, |
||||
{ |
||||
"idiom" : "mac", |
||||
"size" : "128x128", |
||||
"scale" : "2x" |
||||
}, |
||||
{ |
||||
"idiom" : "mac", |
||||
"size" : "256x256", |
||||
"scale" : "1x" |
||||
}, |
||||
{ |
||||
"idiom" : "mac", |
||||
"size" : "256x256", |
||||
"scale" : "2x" |
||||
}, |
||||
{ |
||||
"idiom" : "mac", |
||||
"size" : "512x512", |
||||
"scale" : "1x" |
||||
}, |
||||
{ |
||||
"idiom" : "mac", |
||||
"size" : "512x512", |
||||
"scale" : "2x" |
||||
} |
||||
], |
||||
"info" : { |
||||
"version" : 1, |
||||
"author" : "xcode" |
||||
} |
||||
} |
@ -0,0 +1,6 @@ |
||||
{ |
||||
"info" : { |
||||
"version" : 1, |
||||
"author" : "xcode" |
||||
} |
||||
} |
@ -0,0 +1,717 @@ |
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS"> |
||||
<dependencies> |
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11134"/> |
||||
</dependencies> |
||||
<scenes> |
||||
<!--Application--> |
||||
<scene sceneID="JPo-4y-FX3"> |
||||
<objects> |
||||
<application id="hnw-xV-0zn" sceneMemberID="viewController"> |
||||
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6"> |
||||
<items> |
||||
<menuItem title="HelloWorld" id="1Xt-HY-uBw"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="HelloWorld" systemMenu="apple" id="uQy-DD-JDr"> |
||||
<items> |
||||
<menuItem title="About HelloWorld" id="5kV-Vb-QxS"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/> |
||||
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/> |
||||
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/> |
||||
<menuItem title="Services" id="NMo-om-nkz"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/> |
||||
<menuItem title="Hide HelloWorld" keyEquivalent="h" id="Olw-nP-bQN"> |
||||
<connections> |
||||
<action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO"> |
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> |
||||
<connections> |
||||
<action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Show All" id="Kd2-mp-pUS"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/> |
||||
<menuItem title="Quit HelloWorld" keyEquivalent="q" id="4sb-4s-VLi"> |
||||
<connections> |
||||
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="File" id="dMs-cI-mzQ"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="File" id="bib-Uj-vzu"> |
||||
<items> |
||||
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl"> |
||||
<connections> |
||||
<action selector="newDocument:" target="Ady-hI-5gd" id="4Si-XN-c54"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9"> |
||||
<connections> |
||||
<action selector="openDocument:" target="Ady-hI-5gd" id="bVn-NM-KNZ"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Open Recent" id="tXI-mr-wws"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ"> |
||||
<items> |
||||
<menuItem title="Clear Menu" id="vNY-rz-j42"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="clearRecentDocuments:" target="Ady-hI-5gd" id="Daa-9d-B3U"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/> |
||||
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG"> |
||||
<connections> |
||||
<action selector="performClose:" target="Ady-hI-5gd" id="HmO-Ls-i7Q"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV"> |
||||
<connections> |
||||
<action selector="saveDocument:" target="Ady-hI-5gd" id="teZ-XB-qJY"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A"> |
||||
<connections> |
||||
<action selector="saveDocumentAs:" target="Ady-hI-5gd" id="mDf-zr-I0C"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Revert to Saved" keyEquivalent="r" id="KaW-ft-85H"> |
||||
<connections> |
||||
<action selector="revertDocumentToSaved:" target="Ady-hI-5gd" id="iJ3-Pv-kwq"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/> |
||||
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK"> |
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/> |
||||
<connections> |
||||
<action selector="runPageLayout:" target="Ady-hI-5gd" id="Din-rz-gC5"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS"> |
||||
<connections> |
||||
<action selector="print:" target="Ady-hI-5gd" id="qaZ-4w-aoO"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="Edit" id="5QF-Oa-p0T"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Edit" id="W48-6f-4Dl"> |
||||
<items> |
||||
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg"> |
||||
<connections> |
||||
<action selector="undo:" target="Ady-hI-5gd" id="M6e-cu-g7V"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam"> |
||||
<connections> |
||||
<action selector="redo:" target="Ady-hI-5gd" id="oIA-Rs-6OD"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/> |
||||
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG"> |
||||
<connections> |
||||
<action selector="cut:" target="Ady-hI-5gd" id="YJe-68-I9s"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU"> |
||||
<connections> |
||||
<action selector="copy:" target="Ady-hI-5gd" id="G1f-GL-Joy"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL"> |
||||
<connections> |
||||
<action selector="paste:" target="Ady-hI-5gd" id="UvS-8e-Qdg"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk"> |
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> |
||||
<connections> |
||||
<action selector="pasteAsPlainText:" target="Ady-hI-5gd" id="cEh-KX-wJQ"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Delete" id="pa3-QI-u2k"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="delete:" target="Ady-hI-5gd" id="0Mk-Ml-PaM"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m"> |
||||
<connections> |
||||
<action selector="selectAll:" target="Ady-hI-5gd" id="VNm-Mi-diN"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/> |
||||
<menuItem title="Find" id="4EN-yA-p0u"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Find" id="1b7-l0-nxx"> |
||||
<items> |
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W"> |
||||
<connections> |
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="cD7-Qs-BN4"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz"> |
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> |
||||
<connections> |
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="WD3-Gg-5AJ"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye"> |
||||
<connections> |
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="NDo-RZ-v9R"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV"> |
||||
<connections> |
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="HOh-sY-3ay"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt"> |
||||
<connections> |
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="U76-nv-p5D"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd"> |
||||
<connections> |
||||
<action selector="centerSelectionInVisibleArea:" target="Ady-hI-5gd" id="IOG-6D-g5B"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg"> |
||||
<items> |
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI"> |
||||
<connections> |
||||
<action selector="showGuessPanel:" target="Ady-hI-5gd" id="vFj-Ks-hy3"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7"> |
||||
<connections> |
||||
<action selector="checkSpelling:" target="Ady-hI-5gd" id="fz7-VC-reM"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/> |
||||
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="toggleContinuousSpellChecking:" target="Ady-hI-5gd" id="7w6-Qz-0kB"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="toggleGrammarChecking:" target="Ady-hI-5gd" id="muD-Qn-j4w"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="toggleAutomaticSpellingCorrection:" target="Ady-hI-5gd" id="2lM-Qi-WAP"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="Substitutions" id="9ic-FL-obx"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr"> |
||||
<items> |
||||
<menuItem title="Show Substitutions" id="z6F-FW-3nz"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="orderFrontSubstitutionsPanel:" target="Ady-hI-5gd" id="oku-mr-iSq"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/> |
||||
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="toggleSmartInsertDelete:" target="Ady-hI-5gd" id="3IJ-Se-DZD"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Smart Quotes" id="hQb-2v-fYv"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="Ady-hI-5gd" id="ptq-xd-QOA"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Smart Dashes" id="rgM-f4-ycn"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="toggleAutomaticDashSubstitution:" target="Ady-hI-5gd" id="oCt-pO-9gS"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Smart Links" id="cwL-P1-jid"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="toggleAutomaticLinkDetection:" target="Ady-hI-5gd" id="Gip-E3-Fov"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Data Detectors" id="tRr-pd-1PS"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="toggleAutomaticDataDetection:" target="Ady-hI-5gd" id="R1I-Nq-Kbl"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Text Replacement" id="HFQ-gK-NFA"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="toggleAutomaticTextReplacement:" target="Ady-hI-5gd" id="DvP-Fe-Py6"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="Transformations" id="2oI-Rn-ZJC"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Transformations" id="c8a-y6-VQd"> |
||||
<items> |
||||
<menuItem title="Make Upper Case" id="vmV-6d-7jI"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="uppercaseWord:" target="Ady-hI-5gd" id="sPh-Tk-edu"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Make Lower Case" id="d9M-CD-aMd"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="lowercaseWord:" target="Ady-hI-5gd" id="iUZ-b5-hil"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Capitalize" id="UEZ-Bs-lqG"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="capitalizeWord:" target="Ady-hI-5gd" id="26H-TL-nsh"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="Speech" id="xrE-MZ-jX0"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Speech" id="3rS-ZA-NoH"> |
||||
<items> |
||||
<menuItem title="Start Speaking" id="Ynk-f8-cLZ"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="startSpeaking:" target="Ady-hI-5gd" id="654-Ng-kyl"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Stop Speaking" id="Oyz-dy-DGm"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="stopSpeaking:" target="Ady-hI-5gd" id="dX8-6p-jy9"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="Format" id="jxT-CU-nIS"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Format" id="GEO-Iw-cKr"> |
||||
<items> |
||||
<menuItem title="Font" id="Gi5-1S-RQB"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq"> |
||||
<items> |
||||
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq"> |
||||
<connections> |
||||
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27"> |
||||
<connections> |
||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq"> |
||||
<connections> |
||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S"> |
||||
<connections> |
||||
<action selector="underline:" target="Ady-hI-5gd" id="FYS-2b-JAY"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/> |
||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL"> |
||||
<connections> |
||||
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST"> |
||||
<connections> |
||||
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/> |
||||
<menuItem title="Kern" id="jBQ-r6-VK2"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Kern" id="tlD-Oa-oAM"> |
||||
<items> |
||||
<menuItem title="Use Default" id="GUa-eO-cwY"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="useStandardKerning:" target="Ady-hI-5gd" id="6dk-9l-Ckg"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Use None" id="cDB-IK-hbR"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="turnOffKerning:" target="Ady-hI-5gd" id="U8a-gz-Maa"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Tighten" id="46P-cB-AYj"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="tightenKerning:" target="Ady-hI-5gd" id="hr7-Nz-8ro"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Loosen" id="ogc-rX-tC1"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="loosenKerning:" target="Ady-hI-5gd" id="8i4-f9-FKE"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="Ligatures" id="o6e-r0-MWq"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9"> |
||||
<items> |
||||
<menuItem title="Use Default" id="agt-UL-0e3"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="useStandardLigatures:" target="Ady-hI-5gd" id="7uR-wd-Dx6"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Use None" id="J7y-lM-qPV"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="turnOffLigatures:" target="Ady-hI-5gd" id="iX2-gA-Ilz"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Use All" id="xQD-1f-W4t"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="useAllLigatures:" target="Ady-hI-5gd" id="KcB-kA-TuK"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="Baseline" id="OaQ-X3-Vso"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Baseline" id="ijk-EB-dga"> |
||||
<items> |
||||
<menuItem title="Use Default" id="3Om-Ey-2VK"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="unscript:" target="Ady-hI-5gd" id="0vZ-95-Ywn"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Superscript" id="Rqc-34-cIF"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="superscript:" target="Ady-hI-5gd" id="3qV-fo-wpU"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Subscript" id="I0S-gh-46l"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="subscript:" target="Ady-hI-5gd" id="Q6W-4W-IGz"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Raise" id="2h7-ER-AoG"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="raiseBaseline:" target="Ady-hI-5gd" id="4sk-31-7Q9"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Lower" id="1tx-W0-xDw"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="lowerBaseline:" target="Ady-hI-5gd" id="OF1-bc-KW4"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/> |
||||
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk"> |
||||
<connections> |
||||
<action selector="orderFrontColorPanel:" target="Ady-hI-5gd" id="mSX-Xz-DV3"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/> |
||||
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD"> |
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> |
||||
<connections> |
||||
<action selector="copyFont:" target="Ady-hI-5gd" id="GJO-xA-L4q"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH"> |
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> |
||||
<connections> |
||||
<action selector="pasteFont:" target="Ady-hI-5gd" id="JfD-CL-leO"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="Text" id="Fal-I4-PZk"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Text" id="d9c-me-L2H"> |
||||
<items> |
||||
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1"> |
||||
<connections> |
||||
<action selector="alignLeft:" target="Ady-hI-5gd" id="zUv-R1-uAa"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb"> |
||||
<connections> |
||||
<action selector="alignCenter:" target="Ady-hI-5gd" id="spX-mk-kcS"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Justify" id="J5U-5w-g23"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="alignJustified:" target="Ady-hI-5gd" id="ljL-7U-jND"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4"> |
||||
<connections> |
||||
<action selector="alignRight:" target="Ady-hI-5gd" id="r48-bG-YeY"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/> |
||||
<menuItem title="Writing Direction" id="H1b-Si-o9J"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd"> |
||||
<items> |
||||
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
</menuItem> |
||||
<menuItem id="YGs-j5-SAR"> |
||||
<string key="title"> Default</string> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="makeBaseWritingDirectionNatural:" target="Ady-hI-5gd" id="qtV-5e-UBP"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem id="Lbh-J2-qVU"> |
||||
<string key="title"> Left to Right</string> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="makeBaseWritingDirectionLeftToRight:" target="Ady-hI-5gd" id="S0X-9S-QSf"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem id="jFq-tB-4Kx"> |
||||
<string key="title"> Right to Left</string> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="makeBaseWritingDirectionRightToLeft:" target="Ady-hI-5gd" id="5fk-qB-AqJ"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/> |
||||
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
</menuItem> |
||||
<menuItem id="Nop-cj-93Q"> |
||||
<string key="title"> Default</string> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="makeTextWritingDirectionNatural:" target="Ady-hI-5gd" id="lPI-Se-ZHp"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem id="BgM-ve-c93"> |
||||
<string key="title"> Left to Right</string> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="makeTextWritingDirectionLeftToRight:" target="Ady-hI-5gd" id="caW-Bv-w94"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem id="RB4-Sm-HuC"> |
||||
<string key="title"> Right to Left</string> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="makeTextWritingDirectionRightToLeft:" target="Ady-hI-5gd" id="EXD-6r-ZUu"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/> |
||||
<menuItem title="Show Ruler" id="vLm-3I-IUL"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="toggleRuler:" target="Ady-hI-5gd" id="FOx-HJ-KwY"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5"> |
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/> |
||||
<connections> |
||||
<action selector="copyRuler:" target="Ady-hI-5gd" id="71i-fW-3W2"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI"> |
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/> |
||||
<connections> |
||||
<action selector="pasteRuler:" target="Ady-hI-5gd" id="cSh-wd-qM2"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="View" id="H8h-7b-M4v"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="View" id="HyV-fh-RgO"> |
||||
<items> |
||||
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5"> |
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/> |
||||
<connections> |
||||
<action selector="toggleToolbarShown:" target="Ady-hI-5gd" id="BXY-wc-z0C"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="runToolbarCustomizationPalette:" target="Ady-hI-5gd" id="pQI-g3-MTW"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="hB3-LF-h0Y"/> |
||||
<menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE"> |
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/> |
||||
<connections> |
||||
<action selector="toggleSourceList:" target="Ady-hI-5gd" id="iwa-gc-5KM"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa"> |
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/> |
||||
<connections> |
||||
<action selector="toggleFullScreen:" target="Ady-hI-5gd" id="dU3-MA-1Rq"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="Window" id="aUF-d1-5bR"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo"> |
||||
<items> |
||||
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV"> |
||||
<connections> |
||||
<action selector="performMiniaturize:" target="Ady-hI-5gd" id="VwT-WD-YPe"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem title="Zoom" id="R4o-n2-Eq4"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="performZoom:" target="Ady-hI-5gd" id="DIl-cC-cCs"/> |
||||
</connections> |
||||
</menuItem> |
||||
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/> |
||||
<menuItem title="Bring All to Front" id="LE2-aR-0XJ"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<connections> |
||||
<action selector="arrangeInFront:" target="Ady-hI-5gd" id="DRN-fu-gQh"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
<menuItem title="Help" id="wpr-3q-Mcd"> |
||||
<modifierMask key="keyEquivalentModifierMask"/> |
||||
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ"> |
||||
<items> |
||||
<menuItem title="HelloWorld Help" keyEquivalent="?" id="FKE-Sm-Kum"> |
||||
<connections> |
||||
<action selector="showHelp:" target="Ady-hI-5gd" id="y7X-2Q-9no"/> |
||||
</connections> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
</menuItem> |
||||
</items> |
||||
</menu> |
||||
<connections> |
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/> |
||||
</connections> |
||||
</application> |
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider=""/> |
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/> |
||||
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> |
||||
</objects> |
||||
<point key="canvasLocation" x="75" y="0.0"/> |
||||
</scene> |
||||
<!--Window Controller--> |
||||
<scene sceneID="R2V-B0-nI4"> |
||||
<objects> |
||||
<windowController id="B8D-0N-5wS" sceneMemberID="viewController"> |
||||
<window key="window" title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA"> |
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/> |
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/> |
||||
<rect key="contentRect" x="196" y="240" width="480" height="270"/> |
||||
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/> |
||||
<connections> |
||||
<outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/> |
||||
</connections> |
||||
</window> |
||||
<connections> |
||||
<segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/> |
||||
</connections> |
||||
</windowController> |
||||
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> |
||||
</objects> |
||||
<point key="canvasLocation" x="75" y="250"/> |
||||
</scene> |
||||
<!--View Controller--> |
||||
<scene sceneID="hIz-AP-VOD"> |
||||
<objects> |
||||
<viewController id="XfG-lQ-9wD" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController"> |
||||
<view key="view" wantsLayer="YES" id="m2S-Jp-Qdl"> |
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/> |
||||
<autoresizingMask key="autoresizingMask"/> |
||||
</view> |
||||
</viewController> |
||||
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> |
||||
</objects> |
||||
<point key="canvasLocation" x="75" y="655"/> |
||||
</scene> |
||||
</scenes> |
||||
</document> |
@ -0,0 +1,5 @@ |
||||
<?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/> |
||||
</plist> |
@ -0,0 +1,32 @@ |
||||
<?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>CFBundleIconFile</key> |
||||
<string></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>APPL</string> |
||||
<key>CFBundleShortVersionString</key> |
||||
<string>1.0</string> |
||||
<key>CFBundleVersion</key> |
||||
<string>1</string> |
||||
<key>LSMinimumSystemVersion</key> |
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string> |
||||
<key>NSHumanReadableCopyright</key> |
||||
<string>Copyright © 2018 gRPC. All rights reserved.</string> |
||||
<key>NSMainStoryboardFile</key> |
||||
<string>Main</string> |
||||
<key>NSPrincipalClass</key> |
||||
<string>NSApplication</string> |
||||
</dict> |
||||
</plist> |
@ -0,0 +1,25 @@ |
||||
/*
|
||||
* |
||||
* 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 <Cocoa/Cocoa.h> |
||||
|
||||
@interface ViewController : NSViewController |
||||
|
||||
|
||||
@end |
||||
|
@ -0,0 +1,9 @@ |
||||
source 'https://github.com/CocoaPods/Specs.git' |
||||
platform :macos, '10.9' |
||||
|
||||
install! 'cocoapods', :deterministic_uuids => false |
||||
|
||||
target 'HelloWorld' do |
||||
# Depend on the generated HelloWorld library. |
||||
pod 'HelloWorld', :path => '.' |
||||
end |
@ -0,0 +1,6 @@ |
||||
# gRPC Objective-C Mac OS Hello World Example |
||||
|
||||
A hello world example app on Mac OS. Note that Mac OS is not a first class supported platform of gRPC |
||||
Objective-C library. This example is only for reference. |
||||
|
||||
Refer to [Hello World Example](../helloworld) for instructions on installation and running. |
@ -0,0 +1,43 @@ |
||||
/* |
||||
* |
||||
* 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 <Cocoa/Cocoa.h> |
||||
|
||||
#import <GRPCClient/GRPCCall+ChannelArg.h> |
||||
#import <GRPCClient/GRPCCall+Tests.h> |
||||
#import <HelloWorld/Helloworld.pbrpc.h> |
||||
|
||||
static NSString * const kHostAddress = @"localhost:50051"; |
||||
|
||||
int main(int argc, const char * argv[]) { |
||||
@autoreleasepool { |
||||
[GRPCCall useInsecureConnectionsForHost:kHostAddress]; |
||||
[GRPCCall setUserAgentPrefix:@"HelloWorld/1.0" forHost:kHostAddress]; |
||||
|
||||
HLWGreeter *client = [[HLWGreeter alloc] initWithHost:kHostAddress]; |
||||
|
||||
HLWHelloRequest *request = [HLWHelloRequest message]; |
||||
request.name = @"Objective-C"; |
||||
|
||||
[client sayHelloWithRequest:request handler:^(HLWHelloReply *response, NSError *error) { |
||||
NSLog(@"%@", response.message); |
||||
}]; |
||||
} |
||||
|
||||
return NSApplicationMain(argc, argv); |
||||
} |
@ -1,178 +0,0 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015 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 <stdio.h> |
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/method_params.h" |
||||
#include "src/core/lib/channel/status_util.h" |
||||
#include "src/core/lib/gpr/string.h" |
||||
#include "src/core/lib/gprpp/memory.h" |
||||
|
||||
// As per the retry design, we do not allow more than 5 retry attempts.
|
||||
#define MAX_MAX_RETRY_ATTEMPTS 5 |
||||
|
||||
namespace grpc_core { |
||||
namespace internal { |
||||
|
||||
namespace { |
||||
|
||||
bool ParseWaitForReady( |
||||
grpc_json* field, ClientChannelMethodParams::WaitForReady* wait_for_ready) { |
||||
if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) { |
||||
return false; |
||||
} |
||||
*wait_for_ready = field->type == GRPC_JSON_TRUE |
||||
? ClientChannelMethodParams::WAIT_FOR_READY_TRUE |
||||
: ClientChannelMethodParams::WAIT_FOR_READY_FALSE; |
||||
return true; |
||||
} |
||||
|
||||
// Parses a JSON field of the form generated for a google.proto.Duration
|
||||
// proto message, as per:
|
||||
// https://developers.google.com/protocol-buffers/docs/proto3#json
|
||||
bool ParseDuration(grpc_json* field, grpc_millis* duration) { |
||||
if (field->type != GRPC_JSON_STRING) return false; |
||||
size_t len = strlen(field->value); |
||||
if (field->value[len - 1] != 's') return false; |
||||
UniquePtr<char> buf(gpr_strdup(field->value)); |
||||
*(buf.get() + len - 1) = '\0'; // Remove trailing 's'.
|
||||
char* decimal_point = strchr(buf.get(), '.'); |
||||
int nanos = 0; |
||||
if (decimal_point != nullptr) { |
||||
*decimal_point = '\0'; |
||||
nanos = gpr_parse_nonnegative_int(decimal_point + 1); |
||||
if (nanos == -1) { |
||||
return false; |
||||
} |
||||
int num_digits = static_cast<int>(strlen(decimal_point + 1)); |
||||
if (num_digits > 9) { // We don't accept greater precision than nanos.
|
||||
return false; |
||||
} |
||||
for (int i = 0; i < (9 - num_digits); ++i) { |
||||
nanos *= 10; |
||||
} |
||||
} |
||||
int seconds = |
||||
decimal_point == buf.get() ? 0 : gpr_parse_nonnegative_int(buf.get()); |
||||
if (seconds == -1) return false; |
||||
*duration = seconds * GPR_MS_PER_SEC + nanos / GPR_NS_PER_MS; |
||||
return true; |
||||
} |
||||
|
||||
UniquePtr<ClientChannelMethodParams::RetryPolicy> ParseRetryPolicy( |
||||
grpc_json* field) { |
||||
auto retry_policy = MakeUnique<ClientChannelMethodParams::RetryPolicy>(); |
||||
if (field->type != GRPC_JSON_OBJECT) return nullptr; |
||||
for (grpc_json* sub_field = field->child; sub_field != nullptr; |
||||
sub_field = sub_field->next) { |
||||
if (sub_field->key == nullptr) return nullptr; |
||||
if (strcmp(sub_field->key, "maxAttempts") == 0) { |
||||
if (retry_policy->max_attempts != 0) return nullptr; // Duplicate.
|
||||
if (sub_field->type != GRPC_JSON_NUMBER) return nullptr; |
||||
retry_policy->max_attempts = gpr_parse_nonnegative_int(sub_field->value); |
||||
if (retry_policy->max_attempts <= 1) return nullptr; |
||||
if (retry_policy->max_attempts > MAX_MAX_RETRY_ATTEMPTS) { |
||||
gpr_log(GPR_ERROR, |
||||
"service config: clamped retryPolicy.maxAttempts at %d", |
||||
MAX_MAX_RETRY_ATTEMPTS); |
||||
retry_policy->max_attempts = MAX_MAX_RETRY_ATTEMPTS; |
||||
} |
||||
} else if (strcmp(sub_field->key, "initialBackoff") == 0) { |
||||
if (retry_policy->initial_backoff > 0) return nullptr; // Duplicate.
|
||||
if (!ParseDuration(sub_field, &retry_policy->initial_backoff)) { |
||||
return nullptr; |
||||
} |
||||
if (retry_policy->initial_backoff == 0) return nullptr; |
||||
} else if (strcmp(sub_field->key, "maxBackoff") == 0) { |
||||
if (retry_policy->max_backoff > 0) return nullptr; // Duplicate.
|
||||
if (!ParseDuration(sub_field, &retry_policy->max_backoff)) { |
||||
return nullptr; |
||||
} |
||||
if (retry_policy->max_backoff == 0) return nullptr; |
||||
} else if (strcmp(sub_field->key, "backoffMultiplier") == 0) { |
||||
if (retry_policy->backoff_multiplier != 0) return nullptr; // Duplicate.
|
||||
if (sub_field->type != GRPC_JSON_NUMBER) return nullptr; |
||||
if (sscanf(sub_field->value, "%f", &retry_policy->backoff_multiplier) != |
||||
1) { |
||||
return nullptr; |
||||
} |
||||
if (retry_policy->backoff_multiplier <= 0) return nullptr; |
||||
} else if (strcmp(sub_field->key, "retryableStatusCodes") == 0) { |
||||
if (!retry_policy->retryable_status_codes.Empty()) { |
||||
return nullptr; // Duplicate.
|
||||
} |
||||
if (sub_field->type != GRPC_JSON_ARRAY) return nullptr; |
||||
for (grpc_json* element = sub_field->child; element != nullptr; |
||||
element = element->next) { |
||||
if (element->type != GRPC_JSON_STRING) return nullptr; |
||||
grpc_status_code status; |
||||
if (!grpc_status_code_from_string(element->value, &status)) { |
||||
return nullptr; |
||||
} |
||||
retry_policy->retryable_status_codes.Add(status); |
||||
} |
||||
if (retry_policy->retryable_status_codes.Empty()) return nullptr; |
||||
} |
||||
} |
||||
// Make sure required fields are set.
|
||||
if (retry_policy->max_attempts == 0 || retry_policy->initial_backoff == 0 || |
||||
retry_policy->max_backoff == 0 || retry_policy->backoff_multiplier == 0 || |
||||
retry_policy->retryable_status_codes.Empty()) { |
||||
return nullptr; |
||||
} |
||||
return retry_policy; |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
RefCountedPtr<ClientChannelMethodParams> |
||||
ClientChannelMethodParams::CreateFromJson(const grpc_json* json) { |
||||
RefCountedPtr<ClientChannelMethodParams> method_params = |
||||
MakeRefCounted<ClientChannelMethodParams>(); |
||||
for (grpc_json* field = json->child; field != nullptr; field = field->next) { |
||||
if (field->key == nullptr) continue; |
||||
if (strcmp(field->key, "waitForReady") == 0) { |
||||
if (method_params->wait_for_ready_ != WAIT_FOR_READY_UNSET) { |
||||
return nullptr; // Duplicate.
|
||||
} |
||||
if (!ParseWaitForReady(field, &method_params->wait_for_ready_)) { |
||||
return nullptr; |
||||
} |
||||
} else if (strcmp(field->key, "timeout") == 0) { |
||||
if (method_params->timeout_ > 0) return nullptr; // Duplicate.
|
||||
if (!ParseDuration(field, &method_params->timeout_)) return nullptr; |
||||
} else if (strcmp(field->key, "retryPolicy") == 0) { |
||||
if (method_params->retry_policy_ != nullptr) { |
||||
return nullptr; // Duplicate.
|
||||
} |
||||
method_params->retry_policy_ = ParseRetryPolicy(field); |
||||
if (method_params->retry_policy_ == nullptr) return nullptr; |
||||
} |
||||
} |
||||
return method_params; |
||||
} |
||||
|
||||
} // namespace internal
|
||||
} // namespace grpc_core
|
@ -1,78 +0,0 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015 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_EXT_FILTERS_CLIENT_CHANNEL_METHOD_PARAMS_H |
||||
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_METHOD_PARAMS_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/channel/status_util.h" |
||||
#include "src/core/lib/gprpp/ref_counted.h" |
||||
#include "src/core/lib/gprpp/ref_counted_ptr.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" // for grpc_millis |
||||
#include "src/core/lib/json/json.h" |
||||
|
||||
namespace grpc_core { |
||||
namespace internal { |
||||
|
||||
class ClientChannelMethodParams : public RefCounted<ClientChannelMethodParams> { |
||||
public: |
||||
enum WaitForReady { |
||||
WAIT_FOR_READY_UNSET = 0, |
||||
WAIT_FOR_READY_FALSE, |
||||
WAIT_FOR_READY_TRUE |
||||
}; |
||||
|
||||
struct RetryPolicy { |
||||
int max_attempts = 0; |
||||
grpc_millis initial_backoff = 0; |
||||
grpc_millis max_backoff = 0; |
||||
float backoff_multiplier = 0; |
||||
StatusCodeSet retryable_status_codes; |
||||
}; |
||||
|
||||
/// Creates a method_parameters object from \a json.
|
||||
/// Intended for use with ServiceConfig::CreateMethodConfigTable().
|
||||
static RefCountedPtr<ClientChannelMethodParams> CreateFromJson( |
||||
const grpc_json* json); |
||||
|
||||
grpc_millis timeout() const { return timeout_; } |
||||
WaitForReady wait_for_ready() const { return wait_for_ready_; } |
||||
const RetryPolicy* retry_policy() const { return retry_policy_.get(); } |
||||
|
||||
private: |
||||
// So New() can call our private ctor.
|
||||
template <typename T, typename... Args> |
||||
friend T* grpc_core::New(Args&&... args); |
||||
|
||||
// So Delete() can call our private dtor.
|
||||
template <typename T> |
||||
friend void grpc_core::Delete(T*); |
||||
|
||||
ClientChannelMethodParams() {} |
||||
virtual ~ClientChannelMethodParams() {} |
||||
|
||||
grpc_millis timeout_ = 0; |
||||
WaitForReady wait_for_ready_ = WAIT_FOR_READY_UNSET; |
||||
UniquePtr<RetryPolicy> retry_policy_; |
||||
}; |
||||
|
||||
} // namespace internal
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_METHOD_PARAMS_H */ |
@ -0,0 +1,384 @@ |
||||
/*
|
||||
* |
||||
* 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/ext/filters/client_channel/resolver_result_parsing.h" |
||||
|
||||
#include <ctype.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/string_util.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/client_channel.h" |
||||
#include "src/core/ext/filters/client_channel/lb_policy_registry.h" |
||||
#include "src/core/lib/channel/status_util.h" |
||||
#include "src/core/lib/gpr/string.h" |
||||
#include "src/core/lib/gprpp/memory.h" |
||||
|
||||
// As per the retry design, we do not allow more than 5 retry attempts.
|
||||
#define MAX_MAX_RETRY_ATTEMPTS 5 |
||||
|
||||
namespace grpc_core { |
||||
namespace internal { |
||||
|
||||
namespace { |
||||
|
||||
// Converts string format from JSON to proto.
|
||||
grpc_core::UniquePtr<char> ConvertCamelToSnake(const char* camel) { |
||||
const size_t size = strlen(camel); |
||||
char* snake = static_cast<char*>(gpr_malloc(size * 2)); |
||||
size_t j = 0; |
||||
for (size_t i = 0; i < size; ++i) { |
||||
if (isupper(camel[i])) { |
||||
snake[j++] = '_'; |
||||
snake[j++] = tolower(camel[i]); |
||||
} else { |
||||
snake[j++] = camel[i]; |
||||
} |
||||
} |
||||
snake[j] = '\0'; |
||||
return grpc_core::UniquePtr<char>(snake); |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
ProcessedResolverResult::ProcessedResolverResult( |
||||
const grpc_channel_args* resolver_result, bool parse_retry) { |
||||
ProcessServiceConfig(resolver_result, parse_retry); |
||||
// If no LB config was found above, just find the LB policy name then.
|
||||
if (lb_policy_config_ == nullptr) ProcessLbPolicyName(resolver_result); |
||||
} |
||||
|
||||
void ProcessedResolverResult::ProcessServiceConfig( |
||||
const grpc_channel_args* resolver_result, bool parse_retry) { |
||||
const grpc_arg* channel_arg = |
||||
grpc_channel_args_find(resolver_result, GRPC_ARG_SERVICE_CONFIG); |
||||
const char* service_config_json = grpc_channel_arg_get_string(channel_arg); |
||||
if (service_config_json != nullptr) { |
||||
service_config_json_.reset(gpr_strdup(service_config_json)); |
||||
service_config_ = grpc_core::ServiceConfig::Create(service_config_json); |
||||
if (service_config_ != nullptr) { |
||||
if (parse_retry) { |
||||
channel_arg = |
||||
grpc_channel_args_find(resolver_result, GRPC_ARG_SERVER_URI); |
||||
const char* server_uri = grpc_channel_arg_get_string(channel_arg); |
||||
GPR_ASSERT(server_uri != nullptr); |
||||
grpc_uri* uri = grpc_uri_parse(server_uri, true); |
||||
GPR_ASSERT(uri->path[0] != '\0'); |
||||
server_name_ = uri->path[0] == '/' ? uri->path + 1 : uri->path; |
||||
service_config_->ParseGlobalParams(ParseServiceConfig, this); |
||||
grpc_uri_destroy(uri); |
||||
} else { |
||||
service_config_->ParseGlobalParams(ParseServiceConfig, this); |
||||
} |
||||
method_params_table_ = service_config_->CreateMethodConfigTable( |
||||
ClientChannelMethodParams::CreateFromJson); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void ProcessedResolverResult::ProcessLbPolicyName( |
||||
const grpc_channel_args* resolver_result) { |
||||
const char* lb_policy_name = nullptr; |
||||
// Prefer the LB policy name found in the service config. Note that this is
|
||||
// checking the deprecated loadBalancingPolicy field, rather than the new
|
||||
// loadBalancingConfig field.
|
||||
if (service_config_ != nullptr) { |
||||
lb_policy_name = service_config_->GetLoadBalancingPolicyName(); |
||||
} |
||||
// Otherwise, find the LB policy name set by the client API.
|
||||
if (lb_policy_name == nullptr) { |
||||
const grpc_arg* channel_arg = |
||||
grpc_channel_args_find(resolver_result, GRPC_ARG_LB_POLICY_NAME); |
||||
lb_policy_name = grpc_channel_arg_get_string(channel_arg); |
||||
} |
||||
// Special case: If at least one balancer address is present, we use
|
||||
// the grpclb policy, regardless of what the resolver has returned.
|
||||
const grpc_arg* channel_arg = |
||||
grpc_channel_args_find(resolver_result, GRPC_ARG_LB_ADDRESSES); |
||||
if (channel_arg != nullptr && channel_arg->type == GRPC_ARG_POINTER) { |
||||
grpc_lb_addresses* addresses = |
||||
static_cast<grpc_lb_addresses*>(channel_arg->value.pointer.p); |
||||
if (grpc_lb_addresses_contains_balancer_address(*addresses)) { |
||||
if (lb_policy_name != nullptr && |
||||
gpr_stricmp(lb_policy_name, "grpclb") != 0) { |
||||
gpr_log(GPR_INFO, |
||||
"resolver requested LB policy %s but provided at least one " |
||||
"balancer address -- forcing use of grpclb LB policy", |
||||
lb_policy_name); |
||||
} |
||||
lb_policy_name = "grpclb"; |
||||
} |
||||
} |
||||
// Use pick_first if nothing was specified and we didn't select grpclb
|
||||
// above.
|
||||
if (lb_policy_name == nullptr) lb_policy_name = "pick_first"; |
||||
lb_policy_name_.reset(gpr_strdup(lb_policy_name)); |
||||
} |
||||
|
||||
void ProcessedResolverResult::ParseServiceConfig( |
||||
const grpc_json* field, ProcessedResolverResult* parsing_state) { |
||||
parsing_state->ParseLbConfigFromServiceConfig(field); |
||||
if (parsing_state->server_name_ != nullptr) { |
||||
parsing_state->ParseRetryThrottleParamsFromServiceConfig(field); |
||||
} |
||||
} |
||||
|
||||
void ProcessedResolverResult::ParseLbConfigFromServiceConfig( |
||||
const grpc_json* field) { |
||||
if (lb_policy_config_ != nullptr) return; // Already found.
|
||||
// Find the LB config global parameter.
|
||||
if (field->key == nullptr || strcmp(field->key, "loadBalancingConfig") != 0 || |
||||
field->type != GRPC_JSON_ARRAY) { |
||||
return; // Not valid lb config array.
|
||||
} |
||||
// Find the first LB policy that this client supports.
|
||||
for (grpc_json* lb_config = field->child; lb_config != nullptr; |
||||
lb_config = lb_config->next) { |
||||
if (lb_config->type != GRPC_JSON_OBJECT) return; |
||||
// Find the policy object.
|
||||
grpc_json* policy = nullptr; |
||||
for (grpc_json* field = lb_config->child; field != nullptr; |
||||
field = field->next) { |
||||
if (field->key == nullptr || strcmp(field->key, "policy") != 0 || |
||||
field->type != GRPC_JSON_OBJECT) { |
||||
return; |
||||
} |
||||
if (policy != nullptr) return; // Duplicate.
|
||||
policy = field; |
||||
} |
||||
// Find the specific policy content since the policy object is of type
|
||||
// "oneof".
|
||||
grpc_json* policy_content = nullptr; |
||||
for (grpc_json* field = policy->child; field != nullptr; |
||||
field = field->next) { |
||||
if (field->key == nullptr || field->type != GRPC_JSON_OBJECT) return; |
||||
if (policy_content != nullptr) return; // Violate "oneof" type.
|
||||
policy_content = field; |
||||
} |
||||
grpc_core::UniquePtr<char> lb_policy_name = |
||||
ConvertCamelToSnake(policy_content->key); |
||||
if (!grpc_core::LoadBalancingPolicyRegistry::LoadBalancingPolicyExists( |
||||
lb_policy_name.get())) { |
||||
continue; |
||||
} |
||||
lb_policy_name_ = std::move(lb_policy_name); |
||||
lb_policy_config_ = policy_content->child; |
||||
return; |
||||
} |
||||
} |
||||
|
||||
void ProcessedResolverResult::ParseRetryThrottleParamsFromServiceConfig( |
||||
const grpc_json* field) { |
||||
if (strcmp(field->key, "retryThrottling") == 0) { |
||||
if (retry_throttle_data_ != nullptr) return; // Duplicate.
|
||||
if (field->type != GRPC_JSON_OBJECT) return; |
||||
int max_milli_tokens = 0; |
||||
int milli_token_ratio = 0; |
||||
for (grpc_json* sub_field = field->child; sub_field != nullptr; |
||||
sub_field = sub_field->next) { |
||||
if (sub_field->key == nullptr) return; |
||||
if (strcmp(sub_field->key, "maxTokens") == 0) { |
||||
if (max_milli_tokens != 0) return; // Duplicate.
|
||||
if (sub_field->type != GRPC_JSON_NUMBER) return; |
||||
max_milli_tokens = gpr_parse_nonnegative_int(sub_field->value); |
||||
if (max_milli_tokens == -1) return; |
||||
max_milli_tokens *= 1000; |
||||
} else if (strcmp(sub_field->key, "tokenRatio") == 0) { |
||||
if (milli_token_ratio != 0) return; // Duplicate.
|
||||
if (sub_field->type != GRPC_JSON_NUMBER) return; |
||||
// We support up to 3 decimal digits.
|
||||
size_t whole_len = strlen(sub_field->value); |
||||
uint32_t multiplier = 1; |
||||
uint32_t decimal_value = 0; |
||||
const char* decimal_point = strchr(sub_field->value, '.'); |
||||
if (decimal_point != nullptr) { |
||||
whole_len = static_cast<size_t>(decimal_point - sub_field->value); |
||||
multiplier = 1000; |
||||
size_t decimal_len = strlen(decimal_point + 1); |
||||
if (decimal_len > 3) decimal_len = 3; |
||||
if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len, |
||||
&decimal_value)) { |
||||
return; |
||||
} |
||||
uint32_t decimal_multiplier = 1; |
||||
for (size_t i = 0; i < (3 - decimal_len); ++i) { |
||||
decimal_multiplier *= 10; |
||||
} |
||||
decimal_value *= decimal_multiplier; |
||||
} |
||||
uint32_t whole_value; |
||||
if (!gpr_parse_bytes_to_uint32(sub_field->value, whole_len, |
||||
&whole_value)) { |
||||
return; |
||||
} |
||||
milli_token_ratio = |
||||
static_cast<int>((whole_value * multiplier) + decimal_value); |
||||
if (milli_token_ratio <= 0) return; |
||||
} |
||||
} |
||||
retry_throttle_data_ = |
||||
grpc_core::internal::ServerRetryThrottleMap::GetDataForServer( |
||||
server_name_, max_milli_tokens, milli_token_ratio); |
||||
} |
||||
} |
||||
|
||||
namespace { |
||||
|
||||
bool ParseWaitForReady( |
||||
grpc_json* field, ClientChannelMethodParams::WaitForReady* wait_for_ready) { |
||||
if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) { |
||||
return false; |
||||
} |
||||
*wait_for_ready = field->type == GRPC_JSON_TRUE |
||||
? ClientChannelMethodParams::WAIT_FOR_READY_TRUE |
||||
: ClientChannelMethodParams::WAIT_FOR_READY_FALSE; |
||||
return true; |
||||
} |
||||
|
||||
// Parses a JSON field of the form generated for a google.proto.Duration
|
||||
// proto message, as per:
|
||||
// https://developers.google.com/protocol-buffers/docs/proto3#json
|
||||
bool ParseDuration(grpc_json* field, grpc_millis* duration) { |
||||
if (field->type != GRPC_JSON_STRING) return false; |
||||
size_t len = strlen(field->value); |
||||
if (field->value[len - 1] != 's') return false; |
||||
UniquePtr<char> buf(gpr_strdup(field->value)); |
||||
*(buf.get() + len - 1) = '\0'; // Remove trailing 's'.
|
||||
char* decimal_point = strchr(buf.get(), '.'); |
||||
int nanos = 0; |
||||
if (decimal_point != nullptr) { |
||||
*decimal_point = '\0'; |
||||
nanos = gpr_parse_nonnegative_int(decimal_point + 1); |
||||
if (nanos == -1) { |
||||
return false; |
||||
} |
||||
int num_digits = static_cast<int>(strlen(decimal_point + 1)); |
||||
if (num_digits > 9) { // We don't accept greater precision than nanos.
|
||||
return false; |
||||
} |
||||
for (int i = 0; i < (9 - num_digits); ++i) { |
||||
nanos *= 10; |
||||
} |
||||
} |
||||
int seconds = |
||||
decimal_point == buf.get() ? 0 : gpr_parse_nonnegative_int(buf.get()); |
||||
if (seconds == -1) return false; |
||||
*duration = seconds * GPR_MS_PER_SEC + nanos / GPR_NS_PER_MS; |
||||
return true; |
||||
} |
||||
|
||||
UniquePtr<ClientChannelMethodParams::RetryPolicy> ParseRetryPolicy( |
||||
grpc_json* field) { |
||||
auto retry_policy = MakeUnique<ClientChannelMethodParams::RetryPolicy>(); |
||||
if (field->type != GRPC_JSON_OBJECT) return nullptr; |
||||
for (grpc_json* sub_field = field->child; sub_field != nullptr; |
||||
sub_field = sub_field->next) { |
||||
if (sub_field->key == nullptr) return nullptr; |
||||
if (strcmp(sub_field->key, "maxAttempts") == 0) { |
||||
if (retry_policy->max_attempts != 0) return nullptr; // Duplicate.
|
||||
if (sub_field->type != GRPC_JSON_NUMBER) return nullptr; |
||||
retry_policy->max_attempts = gpr_parse_nonnegative_int(sub_field->value); |
||||
if (retry_policy->max_attempts <= 1) return nullptr; |
||||
if (retry_policy->max_attempts > MAX_MAX_RETRY_ATTEMPTS) { |
||||
gpr_log(GPR_ERROR, |
||||
"service config: clamped retryPolicy.maxAttempts at %d", |
||||
MAX_MAX_RETRY_ATTEMPTS); |
||||
retry_policy->max_attempts = MAX_MAX_RETRY_ATTEMPTS; |
||||
} |
||||
} else if (strcmp(sub_field->key, "initialBackoff") == 0) { |
||||
if (retry_policy->initial_backoff > 0) return nullptr; // Duplicate.
|
||||
if (!ParseDuration(sub_field, &retry_policy->initial_backoff)) { |
||||
return nullptr; |
||||
} |
||||
if (retry_policy->initial_backoff == 0) return nullptr; |
||||
} else if (strcmp(sub_field->key, "maxBackoff") == 0) { |
||||
if (retry_policy->max_backoff > 0) return nullptr; // Duplicate.
|
||||
if (!ParseDuration(sub_field, &retry_policy->max_backoff)) { |
||||
return nullptr; |
||||
} |
||||
if (retry_policy->max_backoff == 0) return nullptr; |
||||
} else if (strcmp(sub_field->key, "backoffMultiplier") == 0) { |
||||
if (retry_policy->backoff_multiplier != 0) return nullptr; // Duplicate.
|
||||
if (sub_field->type != GRPC_JSON_NUMBER) return nullptr; |
||||
if (sscanf(sub_field->value, "%f", &retry_policy->backoff_multiplier) != |
||||
1) { |
||||
return nullptr; |
||||
} |
||||
if (retry_policy->backoff_multiplier <= 0) return nullptr; |
||||
} else if (strcmp(sub_field->key, "retryableStatusCodes") == 0) { |
||||
if (!retry_policy->retryable_status_codes.Empty()) { |
||||
return nullptr; // Duplicate.
|
||||
} |
||||
if (sub_field->type != GRPC_JSON_ARRAY) return nullptr; |
||||
for (grpc_json* element = sub_field->child; element != nullptr; |
||||
element = element->next) { |
||||
if (element->type != GRPC_JSON_STRING) return nullptr; |
||||
grpc_status_code status; |
||||
if (!grpc_status_code_from_string(element->value, &status)) { |
||||
return nullptr; |
||||
} |
||||
retry_policy->retryable_status_codes.Add(status); |
||||
} |
||||
if (retry_policy->retryable_status_codes.Empty()) return nullptr; |
||||
} |
||||
} |
||||
// Make sure required fields are set.
|
||||
if (retry_policy->max_attempts == 0 || retry_policy->initial_backoff == 0 || |
||||
retry_policy->max_backoff == 0 || retry_policy->backoff_multiplier == 0 || |
||||
retry_policy->retryable_status_codes.Empty()) { |
||||
return nullptr; |
||||
} |
||||
return retry_policy; |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
RefCountedPtr<ClientChannelMethodParams> |
||||
ClientChannelMethodParams::CreateFromJson(const grpc_json* json) { |
||||
RefCountedPtr<ClientChannelMethodParams> method_params = |
||||
MakeRefCounted<ClientChannelMethodParams>(); |
||||
for (grpc_json* field = json->child; field != nullptr; field = field->next) { |
||||
if (field->key == nullptr) continue; |
||||
if (strcmp(field->key, "waitForReady") == 0) { |
||||
if (method_params->wait_for_ready_ != WAIT_FOR_READY_UNSET) { |
||||
return nullptr; // Duplicate.
|
||||
} |
||||
if (!ParseWaitForReady(field, &method_params->wait_for_ready_)) { |
||||
return nullptr; |
||||
} |
||||
} else if (strcmp(field->key, "timeout") == 0) { |
||||
if (method_params->timeout_ > 0) return nullptr; // Duplicate.
|
||||
if (!ParseDuration(field, &method_params->timeout_)) return nullptr; |
||||
} else if (strcmp(field->key, "retryPolicy") == 0) { |
||||
if (method_params->retry_policy_ != nullptr) { |
||||
return nullptr; // Duplicate.
|
||||
} |
||||
method_params->retry_policy_ = ParseRetryPolicy(field); |
||||
if (method_params->retry_policy_ == nullptr) return nullptr; |
||||
} |
||||
} |
||||
return method_params; |
||||
} |
||||
|
||||
} // namespace internal
|
||||
} // namespace grpc_core
|
@ -0,0 +1,146 @@ |
||||
/*
|
||||
* |
||||
* 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_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H |
||||
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/retry_throttle.h" |
||||
#include "src/core/lib/channel/status_util.h" |
||||
#include "src/core/lib/gprpp/ref_counted.h" |
||||
#include "src/core/lib/gprpp/ref_counted_ptr.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" // for grpc_millis |
||||
#include "src/core/lib/json/json.h" |
||||
#include "src/core/lib/slice/slice_hash_table.h" |
||||
#include "src/core/lib/transport/service_config.h" |
||||
|
||||
namespace grpc_core { |
||||
namespace internal { |
||||
|
||||
class ClientChannelMethodParams; |
||||
|
||||
// A table mapping from a method name to its method parameters.
|
||||
typedef grpc_core::SliceHashTable< |
||||
grpc_core::RefCountedPtr<ClientChannelMethodParams>> |
||||
ClientChannelMethodParamsTable; |
||||
|
||||
// A container of processed fields from the resolver result. Simplifies the
|
||||
// usage of resolver result.
|
||||
class ProcessedResolverResult { |
||||
public: |
||||
// Processes the resolver result and populates the relative members
|
||||
// for later consumption. Tries to parse retry parameters only if parse_retry
|
||||
// is true.
|
||||
ProcessedResolverResult(const grpc_channel_args* resolver_result, |
||||
bool parse_retry); |
||||
|
||||
// Getters. Any managed object's ownership is transferred.
|
||||
grpc_core::UniquePtr<char> service_config_json() { |
||||
return std::move(service_config_json_); |
||||
} |
||||
grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data() { |
||||
return std::move(retry_throttle_data_); |
||||
} |
||||
grpc_core::RefCountedPtr<ClientChannelMethodParamsTable> |
||||
method_params_table() { |
||||
return std::move(method_params_table_); |
||||
} |
||||
grpc_core::UniquePtr<char> lb_policy_name() { |
||||
return std::move(lb_policy_name_); |
||||
} |
||||
grpc_json* lb_policy_config() { return lb_policy_config_; } |
||||
|
||||
private: |
||||
// Finds the service config; extracts LB config and (maybe) retry throttle
|
||||
// params from it.
|
||||
void ProcessServiceConfig(const grpc_channel_args* resolver_result, |
||||
bool parse_retry); |
||||
|
||||
// Finds the LB policy name (when no LB config was found).
|
||||
void ProcessLbPolicyName(const grpc_channel_args* resolver_result); |
||||
|
||||
// Parses the service config. Intended to be used by
|
||||
// ServiceConfig::ParseGlobalParams.
|
||||
static void ParseServiceConfig(const grpc_json* field, |
||||
ProcessedResolverResult* parsing_state); |
||||
// Parses the LB config from service config.
|
||||
void ParseLbConfigFromServiceConfig(const grpc_json* field); |
||||
// Parses the retry throttle parameters from service config.
|
||||
void ParseRetryThrottleParamsFromServiceConfig(const grpc_json* field); |
||||
|
||||
// Service config.
|
||||
grpc_core::UniquePtr<char> service_config_json_; |
||||
grpc_core::UniquePtr<grpc_core::ServiceConfig> service_config_; |
||||
// LB policy.
|
||||
grpc_json* lb_policy_config_ = nullptr; |
||||
grpc_core::UniquePtr<char> lb_policy_name_; |
||||
// Retry throttle data.
|
||||
char* server_name_ = nullptr; |
||||
grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data_; |
||||
// Method params table.
|
||||
grpc_core::RefCountedPtr<ClientChannelMethodParamsTable> method_params_table_; |
||||
}; |
||||
|
||||
// The parameters of a method.
|
||||
class ClientChannelMethodParams : public RefCounted<ClientChannelMethodParams> { |
||||
public: |
||||
enum WaitForReady { |
||||
WAIT_FOR_READY_UNSET = 0, |
||||
WAIT_FOR_READY_FALSE, |
||||
WAIT_FOR_READY_TRUE |
||||
}; |
||||
|
||||
struct RetryPolicy { |
||||
int max_attempts = 0; |
||||
grpc_millis initial_backoff = 0; |
||||
grpc_millis max_backoff = 0; |
||||
float backoff_multiplier = 0; |
||||
StatusCodeSet retryable_status_codes; |
||||
}; |
||||
|
||||
/// Creates a method_parameters object from \a json.
|
||||
/// Intended for use with ServiceConfig::CreateMethodConfigTable().
|
||||
static RefCountedPtr<ClientChannelMethodParams> CreateFromJson( |
||||
const grpc_json* json); |
||||
|
||||
grpc_millis timeout() const { return timeout_; } |
||||
WaitForReady wait_for_ready() const { return wait_for_ready_; } |
||||
const RetryPolicy* retry_policy() const { return retry_policy_.get(); } |
||||
|
||||
private: |
||||
// So New() can call our private ctor.
|
||||
template <typename T, typename... Args> |
||||
friend T* grpc_core::New(Args&&... args); |
||||
|
||||
// So Delete() can call our private dtor.
|
||||
template <typename T> |
||||
friend void grpc_core::Delete(T*); |
||||
|
||||
ClientChannelMethodParams() {} |
||||
virtual ~ClientChannelMethodParams() {} |
||||
|
||||
grpc_millis timeout_ = 0; |
||||
WaitForReady wait_for_ready_ = WAIT_FOR_READY_UNSET; |
||||
UniquePtr<RetryPolicy> retry_policy_; |
||||
}; |
||||
|
||||
} // namespace internal
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H */ |
@ -0,0 +1,50 @@ |
||||
/*
|
||||
* |
||||
* 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/ext/transport/chttp2/transport/context_list.h" |
||||
|
||||
namespace { |
||||
void (*write_timestamps_callback_g)(void*, grpc_core::Timestamps*) = nullptr; |
||||
} |
||||
|
||||
namespace grpc_core { |
||||
void ContextList::Execute(void* arg, grpc_core::Timestamps* ts, |
||||
grpc_error* error) { |
||||
ContextList* head = static_cast<ContextList*>(arg); |
||||
ContextList* to_be_freed; |
||||
while (head != nullptr) { |
||||
if (error == GRPC_ERROR_NONE && ts != nullptr) { |
||||
if (write_timestamps_callback_g) { |
||||
write_timestamps_callback_g(head->s_->context, ts); |
||||
} |
||||
} |
||||
GRPC_CHTTP2_STREAM_UNREF(static_cast<grpc_chttp2_stream*>(head->s_), |
||||
"timestamp"); |
||||
to_be_freed = head; |
||||
head = head->next_; |
||||
grpc_core::Delete(to_be_freed); |
||||
} |
||||
} |
||||
|
||||
void grpc_http2_set_write_timestamps_callback( |
||||
void (*fn)(void*, grpc_core::Timestamps*)) { |
||||
write_timestamps_callback_g = fn; |
||||
} |
||||
} /* namespace grpc_core */ |
@ -0,0 +1,70 @@ |
||||
/*
|
||||
* |
||||
* 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_CONTEXT_LIST_H |
||||
#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CONTEXT_LIST_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/iomgr/buffer_list.h" |
||||
|
||||
#include "src/core/ext/transport/chttp2/transport/internal.h" |
||||
|
||||
namespace grpc_core { |
||||
/** A list of RPC Contexts */ |
||||
class ContextList { |
||||
public: |
||||
/* Creates a new element with \a context as the value and appends it to the
|
||||
* list. */ |
||||
static void Append(ContextList** head, grpc_chttp2_stream* s) { |
||||
/* Make sure context is not already present */ |
||||
GRPC_CHTTP2_STREAM_REF(s, "timestamp"); |
||||
|
||||
#ifndef NDEBUG |
||||
ContextList* ptr = *head; |
||||
while (ptr != nullptr) { |
||||
if (ptr->s_ == s) { |
||||
GPR_ASSERT( |
||||
false && |
||||
"Trying to append a stream that is already present in the list"); |
||||
} |
||||
ptr = ptr->next_; |
||||
} |
||||
#endif |
||||
|
||||
/* Create a new element in the list and add it at the front */ |
||||
ContextList* elem = grpc_core::New<ContextList>(); |
||||
elem->s_ = s; |
||||
elem->next_ = *head; |
||||
*head = elem; |
||||
} |
||||
|
||||
/* Executes a function \a fn with each context in the list and \a ts. It also
|
||||
* frees up the entire list after this operation. */ |
||||
static void Execute(void* arg, grpc_core::Timestamps* ts, grpc_error* error); |
||||
|
||||
private: |
||||
grpc_chttp2_stream* s_ = nullptr; |
||||
ContextList* next_ = nullptr; |
||||
}; |
||||
|
||||
void grpc_http2_set_write_timestamps_callback( |
||||
void (*fn)(void*, grpc_core::Timestamps*)); |
||||
} /* namespace grpc_core */ |
||||
|
||||
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CONTEXT_LIST_H */ |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue