blob: c55beca0c4af40153c265a46d4e17ec420926445 [file] [log] [blame]
/*
*
* Copyright 2019 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 "GRPCTransport.h"
static const GRPCTransportID gGRPCCoreSecureID = "io.grpc.transport.core.secure";
static const GRPCTransportID gGRPCCoreInsecureID = "io.grpc.transport.core.insecure";
const struct GRPCDefaultTransportImplList GRPCDefaultTransportImplList = {
.core_secure = gGRPCCoreSecureID, .core_insecure = gGRPCCoreInsecureID};
static const GRPCTransportID gDefaultTransportID = gGRPCCoreSecureID;
static GRPCTransportRegistry *gTransportRegistry = nil;
static dispatch_once_t initTransportRegistry;
BOOL TransportIDIsEqual(GRPCTransportID lhs, GRPCTransportID rhs) {
// Directly comparing pointers works because we require users to use the id provided by each
// implementation, not coming up with their own string.
return lhs == rhs;
}
NSUInteger TransportIDHash(GRPCTransportID transportID) {
if (transportID == NULL) {
transportID = gDefaultTransportID;
}
return [NSString stringWithCString:transportID encoding:NSUTF8StringEncoding].hash;
}
@implementation GRPCTransportRegistry {
NSMutableDictionary<NSString *, id<GRPCTransportFactory>> *_registry;
id<GRPCTransportFactory> _defaultFactory;
}
+ (instancetype)sharedInstance {
dispatch_once(&initTransportRegistry, ^{
gTransportRegistry = [[GRPCTransportRegistry alloc] init];
NSAssert(gTransportRegistry != nil, @"Unable to initialize transport registry.");
if (gTransportRegistry == nil) {
NSLog(@"Unable to initialize transport registry.");
[NSException raise:NSGenericException format:@"Unable to initialize transport registry."];
}
});
return gTransportRegistry;
}
- (instancetype)init {
if ((self = [super init])) {
_registry = [NSMutableDictionary dictionary];
}
return self;
}
- (void)registerTransportWithID:(GRPCTransportID)transportID
factory:(id<GRPCTransportFactory>)factory {
NSString *nsTransportID = [NSString stringWithCString:transportID encoding:NSUTF8StringEncoding];
NSAssert(_registry[nsTransportID] == nil, @"The transport %@ has already been registered.",
nsTransportID);
if (_registry[nsTransportID] != nil) {
NSLog(@"The transport %@ has already been registered.", nsTransportID);
return;
}
_registry[nsTransportID] = factory;
// if the default transport is registered, mark it.
if (0 == strcmp(transportID, gDefaultTransportID)) {
_defaultFactory = factory;
}
}
- (id<GRPCTransportFactory>)getTransportFactoryWithID:(GRPCTransportID)transportID {
if (transportID == NULL) {
if (_defaultFactory == nil) {
// fall back to default transport if no transport is provided
[NSException raise:NSInvalidArgumentException
format:@"Did not specify transport and unable to find a default transport."];
return nil;
}
return _defaultFactory;
}
NSString *nsTransportID = [NSString stringWithCString:transportID encoding:NSUTF8StringEncoding];
id<GRPCTransportFactory> transportFactory = _registry[nsTransportID];
if (transportFactory == nil) {
if (_defaultFactory != nil) {
// fall back to default transport if no transport is found
NSLog(@"Unable to find transport with id %s; falling back to default transport.",
transportID);
return _defaultFactory;
} else {
[NSException raise:NSInvalidArgumentException
format:@"Unable to find transport with id %s", transportID];
return nil;
}
}
return transportFactory;
}
@end
@implementation GRPCTransport
- (dispatch_queue_t)dispatchQueue {
[NSException raise:NSGenericException
format:@"Implementations should override the dispatch queue"];
return nil;
}
- (void)startWithRequestOptions:(nonnull GRPCRequestOptions *)requestOptions
callOptions:(nonnull GRPCCallOptions *)callOptions {
[NSException raise:NSGenericException
format:@"Implementations should override the methods of GRPCTransport"];
}
- (void)writeData:(nonnull id)data {
[NSException raise:NSGenericException
format:@"Implementations should override the methods of GRPCTransport"];
}
- (void)cancel {
[NSException raise:NSGenericException
format:@"Implementations should override the methods of GRPCTransport"];
}
- (void)finish {
[NSException raise:NSGenericException
format:@"Implementations should override the methods of GRPCTransport"];
}
- (void)receiveNextMessages:(NSUInteger)numberOfMessages {
[NSException raise:NSGenericException
format:@"Implementations should override the methods of GRPCTransport"];
}
@end