Loading Kinetic.xcodeproj/project.pbxproj +4 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 3E07EA7F1B78E3B500DAB3F1 /* Kinetic.proto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E07EA7E1B78E3B500DAB3F1 /* Kinetic.proto.swift */; }; 3ED681EB1B7CEA0600AFDF79 /* Encoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ED681EA1B7CEA0600AFDF79 /* Encoding.swift */; }; 3EDAAB411B66D32D00F30808 /* Kinetic.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EDAAB401B66D32D00F30808 /* Kinetic.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3EDAAB481B66D32D00F30808 /* Kinetic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EDAAB3D1B66D32D00F30808 /* Kinetic.framework */; }; 3EDAAB4D1B66D32D00F30808 /* KineticTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDAAB4C1B66D32D00F30808 /* KineticTests.swift */; }; Loading Loading @@ -38,6 +39,7 @@ /* Begin PBXFileReference section */ 382D1C00FC0EC4F1BF676411 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3E07EA7E1B78E3B500DAB3F1 /* Kinetic.proto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Kinetic.proto.swift; sourceTree = "<group>"; }; 3ED681EA1B7CEA0600AFDF79 /* Encoding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Encoding.swift; sourceTree = "<group>"; }; 3EDAAB3D1B66D32D00F30808 /* Kinetic.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Kinetic.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3EDAAB401B66D32D00F30808 /* Kinetic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Kinetic.h; sourceTree = "<group>"; }; 3EDAAB421B66D32D00F30808 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; Loading Loading @@ -117,6 +119,7 @@ 3EFB7F1F1B7A6C3300988886 /* Errors.swift */, 3EFB7F1B1B7A55D100988886 /* Core.swift */, 3EFB7F2A1B7B963800988886 /* Channel.swift */, 3ED681EA1B7CEA0600AFDF79 /* Encoding.swift */, 3EFB7F2C1B7BAF8D00988886 /* NetworkChannel.swift */, 3EFB7F2E1B7BB4E700988886 /* Authentication.swift */, 3EDAAB571B66D47200F30808 /* Session.swift */, Loading Loading @@ -311,6 +314,7 @@ 3EFB7F2B1B7B963800988886 /* Channel.swift in Sources */, 3EFB7F201B7A6C3300988886 /* Errors.swift in Sources */, 3EFB7F1E1B7A6A9800988886 /* Put.swift in Sources */, 3ED681EB1B7CEA0600AFDF79 /* Encoding.swift in Sources */, 3EFB7F291B7AB06800988886 /* Delete.swift in Sources */, 3EFB7F2D1B7BAF8D00988886 /* NetworkChannel.swift in Sources */, 3EDAAB581B66D47200F30808 /* Session.swift in Sources */, Loading Kinetic/Encoding.swift 0 → 100644 +90 −0 Original line number Diff line number Diff line // Copyright (c) 2015 Seagate Technology // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // @author: Ignacio Corderi public struct KineticEncoding { public struct Header { public let bytes: Bytes public var isValid: Bool { return self.bytes[0] == 70 } public var protoLength: Int { return Int(bytesToUInt32(self.bytes, offset: 1)) } public var valueLength: Int { return Int(bytesToUInt32(self.bytes, offset: 5)) } public init(bytes: Bytes) { self.bytes = bytes } public init(protoLength: Int, valueLength: Int?) { var buffer = Bytes(count: 9, repeatedValue: 0) buffer[0] = 70 // Magic copyFromUInt32(&buffer, offset: 1, value: UInt32(protoLength)) if valueLength != nil { copyFromUInt32(&buffer, offset: 5, value: UInt32(valueLength!)) } self.bytes = buffer } } public let header: Header public private(set) var proto: Bytes? public private(set) var value: Bytes? public init(_ header: Header, _ proto: Bytes, _ value: Bytes?) { self.header = header self.proto = proto self.value = value } public static func encode(builder: Builder) throws -> KineticEncoding { let proto = try builder.message.build() let protoData = proto.data() let header = Header(protoLength: protoData.length, valueLength: builder.value?.count) return KineticEncoding(header, protoData.asBytes(), builder.value) } public func decode() throws -> RawResponse { if !self.header.isValid { throw KineticConnectionErrors.InvalidMagicNumber } // TODO: make nocopy let protoData = NSData(bytes: self.proto!, length: self.proto!.count) let msg = try Message.parseFromData(protoData) // TODO: verify HMAC let cmd = try Command.parseFromData(msg.commandBytes) return RawResponse(message: msg, command: cmd, value: self.value) } } public extension Builder { public func encode() throws -> KineticEncoding { return try KineticEncoding.encode(self) } } No newline at end of file Kinetic/NetworkChannel.swift +35 −65 Original line number Diff line number Diff line Loading @@ -22,71 +22,26 @@ public let connect = NetworkChannel.connect protocol StreamChannel { var inp: NSInputStream? { get set } var out: NSOutputStream? { get set } } extension StreamChannel { extension NSInputStream { func rawSend(proto: NSData, value: Bytes?) throws { // Prepare 9 bytes header // 1 byte - magic number | 4 bytes - proto length | 4 bytes - value length var headerBuffer = Bytes(count: 9, repeatedValue: 0) headerBuffer[0] = 70 // Magic copyFromUInt32(&headerBuffer, offset: 1, value: UInt32(proto.length)) if value != nil { copyFromUInt32(&headerBuffer, offset: 5, value: UInt32(value!.count)) func read(fully length: Int) -> Bytes { var buffer = Bytes(count:length, repeatedValue: 0) // TODO: loop until you read it all let _ = self.read(&buffer, maxLength: length) return buffer } // Send header, proto and value let outputStream = self.out! outputStream.write(headerBuffer, maxLength: headerBuffer.count) var array = Bytes(count: proto.length, repeatedValue: 0) // TODO: make sure this is a non-memcopy operation proto.getBytes(&array, length: proto.length) outputStream.write(array, maxLength: array.count) if value != nil { outputStream.write(value!, maxLength: value!.count) } } func rawReceive() throws -> (Message, Bytes) { let inputStream = self.inp! var headerBuffer = Bytes(count:9, repeatedValue: 0) extension NSOutputStream { // TODO: what are the semantics of read in swift? does it read all? let _ = inputStream.read(&headerBuffer, maxLength: headerBuffer.count) if headerBuffer[0] != 70 { throw KineticConnectionErrors.InvalidMagicNumber func write(bytes: Bytes) -> Int { return self.write(bytes, maxLength: bytes.count) } let protoLength = Int(bytesToUInt32(headerBuffer, offset: 1)) let valueLength = Int(bytesToUInt32(headerBuffer, offset: 5)) var protoBuffer = Array<UInt8>(count:protoLength, repeatedValue: 0) // TODO: what are the semantics of read in swift? does it read all? let _ = inputStream.read(&protoBuffer, maxLength: protoBuffer.count) let proto = NSData(bytes: &protoBuffer, length: protoLength) let msg = try Message.parseFromData(proto) // TODO: verify HMAC if valueLength > 0 { var value = Bytes(count:valueLength, repeatedValue: 0) // TODO: what are the semantics of read in swift? does it read all? let _ = inputStream.read(&value, maxLength: value.count) return (msg, value) } else { return (msg, []) } } } public class NetworkChannel: CustomStringConvertible, KineticChannel, StreamChannel { public class NetworkChannel: CustomStringConvertible, KineticChannel { public let host: String public let port: Int Loading Loading @@ -119,8 +74,8 @@ public class NetworkChannel: CustomStringConvertible, KineticChannel, StreamChan var device:KineticDevice? = nil do { let (msg, _) = try c.rawReceive() device = KineticDevice(handshake: try Command.parseFromData(msg.commandBytes)) let r = try c.receive() device = KineticDevice(handshake: r.command) } catch let err { c.error = err } Loading @@ -143,15 +98,30 @@ public class NetworkChannel: CustomStringConvertible, KineticChannel, StreamChan } public func send(builder: Builder) throws { let msgProto = try builder.message.build() try self.rawSend(msgProto.data(), value: builder.value) let outputStream = self.out! let encoded = try builder.encode() outputStream.write(encoded.header.bytes) outputStream.write(encoded.proto!) if encoded.value != nil { outputStream.write(encoded.value!) } } public func receive() throws -> RawResponse { let (msg, value) = try self.rawReceive() let cmd = try Command.parseFromData(msg.commandBytes) let inputStream = self.inp! let header = KineticEncoding.Header(bytes: inputStream.read(fully: 9)) let proto = inputStream.read(fully: header.protoLength) var value: Bytes? = nil if header.valueLength > 0 { value = inputStream.read(fully: header.valueLength) } let encoding = KineticEncoding(header, proto, value) return RawResponse(message: msg, command: cmd, value: value) return try encoding.decode() } } Loading Kinetic/Utils.swift +7 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,13 @@ public extension String { extension NSData { public func asBytes() -> Bytes { // TODO: figure out how to do this without copying! var buffer = Bytes(count: self.length, repeatedValue: 0) self.getBytes(&buffer, length: self.length) return buffer } public func toUtf8() -> String { return NSString(data: self, encoding:NSUTF8StringEncoding)!.description } Loading Loading
Kinetic.xcodeproj/project.pbxproj +4 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 3E07EA7F1B78E3B500DAB3F1 /* Kinetic.proto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E07EA7E1B78E3B500DAB3F1 /* Kinetic.proto.swift */; }; 3ED681EB1B7CEA0600AFDF79 /* Encoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ED681EA1B7CEA0600AFDF79 /* Encoding.swift */; }; 3EDAAB411B66D32D00F30808 /* Kinetic.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EDAAB401B66D32D00F30808 /* Kinetic.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3EDAAB481B66D32D00F30808 /* Kinetic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EDAAB3D1B66D32D00F30808 /* Kinetic.framework */; }; 3EDAAB4D1B66D32D00F30808 /* KineticTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDAAB4C1B66D32D00F30808 /* KineticTests.swift */; }; Loading Loading @@ -38,6 +39,7 @@ /* Begin PBXFileReference section */ 382D1C00FC0EC4F1BF676411 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3E07EA7E1B78E3B500DAB3F1 /* Kinetic.proto.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Kinetic.proto.swift; sourceTree = "<group>"; }; 3ED681EA1B7CEA0600AFDF79 /* Encoding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Encoding.swift; sourceTree = "<group>"; }; 3EDAAB3D1B66D32D00F30808 /* Kinetic.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Kinetic.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3EDAAB401B66D32D00F30808 /* Kinetic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Kinetic.h; sourceTree = "<group>"; }; 3EDAAB421B66D32D00F30808 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; Loading Loading @@ -117,6 +119,7 @@ 3EFB7F1F1B7A6C3300988886 /* Errors.swift */, 3EFB7F1B1B7A55D100988886 /* Core.swift */, 3EFB7F2A1B7B963800988886 /* Channel.swift */, 3ED681EA1B7CEA0600AFDF79 /* Encoding.swift */, 3EFB7F2C1B7BAF8D00988886 /* NetworkChannel.swift */, 3EFB7F2E1B7BB4E700988886 /* Authentication.swift */, 3EDAAB571B66D47200F30808 /* Session.swift */, Loading Loading @@ -311,6 +314,7 @@ 3EFB7F2B1B7B963800988886 /* Channel.swift in Sources */, 3EFB7F201B7A6C3300988886 /* Errors.swift in Sources */, 3EFB7F1E1B7A6A9800988886 /* Put.swift in Sources */, 3ED681EB1B7CEA0600AFDF79 /* Encoding.swift in Sources */, 3EFB7F291B7AB06800988886 /* Delete.swift in Sources */, 3EFB7F2D1B7BAF8D00988886 /* NetworkChannel.swift in Sources */, 3EDAAB581B66D47200F30808 /* Session.swift in Sources */, Loading
Kinetic/Encoding.swift 0 → 100644 +90 −0 Original line number Diff line number Diff line // Copyright (c) 2015 Seagate Technology // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // @author: Ignacio Corderi public struct KineticEncoding { public struct Header { public let bytes: Bytes public var isValid: Bool { return self.bytes[0] == 70 } public var protoLength: Int { return Int(bytesToUInt32(self.bytes, offset: 1)) } public var valueLength: Int { return Int(bytesToUInt32(self.bytes, offset: 5)) } public init(bytes: Bytes) { self.bytes = bytes } public init(protoLength: Int, valueLength: Int?) { var buffer = Bytes(count: 9, repeatedValue: 0) buffer[0] = 70 // Magic copyFromUInt32(&buffer, offset: 1, value: UInt32(protoLength)) if valueLength != nil { copyFromUInt32(&buffer, offset: 5, value: UInt32(valueLength!)) } self.bytes = buffer } } public let header: Header public private(set) var proto: Bytes? public private(set) var value: Bytes? public init(_ header: Header, _ proto: Bytes, _ value: Bytes?) { self.header = header self.proto = proto self.value = value } public static func encode(builder: Builder) throws -> KineticEncoding { let proto = try builder.message.build() let protoData = proto.data() let header = Header(protoLength: protoData.length, valueLength: builder.value?.count) return KineticEncoding(header, protoData.asBytes(), builder.value) } public func decode() throws -> RawResponse { if !self.header.isValid { throw KineticConnectionErrors.InvalidMagicNumber } // TODO: make nocopy let protoData = NSData(bytes: self.proto!, length: self.proto!.count) let msg = try Message.parseFromData(protoData) // TODO: verify HMAC let cmd = try Command.parseFromData(msg.commandBytes) return RawResponse(message: msg, command: cmd, value: self.value) } } public extension Builder { public func encode() throws -> KineticEncoding { return try KineticEncoding.encode(self) } } No newline at end of file
Kinetic/NetworkChannel.swift +35 −65 Original line number Diff line number Diff line Loading @@ -22,71 +22,26 @@ public let connect = NetworkChannel.connect protocol StreamChannel { var inp: NSInputStream? { get set } var out: NSOutputStream? { get set } } extension StreamChannel { extension NSInputStream { func rawSend(proto: NSData, value: Bytes?) throws { // Prepare 9 bytes header // 1 byte - magic number | 4 bytes - proto length | 4 bytes - value length var headerBuffer = Bytes(count: 9, repeatedValue: 0) headerBuffer[0] = 70 // Magic copyFromUInt32(&headerBuffer, offset: 1, value: UInt32(proto.length)) if value != nil { copyFromUInt32(&headerBuffer, offset: 5, value: UInt32(value!.count)) func read(fully length: Int) -> Bytes { var buffer = Bytes(count:length, repeatedValue: 0) // TODO: loop until you read it all let _ = self.read(&buffer, maxLength: length) return buffer } // Send header, proto and value let outputStream = self.out! outputStream.write(headerBuffer, maxLength: headerBuffer.count) var array = Bytes(count: proto.length, repeatedValue: 0) // TODO: make sure this is a non-memcopy operation proto.getBytes(&array, length: proto.length) outputStream.write(array, maxLength: array.count) if value != nil { outputStream.write(value!, maxLength: value!.count) } } func rawReceive() throws -> (Message, Bytes) { let inputStream = self.inp! var headerBuffer = Bytes(count:9, repeatedValue: 0) extension NSOutputStream { // TODO: what are the semantics of read in swift? does it read all? let _ = inputStream.read(&headerBuffer, maxLength: headerBuffer.count) if headerBuffer[0] != 70 { throw KineticConnectionErrors.InvalidMagicNumber func write(bytes: Bytes) -> Int { return self.write(bytes, maxLength: bytes.count) } let protoLength = Int(bytesToUInt32(headerBuffer, offset: 1)) let valueLength = Int(bytesToUInt32(headerBuffer, offset: 5)) var protoBuffer = Array<UInt8>(count:protoLength, repeatedValue: 0) // TODO: what are the semantics of read in swift? does it read all? let _ = inputStream.read(&protoBuffer, maxLength: protoBuffer.count) let proto = NSData(bytes: &protoBuffer, length: protoLength) let msg = try Message.parseFromData(proto) // TODO: verify HMAC if valueLength > 0 { var value = Bytes(count:valueLength, repeatedValue: 0) // TODO: what are the semantics of read in swift? does it read all? let _ = inputStream.read(&value, maxLength: value.count) return (msg, value) } else { return (msg, []) } } } public class NetworkChannel: CustomStringConvertible, KineticChannel, StreamChannel { public class NetworkChannel: CustomStringConvertible, KineticChannel { public let host: String public let port: Int Loading Loading @@ -119,8 +74,8 @@ public class NetworkChannel: CustomStringConvertible, KineticChannel, StreamChan var device:KineticDevice? = nil do { let (msg, _) = try c.rawReceive() device = KineticDevice(handshake: try Command.parseFromData(msg.commandBytes)) let r = try c.receive() device = KineticDevice(handshake: r.command) } catch let err { c.error = err } Loading @@ -143,15 +98,30 @@ public class NetworkChannel: CustomStringConvertible, KineticChannel, StreamChan } public func send(builder: Builder) throws { let msgProto = try builder.message.build() try self.rawSend(msgProto.data(), value: builder.value) let outputStream = self.out! let encoded = try builder.encode() outputStream.write(encoded.header.bytes) outputStream.write(encoded.proto!) if encoded.value != nil { outputStream.write(encoded.value!) } } public func receive() throws -> RawResponse { let (msg, value) = try self.rawReceive() let cmd = try Command.parseFromData(msg.commandBytes) let inputStream = self.inp! let header = KineticEncoding.Header(bytes: inputStream.read(fully: 9)) let proto = inputStream.read(fully: header.protoLength) var value: Bytes? = nil if header.valueLength > 0 { value = inputStream.read(fully: header.valueLength) } let encoding = KineticEncoding(header, proto, value) return RawResponse(message: msg, command: cmd, value: value) return try encoding.decode() } } Loading
Kinetic/Utils.swift +7 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,13 @@ public extension String { extension NSData { public func asBytes() -> Bytes { // TODO: figure out how to do this without copying! var buffer = Bytes(count: self.length, repeatedValue: 0) self.getBytes(&buffer, length: self.length) return buffer } public func toUtf8() -> String { return NSString(data: self, encoding:NSUTF8StringEncoding)!.description } Loading