1/* 2 * 3 * Copyright 2019 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19#import "GRPCTransport.h" 20 21static const GRPCTransportID gGRPCCoreSecureID = "io.grpc.transport.core.secure"; 22static const GRPCTransportID gGRPCCoreInsecureID = "io.grpc.transport.core.insecure"; 23 24const struct GRPCDefaultTransportImplList GRPCDefaultTransportImplList = { 25 .core_secure = gGRPCCoreSecureID, .core_insecure = gGRPCCoreInsecureID}; 26 27static const GRPCTransportID gDefaultTransportID = gGRPCCoreSecureID; 28 29static GRPCTransportRegistry *gTransportRegistry = nil; 30static dispatch_once_t initTransportRegistry; 31 32BOOL TransportIDIsEqual(GRPCTransportID lhs, GRPCTransportID rhs) { 33 // Directly comparing pointers works because we require users to use the id provided by each 34 // implementation, not coming up with their own string. 35 return lhs == rhs; 36} 37 38NSUInteger TransportIDHash(GRPCTransportID transportID) { 39 if (transportID == NULL) { 40 transportID = gDefaultTransportID; 41 } 42 return [NSString stringWithCString:transportID encoding:NSUTF8StringEncoding].hash; 43} 44 45@implementation GRPCTransportRegistry { 46 NSMutableDictionary<NSString *, id<GRPCTransportFactory>> *_registry; 47 id<GRPCTransportFactory> _defaultFactory; 48} 49 50+ (instancetype)sharedInstance { 51 dispatch_once(&initTransportRegistry, ^{ 52 gTransportRegistry = [[GRPCTransportRegistry alloc] init]; 53 NSAssert(gTransportRegistry != nil, @"Unable to initialize transport registry."); 54 if (gTransportRegistry == nil) { 55 NSLog(@"Unable to initialize transport registry."); 56 [NSException raise:NSGenericException format:@"Unable to initialize transport registry."]; 57 } 58 }); 59 return gTransportRegistry; 60} 61 62- (instancetype)init { 63 if ((self = [super init])) { 64 _registry = [NSMutableDictionary dictionary]; 65 } 66 return self; 67} 68 69- (void)registerTransportWithID:(GRPCTransportID)transportID 70 factory:(id<GRPCTransportFactory>)factory { 71 NSString *nsTransportID = [NSString stringWithCString:transportID encoding:NSUTF8StringEncoding]; 72 NSAssert(_registry[nsTransportID] == nil, @"The transport %@ has already been registered.", 73 nsTransportID); 74 if (_registry[nsTransportID] != nil) { 75 NSLog(@"The transport %@ has already been registered.", nsTransportID); 76 return; 77 } 78 _registry[nsTransportID] = factory; 79 80 // if the default transport is registered, mark it. 81 if (0 == strcmp(transportID, gDefaultTransportID)) { 82 _defaultFactory = factory; 83 } 84} 85 86- (id<GRPCTransportFactory>)getTransportFactoryWithID:(GRPCTransportID)transportID { 87 if (transportID == NULL) { 88 if (_defaultFactory == nil) { 89 // fall back to default transport if no transport is provided 90 [NSException raise:NSInvalidArgumentException 91 format:@"Did not specify transport and unable to find a default transport."]; 92 return nil; 93 } 94 return _defaultFactory; 95 } 96 NSString *nsTransportID = [NSString stringWithCString:transportID encoding:NSUTF8StringEncoding]; 97 id<GRPCTransportFactory> transportFactory = _registry[nsTransportID]; 98 if (transportFactory == nil) { 99 if (_defaultFactory != nil) { 100 // fall back to default transport if no transport is found 101 NSLog(@"Unable to find transport with id %s; falling back to default transport.", 102 transportID); 103 return _defaultFactory; 104 } else { 105 [NSException raise:NSInvalidArgumentException 106 format:@"Unable to find transport with id %s", transportID]; 107 return nil; 108 } 109 } 110 return transportFactory; 111} 112 113@end 114 115@implementation GRPCTransport 116 117- (dispatch_queue_t)dispatchQueue { 118 [NSException raise:NSGenericException 119 format:@"Implementations should override the dispatch queue"]; 120 return nil; 121} 122 123- (void)startWithRequestOptions:(nonnull GRPCRequestOptions *)requestOptions 124 callOptions:(nonnull GRPCCallOptions *)callOptions { 125 [NSException raise:NSGenericException 126 format:@"Implementations should override the methods of GRPCTransport"]; 127} 128 129- (void)writeData:(nonnull id)data { 130 [NSException raise:NSGenericException 131 format:@"Implementations should override the methods of GRPCTransport"]; 132} 133 134- (void)cancel { 135 [NSException raise:NSGenericException 136 format:@"Implementations should override the methods of GRPCTransport"]; 137} 138 139- (void)finish { 140 [NSException raise:NSGenericException 141 format:@"Implementations should override the methods of GRPCTransport"]; 142} 143 144- (void)receiveNextMessages:(NSUInteger)numberOfMessages { 145 [NSException raise:NSGenericException 146 format:@"Implementations should override the methods of GRPCTransport"]; 147} 148 149@end 150