Moving from govendor to dep, updated dependencies (#48)

* Moving from govendor to dep.

* Making the pull request template more friendly.

* Fixing akward space in PR template.

* goimports run on whole project using ` goimports -w $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./gen-go/*")`

source of command: https://gist.github.com/bgentry/fd1ffef7dbde01857f66
This commit is contained in:
Renan DelValle 2018-01-07 13:13:47 -08:00 committed by GitHub
parent 9631aa3aab
commit 8d445c1c77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2186 changed files with 400410 additions and 352 deletions

21
vendor/git.apache.org/thrift.git/lib/cocoa/README.md generated vendored Normal file
View file

@ -0,0 +1,21 @@
Thrift Cocoa Software Library
License
=======
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.

View file

@ -0,0 +1 @@
Please follow [General Coding Standards](/doc/coding_standards.md)

View file

@ -0,0 +1,55 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TProtocol.h"
extern NSString *TApplicationErrorDomain;
typedef NS_ENUM (int, TApplicationError) {
TApplicationErrorUnknown = 0,
TApplicationErrorUnknownMethod = 1,
TApplicationErrorInvalidMessageType = 2,
TApplicationErrorWrongMethodName = 3,
TApplicationErrorBadSequenceId = 4,
TApplicationErrorMissingResult = 5,
TApplicationErrorInternalError = 6,
TApplicationErrorProtocolError = 7,
TApplicationErrorInvalidTransform = 8,
TApplicationErrorInvalidProtocol = 9,
TApplicationErrorUnsupportedClientType = 10,
};
extern NSString *TApplicationErrorNameKey;
extern NSString *TApplicationErrorReasonKey;
extern NSString *TApplicationErrorMethodKey;
@interface NSError (TApplicationError)
@property (readonly, copy) NSString *name;
@property (readonly, copy) NSString *reason;
+(instancetype) errorWithType:(TApplicationError)type reason:(NSString *)reason;
+(instancetype) read:(id<TProtocol>)protocol;
-(BOOL) write:(id<TProtocol>)outProtocol error:(NSError *__autoreleasing *)error;
@end

View file

@ -0,0 +1,231 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TApplicationError.h"
#import "TProtocolUtil.h"
NSString *TApplicationErrorDomain = @"TApplicationErrorDomain";
NSString *TApplicationErrorNameKey = @"name";
NSString *TApplicationErrorReasonKey = @"reason";
NSString *TApplicationErrorMethodKey = @"method";
@implementation NSError (TApplicationError)
-(NSString *) reason
{
return self.userInfo[TApplicationErrorReasonKey];
}
-(NSString *) name
{
return self.userInfo[TApplicationErrorNameKey];
}
+(instancetype) errorWithType:(TApplicationError)type reason:(NSString *)reason
{
NSString *name;
switch (type) {
case TApplicationErrorUnknownMethod:
name = @"Unknown Method";
break;
case TApplicationErrorInvalidMessageType:
name = @"Invalid Message Type";
break;
case TApplicationErrorWrongMethodName:
name = @"Wrong Method Name";
break;
case TApplicationErrorBadSequenceId:
name = @"Bad Sequence ID";
break;
case TApplicationErrorMissingResult:
name = @"Missing Result";
break;
case TApplicationErrorInternalError:
name = @"Internal Error";
break;
case TApplicationErrorProtocolError:
name = @"Protocol Error";
break;
case TApplicationErrorInvalidTransform:
name = @"Invalid Transform";
break;
case TApplicationErrorInvalidProtocol:
name = @"Invalid Protocol";
break;
case TApplicationErrorUnsupportedClientType:
name = @"Unsupported Client Type";
break;
default:
name = @"Unknown";
break;
}
NSDictionary *userInfo;
if (reason) {
userInfo = @{TApplicationErrorNameKey:name,
TApplicationErrorReasonKey:reason};
}
else {
userInfo = @{TApplicationErrorNameKey:name};
}
return [NSError errorWithDomain:TApplicationErrorDomain
code:type
userInfo:userInfo];
}
+(instancetype) read:(id<TProtocol>)protocol
{
NSString *reason = nil;
SInt32 type = TApplicationErrorUnknown;
SInt32 fieldType;
SInt32 fieldID;
NSError *error;
if (![protocol readStructBeginReturningName:NULL error:&error]) {
return error;
}
while (true) {
if (![protocol readFieldBeginReturningName:NULL
type:&fieldType
fieldID:&fieldID
error:&error])
{
return error;
}
if (fieldType == TTypeSTOP) {
break;
}
switch (fieldID) {
case 1:
if (fieldType == TTypeSTRING) {
if (![protocol readString:&reason error:&error]) {
return error;
}
}
else {
if (![TProtocolUtil skipType:fieldType onProtocol:protocol error:&error]) {
return error;
}
}
break;
case 2:
if (fieldType == TTypeI32) {
if (![protocol readI32:&type error:&error]) {
return error;
}
}
else {
if (![TProtocolUtil skipType:fieldType onProtocol:protocol error:&error]) {
return error;
}
}
break;
default:
if (![TProtocolUtil skipType:fieldType onProtocol:protocol error:&error]) {
return error;
}
break;
}
if (![protocol readFieldEnd:&error]) {
return error;
}
}
if (![protocol readStructEnd:&error]) {
return error;
}
return [NSError errorWithType:type reason:reason];
}
-(BOOL) write:(id<TProtocol>)protocol error:(NSError *__autoreleasing *)error
{
if (![protocol writeStructBeginWithName:@"TApplicationException" error:error]) {
return NO;
}
if (self.localizedDescription != nil) {
if (![protocol writeFieldBeginWithName:@"message"
type:TTypeSTRING
fieldID:1 error:error])
{
return NO;
}
if (![protocol writeString:self.localizedDescription error:error]) {
return NO;
}
if (![protocol writeFieldEnd:error]) {
return NO;
}
}
if (![protocol writeFieldBeginWithName:@"type"
type:TTypeI32
fieldID:2
error:error])
{
return NO;
}
if (![protocol writeI32:(SInt32)self.code error:error]) {
return NO;
}
if (![protocol writeFieldEnd:error]) {
return NO;
}
if (![protocol writeFieldStop:error]) {
return NO;
}
if (![protocol writeStructEnd:error]) {
return NO;
}
return YES;
}
@end

View file

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TProtocol.h"
#import "TApplicationError.h"
@interface TBaseClient : NSObject
-(NSError *) checkIncomingMessageException:(id<TProtocol>)protocol;
@end

View file

@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TBaseClient.h"
#import "TApplicationError.h"
@interface TBaseClient ()
@end
@implementation TBaseClient
-(NSError *) checkIncomingMessageException:(id<TProtocol>)inProtocol
{
NSError *thriftError;
SInt32 msgType = 0;
if (![inProtocol readMessageBeginReturningName:nil type:&msgType sequenceID:NULL error:&thriftError]) {
return thriftError;
}
if (msgType == TMessageTypeEXCEPTION) {
thriftError = [NSError read:inProtocol];
[inProtocol readMessageEnd:NULL];
return thriftError;
}
return nil;
}
@end

View file

@ -0,0 +1,122 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 Foundation
public struct TBinary : TSerializable {
public static var thriftType : TType { return .STRING }
private var storage : NSData
public init() {
self.storage = NSData()
}
public init(contentsOfFile file: String, options: NSDataReadingOptions = []) throws {
self.storage = try NSData(contentsOfFile: file, options: options)
}
public init(contentsOfURL URL: NSURL, options: NSDataReadingOptions = []) throws {
self.storage = try NSData(contentsOfURL: URL, options: options)
}
public init?(base64EncodedData base64Data: NSData, options: NSDataBase64DecodingOptions = []) {
guard let storage = NSData(base64EncodedData: base64Data, options: options) else {
return nil
}
self.storage = storage
}
public init(data: NSData) {
self.storage = data
}
public var length : Int {
return storage.length
}
public var hashValue : Int {
return storage.hashValue
}
public var bytes : UnsafePointer<Void> {
return storage.bytes
}
public func getBytes(buffer: UnsafeMutablePointer<Void>, length: Int) {
storage.getBytes(buffer, length: length)
}
public func getBytes(buffer: UnsafeMutablePointer<Void>, range: Range<Int>) {
storage.getBytes(buffer, range: NSRange(range))
}
public func subBinaryWithRange(range: Range<Int>) -> TBinary {
return TBinary(data: storage.subdataWithRange(NSRange(range)))
}
public func writeToFile(path: String, options: NSDataWritingOptions = []) throws {
try storage.writeToFile(path, options: options)
}
public func writeToURL(url: NSURL, options: NSDataWritingOptions = []) throws {
try storage.writeToURL(url, options: options)
}
public func rangeOfData(dataToFind data: NSData, options: NSDataSearchOptions, range: Range<Int>) -> Range<Int>? {
return storage.rangeOfData(data, options: options, range: NSRange(range)).toRange()
}
public func enumerateByteRangesUsingBlock(block: (UnsafePointer<Void>, Range<Int>, inout Bool) -> Void) {
storage.enumerateByteRangesUsingBlock { bytes, range, stop in
var stopTmp = Bool(stop.memory)
block(bytes, range.toRange()!, &stopTmp)
stop.memory = ObjCBool(stopTmp)
}
}
public static func readValueFromProtocol(proto: TProtocol) throws -> TBinary {
var data : NSData?
try proto.readBinary(&data)
return TBinary(data: data!)
}
public static func writeValue(value: TBinary, toProtocol proto: TProtocol) throws {
try proto.writeBinary(value.storage)
}
}
extension TBinary : CustomStringConvertible, CustomDebugStringConvertible {
public var description : String {
return storage.description
}
public var debugDescription : String {
return storage.debugDescription
}
}
public func ==(lhs: TBinary, rhs: TBinary) -> Bool {
return lhs.storage == rhs.storage
}

View file

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 Foundation
public protocol TEnum : TSerializable {
}
public extension TEnum {
public static var thriftType : TType { return TType.I32 }
}

View file

@ -0,0 +1,23 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
extern NSString *TErrorDomain;

View file

@ -0,0 +1,23 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TError.h"
NSString *TErrorDomain = @"TErrorDomain";

View file

@ -0,0 +1,148 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 Foundation
public struct TList<Element : TSerializable> : MutableCollectionType, Hashable, ArrayLiteralConvertible, TSerializable {
public static var thriftType : TType { return .LIST }
typealias Storage = Array<Element>
public typealias Index = Storage.Index
private var storage = Storage()
public var startIndex : Index {
return storage.startIndex
}
public var endIndex : Index {
return storage.endIndex
}
public subscript (position: Index) -> Element {
get {
return storage[position]
}
set {
storage[position] = newValue
}
}
public var hashValue : Int {
let prime = 31
var result = 1
for element in storage {
result = prime * result + element.hashValue
}
return result
}
public init(arrayLiteral elements: Element...) {
self.storage = Storage(storage)
}
public init() {
self.storage = Storage()
}
public mutating func append(newElement: Element) {
self.storage.append(newElement)
}
public mutating func appendContentsOf<C : CollectionType where C.Generator.Element == Element>(newstorage: C) {
self.storage.appendContentsOf(newstorage)
}
public mutating func insert(newElement: Element, atIndex index: Int) {
self.storage.insert(newElement, atIndex: index)
}
public mutating func insertContentsOf<C : CollectionType where C.Generator.Element == Element>(newElements: C, at index: Int) {
self.storage.insertContentsOf(newElements, at: index)
}
public mutating func removeAll(keepCapacity keepCapacity: Bool = true) {
self.storage.removeAll(keepCapacity: keepCapacity)
}
public mutating func removeAtIndex(index: Index) {
self.storage.removeAtIndex(index)
}
public mutating func removeFirst(n: Int = 0) {
self.storage.removeFirst(n)
}
public mutating func removeLast() -> Element {
return self.storage.removeLast()
}
public mutating func removeRange(subRange: Range<Index>) {
self.storage.removeRange(subRange)
}
public mutating func reserveCapacity(minimumCapacity: Int) {
self.storage.reserveCapacity(minimumCapacity)
}
public static func readValueFromProtocol(proto: TProtocol) throws -> TList {
let (elementType, size) = try proto.readListBegin()
if elementType != Element.thriftType {
throw NSError(
domain: TProtocolErrorDomain,
code: Int(TProtocolError.InvalidData.rawValue),
userInfo: [TProtocolErrorExtendedErrorKey: NSNumber(int: TProtocolExtendedError.UnexpectedType.rawValue)])
}
var list = TList()
for _ in 0..<size {
let element = try Element.readValueFromProtocol(proto)
list.storage.append(element)
}
try proto.readListEnd()
return list
}
public static func writeValue(value: TList, toProtocol proto: TProtocol) throws {
try proto.writeListBeginWithElementType(Element.thriftType, size: value.count)
for element in value.storage {
try Element.writeValue(element, toProtocol: proto)
}
try proto.writeListEnd()
}
}
extension TList : CustomStringConvertible, CustomDebugStringConvertible {
public var description : String {
return storage.description
}
public var debugDescription : String {
return storage.debugDescription
}
}
public func ==<Element>(lhs: TList<Element>, rhs: TList<Element>) -> Bool {
return lhs.storage == rhs.storage
}

View file

@ -0,0 +1,158 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 Foundation
public struct TMap<Key : TSerializable, Value : TSerializable> : CollectionType, DictionaryLiteralConvertible, TSerializable {
public static var thriftType : TType { return .MAP }
typealias Storage = Dictionary<Key, Value>
public typealias Index = Storage.Index
public typealias Element = Storage.Element
private var storage : Storage
public var startIndex : Index {
return storage.startIndex
}
public var endIndex: Index {
return storage.endIndex
}
public var keys: LazyMapCollection<[Key : Value], Key> {
return storage.keys
}
public var values: LazyMapCollection<[Key : Value], Value> {
return storage.values
}
public init() {
storage = Storage()
}
public init(dictionaryLiteral elements: (Key, Value)...) {
storage = Storage()
for (key, value) in elements {
storage[key] = value
}
}
public init(minimumCapacity: Int) {
storage = Storage(minimumCapacity: minimumCapacity)
}
public subscript (position: Index) -> Element {
get {
return storage[position]
}
}
public func indexForKey(key: Key) -> Index? {
return storage.indexForKey(key)
}
public subscript (key: Key) -> Value? {
get {
return storage[key]
}
set {
storage[key] = newValue
}
}
public mutating func updateValue(value: Value, forKey key: Key) -> Value? {
return updateValue(value, forKey: key)
}
public mutating func removeAtIndex(index: DictionaryIndex<Key, Value>) -> (Key, Value) {
return removeAtIndex(index)
}
public mutating func removeValueForKey(key: Key) -> Value? {
return storage.removeValueForKey(key)
}
public mutating func removeAll(keepCapacity keepCapacity: Bool = false) {
storage.removeAll(keepCapacity: keepCapacity)
}
public var hashValue : Int {
let prime = 31
var result = 1
for (key, value) in storage {
result = prime * result + key.hashValue
result = prime * result + value.hashValue
}
return result
}
public static func readValueFromProtocol(proto: TProtocol) throws -> TMap {
let (keyType, valueType, size) = try proto.readMapBegin()
if keyType != Key.thriftType || valueType != Value.thriftType {
throw NSError(
domain: TProtocolErrorDomain,
code: Int(TProtocolError.InvalidData.rawValue),
userInfo: [TProtocolErrorExtendedErrorKey: NSNumber(int: TProtocolExtendedError.UnexpectedType.rawValue)])
}
var map = TMap()
for _ in 0..<size {
let key = try Key.readValueFromProtocol(proto)
let value = try Value.readValueFromProtocol(proto)
map.storage[key] = value
}
try proto.readMapEnd()
return map
}
public static func writeValue(value: TMap, toProtocol proto: TProtocol) throws {
try proto.writeMapBeginWithKeyType(Key.thriftType, valueType: Value.thriftType, size: value.count)
for (key, value) in value.storage {
try Key.writeValue(key, toProtocol: proto)
try Value.writeValue(value, toProtocol: proto)
}
try proto.writeMapEnd()
}
}
extension TMap : CustomStringConvertible, CustomDebugStringConvertible {
public var description : String {
return storage.description
}
public var debugDescription : String {
return storage.debugDescription
}
}
public func ==<Key, Value>(lhs: TMap<Key,Value>, rhs: TMap<Key, Value>) -> Bool {
if lhs.count != rhs.count {
return false
}
return lhs.storage == rhs.storage
}

View file

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@protocol TProcessor <NSObject>
-(BOOL) processOnInputProtocol:(id <TProtocol>)inProtocol
outputProtocol:(id <TProtocol>)outProtocol
error:(NSError **)error;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TProcessor.h"
NS_ASSUME_NONNULL_BEGIN
@protocol TProcessorFactory <NSObject>
-(id<TProcessor>) processorForTransport:(id<TTransport>)transport;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,190 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 Foundation
public extension TProtocol {
public func readMessageBegin() throws -> (String, TMessageType, Int) {
var name : NSString?
var type : Int32 = -1
var sequenceID : Int32 = -1
try readMessageBeginReturningName(&name, type: &type, sequenceID: &sequenceID)
return (name as String!, TMessageType(rawValue: type)!, Int(sequenceID))
}
public func writeMessageBeginWithName(name: String, type: TMessageType, sequenceID: Int) throws {
try writeMessageBeginWithName(name, type: type.rawValue, sequenceID: Int32(sequenceID))
}
public func readStructBegin() throws -> (String?) {
var name : NSString? = nil
try readStructBeginReturningName(&name)
return (name as String?)
}
public func readFieldBegin() throws -> (String?, TType, Int) {
var name : NSString? = nil
var type : Int32 = -1
var fieldID : Int32 = -1
try readFieldBeginReturningName(&name, type: &type, fieldID: &fieldID)
return (name as String?, TType(rawValue: type)!, Int(fieldID))
}
public func writeFieldBeginWithName(name: String, type: TType, fieldID: Int) throws {
try writeFieldBeginWithName(name, type: type.rawValue, fieldID: Int32(fieldID))
}
public func readMapBegin() throws -> (TType, TType, Int32) {
var keyType : Int32 = -1
var valueType : Int32 = -1
var size : Int32 = 0
try readMapBeginReturningKeyType(&keyType, valueType: &valueType, size: &size)
return (TType(rawValue: keyType)!, TType(rawValue: valueType)!, size)
}
public func writeMapBeginWithKeyType(keyType: TType, valueType: TType, size: Int) throws {
try writeMapBeginWithKeyType(keyType.rawValue, valueType: valueType.rawValue, size: Int32(size))
}
public func readSetBegin() throws -> (TType, Int32) {
var elementType : Int32 = -1
var size : Int32 = 0
try readSetBeginReturningElementType(&elementType, size: &size)
return (TType(rawValue: elementType)!, size)
}
public func writeSetBeginWithElementType(elementType: TType, size: Int) throws {
try writeSetBeginWithElementType(elementType.rawValue, size: Int32(size))
}
public func readListBegin() throws -> (TType, Int32) {
var elementType : Int32 = -1
var size : Int32 = 0
try readListBeginReturningElementType(&elementType, size: &size)
return (TType(rawValue: elementType)!, size)
}
public func writeListBeginWithElementType(elementType: TType, size: Int) throws {
try writeListBeginWithElementType(elementType.rawValue, size: Int32(size))
}
public func writeFieldValue<T: TSerializable>(value: T, name: String, type: TType, id: Int32) throws {
try writeFieldBeginWithName(name, type: type.rawValue, fieldID: id)
try writeValue(value)
try writeFieldEnd()
}
public func readValue<T: TSerializable>() throws -> T {
return try T.readValueFromProtocol(self)
}
public func writeValue<T: TSerializable>(value: T) throws {
try T.writeValue(value, toProtocol: self)
}
public func readResultMessageBegin() throws {
let (_, type, _) = try readMessageBegin();
if type == .EXCEPTION {
let x = try readException()
throw x
}
return
}
public func validateValue(value: Any?, named name: String) throws {
if value == nil {
throw NSError(
domain: TProtocolErrorDomain,
code: Int(TProtocolError.Unknown.rawValue),
userInfo: [TProtocolErrorFieldNameKey: name])
}
}
public func readException() throws -> ErrorType {
var reason : String?
var type = TApplicationError.Unknown
try readStructBegin()
fields: while (true) {
let (_, fieldType, fieldID) = try readFieldBegin()
switch (fieldID, fieldType) {
case (_, .STOP):
break fields
case (1, .STRING):
reason = try readValue() as String
case (2, .I32):
let typeVal = try readValue() as Int32
if let tmp = TApplicationError(rawValue: typeVal) {
type = tmp
}
case let (_, unknownType):
try skipType(unknownType)
}
try readFieldEnd()
}
try readStructEnd()
return NSError(type:type, reason:reason ?? "")
}
public func writeExceptionForMessageName(name: String, sequenceID: Int, ex: NSError) throws {
try writeMessageBeginWithName(name, type: .EXCEPTION, sequenceID: sequenceID)
try ex.write(self)
try writeMessageEnd()
}
public func skipType(type: TType) throws {
try TProtocolUtil.skipType(type.rawValue, onProtocol: self)
}
}

View file

@ -0,0 +1,178 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 Foundation
public protocol TSerializable : Hashable {
static var thriftType : TType { get }
init()
static func readValueFromProtocol(proto: TProtocol) throws -> Self
static func writeValue(value: Self, toProtocol proto: TProtocol) throws
}
infix operator ?== {}
public func ?==<T: TSerializable>(lhs: T?, rhs: T?) -> Bool {
if let l = lhs, r = rhs {
return l == r
}
return lhs == rhs
}
public func ?==<T: TSerializable>(lhs: T, rhs: T) -> Bool {
return lhs == rhs
}
extension Bool : TSerializable {
public static let thriftType = TType.BOOL
public static func readValueFromProtocol(proto: TProtocol) throws -> Bool {
var value : ObjCBool = false
try proto.readBool(&value)
return value.boolValue
}
public static func writeValue(value: Bool, toProtocol proto: TProtocol) throws {
try proto.writeBool(value)
}
}
extension Int8 : TSerializable {
public static let thriftType = TType.BYTE
public static func readValueFromProtocol(proto: TProtocol) throws -> Int8 {
var value = UInt8()
try proto.readByte(&value)
return Int8(value)
}
public static func writeValue(value: Int8, toProtocol proto: TProtocol) throws {
try proto.writeByte(UInt8(value))
}
}
extension Int16 : TSerializable {
public static let thriftType = TType.I16
public static func readValueFromProtocol(proto: TProtocol) throws -> Int16 {
var value = Int16()
try proto.readI16(&value)
return value
}
public static func writeValue(value: Int16, toProtocol proto: TProtocol) throws {
try proto.writeI16(value)
}
}
extension Int : TSerializable {
public static let thriftType = TType.I32
public static func readValueFromProtocol(proto: TProtocol) throws -> Int {
var value = Int32()
try proto.readI32(&value)
return Int(value)
}
public static func writeValue(value: Int, toProtocol proto: TProtocol) throws {
try proto.writeI32(Int32(value))
}
}
extension Int32 : TSerializable {
public static let thriftType = TType.I32
public static func readValueFromProtocol(proto: TProtocol) throws -> Int32 {
var value = Int32()
try proto.readI32(&value)
return value
}
public static func writeValue(value: Int32, toProtocol proto: TProtocol) throws {
try proto.writeI32(value)
}
}
extension Int64 : TSerializable {
public static let thriftType = TType.I64
public static func readValueFromProtocol(proto: TProtocol) throws -> Int64 {
var value = Int64()
try proto.readI64(&value)
return value
}
public static func writeValue(value: Int64, toProtocol proto: TProtocol) throws {
try proto.writeI64(value)
}
}
extension Double : TSerializable {
public static let thriftType = TType.DOUBLE
public static func readValueFromProtocol(proto: TProtocol) throws -> Double {
var value = Double()
try proto.readDouble(&value)
return value
}
public static func writeValue(value: Double, toProtocol proto: TProtocol) throws {
try proto.writeDouble(value)
}
}
extension String : TSerializable {
public static let thriftType = TType.STRING
public static func readValueFromProtocol(proto: TProtocol) throws -> String {
var value : NSString?
try proto.readString(&value)
return value as! String
}
public static func writeValue(value: String, toProtocol proto: TProtocol) throws {
try proto.writeString(value)
}
}

View file

@ -0,0 +1,161 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 Foundation
public struct TSet<Element : TSerializable> : CollectionType, ArrayLiteralConvertible, TSerializable {
public static var thriftType : TType { return .SET }
public typealias Index = Storage.Index
typealias Storage = Set<Element>
private var storage : Storage
public init() {
storage = Storage()
}
public init(arrayLiteral elements: Element...) {
storage = Storage(elements)
}
public init<S : SequenceType where S.Generator.Element == Element>(_ sequence: S) {
storage = Storage(sequence)
}
public var startIndex : Index { return storage.startIndex }
public var endIndex : Index { return storage.endIndex }
public mutating func insert(member: Element) {
return storage.insert(member)
}
public mutating func remove(element: Element) -> Element? {
return storage.remove(element)
}
public mutating func removeAll(keepCapacity keepCapacity: Bool = false) {
return storage.removeAll(keepCapacity: keepCapacity)
}
public mutating func removeAtIndex(index: SetIndex<Element>) -> Element {
return storage.removeAtIndex(index)
}
public subscript (position: SetIndex<Element>) -> Element {
return storage[position]
}
public func union(other: TSet) -> TSet {
return TSet(storage.union(other))
}
public func intersect(other: TSet) -> TSet {
return TSet(storage.intersect(other))
}
public func exclusiveOr(other: TSet) -> TSet {
return TSet(storage.exclusiveOr(other))
}
public func subtract(other: TSet) -> TSet {
return TSet(storage.subtract(other))
}
public mutating func intersectInPlace(other: TSet) {
storage.intersectInPlace(other)
}
public mutating func exclusiveOrInPlace(other: TSet) {
storage.exclusiveOrInPlace(other)
}
public mutating func subtractInPlace(other: TSet) {
storage.subtractInPlace(other)
}
public func isSubsetOf(other: TSet) -> Bool {
return storage.isSubsetOf(other)
}
public func isDisjointWith(other: TSet) -> Bool {
return storage.isDisjointWith(other)
}
public func isSupersetOf(other: TSet) -> Bool {
return storage.isSupersetOf(other)
}
public var isEmpty: Bool { return storage.isEmpty }
public var hashValue : Int {
let prime = 31
var result = 1
for element in storage {
result = prime * result + element.hashValue
}
return result
}
public static func readValueFromProtocol(proto: TProtocol) throws -> TSet {
let (elementType, size) = try proto.readSetBegin()
if elementType != Element.thriftType {
throw NSError(
domain: TProtocolErrorDomain,
code: Int(TProtocolError.InvalidData.rawValue),
userInfo: [TProtocolErrorExtendedErrorKey: NSNumber(int: elementType.rawValue)])
}
var set = TSet()
for _ in 0..<size {
let element = try Element.readValueFromProtocol(proto)
set.storage.insert(element)
}
try proto.readSetEnd()
return set
}
public static func writeValue(value: TSet, toProtocol proto: TProtocol) throws {
try proto.writeSetBeginWithElementType(Element.thriftType, size: value.count)
for element in value.storage {
try Element.writeValue(element, toProtocol: proto)
}
try proto.writeSetEnd()
}
}
extension TSet : CustomStringConvertible, CustomDebugStringConvertible {
public var description : String {
return storage.description
}
public var debugDescription : String {
return storage.debugDescription
}
}
public func ==<Element>(lhs: TSet<Element>, rhs: TSet<Element>) -> Bool {
return lhs.storage == rhs.storage
}

View file

@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TProcessorFactory.h"
@interface TSharedProcessorFactory : NSObject <TProcessorFactory>
-(id) initWithSharedProcessor:(id<TProcessor>)sharedProcessor;
@end

View file

@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TSharedProcessorFactory.h"
@interface TSharedProcessorFactory ()
@property(strong, nonatomic) id<TProcessor> sharedProcessor;
@end
@implementation TSharedProcessorFactory
-(id) initWithSharedProcessor:(id<TProcessor>)sharedProcessor
{
self = [super init];
if (self) {
_sharedProcessor = sharedProcessor;
}
return self;
}
-(id<TProcessor>) processorForTransport:(id<TTransport>)transport
{
return _sharedProcessor;
}
@end

View file

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 Foundation
public protocol TStruct : TSerializable {
}
public extension TStruct {
public static var thriftType : TType { return TType.STRUCT }
}

View file

@ -0,0 +1,20 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#define ThriftVersion @"0.10.0"

View file

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TProtocol.h"
@protocol TBase <NSObject>
/**
* De-serialize object from the given input protocol
*
* @param input protocol used for reading
*/
-(BOOL) read:(id <TProtocol>)inProtocol error:(NSError **)error;
/**
* Serialize object to the given protocol
*
* @param buf output protocol used for writing
*/
-(BOOL) write:(id <TProtocol>)outProtocol error:(NSError **)error;
/**
* Validate required fields
*/
-(BOOL) validate:(NSError *__autoreleasing *)__thriftError;
@end

View file

@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TProtocol.h"
#import "TTransport.h"
#import "TProtocolFactory.h"
NS_ASSUME_NONNULL_BEGIN
@interface TBinaryProtocol : NSObject <TProtocol>
@property (assign, nonatomic) UInt32 messageSizeLimit;
-(id) initWithTransport:(id <TTransport>)transport;
-(id) initWithTransport:(id <TTransport>)transport
strictRead:(BOOL)strictRead
strictWrite:(BOOL)strictWrite;
@end;
@interface TBinaryProtocolFactory : NSObject <TProtocolFactory>
+(TBinaryProtocolFactory *) sharedFactory;
-(TBinaryProtocol *) newProtocolOnTransport:(id <TTransport>)transport;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,740 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TBinaryProtocol.h"
#import "TProtocolError.h"
static SInt32 VERSION_1 = 0x80010000;
static SInt32 VERSION_MASK = 0xffff0000;
static TBinaryProtocolFactory *gSharedFactory = nil;
@implementation TBinaryProtocolFactory
+(TBinaryProtocolFactory *) sharedFactory
{
if (gSharedFactory == nil) {
gSharedFactory = [[TBinaryProtocolFactory alloc] init];
}
return gSharedFactory;
}
-(NSString *) protocolName
{
return @"binary";
}
-(TBinaryProtocol *) newProtocolOnTransport:(id <TTransport>)transport
{
return [[TBinaryProtocol alloc] initWithTransport:transport];
}
@end
@interface TBinaryProtocol ()
@property(strong, nonatomic) id <TTransport> transport;
@property(assign, nonatomic) BOOL strictRead;
@property(assign, nonatomic) BOOL strictWrite;
@property(strong, nonatomic) NSString *currentMessageName;
@property(strong, nonatomic) NSString *currentFieldName;
@end
@implementation TBinaryProtocol
-(id) initWithTransport:(id <TTransport>)aTransport
{
return [self initWithTransport:aTransport strictRead:NO strictWrite:YES];
}
-(id) initWithTransport:(id <TTransport>)transport
strictRead:(BOOL)strictRead
strictWrite:(BOOL)strictWrite
{
self = [super init];
if (self) {
_transport = transport;
_strictRead = strictRead;
_strictWrite = strictWrite;
}
return self;
}
-(id <TTransport>) transport
{
return _transport;
}
-(NSString *) readStringBody:(int)size error:(NSError **)error
{
NSMutableData *data = [NSMutableData dataWithLength:size];
if (!data) {
PROTOCOL_ERROR(nil, Unknown, @"Unable to allocate %d bytes", size);
}
if (![_transport readAll:data.mutableBytes offset:0 length:size error:error]) {
PROTOCOL_TRANSPORT_ERROR(nil, error, @"Transport read failed");
}
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
-(BOOL) readMessageBeginReturningName:(NSString **)name
type:(SInt32 *)type
sequenceID:(SInt32 *)sequenceID
error:(NSError *__autoreleasing *)error
{
SInt32 size;
if (![self readI32:&size error:error]) {
return NO;
}
;
if (size < 0) {
int version = size & VERSION_MASK;
if (version != VERSION_1) {
PROTOCOL_ERROR(NO, BadVersion, @"Bad message version");
}
if (type != NULL) {
*type = size & 0x00FF;
}
NSString *messageName;
if (![self readString:&messageName error:error]) {
return NO;
}
if (name != nil) {
*name = messageName;
}
}
else {
if (_strictRead) {
PROTOCOL_ERROR(NO, InvalidData, @"Missing message version, old client?");
}
if (_messageSizeLimit > 0 && size > _messageSizeLimit) {
PROTOCOL_ERROR(NO, SizeLimit, @"Message exceeeds size limit of %d", (int)size);
}
NSString *messageName = [self readStringBody:size error:error];
if (!messageName) {
return NO;
}
if (name != NULL) {
*name = messageName;
}
UInt8 messageType;
if (![self readByte:&messageType error:error]) {
return NO;
}
if (type != NULL) {
*type = messageType;
}
}
SInt32 seqID;
if (![self readI32:&seqID error:error]) {
return NO;
}
if (sequenceID != NULL) {
*sequenceID = seqID;
}
return YES;
}
-(BOOL) readMessageEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) readStructBeginReturningName:(NSString *__autoreleasing *)name error:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) readStructEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) readFieldBeginReturningName:(NSString *__autoreleasing *)name
type:(SInt32 *)fieldType
fieldID:(SInt32 *)fieldID
error:(NSError *__autoreleasing *)error
{
if (name != nil) {
*name = nil;
}
UInt8 ft;
if (![self readByte:&ft error:error]) {
return NO;
}
if (fieldType != NULL) {
*fieldType = ft;
}
if (ft != TTypeSTOP) {
SInt16 fid;
if (![self readI16:&fid error:error]) {
return NO;
}
if (fieldID != NULL) {
*fieldID = fid;
}
}
return YES;
}
-(BOOL) readFieldEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) readString:(NSString *__autoreleasing *)value error:(NSError *__autoreleasing *)error
{
SInt32 size;
if (![self readI32:&size error:error]) {
return NO;
}
NSString *string = [self readStringBody:size error:error];
if (!string) {
return NO;
}
*value = string;
return YES;
}
-(BOOL) readBool:(BOOL *)value error:(NSError *__autoreleasing *)error
{
UInt8 byte;
if (![self readByte:&byte error:error]) {
return NO;
}
*value = byte == 1;
return YES;
}
-(BOOL) readByte:(UInt8 *)value error:(NSError *__autoreleasing *)error
{
UInt8 buff[1];
if (![_transport readAll:buff offset:0 length:1 error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed");
}
*value = buff[0];
return YES;
}
-(BOOL) readI16:(SInt16 *)value error:(NSError *__autoreleasing *)error
{
UInt8 buff[2];
if (![_transport readAll:buff offset:0 length:2 error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed");
}
*value =
((SInt16)(buff[0] & 0xff) << 8) |
((SInt16)(buff[1] & 0xff));
return YES;
}
-(BOOL) readI32:(SInt32 *)value error:(NSError *__autoreleasing *)error
{
UInt8 i32rd[4];
if (![_transport readAll:i32rd offset:0 length:4 error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed");
}
*value =
((i32rd[0] & 0xff) << 24) |
((i32rd[1] & 0xff) << 16) |
((i32rd[2] & 0xff) << 8) |
((i32rd[3] & 0xff));
return YES;
}
-(BOOL) readI64:(SInt64 *)value error:(NSError *__autoreleasing *)error
{
UInt8 buff[8];
if (![_transport readAll:buff offset:0 length:8 error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed");
}
*value =
((SInt64)(buff[0] & 0xff) << 56) |
((SInt64)(buff[1] & 0xff) << 48) |
((SInt64)(buff[2] & 0xff) << 40) |
((SInt64)(buff[3] & 0xff) << 32) |
((SInt64)(buff[4] & 0xff) << 24) |
((SInt64)(buff[5] & 0xff) << 16) |
((SInt64)(buff[6] & 0xff) << 8) |
((SInt64)(buff[7] & 0xff));
return YES;
}
-(BOOL) readDouble:(double *)value error:(NSError *__autoreleasing *)error
{
// FIXME - will this get us into trouble on PowerPC?
return [self readI64:(SInt64 *)value error:error];
}
-(BOOL) readBinary:(NSData *__autoreleasing *)value error:(NSError *__autoreleasing *)error
{
SInt32 size;
if (![self readI32:&size error:error]) {
return NO;
}
NSMutableData *data = [NSMutableData dataWithLength:size];
if (!data) {
PROTOCOL_ERROR(NO, Unknown, @"Unable to allocate %d bytes", (int)size);
}
if (![_transport readAll:data.mutableBytes offset:0 length:size error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed");
}
*value = data;
return YES;
}
-(BOOL) readMapBeginReturningKeyType:(SInt32 *)keyType
valueType:(SInt32 *)valueType
size:(SInt32 *)size
error:(NSError *__autoreleasing *)error
{
UInt8 kt;
if (![self readByte:&kt error:error]) {
return NO;
}
UInt8 vt;
if (![self readByte:&vt error:error]) {
return NO;
}
SInt32 s;
if (![self readI32:&s error:error]) {
return NO;
}
if (keyType != NULL) {
*keyType = kt;
}
if (valueType != NULL) {
*valueType = vt;
}
if (size != NULL) {
*size = s;
}
return YES;
}
-(BOOL) readMapEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) readSetBeginReturningElementType:(SInt32 *)elementType
size:(SInt32 *)size
error:(NSError *__autoreleasing *)error
{
UInt8 et;
if (![self readByte:&et error:error]) {
return NO;
}
SInt32 s;
if (![self readI32:&s error:error]) {
return NO;
}
if (elementType != NULL) {
*elementType = et;
}
if (size != NULL) {
*size = s;
}
return YES;
}
-(BOOL) readSetEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) readListBeginReturningElementType:(SInt32 *)elementType
size:(SInt32 *)size
error:(NSError *__autoreleasing *)error
{
UInt8 et;
if (![self readByte:&et error:error]) {
return NO;
}
SInt32 s;
if (![self readI32:&s error:error]) {
return NO;
}
if (elementType != NULL) {
*elementType = et;
}
if (size != NULL) {
*size = s;
}
return YES;
}
-(BOOL) readListEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) writeMessageBeginWithName:(NSString *)name
type:(SInt32)messageType
sequenceID:(SInt32)sequenceID
error:(NSError *__autoreleasing *)error
{
if (_strictWrite) {
int version = VERSION_1 | messageType;
if (![self writeI32:version error:error]) {
return NO;
}
if (![self writeString:name error:error]) {
return NO;
}
if (![self writeI32:sequenceID error:error]) {
return NO;
}
}
else {
if (![self writeString:name error:error]) {
return NO;
}
if (![self writeByte:messageType error:error]) {
return NO;
}
if (![self writeI32:sequenceID error:error]) {
return NO;
}
}
_currentMessageName = name;
return YES;
}
-(BOOL) writeMessageEnd:(NSError *__autoreleasing *)error
{
_currentMessageName = nil;
return YES;
}
-(BOOL) writeStructBeginWithName:(NSString *)name
error:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) writeStructEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) writeFieldBeginWithName:(NSString *)name
type:(SInt32)fieldType
fieldID:(SInt32)fieldID
error:(NSError *__autoreleasing *)error
{
if (![self writeByte:fieldType error:error]) {
return NO;
}
if (![self writeI16:fieldID error:error]) {
return NO;
}
return YES;
}
-(BOOL) writeBool:(BOOL)value error:(NSError *__autoreleasing *)error
{
return [self writeByte:(value ? 1 : 0) error:error];
}
-(BOOL) writeByte:(UInt8)value error:(NSError *__autoreleasing *)error
{
if (![_transport write:&value offset:0 length:1 error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed");
}
return YES;
}
-(BOOL) writeI16:(short)value error:(NSError *__autoreleasing *)error
{
UInt8 buff[2];
buff[0] = 0xff & (value >> 8);
buff[1] = 0xff & value;
if (![_transport write:buff offset:0 length:2 error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed");
}
return YES;
}
-(BOOL) writeI32:(SInt32)value error:(NSError *__autoreleasing *)error
{
UInt8 buff[4];
buff[0] = 0xFF & (value >> 24);
buff[1] = 0xFF & (value >> 16);
buff[2] = 0xFF & (value >> 8);
buff[3] = 0xFF & value;
if (![_transport write:buff offset:0 length:4 error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed");
}
return YES;
}
-(BOOL) writeI64:(SInt64)value error:(NSError *__autoreleasing *)error
{
UInt8 buff[8];
buff[0] = 0xFF & (value >> 56);
buff[1] = 0xFF & (value >> 48);
buff[2] = 0xFF & (value >> 40);
buff[3] = 0xFF & (value >> 32);
buff[4] = 0xFF & (value >> 24);
buff[5] = 0xFF & (value >> 16);
buff[6] = 0xFF & (value >> 8);
buff[7] = 0xFF & value;
if (![_transport write:buff offset:0 length:8 error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed");
}
return YES;
}
-(BOOL) writeDouble:(double)value error:(NSError *__autoreleasing *)error
{
// FIXME - will this get us in trouble on PowerPC?
if (![self writeI64:*(SInt64 *)&value error:error]) {
return NO;
}
return YES;
}
-(BOOL) writeString:(NSString *)value error:(NSError *__autoreleasing *)error
{
if (value != nil) {
const char *utf8Bytes = [value UTF8String];
SInt32 length = (SInt32)strlen(utf8Bytes);
if (![self writeI32:length error:error]) {
return NO;
}
if (![_transport write:(UInt8 *)utf8Bytes offset:0 length:(int)length error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed");
}
}
else {
// instead of crashing when we get null, let's write out a zero
// length string
if (![self writeI32:0 error:error]) {
return NO;
}
}
return YES;
}
-(BOOL) writeBinary:(NSData *)data error:(NSError *__autoreleasing *)error
{
if (![self writeI32:(SInt32)data.length error:error]) {
return NO;
}
if (![_transport write:data.bytes offset:0 length:(UInt32)data.length error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed");
}
return YES;
}
-(BOOL) writeFieldStop:(NSError *__autoreleasing *)error
{
if (![self writeByte:TTypeSTOP error:error]) {
return NO;
}
return YES;
}
-(BOOL) writeFieldEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) writeMapBeginWithKeyType:(SInt32)keyType
valueType:(SInt32)valueType
size:(SInt32)size
error:(NSError *__autoreleasing *)error
{
if (![self writeByte:keyType error:error]) {
return NO;
}
if (![self writeByte:valueType error:error]) {
return NO;
}
if (![self writeI32:(int)size error:error]) {
return NO;
}
return YES;
}
-(BOOL) writeMapEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) writeSetBeginWithElementType:(SInt32)elementType
size:(SInt32)size
error:(NSError *__autoreleasing *)error
{
if (![self writeByte:elementType error:error]) {
return NO;
}
if (![self writeI32:size error:error]) {
return NO;
}
return YES;
}
-(BOOL) writeSetEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) writeListBeginWithElementType:(SInt32)elementType
size:(SInt32)size
error:(NSError *__autoreleasing *)error
{
if (![self writeByte:elementType error:error]) {
return NO;
}
if (![self writeI32:size error:error]) {
return NO;
}
return YES;
}
-(BOOL) writeListEnd:(NSError *__autoreleasing *)error
{
return YES;
}
@end

View file

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TProtocol.h"
#import "TTransport.h"
#import "TProtocolFactory.h"
NS_ASSUME_NONNULL_BEGIN
@interface TCompactProtocol : NSObject <TProtocol>
-(id) initWithTransport:(id <TTransport>)transport;
@end
@interface TCompactProtocolFactory : NSObject <TProtocolFactory>
+(TCompactProtocolFactory *) sharedFactory;
-(TCompactProtocol *) newProtocolOnTransport:(id <TTransport>)transport;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,983 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TCompactProtocol.h"
#import "TProtocolError.h"
static const UInt8 COMPACT_PROTOCOL_ID = 0x82;
static const UInt8 COMPACT_VERSION = 1;
static const UInt8 COMPACT_VERSION_MASK = 0x1F; // 0001 1111
static const UInt8 COMPACT_TYPE_MASK = 0xE0; // 1110 0000
static const UInt8 COMPACT_TYPE_BITS = 0x07; // 0000 0111
static const int COMPACT_TYPE_SHIFT_AMOUNT = 5;
enum {
TCType_STOP = 0x00,
TCType_BOOLEAN_TRUE = 0x01,
TCType_BOOLEAN_FALSE = 0x02,
TCType_BYTE = 0x03,
TCType_I16 = 0x04,
TCType_I32 = 0x05,
TCType_I64 = 0x06,
TCType_DOUBLE = 0x07,
TCType_BINARY = 0x08,
TCType_LIST = 0x09,
TCType_SET = 0x0A,
TCType_MAP = 0x0B,
TCType_STRUCT = 0x0C,
};
@implementation TCompactProtocolFactory
+(TCompactProtocolFactory *) sharedFactory
{
static TCompactProtocolFactory *gSharedFactory = nil;
if (gSharedFactory == nil) {
gSharedFactory = [[TCompactProtocolFactory alloc] init];
}
return gSharedFactory;
}
-(NSString *) protocolName
{
return @"compact";
}
-(TCompactProtocol *) newProtocolOnTransport:(id <TTransport>)transport
{
return [[TCompactProtocol alloc] initWithTransport:transport];
}
@end
@interface TCompactProtocol ()
@property(strong, nonatomic) id <TTransport> transport;
@property(strong, nonatomic) NSMutableArray *lastField;
@property(assign, nonatomic) short lastFieldId;
@property(strong, nonatomic) NSString *boolFieldName;
@property(strong, nonatomic) NSNumber *boolFieldType;
@property(strong, nonatomic) NSNumber *boolFieldId;
@property(strong, nonatomic) NSNumber *booleanValue;
@property(strong, nonatomic) NSString *currentMessageName;
@end
@implementation TCompactProtocol
-(id) init
{
self = [super init];
if (self != nil) {
_lastField = [[NSMutableArray alloc] init];
}
return self;
}
-(id) initWithTransport:(id <TTransport>)aTransport
{
self = [self init];
if (self != nil) {
_transport = aTransport;
}
return self;
}
-(id <TTransport>) transport
{
return _transport;
}
-(BOOL) writeByteDirect:(UInt8)n error:(NSError *__autoreleasing *)error
{
if (![_transport write:(UInt8 *)&n offset:0 length:1 error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed");
}
return YES;
}
-(BOOL) writeVarint32:(UInt32)n error:(NSError *__autoreleasing *)error
{
UInt8 i32buf[5] = {0};
UInt32 idx = 0;
while (true) {
if ((n & ~0x7F) == 0) {
i32buf[idx++] = (UInt8)n;
break;
}
else {
i32buf[idx++] = (UInt8)((n & 0x7F) | 0x80);
n >>= 7;
}
}
if (![_transport write:i32buf offset:0 length:idx error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed");
}
return YES;
}
-(BOOL) writeMessageBeginWithName:(NSString *)name
type:(SInt32)messageType
sequenceID:(SInt32)sequenceID
error:(NSError *__autoreleasing *)error
{
if (![self writeByteDirect:COMPACT_PROTOCOL_ID error:error]) {
return NO;
}
if (![self writeByteDirect:(UInt8)((COMPACT_VERSION & COMPACT_VERSION_MASK) |
((((UInt32)messageType) << COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_MASK)) error:error])
{
return NO;
}
if (![self writeVarint32:(UInt32)sequenceID error:error]) {
return NO;
}
if (![self writeString:name error:error]) {
return NO;
}
_currentMessageName = name;
return YES;
}
-(BOOL) writeStructBeginWithName:(NSString *)name error:(NSError *__autoreleasing *)error
{
[_lastField addObject:@(_lastFieldId)];
_lastFieldId = 0;
return YES;
}
-(BOOL) writeStructEnd:(NSError *__autoreleasing *)error
{
_lastFieldId = [_lastField.lastObject shortValue];
[_lastField removeLastObject];
return YES;
}
-(BOOL) writeFieldBeginWithName:(NSString *)name
type:(SInt32)fieldType
fieldID:(SInt32)fieldID
error:(NSError *__autoreleasing *)error
{
if (fieldType == TTypeBOOL) {
_boolFieldName = [name copy];
_boolFieldType = @(fieldType);
_boolFieldId = @(fieldID);
return YES;
}
else {
return [self writeFieldBeginInternalWithName:name
type:fieldType
fieldID:fieldID
typeOverride:0xFF
error:error];
}
}
-(BOOL) writeFieldBeginInternalWithName:(NSString *)name
type:(SInt32)fieldType
fieldID:(SInt32)fieldID
typeOverride:(UInt8)typeOverride
error:(NSError *__autoreleasing *)error
{
UInt8 typeToWrite = typeOverride == 0xFF ? [self compactTypeForTType:fieldType] : typeOverride;
// check if we can use delta encoding for the field id
if (fieldID > _lastFieldId && fieldID - _lastFieldId <= 15) {
// Write them together
if (![self writeByteDirect:(fieldID - _lastFieldId) << 4 | typeToWrite error:error]) {
return NO;
}
}
else {
// Write them separate
if (![self writeByteDirect:typeToWrite error:error]) {
return NO;
}
if (![self writeI16:fieldID error:error]) {
return NO;
}
}
_lastFieldId = fieldID;
return YES;
}
-(BOOL) writeFieldStop:(NSError *__autoreleasing *)error
{
return [self writeByteDirect:TCType_STOP error:error];
}
-(BOOL) writeMapBeginWithKeyType:(SInt32)keyType
valueType:(SInt32)valueType
size:(SInt32)size
error:(NSError *__autoreleasing *)error
{
if (size == 0) {
if (![self writeByteDirect:0 error:error]) {
return NO;
}
}
else {
if (![self writeVarint32:(UInt32)size error:error]) {
return NO;
}
if (![self writeByteDirect:[self compactTypeForTType:keyType] << 4 | [self compactTypeForTType:valueType] error:error]) {
return NO;
}
}
return YES;
}
-(BOOL) writeListBeginWithElementType:(SInt32)elementType
size:(SInt32)size
error:(NSError *__autoreleasing *)error
{
return [self writeCollectionBeginWithElementType:elementType size:size error:error];
}
-(BOOL) writeSetBeginWithElementType:(SInt32)elementType
size:(SInt32)size
error:(NSError *__autoreleasing *)error
{
return [self writeCollectionBeginWithElementType:elementType size:size error:error];
}
-(BOOL) writeBool:(BOOL)b error:(NSError *__autoreleasing *)error
{
BOOL result;
if (_boolFieldId != nil && _boolFieldName != nil && _boolFieldType != nil) {
// we haven't written the field header yet
result = [self writeFieldBeginInternalWithName:_boolFieldName
type:_boolFieldType.intValue
fieldID:_boolFieldId.intValue
typeOverride:b ? TCType_BOOLEAN_TRUE : TCType_BOOLEAN_FALSE
error:error];
_boolFieldId = nil;
_boolFieldName = nil;
_boolFieldType = nil;
}
else {
// we're not part of a field, so just Write the value.
result = [self writeByteDirect:b ? TCType_BOOLEAN_TRUE : TCType_BOOLEAN_FALSE error:error];
}
return result;
}
-(BOOL) writeByte:(UInt8)value error:(NSError *__autoreleasing *)error
{
return [self writeByteDirect:value error:error];
}
-(BOOL) writeI16:(SInt16)value error:(NSError *__autoreleasing *)error
{
return [self writeVarint32:[self i32ToZigZag:value] error:error];
}
-(BOOL) writeI32:(SInt32)value error:(NSError *__autoreleasing *)error
{
return [self writeVarint32:[self i32ToZigZag:value] error:error];
}
-(BOOL) writeI64:(SInt64)value error:(NSError *__autoreleasing *)error
{
return [self writeVarint64:[self i64ToZigZag:value] error:error];
}
-(BOOL) writeDouble:(double)value error:(NSError *__autoreleasing *)error
{
// Safe bit-casting double->uint64
UInt64 bits = 0;
memcpy(&bits, &value, 8);
bits = OSSwapHostToLittleInt64(bits);
if (![_transport write:(UInt8 *)&bits offset:0 length:8 error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed");
}
return YES;
}
-(BOOL) writeString:(NSString *)value error:(NSError *__autoreleasing *)error
{
return [self writeBinary:[value dataUsingEncoding:NSUTF8StringEncoding] error:error];
}
-(BOOL) writeBinary:(NSData *)data error:(NSError *__autoreleasing *)error
{
if (![self writeVarint32:(UInt32)data.length error:error]) {
return NO;
}
if (![_transport write:data.bytes offset:0 length:(UInt32)data.length error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed");
}
return YES;
}
-(BOOL) writeMessageEnd:(NSError *__autoreleasing *)error
{
_currentMessageName = nil;
return YES;
}
-(BOOL) writeMapEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) writeListEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) writeSetEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) writeFieldEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) writeCollectionBeginWithElementType:(SInt32)elementType
size:(SInt32)size
error:(NSError *__autoreleasing *)error
{
UInt8 ctypeElement = [self compactTypeForTType:elementType];
if (size <= 14) {
if (![self writeByteDirect:size << 4 | ctypeElement error:error]) {
return NO;
}
}
else {
if (![self writeByteDirect:0xf0 | ctypeElement error:error]) {
return NO;
}
if (![self writeVarint32:(UInt32)size error:error]) {
return NO;
}
}
return YES;
}
-(BOOL) writeVarint64:(UInt64)n error:(NSError *__autoreleasing *)error
{
UInt8 varint64out[10] = {0};
int idx = 0;
while (true) {
if ((n & ~0x7FL) == 0) {
varint64out[idx++] = (UInt8)n;
break;
}
else {
varint64out[idx++] = (UInt8)((n & 0x7F) | 0x80);
n >>= 7;
}
}
if (![_transport write:varint64out offset:0 length:idx error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed");
}
return YES;
}
-(UInt32) i32ToZigZag:(SInt32)n
{
/*
ZigZag encoding maps signed integers to unsigned integers so that
numbers with a small absolute value (for instance, -1) have
a small varint encoded value too. It does this in a way that
"zig-zags" back and forth through the positive and negative integers,
so that -1 is encoded as 1, 1 is encoded as 2, -2 is encoded as 3, and so
on
*/
return (UInt32)(n << 1) ^ (UInt32)(n >> 31);
}
-(UInt64) i64ToZigZag:(SInt64)n
{
return (UInt64)(n << 1) ^ (UInt64)(n >> 63);
}
-(BOOL) readMessageBeginReturningName:(NSString **)pname
type:(SInt32 *)ptype
sequenceID:(SInt32 *)psequenceID
error:(NSError *__autoreleasing *)error
{
UInt8 protocolId;
if (![self readByte:&protocolId error:error]) {
return NO;
}
if (protocolId != COMPACT_PROTOCOL_ID) {
if (error) {
*error = [NSError errorWithDomain:TProtocolErrorDomain
code:TProtocolErrorUnknown
userInfo:@{TProtocolErrorExtendedErrorKey: @(TProtocolExtendedErrorMismatchedProtocol),
TProtocolErrorExpectedIdKey: @(COMPACT_PROTOCOL_ID)}];
}
return NO;
}
UInt8 versionAndType;
if (![self readByte:&versionAndType error:error]) {
return NO;
}
UInt8 version = versionAndType & COMPACT_VERSION_MASK;
if (version != COMPACT_VERSION) {
if (error) {
*error = [NSError errorWithDomain:TProtocolErrorDomain
code:TProtocolErrorBadVersion
userInfo:@{TProtocolErrorExpectedVersionKey: @(COMPACT_VERSION)}];
}
return NO;
}
int type = (versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_BITS;
UInt32 sequenceID;
if (![self readVarint32:&sequenceID error:error]) {
return NO;
}
NSString *name;
if (![self readString:&name error:error]) {
return NO;
}
if (ptype != NULL) {
*ptype = type;
}
if (psequenceID != NULL) {
*psequenceID = sequenceID;
}
if (pname != NULL) {
*pname = name;
}
return YES;
}
-(BOOL) readStructBeginReturningName:(NSString **)pname error:(NSError *__autoreleasing *)error
{
[_lastField addObject:@(_lastFieldId)];
_lastFieldId = 0;
if (pname != NULL) {
*pname = @"";
}
return YES;
}
-(BOOL) readStructEnd:(NSError *__autoreleasing *)error
{
_lastFieldId = [_lastField.lastObject shortValue];
[_lastField removeLastObject];
return YES;
}
-(BOOL) readFieldBeginReturningName:(NSString **)pname
type:(SInt32 *)pfieldType
fieldID:(SInt32 *)pfieldID
error:(NSError *__autoreleasing *)error
{
UInt8 byte;
if (![self readByte:&byte error:error]) {
return NO;
}
UInt8 type = byte & 0x0f;
// if it's a stop, then we can return immediately, as the struct is over.
if (type == TCType_STOP) {
if (pname != NULL) {
*pname = @"";
}
if (pfieldType != NULL) {
*pfieldType = TTypeSTOP;
}
if (pfieldID != NULL) {
*pfieldID = 0;
}
return YES;
}
short fieldId = 0;
// mask off the 4 MSB of the type header. it could contain a field id delta.
short modifier = (byte & 0xf0) >> 4;
if (modifier == 0) {
// not a delta. look ahead for the zigzag varint field id.
if (![self readI16:&fieldId error:error]) {
return NO;
}
}
else {
// has a delta. add the delta to the last Read field id.
fieldId = _lastFieldId + modifier;
}
UInt8 fieldType;
if (![self ttype:&fieldType forCompactType:type error:error]) {
return NO;
}
if (pname != NULL) {
*pname = @"";
}
if (pfieldType != NULL) {
*pfieldType = fieldType;
}
if (pfieldID != NULL) {
*pfieldID = fieldId;
}
// if this happens to be a boolean field, the value is encoded in the type
if (type == TCType_BOOLEAN_TRUE ||
type == TCType_BOOLEAN_FALSE)
{
// save the boolean value in a special instance variable.
_booleanValue = [NSNumber numberWithBool:type == TCType_BOOLEAN_TRUE];
}
// push the new field onto the field stack so we can keep the deltas going.
_lastFieldId = fieldId;
return YES;
}
-(BOOL) readMapBeginReturningKeyType:(SInt32 *)pkeyType
valueType:(SInt32 *)pvalueType
size:(SInt32 *)psize
error:(NSError *__autoreleasing *)error
{
UInt8 keyAndValueType = 0;
UInt32 size;
if (![self readVarint32:&size error:error]) {
return NO;
}
if (size != 0) {
if (![self readByte:&keyAndValueType error:error]) {
return NO;
}
}
UInt8 keyType;
if (![self ttype:&keyType forCompactType:keyAndValueType >> 4 error:error]) {
return NO;
}
UInt8 valueType;
if (![self ttype:&valueType forCompactType:keyAndValueType & 0xf error:error]) {
return NO;
}
if (pkeyType != NULL) {
*pkeyType = keyType;
}
if (pvalueType != NULL) {
*pvalueType = valueType;
}
if (psize != NULL) {
*psize = size;
}
return YES;
}
-(BOOL) readListBeginReturningElementType:(SInt32 *)pelementType
size:(SInt32 *)psize
error:(NSError *__autoreleasing *)error
{
UInt8 sizeAndType;
if (![self readByte:&sizeAndType error:error]) {
return NO;
}
UInt32 size = (sizeAndType >> 4) & 0x0f;
if (size == 15) {
if (![self readVarint32:&size error:error]) {
return NO;
}
}
UInt8 elementType;
if (![self ttype:&elementType forCompactType:sizeAndType & 0x0f error:error]) {
return NO;
}
if (pelementType != NULL) {
*pelementType = elementType;
}
if (psize != NULL) {
*psize = size;
}
return YES;
}
-(BOOL) readSetBeginReturningElementType:(SInt32 *)pelementType
size:(SInt32 *)psize
error:(NSError *__autoreleasing *)error
{
return [self readListBeginReturningElementType:pelementType size:psize error:error];
}
-(BOOL) readBool:(BOOL *)value error:(NSError *__autoreleasing *)error
{
if (_booleanValue != nil) {
BOOL result = _booleanValue.boolValue;
_booleanValue = nil;
*value = result;
}
else {
UInt8 result;
if (![self readByte:&result error:error]) {
return NO;
}
*value = result == TCType_BOOLEAN_TRUE;
}
return YES;
}
-(BOOL) readByte:(UInt8 *)value error:(NSError *__autoreleasing *)error
{
if (![_transport readAll:value offset:0 length:1 error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed");
}
return YES;
}
-(BOOL) readI16:(SInt16 *)value error:(NSError *__autoreleasing *)error
{
UInt32 v;
if (![self readVarint32:&v error:error]) {
return NO;
}
if (value) {
*value = (SInt16)[self zigZagToi32:v];
}
return YES;
}
-(BOOL) readI32:(SInt32 *)value error:(NSError *__autoreleasing *)error
{
UInt32 v;
if (![self readVarint32:&v error:error]) {
return NO;
}
if (value) {
*value = [self zigZagToi32:v];
}
return YES;
}
-(BOOL) readI64:(SInt64 *)value error:(NSError *__autoreleasing *)error
{
UInt64 v;
if (![self readVarint64:&v error:error]) {
return NO;
}
if (value) {
*value = [self zigZagToi64:v];
}
return YES;
}
-(BOOL) readDouble:(double *)value error:(NSError *__autoreleasing *)error
{
UInt64 bits;
if (![_transport readAll:(UInt8 *)&bits offset:0 length:8 error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed");
}
bits = OSSwapLittleToHostInt64(bits);
if (value) {
memcpy(value, &bits, sizeof(bits));
}
return YES;
}
-(BOOL) readString:(NSString *__autoreleasing *)value error:(NSError *__autoreleasing *)error
{
UInt32 length;
if (![self readVarint32:&length error:error]) {
return NO;
}
NSString *result;
if (length != 0) {
NSData *data;
if (![self readBinaryOfLength:length data:&data error:error]) {
return NO;
}
result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
}
else {
result = @"";
}
if (value) {
*value = result;
}
return YES;
}
-(BOOL) readBinary:(NSData *__autoreleasing *)value error:(NSError *__autoreleasing *)error
{
UInt32 length;
if (![self readVarint32:&length error:error]) {
return NO;
}
return [self readBinaryOfLength:length data:value error:error];
}
-(BOOL) readBinaryOfLength:(UInt32)length data:(NSData *__autoreleasing *)value error:(NSError *__autoreleasing *)error
{
NSData *result;
if (length != 0) {
NSMutableData *buf = [NSMutableData dataWithLength:length];
if (![_transport readAll:buf.mutableBytes offset:0 length:length error:error]) {
PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed");
}
result = buf;
}
else {
result = [NSData data];
}
if (value) {
*value = result;
}
return YES;
}
-(BOOL) readMessageEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) readFieldEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) readMapEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) readListEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) readSetEnd:(NSError *__autoreleasing *)error
{
return YES;
}
-(BOOL) readVarint32:(UInt32 *)value error:(NSError *__autoreleasing *)error
{
UInt32 result = 0;
int shift = 0;
while (true) {
UInt8 byte;
if (![self readByte:&byte error:error]) {
return NO;
}
result |= (UInt32)(byte & 0x7f) << shift;
if (!(byte & 0x80)) {
break;
}
shift += 7;
}
if (value) {
*value = result;
}
return YES;
}
-(BOOL) readVarint64:(UInt64 *)value error:(NSError *__autoreleasing *)error
{
int shift = 0;
UInt64 result = 0;
while (true) {
UInt8 byte;
if (![self readByte:&byte error:error]) {
return NO;
}
result |= (UInt64)(byte & 0x7f) << shift;
if (!(byte & 0x80)) {
break;
}
shift += 7;
}
if (value) {
*value = result;
}
return YES;
}
-(SInt32) zigZagToi32:(UInt32)n
{
return (SInt32)(n >> 1) ^ (-(SInt32)(n & 1));
}
-(SInt64) zigZagToi64:(UInt64)n
{
return (SInt64)(n >> 1) ^ (-(SInt64)(n & 1));
}
-(BOOL) ttype:(UInt8 *)ttype forCompactType:(UInt8)ctype error:(NSError *__autoreleasing *)error
{
switch (ctype & 0x0f) {
case TCType_STOP:
*ttype = TTypeSTOP;
return YES;
case TCType_BOOLEAN_FALSE:
case TCType_BOOLEAN_TRUE:
*ttype = TTypeBOOL;
return YES;
case TCType_BYTE:
*ttype = TTypeBYTE;
return YES;
case TCType_I16:
*ttype = TTypeI16;
return YES;
case TCType_I32:
*ttype = TTypeI32;
return YES;
case TCType_I64:
*ttype = TTypeI64;
return YES;
case TCType_DOUBLE:
*ttype = TTypeDOUBLE;
return YES;
case TCType_BINARY:
*ttype = TTypeSTRING;
return YES;
case TCType_LIST:
*ttype = TTypeLIST;
return YES;
case TCType_SET:
*ttype = TTypeSET;
return YES;
case TCType_MAP:
*ttype = TTypeMAP;
return YES;
case TCType_STRUCT:
*ttype = TTypeSTRUCT;
return YES;
default:
if (error) {
*error = [NSError errorWithDomain:TProtocolErrorDomain
code:TProtocolErrorUnknown
userInfo:@{TProtocolErrorTypeKey: @((UInt8)(ctype & 0x0F))}];
}
return NO;
}
}
-(UInt8) compactTypeForTType:(UInt8)ttype
{
static UInt8 ttypeToCompactType[] = {
[TTypeSTOP] = TCType_STOP,
[TTypeBOOL] = TCType_BOOLEAN_FALSE,
[TTypeBYTE] = TCType_BYTE,
[TTypeDOUBLE] = TCType_DOUBLE,
[TTypeI16] = TCType_I16,
[TTypeI32] = TCType_I32,
[TTypeI64] = TCType_I64,
[TTypeSTRING] = TCType_BINARY,
[TTypeSTRUCT] = TCType_STRUCT,
[TTypeMAP] = TCType_MAP,
[TTypeSET] = TCType_SET,
[TTypeLIST] = TCType_LIST
};
return ttypeToCompactType[ttype];
}
@end

View file

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TProtocolDecorator.h"
NS_ASSUME_NONNULL_BEGIN
extern NSString *TMultiplexedProtocolSeperator;
@interface TMultiplexedProtocol : TProtocolDecorator
-(id) initWithProtocol:(id <TProtocol>)protocol
serviceName:(NSString *)name;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TMultiplexedProtocol.h"
#import "TProtocol.h"
NSString *TMultiplexedProtocolSeperator = @":";
@interface TMultiplexedProtocol ()
@property(strong, nonatomic) NSString *serviceName;
@end
@implementation TMultiplexedProtocol
-(id) initWithProtocol:(id <TProtocol>)protocol
serviceName:(NSString *)name
{
self = [super initWithProtocol:protocol];
if (self) {
_serviceName = name;
}
return self;
}
-(BOOL) writeMessageBeginWithName:(NSString *)name
type:(SInt32)messageType
sequenceID:(SInt32)sequenceID
error:(NSError *__autoreleasing *)error
{
switch (messageType) {
case TMessageTypeCALL:
case TMessageTypeONEWAY: {
NSMutableString *serviceFunction = [[NSMutableString alloc] initWithString:_serviceName];
[serviceFunction appendString:TMultiplexedProtocolSeperator];
[serviceFunction appendString:name];
return [super writeMessageBeginWithName:serviceFunction type:messageType sequenceID:sequenceID error:error];
}
break;
default:
return [super writeMessageBeginWithName:name type:messageType sequenceID:sequenceID error:error];
}
}
@end

View file

@ -0,0 +1,164 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TTransport.h"
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM (int, TMessageType) {
TMessageTypeCALL = 1,
TMessageTypeREPLY = 2,
TMessageTypeEXCEPTION = 3,
TMessageTypeONEWAY = 4
};
typedef NS_ENUM (int, TType) {
TTypeSTOP = 0,
TTypeVOID = 1,
TTypeBOOL = 2,
TTypeBYTE = 3,
TTypeDOUBLE = 4,
TTypeI16 = 6,
TTypeI32 = 8,
TTypeI64 = 10,
TTypeSTRING = 11,
TTypeSTRUCT = 12,
TTypeMAP = 13,
TTypeSET = 14,
TTypeLIST = 15
};
@protocol TProtocol <NSObject>
-(id <TTransport>) transport;
-(BOOL) readMessageBeginReturningName:(NSString *__nullable __autoreleasing *__nullable)name
type:(nullable SInt32 *)type
sequenceID:(nullable SInt32 *)sequenceID
error:(NSError *__autoreleasing *)error;
-(BOOL) readMessageEnd:(NSError *__autoreleasing *)error;
-(BOOL) readStructBeginReturningName:(NSString *__nullable __autoreleasing *__nullable)name
error:(NSError *__autoreleasing *)error;
-(BOOL) readStructEnd:(NSError *__autoreleasing *)error;
-(BOOL) readFieldBeginReturningName:(NSString *__nullable __autoreleasing *__nullable)name
type:(SInt32 *)fieldType
fieldID:(nullable SInt32 *)fieldID
error:(NSError *__autoreleasing *)error;
-(BOOL) readFieldEnd:(NSError *__autoreleasing *)error;
-(BOOL) readString:(NSString *__nonnull __autoreleasing *__nonnull)value error:(NSError **)error;
-(BOOL) readBool:(BOOL *)value error:(NSError *__autoreleasing *)error;
-(BOOL) readByte:(UInt8 *)value error:(NSError *__autoreleasing *)error;
-(BOOL) readI16:(SInt16 *)value error:(NSError *__autoreleasing *)error;
-(BOOL) readI32:(SInt32 *)value error:(NSError *__autoreleasing *)error;
-(BOOL) readI64:(SInt64 *)value error:(NSError *__autoreleasing *)error;
-(BOOL) readDouble:(double *)value error:(NSError *__autoreleasing *)error;
-(BOOL) readBinary:(NSData *__nonnull __autoreleasing *__nonnull)value error:(NSError **)error;
-(BOOL) readMapBeginReturningKeyType:(nullable SInt32 *)keyType
valueType:(nullable SInt32 *)valueType
size:(SInt32 *)size
error:(NSError *__autoreleasing *)error;
-(BOOL) readMapEnd:(NSError *__autoreleasing *)error;
-(BOOL) readSetBeginReturningElementType:(nullable SInt32 *)elementType
size:(SInt32 *)size
error:(NSError *__autoreleasing *)error;
-(BOOL) readSetEnd:(NSError *__autoreleasing *)error;
-(BOOL) readListBeginReturningElementType:(nullable SInt32 *)elementType
size:(SInt32 *)size
error:(NSError *__autoreleasing *)error;
-(BOOL) readListEnd:(NSError *__autoreleasing *)error;
-(BOOL) writeMessageBeginWithName:(NSString *)name
type:(SInt32)messageType
sequenceID:(SInt32)sequenceID
error:(NSError *__autoreleasing *)error;
-(BOOL) writeMessageEnd:(NSError *__autoreleasing *)error;
-(BOOL) writeStructBeginWithName:(NSString *)name error:(NSError **)error;
-(BOOL) writeStructEnd:(NSError *__autoreleasing *)error;
-(BOOL) writeFieldBeginWithName:(NSString *)name
type:(SInt32)fieldType
fieldID:(SInt32)fieldID
error:(NSError *__autoreleasing *)error;
-(BOOL) writeI32:(SInt32)value error:(NSError *__autoreleasing *)error;
-(BOOL) writeI64:(SInt64)value error:(NSError *__autoreleasing *)error;
-(BOOL) writeI16:(short)value error:(NSError *__autoreleasing *)error;
-(BOOL) writeByte:(UInt8)value error:(NSError *__autoreleasing *)error;
-(BOOL) writeString:(NSString *)value error:(NSError *__autoreleasing *)error;
-(BOOL) writeDouble:(double)value error:(NSError *__autoreleasing *)error;
-(BOOL) writeBool:(BOOL)value error:(NSError *__autoreleasing *)error;
-(BOOL) writeBinary:(NSData *)data error:(NSError *__autoreleasing *)error;
-(BOOL) writeFieldStop:(NSError *__autoreleasing *)error;
-(BOOL) writeFieldEnd:(NSError *__autoreleasing *)error;
-(BOOL) writeMapBeginWithKeyType:(SInt32)keyType
valueType:(SInt32)valueType
size:(SInt32)size
error:(NSError *__autoreleasing *)error;
-(BOOL) writeMapEnd:(NSError *__autoreleasing *)error;
-(BOOL) writeSetBeginWithElementType:(SInt32)elementType
size:(SInt32)size
error:(NSError *__autoreleasing *)error;
-(BOOL) writeSetEnd:(NSError *__autoreleasing *)error;
-(BOOL) writeListBeginWithElementType:(SInt32)elementType
size:(SInt32)size
error:(NSError *__autoreleasing *)error;
-(BOOL) writeListEnd:(NSError *__autoreleasing *)error;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface TProtocolDecorator : NSObject <TProtocol>
-(id) initWithProtocol:(id <TProtocol>)protocol;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,295 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TProtocolDecorator.h"
@interface TProtocolDecorator ()
@property(strong, nonatomic) id<TProtocol> concreteProtocol;
@end
@implementation TProtocolDecorator
-(id) initWithProtocol:(id <TProtocol>)protocol
{
self = [super init];
if (self) {
_concreteProtocol = protocol;
}
return self;
}
-(id <TTransport>) transport
{
return [_concreteProtocol transport];
}
-(BOOL) readMessageBeginReturningName:(NSString **)name
type:(SInt32 *)type
sequenceID:(SInt32 *)sequenceID
error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readMessageBeginReturningName:name
type:type
sequenceID:sequenceID
error:error];
}
-(BOOL) readMessageEnd:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readMessageEnd:error];
}
-(BOOL) readStructBeginReturningName:(NSString **)name
error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readStructBeginReturningName:name error:error];
}
-(BOOL) readStructEnd:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readStructEnd:error];
}
-(BOOL) readFieldBeginReturningName:(NSString **)name
type:(SInt32 *)fieldType
fieldID:(SInt32 *)fieldID
error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readFieldBeginReturningName:name
type:fieldType
fieldID:fieldID
error:error];
}
-(BOOL) readFieldEnd:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readFieldEnd:error];
}
-(BOOL) readString:(NSString *__autoreleasing *)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readString:value error:error];
}
-(BOOL) readBool:(BOOL *)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readBool:value error:error];
}
-(BOOL) readByte:(UInt8 *)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readByte:value error:error];
}
-(BOOL) readI16:(SInt16 *)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readI16:value error:error];
}
-(BOOL) readI32:(SInt32 *)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readI32:value error:error];
}
-(BOOL) readI64:(SInt64 *)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readI64:value error:error];
}
-(BOOL) readDouble:(double *)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readDouble:value error:error];
}
-(BOOL) readBinary:(NSData *__autoreleasing *)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readBinary:value error:error];
}
-(BOOL) readMapBeginReturningKeyType:(SInt32 *)keyType
valueType:(SInt32 *)valueType
size:(SInt32 *)size
error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readMapBeginReturningKeyType:keyType
valueType:valueType
size:size
error:error];
}
-(BOOL) readMapEnd:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readMapEnd:error];
}
-(BOOL) readSetBeginReturningElementType:(SInt32 *)elementType
size:(SInt32 *)size
error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readSetBeginReturningElementType:elementType
size:size
error:error];
}
-(BOOL) readSetEnd:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readSetEnd:error];
}
-(BOOL) readListBeginReturningElementType:(SInt32 *)elementType
size:(SInt32 *)size
error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readListBeginReturningElementType:elementType
size:size
error:error];
}
-(BOOL) readListEnd:(NSError *__autoreleasing *)error
{
return [_concreteProtocol readListEnd:error];
}
-(BOOL) writeMessageBeginWithName:(NSString *)name
type:(SInt32)messageType
sequenceID:(SInt32)sequenceID
error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeMessageBeginWithName:name
type:messageType
sequenceID:sequenceID
error:error];
}
-(BOOL) writeMessageEnd:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeMessageEnd:error];
}
-(BOOL) writeStructBeginWithName:(NSString *)name error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeStructBeginWithName:name error:error];
}
-(BOOL) writeStructEnd:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeStructEnd:error];
}
-(BOOL) writeFieldBeginWithName:(NSString *)name
type:(SInt32)fieldType
fieldID:(SInt32)fieldID
error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeFieldBeginWithName:name
type:fieldType
fieldID:fieldID
error:error];
}
-(BOOL) writeI32:(SInt32)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeI32:value error:error];
}
-(BOOL) writeI64:(SInt64)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeI64:value error:error];
}
-(BOOL) writeI16:(SInt16)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeI16:value error:error];
}
-(BOOL) writeByte:(UInt8)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeByte:value error:error];
}
-(BOOL) writeString:(NSString *)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeString:value error:error];
}
-(BOOL) writeDouble:(double)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeDouble:value error:error];
}
-(BOOL) writeBool:(BOOL)value error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeBool:value error:error];
}
-(BOOL) writeBinary:(NSData *)data error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeBinary:data error:error];
}
-(BOOL) writeFieldStop:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeFieldStop:error];
}
-(BOOL) writeFieldEnd:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeFieldEnd:error];
}
-(BOOL) writeMapBeginWithKeyType:(SInt32)keyType
valueType:(SInt32)valueType
size:(SInt32)size
error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeMapBeginWithKeyType:keyType
valueType:valueType
size:size
error:error];
}
-(BOOL) writeMapEnd:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeMapEnd:error];
}
-(BOOL) writeSetBeginWithElementType:(SInt32)elementType
size:(SInt32)size
error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeSetBeginWithElementType:elementType size:size error:error];
}
-(BOOL) writeSetEnd:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeSetEnd:error];
}
-(BOOL) writeListBeginWithElementType:(SInt32)elementType
size:(SInt32)size
error:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeListBeginWithElementType:elementType size:size error:error];
}
-(BOOL) writeListEnd:(NSError *__autoreleasing *)error
{
return [_concreteProtocol writeListEnd:error];
}
@end

View file

@ -0,0 +1,76 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TError.h"
extern NSString *TProtocolErrorDomain;
typedef NS_ENUM (int, TProtocolError) {
TProtocolErrorUnknown = 0,
TProtocolErrorInvalidData = 1,
TProtocolErrorNegativeSize = 2,
TProtocolErrorSizeLimit = 3,
TProtocolErrorBadVersion = 4,
TProtocolErrorNotImplemented = 5,
TProtocolErrorDepthLimit = 6,
};
typedef NS_ENUM(int, TProtocolExtendedError) {
TProtocolExtendedErrorMissingRequiredField = 1001,
TProtocolExtendedErrorUnexpectedType = 1002,
TProtocolExtendedErrorMismatchedProtocol = 1003,
};
extern NSString *TProtocolErrorExtendedErrorKey;
extern NSString *TProtocolErrorFieldNameKey;
extern NSString *TProtocolErrorExpectedIdKey;
extern NSString *TProtocolErrorExpectedVersionKey;
extern NSString *TProtocolErrorTypeKey;
extern NSString *TProtocolErrorSourceLineKey;
extern NSString *TProtocolErrorSourceFileKey;
extern NSString *TProtocolErrorSourceMethodKey;
extern NSString *TProtocolErrorMessageNameKey;
#define PROTOCOL_ERROR(ret, err, ...) \
if (error) { \
*error = [NSError errorWithDomain:TProtocolErrorDomain \
code:TProtocolError ## err \
userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:__VA_ARGS__], \
@"SourceFile": [NSString stringWithUTF8String:__FILE__], \
@"SourceLine": @(__LINE__), \
@"SourceFunction": [NSString stringWithUTF8String:__PRETTY_FUNCTION__], \
@"Message": self.currentMessageName ? self.currentMessageName : @""}]; \
} \
return ret
#define PROTOCOL_TRANSPORT_ERROR(ret, errorPtr, ...) \
if (errorPtr) { \
*error = [NSError errorWithDomain:TProtocolErrorDomain \
code:TProtocolErrorUnknown \
userInfo:@{NSLocalizedDescriptionKey: [[NSString stringWithFormat:__VA_ARGS__] stringByAppendingFormat:@": %@", [(*errorPtr) localizedDescription]], \
TProtocolErrorSourceFileKey: [NSString stringWithUTF8String:__FILE__], \
TProtocolErrorSourceLineKey: @(__LINE__), \
TProtocolErrorSourceMethodKey: [NSString stringWithUTF8String:__PRETTY_FUNCTION__], \
TProtocolErrorMessageNameKey: self.currentMessageName ? self.currentMessageName : @"", \
NSUnderlyingErrorKey: *errorPtr}]; \
} \
return ret

View file

@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TProtocolError.h"
NSString *TProtocolErrorDomain = @"TProtocolErrorDomain";
NSString *TProtocolErrorExtendedErrorKey = @"extendedError";
NSString *TProtocolErrorFieldNameKey = @"field";
NSString *TProtocolErrorExpectedIdKey = @"expectedId";
NSString *TProtocolErrorExpectedVersionKey = @"expectedVersion";
NSString *TProtocolErrorTypeKey = @"type";
NSString *TProtocolErrorSourceLineKey = @"sourceLine";
NSString *TProtocolErrorSourceFileKey = @"sourceFile";
NSString *TProtocolErrorSourceMethodKey = @"sourceMethod";
NSString *TProtocolErrorMessageNameKey = @"messageName";

View file

@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TProtocol.h"
#import "TTransport.h"
NS_ASSUME_NONNULL_BEGIN
@protocol TProtocolFactory <NSObject>
@property (readonly, nonatomic) NSString *protocolName;
-(id<TProtocol>) newProtocolOnTransport:(id<TTransport>)transport;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TProtocol.h"
#import "TTransport.h"
NS_ASSUME_NONNULL_BEGIN
@interface TProtocolUtil : NSObject
+(BOOL) skipType:(int)type onProtocol:(id <TProtocol>)protocol error:(NSError **)error;
@end;
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,171 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TProtocolUtil.h"
@implementation TProtocolUtil
+(BOOL) skipType:(int)type onProtocol:(id <TProtocol>)protocol error:(NSError **)error
{
switch (type) {
case TTypeBOOL: {
BOOL val;
if (![protocol readBool:&val error:error]) {
return NO;
}
}
break;
case TTypeBYTE: {
UInt8 val;
if (![protocol readByte:&val error:error]) {
return NO;
}
}
break;
case TTypeI16: {
SInt16 val;
if (![protocol readI16:&val error:error]) {
return NO;
}
}
break;
case TTypeI32: {
SInt32 val;
if (![protocol readI32:&val error:error]) {
return NO;
}
}
break;
case TTypeI64: {
SInt64 val;
if (![protocol readI64:&val error:error]) {
return NO;
}
}
break;
case TTypeDOUBLE: {
double val;
if (![protocol readDouble:&val error:error]) {
return NO;
}
}
break;
case TTypeSTRING: {
NSString *val;
if (![protocol readString:&val error:error]) {
return NO;
}
}
break;
case TTypeSTRUCT: {
if (![protocol readStructBeginReturningName:NULL error:error]) {
return NO;
}
while (true) {
SInt32 fieldType;
if (![protocol readFieldBeginReturningName:nil type:&fieldType fieldID:nil error:error]) {
return NO;
}
if (fieldType == TTypeSTOP) {
break;
}
if (![self skipType:fieldType onProtocol:protocol error:error]) {
return NO;
}
if (![protocol readFieldEnd:error]) {
return NO;
}
}
if (![protocol readStructEnd:error]) {
return NO;
}
}
break;
case TTypeMAP: {
SInt32 keyType;
SInt32 valueType;
SInt32 size;
if (![protocol readMapBeginReturningKeyType:&keyType valueType:&valueType size:&size error:error]) {
return NO;
}
int i;
for (i = 0; i < size; i++) {
if (![TProtocolUtil skipType:keyType onProtocol:protocol error:error]) {
return NO;
}
if (![TProtocolUtil skipType:valueType onProtocol:protocol error:error]) {
return NO;
}
}
if (![protocol readMapEnd:error]) {
return NO;
}
}
break;
case TTypeSET: {
SInt32 elemType;
SInt32 size;
if (![protocol readSetBeginReturningElementType:&elemType size:&size error:error]) {
return NO;
}
int i;
for (i = 0; i < size; i++) {
if (![TProtocolUtil skipType:elemType onProtocol:protocol error:error]) {
return NO;
}
}
if (![protocol readSetEnd:error]) {
return NO;
}
}
break;
case TTypeLIST: {
SInt32 elemType;
SInt32 size;
if (![protocol readListBeginReturningElementType:&elemType size:&size error:error]) {
return NO;
}
int i;
for (i = 0; i < size; i++) {
if (![TProtocolUtil skipType:elemType onProtocol:protocol error:error]) {
return NO;
}
}
if (![protocol readListEnd:error]) {
return NO;
}
}
break;
}
return YES;
}
@end

View file

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TProtocolFactory.h"
#import "TProcessorFactory.h"
#if !TARGET_OS_IPHONE
#import <CoreServices/CoreServices.h>
#else
#import <CFNetwork/CFNetwork.h>
#endif
NS_ASSUME_NONNULL_BEGIN
extern NSString *const TSocketServerClientConnectionFinished;
extern NSString *const TSocketServerProcessorKey;
extern NSString *const TSockerServerTransportKey;
@interface TSocketServer : NSObject
-(instancetype) initWithPort:(int)port
protocolFactory:(id <TProtocolFactory>)protocolFactory
processorFactory:(id <TProcessorFactory>)processorFactory;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,164 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TSocketServer.h"
#import "TNSFileHandleTransport.h"
#import "TProtocol.h"
#import "TTransportError.h"
#import <sys/socket.h>
#include <netinet/in.h>
NSString *const TSocketServerClientConnectionFinished = @"TSocketServerClientConnectionFinished";
NSString *const TSocketServerProcessorKey = @"TSocketServerProcessor";
NSString *const TSockerServerTransportKey = @"TSockerServerTransport";
@interface TSocketServer ()
@property(strong, nonatomic) id<TProtocolFactory> inputProtocolFactory;
@property(strong, nonatomic) id<TProtocolFactory> outputProtocolFactory;
@property(strong, nonatomic) id<TProcessorFactory> processorFactory;
@property(strong, nonatomic) NSFileHandle *socketFileHandle;
@property(strong, nonatomic) dispatch_queue_t processingQueue;
@end
@implementation TSocketServer
-(instancetype) initWithPort:(int)port
protocolFactory:(id <TProtocolFactory>)protocolFactory
processorFactory:(id <TProcessorFactory>)processorFactory;
{
self = [super init];
_inputProtocolFactory = protocolFactory;
_outputProtocolFactory = protocolFactory;
_processorFactory = processorFactory;
dispatch_queue_attr_t processingQueueAttr =
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_BACKGROUND, 0);
_processingQueue = dispatch_queue_create("TSocketServer.processing", processingQueueAttr);
// create a socket.
int fd = -1;
CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL);
if (socket) {
CFSocketSetSocketFlags(socket, CFSocketGetSocketFlags(socket) & ~kCFSocketCloseOnInvalidate);
fd = CFSocketGetNative(socket);
int yes = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
NSData *address = [NSData dataWithBytes:&addr length:sizeof(addr)];
if (CFSocketSetAddress(socket, (__bridge CFDataRef)address) != kCFSocketSuccess) {
CFSocketInvalidate(socket);
CFRelease(socket);
NSLog(@"TSocketServer: Could not bind to address");
return nil;
}
}
else {
NSLog(@"TSocketServer: No server socket");
return nil;
}
// wrap it in a file handle so we can get messages from it
_socketFileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fd
closeOnDealloc:YES];
// throw away our socket
CFSocketInvalidate(socket);
CFRelease(socket);
// register for notifications of accepted incoming connections
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(connectionAccepted:)
name:NSFileHandleConnectionAcceptedNotification
object:_socketFileHandle];
// tell socket to listen
[_socketFileHandle acceptConnectionInBackgroundAndNotify];
NSLog(@"TSocketServer: Listening on TCP port %d", port);
return self;
}
-(void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void) connectionAccepted:(NSNotification *)notification
{
NSFileHandle *socket = [notification.userInfo objectForKey:NSFileHandleNotificationFileHandleItem];
// Now that we have a client connected, handle request on queue
dispatch_async(_processingQueue, ^{
[self handleClientConnection:socket];
});
// Continue accepting connections
[_socketFileHandle acceptConnectionInBackgroundAndNotify];
}
-(void) handleClientConnection:(NSFileHandle *)clientSocket
{
@autoreleasepool {
TNSFileHandleTransport *transport = [[TNSFileHandleTransport alloc] initWithFileHandle:clientSocket];
id<TProcessor> processor = [_processorFactory processorForTransport:transport];
id <TProtocol> inProtocol = [_inputProtocolFactory newProtocolOnTransport:transport];
id <TProtocol> outProtocol = [_outputProtocolFactory newProtocolOnTransport:transport];
NSError *error;
if (![processor processOnInputProtocol:inProtocol outputProtocol:outProtocol error:&error]) {
// Handle error
NSLog(@"Error processing request: %@", error);
}
dispatch_async(dispatch_get_main_queue(), ^{
[NSNotificationCenter.defaultCenter postNotificationName:TSocketServerClientConnectionFinished
object:self
userInfo:@{TSocketServerProcessorKey: processor,
TSockerServerTransportKey: transport}];
});
}
}
@end

View file

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TTransport.h"
NS_ASSUME_NONNULL_BEGIN
@protocol TAsyncTransport;
@protocol TAsyncTransportFactory <NSObject>
-(id<TAsyncTransport>) newTransport;
@end
typedef void (^TAsyncCompletionBlock)();
typedef void (^TAsyncFailureBlock)(NSError * __nonnull);
@protocol TAsyncTransport <TTransport>
-(void) flushWithCompletion:(TAsyncCompletionBlock)completed failure:(TAsyncFailureBlock)failure;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TTransport.h"
NS_ASSUME_NONNULL_BEGIN
@interface TFramedTransport : NSObject <TTransport>
-(id) initWithTransport:(id <TTransport>)transport;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,180 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TFramedTransport.h"
#import "TTransportError.h"
#define HEADER_SIZE 4
#define INIT_FRAME_SIZE 1024
@interface TFramedTransport ()
@property(strong, nonatomic) id<TTransport> transport;
@property(strong, nonatomic) NSMutableData *writeBuffer;
@property(strong, nonatomic) NSMutableData *readBuffer;
@property(assign, nonatomic) NSUInteger readOffset;
@end
@implementation TFramedTransport
-(id) initWithTransport:(id <TTransport>)aTransport
{
if ((self = [self init])) {
_transport = aTransport;
_readBuffer = nil;
_readOffset = 0;
_writeBuffer = [NSMutableData dataWithLength:HEADER_SIZE];
}
return self;
}
-(BOOL) flush:(NSError **)error
{
int len = (int)[_writeBuffer length];
int data_len = len - HEADER_SIZE;
if (data_len < 0) {
if (error) {
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorUnknown
userInfo:@{}];
}
return NO;
}
UInt8 i32rd[HEADER_SIZE];
i32rd[0] = (UInt8)(0xff & (data_len >> 24));
i32rd[1] = (UInt8)(0xff & (data_len >> 16));
i32rd[2] = (UInt8)(0xff & (data_len >> 8));
i32rd[3] = (UInt8)(0xff & (data_len));
// should we make a copy of the writeBuffer instead? Better for threaded
// operations!
[_writeBuffer replaceBytesInRange:NSMakeRange(0, HEADER_SIZE)
withBytes:i32rd length:HEADER_SIZE];
if (![_transport write:_writeBuffer.mutableBytes offset:0 length:len error:error]) {
return NO;
}
if (![_transport flush:error]) {
return NO;
}
_writeBuffer.length = HEADER_SIZE;
return YES;
}
-(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error
{
[_writeBuffer appendBytes:data+offset length:length];
return YES;
}
-(BOOL) readAll:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset length:(UInt32)length error:(NSError *__autoreleasing *)error
{
UInt32 got = [self readAvail:outBuffer offset:outBufferOffset maxLength:length error:error];
if (got != length) {
// Report underflow only if readAvail didn't report error already
if (error && !*error) {
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorEndOfFile
userInfo:nil];
}
return NO;
}
return YES;
}
-(UInt32) readAvail:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset maxLength:(UInt32)length error:(NSError *__autoreleasing *)error
{
UInt32 got = 0;
while (got < length) {
NSUInteger avail = _readBuffer.length - _readOffset;
if (avail == 0) {
if (![self readFrame:error]) {
return 0;
}
avail = _readBuffer.length;
}
NSRange range;
range.location = _readOffset;
range.length = MIN(length - got, avail);
[_readBuffer getBytes:outBuffer+outBufferOffset+got range:range];
_readOffset += range.length;
got += range.length;
}
return got;
}
-(BOOL) readFrame:(NSError **)error
{
UInt8 i32rd[HEADER_SIZE];
if (![_transport readAll:i32rd offset:0 length:HEADER_SIZE error:error]) {
return NO;
}
SInt32 size =
((i32rd[0] & 0xff) << 24) |
((i32rd[1] & 0xff) << 16) |
((i32rd[2] & 0xff) << 8) |
((i32rd[3] & 0xff));
if (_readBuffer == nil) {
_readBuffer = [NSMutableData dataWithLength:size];
}
else {
SInt32 len = (SInt32)_readBuffer.length;
if (len >= size) {
_readBuffer.length = size;
}
else {
// increase length of data buffer
[_readBuffer increaseLengthBy:size-len];
}
}
// copy into internal memory buffer
if (![_transport readAll:_readBuffer.mutableBytes offset:0 length:size error:error]) {
return NO;
}
return YES;
}
@end

View file

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TAsyncTransport.h"
NS_ASSUME_NONNULL_BEGIN
typedef NSError *__nullable (^THTTPSessionTransportResponseValidateBlock) (NSHTTPURLResponse *response, NSData *responseData);
@interface THTTPSessionTransportFactory : NSObject<TAsyncTransportFactory>
@property (strong, nonatomic) THTTPSessionTransportResponseValidateBlock responseValidate;
+(void) setupDefaultsForSessionConfiguration:(NSURLSessionConfiguration *)config
withProtocolName:(NSString *)protocolName;
-(id) initWithSession:(NSURLSession *)session
URL:(NSURL *)aURL;
@end
@interface THTTPSessionTransport : NSObject <TAsyncTransport>
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,268 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "THTTPSessionTransport.h"
#import "TTransportError.h"
@interface THTTPSessionTransportFactory ()
@property (strong, nonatomic) NSURLSession *session;
@property (strong, nonatomic) NSURL *url;
@end
@interface THTTPSessionTransport ()
@property (strong, nonatomic) THTTPSessionTransportFactory *factory;
@property (strong, nonatomic) NSMutableData *requestData;
@property (strong, nonatomic) NSData *responseData;
@property (assign, nonatomic) NSUInteger responseDataOffset;
-(instancetype) initWithFactory:(THTTPSessionTransportFactory *)factory;
@end
@implementation THTTPSessionTransportFactory
+(void) setupDefaultsForSessionConfiguration:(NSURLSessionConfiguration *)config withProtocolName:(NSString *)protocolName
{
NSString *thriftContentType = @"application/x-thrift";
if (protocolName.length) {
thriftContentType = [thriftContentType stringByAppendingFormat:@"; p=%@", protocolName];
}
config.requestCachePolicy = NSURLRequestReloadIgnoringCacheData;
config.HTTPShouldUsePipelining = YES;
config.HTTPShouldSetCookies = NO;
config.URLCache = nil;
config.HTTPAdditionalHeaders = @{@"Content-Type":thriftContentType,
@"Accept":thriftContentType,
@"User-Agent":@"Thrift/Cocoa (Session)"};
}
-(id) initWithSession:(NSURLSession *)session URL:(NSURL *)url
{
self = [super init];
if (self) {
_session = session;
_url = url;
}
return self;
}
-(id<TAsyncTransport>) newTransport
{
return [[THTTPSessionTransport alloc] initWithFactory:self];
}
-(NSURLSessionDataTask *) taskWithRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler
error:(NSError *__autoreleasing *)error
{
NSURLSessionDataTask *newTask = [_session dataTaskWithRequest:request completionHandler:completionHandler];
if (!newTask) {
if (error) {
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorUnknown
userInfo:@{NSLocalizedDescriptionKey:@"Failed to create session data task"}];
}
return nil;
}
return newTask;
}
-(NSError *) validateResponse:(NSHTTPURLResponse *)response data:(NSData *)data
{
if (_responseValidate) {
return _responseValidate(response, data);
}
return nil;
}
@end
@implementation THTTPSessionTransport
-(instancetype) initWithFactory:(THTTPSessionTransportFactory *)factory
{
self = [super init];
if (self) {
_factory = factory;
}
return self;
}
-(BOOL) readAll:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset length:(UInt32)length error:(NSError *__autoreleasing *)error
{
UInt32 got = [self readAvail:outBuffer offset:outBufferOffset maxLength:length error:error];
if (got != length) {
// Report underflow only if readAvail didn't report error already
if (error && !*error) {
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorEndOfFile
userInfo:nil];
}
return NO;
}
return YES;
}
-(UInt32) readAvail:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset maxLength:(UInt32)maxLength error:(NSError *__autoreleasing *)error
{
NSUInteger avail = _responseData.length - _responseDataOffset;
NSRange range;
range.location = _responseDataOffset;
range.length = MIN(maxLength, avail);
[_responseData getBytes:outBuffer+outBufferOffset range:range];
_responseDataOffset += range.length;
return (UInt32)range.length;
}
-(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error
{
if (!_requestData) {
_requestData = [NSMutableData dataWithCapacity:256];
}
[_requestData appendBytes:data+offset length:length];
return YES;
}
-(void) flushWithCompletion:(TAsyncCompletionBlock)completed failure:(TAsyncFailureBlock)failure
{
NSError *error;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_factory.url];
request.HTTPMethod = @"POST";
request.HTTPBody = _requestData;
_requestData = nil;
NSURLSessionDataTask *task = [_factory taskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// Check response type
if (!error && ![response isKindOfClass:NSHTTPURLResponse.class]) {
error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorUnknown
userInfo:@{TTransportErrorHttpErrorKey: @(THttpTransportErrorInvalidResponse)}];
}
// Check status code
NSHTTPURLResponse *httpResponse = (id)response;
if (!error && httpResponse.statusCode != 200) {
THttpTransportError code;
if (httpResponse.statusCode == 401) {
code = THttpTransportErrorAuthentication;
}
else {
code = THttpTransportErrorInvalidStatus;
}
error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorUnknown
userInfo:@{TTransportErrorHttpErrorKey: @(code),
@"statusCode":@(httpResponse.statusCode)}];
}
// Allow factory to check
if (!error) {
error = [_factory validateResponse:httpResponse data:data];
}
_responseDataOffset = 0;
if (error) {
_responseData = nil;
failure(error);
}
else {
if (data == nil) {
data = [NSData data];
}
_responseData = data;
completed(self);
}
} error:&error];
if (!task) {
failure(error);
return;
}
[task resume];
}
-(BOOL) flush:(NSError *__autoreleasing *)error
{
dispatch_semaphore_t completed = dispatch_semaphore_create(0);
__block BOOL result;
__block NSError *internalError;
[self flushWithCompletion:^(id < TAsyncTransport > transport) {
result = YES;
dispatch_semaphore_signal(completed);
} failure:^(NSError *error) {
internalError = error;
result = NO;
dispatch_semaphore_signal(completed);
}];
dispatch_semaphore_wait(completed, DISPATCH_TIME_FOREVER);
if (error) {
*error = internalError;
}
return result;
}
@end

View file

@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TTransport.h"
NS_ASSUME_NONNULL_BEGIN
@interface THTTPTransport : NSObject <TTransport>
-(id) initWithURL:(NSURL *)aURL;
-(id) initWithURL:(NSURL *)aURL
userAgent:(nullable NSString *)userAgent
timeout:(int)timeout;
-(void) setURL:(NSURL *)aURL;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,182 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "THTTPTransport.h"
#import "TTransportError.h"
@interface THTTPTransport ()
@property (strong, nonatomic) NSURL *url;
@property (strong, nonatomic) NSMutableURLRequest *request;
@property (strong, nonatomic) NSMutableData *requestData;
@property (strong, nonatomic) NSData *responseData;
@property (assign, nonatomic) NSUInteger responseDataOffset;
@property (strong, nonatomic) NSString *userAgent;
@property (assign, nonatomic) NSTimeInterval timeout;
@end
@implementation THTTPTransport
-(void) setupRequest
{
// set up our request object that we'll use for each request
_request = [[NSMutableURLRequest alloc] initWithURL:_url];
[_request setHTTPMethod:@"POST"];
[_request setValue:@"application/x-thrift" forHTTPHeaderField:@"Content-Type"];
[_request setValue:@"application/x-thrift" forHTTPHeaderField:@"Accept"];
NSString *userAgent = _userAgent;
if (!userAgent) {
userAgent = @"Thrift/Cocoa";
}
[_request setValue:userAgent forHTTPHeaderField:@"User-Agent"];
[_request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
if (_timeout) {
[_request setTimeoutInterval:_timeout];
}
}
-(id) initWithURL:(NSURL *)aURL
{
return [self initWithURL:aURL
userAgent:nil
timeout:0];
}
-(id) initWithURL:(NSURL *)aURL
userAgent:(NSString *)aUserAgent
timeout:(int)aTimeout
{
self = [super init];
if (!self) {
return nil;
}
_timeout = aTimeout;
_userAgent = aUserAgent;
_url = aURL;
[self setupRequest];
// create our request data buffer
_requestData = [[NSMutableData alloc] initWithCapacity:1024];
return self;
}
-(void) setURL:(NSURL *)aURL
{
_url = aURL;
[self setupRequest];
}
-(BOOL) readAll:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset length:(UInt32)length error:(NSError *__autoreleasing *)error
{
UInt32 got = [self readAvail:outBuffer offset:outBufferOffset maxLength:length error:error];
if (got != length) {
// Report underflow only if readAvail didn't report error already
if (error && !*error) {
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorEndOfFile
userInfo:nil];
}
return NO;
}
return YES;
}
-(UInt32) readAvail:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset maxLength:(UInt32)maxLength error:(NSError *__autoreleasing *)error
{
NSUInteger avail = _responseData.length - _responseDataOffset;
NSRange range;
range.location = _responseDataOffset;
range.length = MIN(maxLength, avail);
[_responseData getBytes:outBuffer+outBufferOffset range:range];
_responseDataOffset += range.length;
return (UInt32)range.length;
}
-(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error
{
[_requestData appendBytes:data+offset length:length];
return YES;
}
-(BOOL) flush:(NSError *__autoreleasing *)error
{
[_request setHTTPBody:_requestData];
_responseDataOffset = 0;
// make the HTTP request
NSURLResponse *response;
_responseData = [NSURLConnection sendSynchronousRequest:_request returningResponse:&response error:error];
if (!_responseData) {
return NO;
}
[_requestData setLength:0];
if (![response isKindOfClass:NSHTTPURLResponse.class]) {
if (error) {
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorUnknown
userInfo:@{TTransportErrorHttpErrorKey: @(THttpTransportErrorInvalidResponse)}];
}
return NO;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if ([httpResponse statusCode] != 200) {
if (error) {
THttpTransportError code;
if (httpResponse.statusCode == 401) {
code = THttpTransportErrorAuthentication;
}
else {
code = THttpTransportErrorInvalidStatus;
}
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorUnknown
userInfo:@{TTransportErrorHttpErrorKey: @(code),
@"statusCode":@(httpResponse.statusCode)}];
}
return NO;
}
return YES;
}
@end

View file

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TTransport.h"
NS_ASSUME_NONNULL_BEGIN
@interface TMemoryBuffer : NSObject <TTransport>
-(NSData *) buffer;
-(id) initWithData:(NSData *)data;
-(id) initWithDataNoCopy:(NSMutableData *)data;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,121 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TMemoryBuffer.h"
#import "TTransportError.h"
#define GARBAGE_BUFFER_SIZE 4096 // 4KiB
@interface TMemoryBuffer ()
@property(strong, nonatomic) NSMutableData *buffer;
@property(assign, nonatomic) UInt32 bufferOffset;
@end
@implementation TMemoryBuffer
-(id) init
{
if ((self = [super init])) {
_buffer = [NSMutableData new];
_bufferOffset = 0;
}
return self;
}
-(id) initWithData:(NSData *)data
{
if (self = [super init]) {
_buffer = [data mutableCopy];
_bufferOffset = 0;
}
return self;
}
-(id) initWithDataNoCopy:(NSMutableData *)data
{
if (self = [super init]) {
_buffer = data;
_bufferOffset = 0;
}
return self;
}
-(BOOL) readAll:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset length:(UInt32)length error:(NSError *__autoreleasing *)error
{
UInt32 got = [self readAvail:outBuffer offset:outBufferOffset maxLength:length error:error];
if (got != length) {
// Report underflow only if readAvail didn't report error already
if (error && !*error) {
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorEndOfFile
userInfo:nil];
}
return NO;
}
return YES;
}
-(UInt32) readAvail:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset maxLength:(UInt32)maxLength error:(NSError *__autoreleasing *)error
{
UInt32 avail = (UInt32)_buffer.length - _bufferOffset;
if (avail == 0) {
return 0;
}
NSRange range;
range.location = _bufferOffset;
range.length = MIN(maxLength, avail);
[_buffer getBytes:outBuffer + outBufferOffset range:range];
_bufferOffset += range.length;
if (_bufferOffset >= GARBAGE_BUFFER_SIZE) {
[_buffer replaceBytesInRange:NSMakeRange(0, _bufferOffset) withBytes:NULL length:0];
_bufferOffset = 0;
}
return (UInt32)range.length;
}
-(BOOL) write:(const UInt8 *)inBuffer offset:(UInt32)inBufferOffset length:(UInt32)length error:(NSError *__autoreleasing *)error
{
[_buffer appendBytes:inBuffer + inBufferOffset length:length];
return YES;
}
-(NSData *) buffer
{
return _buffer;
}
-(BOOL) flush:(NSError *__autoreleasing *)error
{
return YES;
}
@end

View file

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TTransport.h"
NS_ASSUME_NONNULL_BEGIN
@interface TNSFileHandleTransport : NSObject <TTransport>
-(id) initWithFileHandle:(NSFileHandle *)fileHandle;
-(id) initWithInputFileHandle:(NSFileHandle *)inputFileHandle
outputFileHandle:(NSFileHandle *)outputFileHandle;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,118 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TNSFileHandleTransport.h"
#import "TTransportError.h"
@interface TNSFileHandleTransport ()
@property(strong, nonatomic) NSFileHandle *inputFileHandle;
@property(strong, nonatomic) NSFileHandle *outputFileHandle;
@end
@implementation TNSFileHandleTransport
-(id) initWithFileHandle:(NSFileHandle *)fileHandle
{
return [self initWithInputFileHandle:fileHandle
outputFileHandle:fileHandle];
}
-(id) initWithInputFileHandle:(NSFileHandle *)aInputFileHandle
outputFileHandle:(NSFileHandle *)aOutputFileHandle
{
self = [super init];
if (self) {
_inputFileHandle = aInputFileHandle;
_outputFileHandle = aOutputFileHandle;
}
return self;
}
-(BOOL) readAll:(UInt8 *)buf offset:(UInt32)off length:(UInt32)len error:(NSError *__autoreleasing *)error
{
UInt32 got = 0;
while (got < len) {
NSData *d = [_inputFileHandle readDataOfLength:len-got];
if (d.length == 0) {
if (error) {
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorEndOfFile
userInfo:nil];
}
return NO;
}
[d getBytes:buf+got length:d.length];
got += d.length;
}
return YES;
}
-(UInt32) readAvail:(UInt8 *)buf offset:(UInt32)off maxLength:(UInt32)len error:(NSError *__autoreleasing *)error
{
UInt32 got = 0;
while (got < len) {
NSData *d = [_inputFileHandle readDataOfLength:len-got];
if (d.length == 0) {
break;
}
[d getBytes:buf+got length:d.length];
got += d.length;
}
return got;
}
-(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error
{
void *pos = (void *)data + offset;
@try {
[_outputFileHandle writeData:[NSData dataWithBytesNoCopy:pos length:length freeWhenDone:NO]];
}
@catch (NSException *e) {
if (error) {
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorNotOpen
userInfo:@{}];
}
return NO;
}
return YES;
}
-(BOOL) flush:(NSError *__autoreleasing *)error
{
return YES;
}
@end

View file

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TTransport.h"
NS_ASSUME_NONNULL_BEGIN
@interface TNSStreamTransport : NSObject <TTransport>
@property (strong, nonatomic) NSInputStream *input;
@property (strong, nonatomic) NSOutputStream *output;
-(id) initWithInputStream:(nullable NSInputStream *)input
outputStream:(nullable NSOutputStream *)output;
-(id) initWithInputStream:(NSInputStream *)input;
-(id) initWithOutputStream:(NSOutputStream *)output;
-(void) close;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,153 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TNSStreamTransport.h"
#import "TTransportError.h"
@interface TNSStreamTransport ()
@end
@implementation TNSStreamTransport
-(id) initWithInputStream:(NSInputStream *)input
outputStream:(NSOutputStream *)output
{
self = [super init];
if (self) {
_input = input;
_output = output;
}
return self;
}
-(id) initWithInputStream:(NSInputStream *)input
{
return [self initWithInputStream:input outputStream:nil];
}
-(id) initWithOutputStream:(NSOutputStream *)output
{
return [self initWithInputStream:nil outputStream:output];
}
-(void) dealloc
{
[self close];
}
-(BOOL) readAll:(UInt8 *)buf offset:(UInt32)off length:(UInt32)len error:(NSError *__autoreleasing *)error
{
UInt32 got = 0;
while (got < len) {
UInt32 read = (UInt32)[_input read:buf+off+got maxLength:len-got];
if (read <= 0) {
if (error) {
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorNotOpen
userInfo:@{}];
}
return NO;
}
got += read;
}
return YES;
}
-(UInt32) readAvail:(UInt8 *)buf offset:(UInt32)off maxLength:(UInt32)len error:(NSError *__autoreleasing *)error
{
UInt32 got = 0;
while (got < len) {
UInt32 read = (UInt32)[_input read:buf+off+got maxLength:len-got];
if (read <= 0) {
break;
}
got += read;
}
return got;
}
-(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error
{
int got = 0;
NSInteger total = 0;
while (got < length) {
total = [_output write:data+offset+got maxLength:length-got];
if (total == -1) {
if (error) {
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorNotOpen
userInfo:@{}];
}
return NO;
}
else if (total == 0) {
if (error) {
*error = [NSError errorWithDomain:TTransportErrorDomain
code:TTransportErrorEndOfFile
userInfo:@{}];
}
return NO;
}
got += total;
}
return YES;
}
-(BOOL) flush:(NSError *__autoreleasing *)error
{
return YES;
}
-(void) close
{
NSInputStream *input = self.input;
if (input) {
// Close and reset inputstream
CFReadStreamSetProperty((__bridge CFReadStreamRef)(input), kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
[input setDelegate:nil];
[input close];
[input removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
input = nil;
}
NSOutputStream *output = self.output;
if (output) {
// Close and reset outputstream
CFWriteStreamSetProperty((__bridge CFWriteStreamRef)(output), kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
[output setDelegate:nil];
[output close];
[output removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
output = nil;
}
}
@end

View file

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TNSStreamTransport.h"
NS_ASSUME_NONNULL_BEGIN
@interface TSSLSocketTransport : TNSStreamTransport <NSStreamDelegate>
-(id) initWithHostname:(NSString *)hostname
port:(int)port
error:(NSError **)error;
-(BOOL) isOpen;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,304 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
#import "TSSLSocketTransport.h"
#import "TSSLSocketTransportError.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#if !TARGET_OS_IPHONE
#import <CoreServices/CoreServices.h>
#else
#import <CFNetwork/CFNetwork.h>
#endif
@interface TSSLSocketTransport ()
@property(strong, nonatomic) NSString *sslHostname;
@property(assign, nonatomic) int sd;
@end
@implementation TSSLSocketTransport
-(id) initWithHostname:(NSString *)hostname
port:(int)port
error:(NSError **)error
{
_sslHostname = hostname;
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
/* create a socket structure */
struct sockaddr_in pin;
struct hostent *hp = NULL;
for (int i = 0; i < 10; i++) {
if ((hp = gethostbyname([hostname UTF8String])) == NULL) {
NSLog(@"failed to resolve hostname %@", hostname);
herror("resolv");
if (i == 9) {
if (error) {
*error = [NSError errorWithDomain:TSSLSocketTransportErrorDomain
code:TSSLSocketTransportErrorHostanameResolution
userInfo:nil];
}
return nil;
}
[NSThread sleepForTimeInterval:0.2];
}
else {
break;
}
}
memset(&pin, 0, sizeof(pin));
pin.sin_family = AF_INET;
memcpy(&pin.sin_addr, hp->h_addr, sizeof(struct in_addr));
pin.sin_port = htons(port);
/* create the socket */
if ((_sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
NSLog(@"failed to create socket for host %@:%d", hostname, port);
if (error) {
*error = [NSError errorWithDomain:TSSLSocketTransportErrorDomain
code:TSSLSocketTransportErrorSocketCreate
userInfo:nil];
}
return nil;
}
/* open a connection */
if (connect(_sd, (struct sockaddr *)&pin, sizeof(pin)) == -1) {
NSLog(@"failed to create conenct to host %@:%d", hostname, port);
if (error) {
*error = [NSError errorWithDomain:TSSLSocketTransportErrorDomain
code:TSSLSocketTransportErrorConnect
userInfo:nil];
}
return nil;
}
CFStreamCreatePairWithSocket(kCFAllocatorDefault, _sd, &readStream, &writeStream);
CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
NSInputStream *inputStream;
NSOutputStream *outputStream;
if (readStream && writeStream) {
CFReadStreamSetProperty(readStream,
kCFStreamPropertySocketSecurityLevel,
kCFStreamSocketSecurityLevelTLSv1);
NSDictionary *settings = @{(__bridge NSString *)kCFStreamSSLValidatesCertificateChain: @YES};
CFReadStreamSetProperty((CFReadStreamRef)readStream,
kCFStreamPropertySSLSettings,
(CFTypeRef)settings);
CFWriteStreamSetProperty((CFWriteStreamRef)writeStream,
kCFStreamPropertySSLSettings,
(CFTypeRef)settings);
inputStream = (__bridge NSInputStream *)readStream;
[inputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
outputStream = (__bridge NSOutputStream *)writeStream;
[outputStream setDelegate:self];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream open];
CFRelease(readStream);
CFRelease(writeStream);
}
self = [super initWithInputStream:inputStream outputStream:outputStream];
return self;
}
-(void) dealloc
{
[self close];
}
#pragma mark -
#pragma mark NSStreamDelegate
-(void) stream:(NSStream *)aStream
handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventNone:
break;
case NSStreamEventHasBytesAvailable:
break;
case NSStreamEventOpenCompleted:
break;
case NSStreamEventHasSpaceAvailable: {
BOOL proceed = NO;
SecTrustResultType trustResult = kSecTrustResultInvalid;
CFMutableArrayRef newPolicies = NULL;
do {
SecTrustRef trust = (__bridge SecTrustRef)[aStream propertyForKey:(NSString *)kCFStreamPropertySSLPeerTrust];
// Add new policy to current list of policies
SecPolicyRef policy = SecPolicyCreateSSL(NO, (__bridge CFStringRef)(_sslHostname));
if (!policy) {
break;
}
CFArrayRef policies;
if (SecTrustCopyPolicies(trust, &policies) != errSecSuccess) {
CFRelease(policy);
break;
}
newPolicies = CFArrayCreateMutableCopy(NULL, 0, policies);
CFArrayAppendValue(newPolicies, policy);
CFRelease(policies);
CFRelease(policy);
// Update trust policies
if (SecTrustSetPolicies(trust, newPolicies) != errSecSuccess) {
break;
}
// Evaluate the trust chain
if (SecTrustEvaluate(trust, &trustResult) != errSecSuccess) {
break;
}
switch (trustResult) {
case kSecTrustResultProceed:
// NSLog(@"Trusted by USER");
proceed = YES;
break;
case kSecTrustResultUnspecified:
// NSLog(@"Trusted by OS");
proceed = YES;
break;
case kSecTrustResultRecoverableTrustFailure:
proceed = recoverFromTrustFailure(trust, trustResult);
break;
case kSecTrustResultDeny:
// NSLog(@"Deny");
break;
case kSecTrustResultFatalTrustFailure:
// NSLog(@"FatalTrustFailure");
break;
case kSecTrustResultOtherError:
// NSLog(@"OtherError");
break;
case kSecTrustResultInvalid:
// NSLog(@"Invalid");
break;
default:
// NSLog(@"Default");
break;
}
}
while (NO);
if (!proceed) {
NSLog(@"TSSLSocketTransport: Cannot trust certificate. Result: %u", trustResult);
[aStream close];
}
if (newPolicies) {
CFRelease(newPolicies);
}
}
break;
case NSStreamEventErrorOccurred: {
NSLog(@"TSSLSocketTransport: Error occurred opening stream: %@", [aStream streamError]);
break;
}
case NSStreamEventEndEncountered:
break;
}
}
BOOL recoverFromTrustFailure(SecTrustRef myTrust, SecTrustResultType lastTrustResult)
{
CFAbsoluteTime trustTime = SecTrustGetVerifyTime(myTrust);
CFAbsoluteTime currentTime = CFAbsoluteTimeGetCurrent();
CFAbsoluteTime timeIncrement = 31536000;
CFAbsoluteTime newTime = currentTime - timeIncrement;
if (trustTime - newTime) {
CFDateRef newDate = CFDateCreate(NULL, newTime);
SecTrustSetVerifyDate(myTrust, newDate);
CFRelease(newDate);
if (SecTrustEvaluate(myTrust, &lastTrustResult) != errSecSuccess) {
return NO;
}
}
if (lastTrustResult == kSecTrustResultProceed || lastTrustResult == kSecTrustResultUnspecified) {
return YES;
}
NSLog(@"TSSLSocketTransport: Unable to recover certificate trust failure");
return YES;
}
-(BOOL) isOpen
{
if (_sd > 0) {
return TRUE;
}
else {
return FALSE;
}
}
@end

View file

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TTransportError.h"
extern NSString *TSSLSocketTransportErrorDomain;
typedef NS_ENUM (int, TSSLSocketTransportError) {
TSSLSocketTransportErrorHostanameResolution = -10000,
TSSLSocketTransportErrorSocketCreate = -10001,
TSSLSocketTransportErrorConnect = -10002,
};

View file

@ -0,0 +1,23 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TSSLSocketTransportError.h"
NSString *TSSLSocketTransportErrorDomain = @"TSSLSocketTransportErrorDomain";

View file

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
#import "TNSStreamTransport.h"
NS_ASSUME_NONNULL_BEGIN
@interface TSocketTransport : TNSStreamTransport
-(id) initWithHostname:(NSString *)hostname
port:(int)port;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,73 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TSocketTransport.h"
#if !TARGET_OS_IPHONE
#import <CoreServices/CoreServices.h>
#else
#import <CFNetwork/CFNetwork.h>
#endif
@interface TSocketTransport () <NSStreamDelegate>
@end
@implementation TSocketTransport
-(id) initWithHostname:(NSString *)hostname
port:(int)port
{
NSInputStream *inputStream = nil;
NSOutputStream *outputStream = nil;
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)hostname, port, &readStream, &writeStream);
if (readStream && writeStream) {
CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
inputStream = (__bridge NSInputStream *)readStream;
[inputStream setDelegate:self];
[inputStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSDefaultRunLoopMode];
[inputStream open];
outputStream = (__bridge NSOutputStream *)writeStream;
[outputStream setDelegate:self];
[outputStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSDefaultRunLoopMode];
[outputStream open];
}
else {
if (readStream) {
CFRelease(readStream);
}
if (writeStream) {
CFRelease(writeStream);
}
return nil;
}
return [super initWithInputStream:inputStream outputStream:outputStream];
}
@end

View file

@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@protocol TTransport <NSObject>
/**
* Guarantees that all of len bytes are read
*
* @param buf Buffer to read into
* @param off Index in buffer to start storing bytes at
* @param len Maximum number of bytes to read
* @return YES if succeeded, NO if failed
* @throws TTransportError if there was an error reading data
*/
-(BOOL) readAll:(UInt8 *)buf offset:(UInt32)off length:(UInt32)len error:(NSError *__autoreleasing *)error;
-(UInt32) readAvail:(UInt8 *)buf offset:(UInt32)off maxLength:(UInt32)maxLen error:(NSError *__autoreleasing *)error;
-(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error;
-(BOOL) flush:(NSError *__autoreleasing *)error;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TError.h"
extern NSString *TTransportErrorDomain;
typedef NS_ENUM (int, TTransportError) {
TTransportErrorUnknown = 0,
TTransportErrorNotOpen = 1,
TTransportErrorAlreadyOpen = 2,
TTransportErrorTimedOut = 3,
TTransportErrorEndOfFile = 4,
};
extern NSString *TTransportErrorExtendedErrorKey;
extern NSString *TTransportErrorHttpErrorKey;
typedef NS_ENUM(int, THttpTransportError) {
THttpTransportErrorInvalidResponse = 1001,
THttpTransportErrorInvalidStatus = 1002,
THttpTransportErrorAuthentication = 1003,
};

View file

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "TTransportError.h"
NSString *TTransportErrorDomain = @"TTransportErrorDomain";
NSString *TTransportErrorExtendedErrorKey = @"extendedError";
NSString *TTransportErrorHttpErrorKey = @"httpError";