aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs6
-rw-r--r--src/csharp/Grpc.Core/AsyncAuthInterceptor.cs84
-rw-r--r--src/csharp/Grpc.Core/CallCredentials.cs8
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.csproj7
-rw-r--r--src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs13
-rw-r--r--src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs2
-rw-r--r--src/csharp/ext/grpc_csharp_ext.c7
-rw-r--r--src/node/ext/byte_buffer.cc1
-rw-r--r--src/node/ext/call.cc13
-rw-r--r--src/node/src/credentials.js5
-rw-r--r--src/objective-c/GRPCClient/GRPCCall.h43
-rw-r--r--src/objective-c/GRPCClient/GRPCCall.m2
-rw-r--r--src/objective-c/GRPCClient/private/GRPCRequestHeaders.h13
-rw-r--r--src/objective-c/GRPCClient/private/GRPCRequestHeaders.m43
-rw-r--r--src/objective-c/GRPCClient/private/GRPCWrappedCall.h2
-rw-r--r--src/objective-c/GRPCClient/private/GRPCWrappedCall.m2
16 files changed, 184 insertions, 67 deletions
diff --git a/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs b/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs
index 1c14c5bb5b..f77e9c6573 100644
--- a/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs
+++ b/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs
@@ -57,9 +57,9 @@ namespace Grpc.Auth
/// <returns>The interceptor.</returns>
public static AsyncAuthInterceptor FromCredential(ITokenAccess credential)
{
- return new AsyncAuthInterceptor(async (authUri, metadata) =>
+ return new AsyncAuthInterceptor(async (context, metadata) =>
{
- var accessToken = await credential.GetAccessTokenForRequestAsync(authUri, CancellationToken.None).ConfigureAwait(false);
+ var accessToken = await credential.GetAccessTokenForRequestAsync(context.ServiceUrl, CancellationToken.None).ConfigureAwait(false);
metadata.Add(CreateBearerTokenHeader(accessToken));
});
}
@@ -72,7 +72,7 @@ namespace Grpc.Auth
public static AsyncAuthInterceptor FromAccessToken(string accessToken)
{
Preconditions.CheckNotNull(accessToken);
- return new AsyncAuthInterceptor(async (authUri, metadata) =>
+ return new AsyncAuthInterceptor(async (context, metadata) =>
{
metadata.Add(CreateBearerTokenHeader(accessToken));
});
diff --git a/src/csharp/Grpc.Core/AsyncAuthInterceptor.cs b/src/csharp/Grpc.Core/AsyncAuthInterceptor.cs
new file mode 100644
index 0000000000..5c9ab04812
--- /dev/null
+++ b/src/csharp/Grpc.Core/AsyncAuthInterceptor.cs
@@ -0,0 +1,84 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core
+{
+ /// <summary>
+ /// Asynchronous authentication interceptor for <see cref="CallCredentials"/>.
+ /// </summary>
+ /// <param name="context">The interceptor context.</param>
+ /// <param name="metadata">Metadata to populate with entries that will be added to outgoing call's headers.</param>
+ /// <returns></returns>
+ public delegate Task AsyncAuthInterceptor(AuthInterceptorContext context, Metadata metadata);
+
+ /// <summary>
+ /// Context for an RPC being intercepted by <see cref="AsyncAuthInterceptor"/>.
+ /// </summary>
+ public class AuthInterceptorContext
+ {
+ readonly string serviceUrl;
+ readonly string methodName;
+
+ /// <summary>
+ /// Initializes a new instance of <c>AuthInterceptorContext</c>.
+ /// </summary>
+ public AuthInterceptorContext(string serviceUrl, string methodName)
+ {
+ this.serviceUrl = Preconditions.CheckNotNull(serviceUrl);
+ this.methodName = Preconditions.CheckNotNull(methodName);
+ }
+
+ /// <summary>
+ /// The fully qualified service URL for the RPC being called.
+ /// </summary>
+ public string ServiceUrl
+ {
+ get { return serviceUrl; }
+ }
+
+ /// <summary>
+ /// The method name of the RPC being called.
+ /// </summary>
+ public string MethodName
+ {
+ get { return methodName; }
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/CallCredentials.cs b/src/csharp/Grpc.Core/CallCredentials.cs
index 5ea179dfea..a71c8904fe 100644
--- a/src/csharp/Grpc.Core/CallCredentials.cs
+++ b/src/csharp/Grpc.Core/CallCredentials.cs
@@ -41,14 +41,6 @@ using Grpc.Core.Utils;
namespace Grpc.Core
{
/// <summary>
- /// Asynchronous authentication interceptor for <see cref="CallCredentials"/>.
- /// </summary>
- /// <param name="authUri">URL of a service to which current remote call needs to authenticate</param>
- /// <param name="metadata">Metadata to populate with entries that will be added to outgoing call's headers.</param>
- /// <returns></returns>
- public delegate Task AsyncAuthInterceptor(string authUri, Metadata metadata);
-
- /// <summary>
/// Client-side call credentials. Provide authorization with per-call granularity.
/// </summary>
public abstract class CallCredentials
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index c4f799297d..486e47945c 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -48,6 +48,7 @@
<ItemGroup>
<Compile Include="AsyncDuplexStreamingCall.cs" />
<Compile Include="AsyncServerStreamingCall.cs" />
+ <Compile Include="AsyncAuthInterceptor.cs" />
<Compile Include="CallCredentials.cs" />
<Compile Include="IClientStreamWriter.cs" />
<Compile Include="Internal\NativeMetadataCredentialsPlugin.cs" />
@@ -155,7 +156,5 @@
<Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" />
<Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" />
<ItemGroup />
- <ItemGroup>
- <Folder Include="Profiling\" />
- </ItemGroup>
-</Project>
+ <ItemGroup />
+</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
index 2a571cd6c9..69a7cd98cb 100644
--- a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
@@ -38,7 +38,7 @@ using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
- internal delegate void NativeMetadataInterceptor(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy);
+ internal delegate void NativeMetadataInterceptor(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr methodNamePtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy);
internal class NativeMetadataCredentialsPlugin
{
@@ -71,7 +71,7 @@ namespace Grpc.Core.Internal
get { return credentials; }
}
- private void NativeMetadataInterceptorHandler(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy)
+ private void NativeMetadataInterceptorHandler(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr methodNamePtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy)
{
if (isDestroy)
{
@@ -81,8 +81,9 @@ namespace Grpc.Core.Internal
try
{
- string serviceUrl = Marshal.PtrToStringAnsi(serviceUrlPtr);
- StartGetMetadata(serviceUrl, callbackPtr, userDataPtr);
+ var context = new AuthInterceptorContext(Marshal.PtrToStringAnsi(serviceUrlPtr),
+ Marshal.PtrToStringAnsi(methodNamePtr));
+ StartGetMetadata(context, callbackPtr, userDataPtr);
}
catch (Exception e)
{
@@ -91,12 +92,12 @@ namespace Grpc.Core.Internal
}
}
- private async void StartGetMetadata(string serviceUrl, IntPtr callbackPtr, IntPtr userDataPtr)
+ private async void StartGetMetadata(AuthInterceptorContext context, IntPtr callbackPtr, IntPtr userDataPtr)
{
try
{
var metadata = new Metadata();
- await interceptor(serviceUrl, metadata);
+ await interceptor(context, metadata);
using (var metadataArray = MetadataArraySafeHandle.Create(metadata))
{
diff --git a/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
index 3d56678b99..35230f48c1 100644
--- a/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
@@ -67,7 +67,7 @@ namespace Grpc.IntegrationTesting
new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride)
};
- var asyncAuthInterceptor = new AsyncAuthInterceptor(async (authUri, metadata) =>
+ var asyncAuthInterceptor = new AsyncAuthInterceptor(async (context, metadata) =>
{
await Task.Delay(100); // make sure the operation is asynchronous.
metadata.Add("authorization", "SECRET_TOKEN");
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index b8705c49d3..0ef9be33a6 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -927,7 +927,8 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin(
}
typedef void(GPR_CALLTYPE *grpcsharp_metadata_interceptor_func)(
- void *state, const char *service_url, grpc_credentials_plugin_metadata_cb cb,
+ void *state, const char *service_url, const char *method_name,
+ grpc_credentials_plugin_metadata_cb cb,
void *user_data, gpr_int32 is_destroy);
static void grpcsharp_get_metadata_handler(
@@ -935,13 +936,13 @@ static void grpcsharp_get_metadata_handler(
grpc_credentials_plugin_metadata_cb cb, void *user_data) {
grpcsharp_metadata_interceptor_func interceptor =
(grpcsharp_metadata_interceptor_func)(gpr_intptr)state;
- interceptor(state, context.service_url, cb, user_data, 0);
+ interceptor(state, context.service_url, context.method_name, cb, user_data, 0);
}
static void grpcsharp_metadata_credentials_destroy_handler(void *state) {
grpcsharp_metadata_interceptor_func interceptor =
(grpcsharp_metadata_interceptor_func)(gpr_intptr)state;
- interceptor(state, NULL, NULL, NULL, 1);
+ interceptor(state, NULL, NULL, NULL, NULL, 1);
}
GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_create_from_plugin(
diff --git a/src/node/ext/byte_buffer.cc b/src/node/ext/byte_buffer.cc
index e1786ddba7..c306292c04 100644
--- a/src/node/ext/byte_buffer.cc
+++ b/src/node/ext/byte_buffer.cc
@@ -77,6 +77,7 @@ Local<Value> ByteBufferToBuffer(grpc_byte_buffer *buffer) {
while (grpc_byte_buffer_reader_next(&reader, &next) != 0) {
memcpy(result + offset, GPR_SLICE_START_PTR(next), GPR_SLICE_LENGTH(next));
offset += GPR_SLICE_LENGTH(next);
+ gpr_slice_unref(next);
}
return scope.Escape(MakeFastBuffer(
Nan::NewBuffer(result, length).ToLocalChecked()));
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index a98ae85427..c0e2b0f0e8 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -234,6 +234,14 @@ class SendMetadataOp : public Op {
class SendMessageOp : public Op {
public:
+ SendMessageOp() {
+ send_message = NULL;
+ }
+ ~SendMessageOp() {
+ if (send_message != NULL) {
+ grpc_byte_buffer_destroy(send_message);
+ }
+ }
Local<Value> GetNodeValue() const {
EscapableHandleScope scope;
return scope.Escape(Nan::True());
@@ -253,7 +261,8 @@ class SendMessageOp : public Op {
out->flags = maybe_flag.FromMaybe(0) & GRPC_WRITE_USED_MASK;
}
}
- out->data.send_message = BufferToByteBuffer(value);
+ send_message = BufferToByteBuffer(value);
+ out->data.send_message = send_message;
PersistentValue *handle = new PersistentValue(value);
resources->handles.push_back(unique_ptr<PersistentValue>(handle));
return true;
@@ -262,6 +271,8 @@ class SendMessageOp : public Op {
std::string GetTypeString() const {
return "send_message";
}
+ private:
+ grpc_byte_buffer *send_message;
};
class SendClientCloseOp : public Op {
diff --git a/src/node/src/credentials.js b/src/node/src/credentials.js
index ff10a22e6a..dcbfac18f4 100644
--- a/src/node/src/credentials.js
+++ b/src/node/src/credentials.js
@@ -91,7 +91,7 @@ exports.createSsl = ChannelCredentials.createSsl;
*/
exports.createFromMetadataGenerator = function(metadata_generator) {
return CallCredentials.createFromPlugin(function(service_url, callback) {
- metadata_generator(service_url, function(error, metadata) {
+ metadata_generator({service_url: service_url}, function(error, metadata) {
var code = grpc.status.OK;
var message = '';
if (error) {
@@ -114,7 +114,8 @@ exports.createFromMetadataGenerator = function(metadata_generator) {
* @return {CallCredentials} The resulting credentials object
*/
exports.createFromGoogleCredential = function(google_credential) {
- return exports.createFromMetadataGenerator(function(service_url, callback) {
+ return exports.createFromMetadataGenerator(function(auth_context, callback) {
+ var service_url = auth_context.service_url;
google_credential.getRequestMetadata(service_url, function(err, header) {
if (err) {
callback(err);
diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h
index 5918f8857a..c9fda42855 100644
--- a/src/objective-c/GRPCClient/GRPCCall.h
+++ b/src/objective-c/GRPCClient/GRPCCall.h
@@ -50,6 +50,8 @@
#import <Foundation/Foundation.h>
#import <RxLibrary/GRXWriter.h>
+#include <AvailabilityMacros.h>
+
#pragma mark gRPC errors
/** Domain of NSError objects produced by gRPC. */
@@ -161,6 +163,9 @@ extern id const kGRPCTrailersKey;
#pragma mark GRPCCall
+/** Represents a single gRPC remote call. */
+@interface GRPCCall : GRXWriter
+
/**
* The container of the request headers of an RPC conforms to this protocol, which is a subset of
* NSMutableDictionary's interface. It will become a NSMutableDictionary later on.
@@ -170,21 +175,6 @@ extern id const kGRPCTrailersKey;
* A header value is a NSString object (with only ASCII characters), unless the header name has the
* suffix "-bin", in which case the value has to be a NSData object.
*/
-@protocol GRPCRequestHeaders <NSObject>
-
-@property(nonatomic, readonly) NSUInteger count;
-
-- (id)objectForKeyedSubscript:(NSString *)key;
-- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key;
-
-- (void)removeAllObjects;
-- (void)removeObjectForKey:(NSString *)key;
-
-@end
-
-/** Represents a single gRPC remote call. */
-@interface GRPCCall : GRXWriter
-
/**
* These HTTP headers will be passed to the server as part of this call. Each HTTP header is a
* name-value pair with string names and either string or binary values.
@@ -200,7 +190,7 @@ extern id const kGRPCTrailersKey;
*
* The property is initialized to an empty NSMutableDictionary.
*/
-@property(atomic, readonly) id<GRPCRequestHeaders> requestHeaders;
+@property(atomic, readonly) NSMutableDictionary *requestHeaders;
/**
* This dictionary is populated with the HTTP headers received from the server. This happens before
@@ -243,3 +233,24 @@ extern id const kGRPCTrailersKey;
// TODO(jcanizales): Let specify a deadline. As a category of GRXWriter?
@end
+
+#pragma mark Backwards compatibiity
+
+/** This protocol is kept for backwards compatibility with existing code. */
+DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.")
+@protocol GRPCRequestHeaders <NSObject>
+@property(nonatomic, readonly) NSUInteger count;
+
+- (id)objectForKeyedSubscript:(NSString *)key;
+- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key;
+
+- (void)removeAllObjects;
+- (void)removeObjectForKey:(NSString *)key;
+@end
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated"
+/** This is only needed for backwards-compatibility. */
+@interface NSMutableDictionary (GRPCRequestHeaders) <GRPCRequestHeaders>
+@end
+#pragma clang diagnostic pop
diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m
index b6986bf59c..f79b7d0bc0 100644
--- a/src/objective-c/GRPCClient/GRPCCall.m
+++ b/src/objective-c/GRPCClient/GRPCCall.m
@@ -221,7 +221,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
#pragma mark Send headers
-- (void)sendHeaders:(id<GRPCRequestHeaders>)headers {
+- (void)sendHeaders:(NSDictionary *)headers {
// TODO(jcanizales): Add error handlers for async failures
[_wrappedCall startBatchWithOperations:@[[[GRPCOpSendMetadata alloc] initWithMetadata:headers
handler:nil]]];
diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h
index cf5a1be9d6..b580f19406 100644
--- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h
+++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h
@@ -32,21 +32,14 @@
*/
#import <Foundation/Foundation.h>
-#include <grpc/grpc.h>
#import "../GRPCCall.h"
-@interface GRPCRequestHeaders : NSObject<GRPCRequestHeaders>
-
-@property(nonatomic, readonly) NSUInteger count;
-@property(nonatomic, readonly) grpc_metadata *grpc_metadataArray;
+@interface GRPCRequestHeaders : NSMutableDictionary
- (instancetype)initWithCall:(GRPCCall *)call;
-- (id)objectForKeyedSubscript:(NSString *)key;
-- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key;
-
-- (void)removeAllObjects;
-- (void)removeObjectForKey:(NSString *)key;
+- (instancetype)initWithCall:(GRPCCall *)call
+ storage:(NSMutableDictionary *)storage NS_DESIGNATED_INITIALIZER;
@end
diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m
index d23f21c0f9..c6a03c145e 100644
--- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m
+++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m
@@ -68,17 +68,44 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) {
@implementation GRPCRequestHeaders {
__weak GRPCCall *_call;
+ // The NSMutableDictionary superclass doesn't hold any storage (so that people can implement their
+ // own in subclasses). As that's not the reason we're subclassing, we just delegate storage to the
+ // default NSMutableDictionary subclass returned by the cluster (e.g. __NSDictionaryM on iOS 9).
NSMutableDictionary *_delegate;
}
+- (instancetype)init {
+ return [self initWithCall:nil];
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ return [self init];
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+ return [self init];
+}
+
- (instancetype)initWithCall:(GRPCCall *)call {
+ return [self initWithCall:call storage:[NSMutableDictionary dictionary]];
+}
+
+// Designated initializer
+- (instancetype)initWithCall:(GRPCCall *)call storage:(NSMutableDictionary *)storage {
+ // TODO(jcanizales): Throw if call or storage are nil.
if ((self = [super init])) {
_call = call;
- _delegate = [NSMutableDictionary dictionary];
+ _delegate = storage;
}
return self;
}
+- (instancetype)initWithObjects:(const id _Nonnull __unsafe_unretained *)objects
+ forKeys:(const id<NSCopying> _Nonnull __unsafe_unretained *)keys
+ count:(NSUInteger)cnt {
+ return [self init];
+}
+
- (void)checkCallIsNotStarted {
if (_call.state != GRXWriterStateNotStarted) {
[NSException raise:@"Invalid modification"
@@ -86,11 +113,11 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) {
}
}
-- (id)objectForKeyedSubscript:(NSString *)key {
+- (id)objectForKey:(NSString *)key {
return _delegate[key.lowercaseString];
}
-- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key {
+- (void)setObject:(id)obj forKey:(NSString *)key {
[self checkCallIsNotStarted];
CheckIsNonNilASCII(@"Header name", key);
key = key.lowercaseString;
@@ -103,16 +130,12 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) {
[_delegate removeObjectForKey:key.lowercaseString];
}
-- (void)removeAllObjects {
- [self checkCallIsNotStarted];
- [_delegate removeAllObjects];
-}
-
- (NSUInteger)count {
return _delegate.count;
}
-- (grpc_metadata *)grpc_metadataArray {
- return _delegate.grpc_metadataArray;
+- (NSEnumerator * _Nonnull)keyEnumerator {
+ return [_delegate keyEnumerator];
}
+
@end
diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h
index 7747aa53ef..71e7e0e54e 100644
--- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h
+++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h
@@ -45,7 +45,7 @@
@interface GRPCOpSendMetadata : GRPCOperation
-- (instancetype)initWithMetadata:(GRPCRequestHeaders *)metadata
+- (instancetype)initWithMetadata:(NSDictionary *)metadata
handler:(void(^)())handler NS_DESIGNATED_INITIALIZER;
@end
diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
index cea7c479e0..fe3d51da53 100644
--- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
+++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
@@ -65,7 +65,7 @@
return [self initWithMetadata:nil handler:nil];
}
-- (instancetype)initWithMetadata:(GRPCRequestHeaders *)metadata handler:(void (^)())handler {
+- (instancetype)initWithMetadata:(NSDictionary *)metadata handler:(void (^)())handler {
if (self = [super init]) {
_op.op = GRPC_OP_SEND_INITIAL_METADATA;
_op.data.send_initial_metadata.count = metadata.count;