Commit 601eef7f authored by Ignacio Corderi's avatar Ignacio Corderi
Browse files

First step of client refactoring

parent e462ca7f
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@
		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 */; };
		3EDAAB581B66D47200F30808 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDAAB571B66D47200F30808 /* Client.swift */; };
		3EDAAB581B66D47200F30808 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDAAB571B66D47200F30808 /* Session.swift */; };
		3EFB7F1C1B7A55D100988886 /* Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB7F1B1B7A55D100988886 /* Core.swift */; };
		3EFB7F1E1B7A6A9800988886 /* Put.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB7F1D1B7A6A9800988886 /* Put.swift */; };
		3EFB7F201B7A6C3300988886 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB7F1F1B7A6C3300988886 /* Errors.swift */; };
@@ -19,6 +19,9 @@
		3EFB7F251B7A977500988886 /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB7F241B7A977500988886 /* Common.swift */; };
		3EFB7F271B7AA45A00988886 /* Get.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB7F261B7AA45A00988886 /* Get.swift */; };
		3EFB7F291B7AB06800988886 /* Delete.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB7F281B7AB06800988886 /* Delete.swift */; };
		3EFB7F2B1B7B963800988886 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB7F2A1B7B963800988886 /* Channel.swift */; };
		3EFB7F2D1B7BAF8D00988886 /* NetworkChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB7F2C1B7BAF8D00988886 /* NetworkChannel.swift */; };
		3EFB7F2F1B7BB4E700988886 /* Authentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB7F2E1B7BB4E700988886 /* Authentication.swift */; };
		921636AE408C3549DE7A1141 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 382D1C00FC0EC4F1BF676411 /* Pods.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
/* End PBXBuildFile section */

@@ -41,7 +44,7 @@
		3EDAAB471B66D32D00F30808 /* KineticTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KineticTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
		3EDAAB4C1B66D32D00F30808 /* KineticTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KineticTests.swift; sourceTree = "<group>"; };
		3EDAAB4E1B66D32D00F30808 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		3EDAAB571B66D47200F30808 /* Client.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = "<group>"; };
		3EDAAB571B66D47200F30808 /* Session.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Session.swift; sourceTree = "<group>"; };
		3EFB7F121B78EE0900988886 /* KineticPlayground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; name = KineticPlayground.playground; path = "../../../../Library/Autosave Information/KineticPlayground.playground"; sourceTree = "<group>"; };
		3EFB7F1B1B7A55D100988886 /* Core.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Core.swift; sourceTree = "<group>"; };
		3EFB7F1D1B7A6A9800988886 /* Put.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Put.swift; sourceTree = "<group>"; };
@@ -50,6 +53,9 @@
		3EFB7F241B7A977500988886 /* Common.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Common.swift; sourceTree = "<group>"; };
		3EFB7F261B7AA45A00988886 /* Get.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Get.swift; sourceTree = "<group>"; };
		3EFB7F281B7AB06800988886 /* Delete.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Delete.swift; sourceTree = "<group>"; };
		3EFB7F2A1B7B963800988886 /* Channel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Channel.swift; sourceTree = "<group>"; };
		3EFB7F2C1B7BAF8D00988886 /* NetworkChannel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkChannel.swift; sourceTree = "<group>"; };
		3EFB7F2E1B7BB4E700988886 /* Authentication.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Authentication.swift; sourceTree = "<group>"; };
		80777030020DBD5A301CA196 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
		FB4A7FCA365ECAF75E20A4A9 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -110,7 +116,10 @@
				3EFB7F211B7A7A7F00988886 /* Utils.swift */,
				3EFB7F1F1B7A6C3300988886 /* Errors.swift */,
				3EFB7F1B1B7A55D100988886 /* Core.swift */,
				3EDAAB571B66D47200F30808 /* Client.swift */,
				3EFB7F2A1B7B963800988886 /* Channel.swift */,
				3EFB7F2C1B7BAF8D00988886 /* NetworkChannel.swift */,
				3EFB7F2E1B7BB4E700988886 /* Authentication.swift */,
				3EDAAB571B66D47200F30808 /* Session.swift */,
				3EFB7F231B7A951000988886 /* Commands */,
				3EDAAB401B66D32D00F30808 /* Kinetic.h */,
				3EDAAB421B66D32D00F30808 /* Info.plist */,
@@ -291,14 +300,17 @@
			buildActionMask = 2147483647;
			files = (
				3EFB7F1C1B7A55D100988886 /* Core.swift in Sources */,
				3EFB7F2B1B7B963800988886 /* Channel.swift in Sources */,
				3EFB7F201B7A6C3300988886 /* Errors.swift in Sources */,
				3EFB7F1E1B7A6A9800988886 /* Put.swift in Sources */,
				3EFB7F291B7AB06800988886 /* Delete.swift in Sources */,
				3EDAAB581B66D47200F30808 /* Client.swift in Sources */,
				3EFB7F2D1B7BAF8D00988886 /* NetworkChannel.swift in Sources */,
				3EDAAB581B66D47200F30808 /* Session.swift in Sources */,
				3EFB7F271B7AA45A00988886 /* Get.swift in Sources */,
				3E07EA7F1B78E3B500DAB3F1 /* Kinetic.proto.swift in Sources */,
				3EFB7F221B7A7A8000988886 /* Utils.swift in Sources */,
				3EFB7F251B7A977500988886 /* Common.swift in Sources */,
				3EFB7F2F1B7BB4E700988886 /* Authentication.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
+45 −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 protocol AuthenticationCredential {
    
    func authenticate(builder: Builder)
    
}

public struct HmacCredential: AuthenticationCredential  {
    public let identity: Int64
    public let key: String

    public static func defaultCredentials() -> HmacCredential {
        return HmacCredential(identity: 1, key: "asdfasdf")
    }
    
    public func authenticate(builder: Builder) {
        let m = builder.message
        m.authType = .Hmacauth
        
        let a = m.getHmacAuthBuilder()
        a.identity = self.identity
        a.hmac = m.commandBytes.hmacSha1(self.key)
    }
}
 No newline at end of file
+17 −100
Original line number Diff line number Diff line
@@ -20,69 +20,23 @@

// @author: Ignacio Corderi

import Foundation
import CryptoSwift

public func connect(host:String, port:Int) throws -> Client {
    let c = Client(host: host, port: port)
    try c.connect()
    return c
}

public class Client : CustomStringConvertible, SynchornousChannel {
    
    public let host: String
    public let port: Int
    
    public let identity: Int64 = 1
    public let key = "asdfasdf"
    
    var inp: NSInputStream?
    var out: NSOutputStream?
    
    var handshake: Command?
    
    // Session information
    var sequenceId: Int64 = 0
    
    public var connectionId: Int64 {
        return handshake!.header.connectionId
    }
    
    var clusterVersion: Int64 {
        return handshake!.header.clusterVersion
    }
    
    // Device information
    public var wwn: String {
        let config = handshake!.body.getLog.configuration
        return NSString(data: config.worldWideName, encoding:NSUTF8StringEncoding)!.description
    }
    
    // CustomStringConvertible (a.k.a toString)
    public var description: String {
        get {
            return "Connected to \(wwn)"
        }
public protocol KineticChannel {
    var error: ErrorType? { get }
    var connected: Bool { get }
    func connect() -> KineticSession
    func send(builder: Builder) throws
    func receive() throws -> RawResponse
    func close()
}

    init(host:String, port:Int) {
        self.host = host
        self.port = port
protocol StreamChannel {
    var inp: NSInputStream? { get set }
    var out: NSOutputStream? { get set }
}

    func connect() throws {
        NSStream.getStreamsToHostWithName(self.host, port: self.port, inputStream: &self.inp, outputStream: &self.out)
        
        self.inp!.open()
        self.out!.open()
        
        let (msg, _) = try self.rawReceive()
        
        self.handshake = try Command.parseFromData(msg.commandBytes)
    }
extension StreamChannel {        
    
    private func rawSend(proto: NSData, value: Bytes?) throws {
    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)
@@ -104,7 +58,7 @@ public class Client : CustomStringConvertible, SynchornousChannel {
        }
    }
    
    private func rawReceive() throws -> (Message, Bytes) {
    func rawReceive() throws -> (Message, Bytes) {
        let inputStream = self.inp!
        
        var headerBuffer = Bytes(count:9, repeatedValue: 0)
@@ -137,42 +91,5 @@ public class Client : CustomStringConvertible, SynchornousChannel {
            return (msg, [])
        }
    }
    
    public func send<C: ChannelCommand>(cmd: C) throws -> C.ResponseType {
        // Prepare command contents
        let builder = cmd.build(Builder())
        
        // Prepare header
        let h = builder.header
        h.clusterVersion = self.clusterVersion
        h.connectionId = self.clusterVersion
        h.sequence = self.clusterVersion
        
        let m = builder.message
        
        // Build command proto
        let cmdProto = try builder.command.build()
        print(cmdProto) // TODO: Remove this line
        m.commandBytes = cmdProto.data()
        
        // Prepare authentication
        let a = m.getHmacAuthBuilder()
        a.identity = self.identity
        a.hmac = m.commandBytes.hmacSha1(self.key)
        m.authType = .Hmacauth
        
        // Build message proto
        let msgProto = try m.build()
        
        // Send & Receive
        try self.rawSend(msgProto.data(), value: builder.value)
        let (respMsg, respValue) = try self.rawReceive()
        
        // Unwrap command
        let respCmd = try Command.parseFromData(respMsg.commandBytes)
        
        let r = RawResponse(message: respMsg, command: respCmd, value: respValue)
        return C.ResponseType.parse(r)
}
}
 No newline at end of file
+2 −7
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@
typealias Message = Com.Seagate.Kinetic.Proto.Message_
typealias Command = Com.Seagate.Kinetic.Proto.Command


public class Builder {
    var message: Message.Builder
    var command: Command.Builder
@@ -66,8 +65,8 @@ public protocol ChannelCommand {
}

public extension ChannelCommand {
    func sendTo(channel: SynchornousChannel) throws -> Self.ResponseType {
        return try channel.send(self)
    func sendTo(session: KineticSession) throws -> Self.ResponseType {
        return try session.send(self)
    }
}

@@ -91,7 +90,3 @@ public extension ChannelResponse {
        }
    }
}

public protocol SynchornousChannel {
    func send<C: ChannelCommand>(cmd: C) throws -> C.ResponseType
}
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ extension DeleteCommand: CustomStringConvertible {
    }
}

public extension SynchornousChannel {
public extension KineticSession {
    func delete(key: String) throws -> DeleteCommand.ResponseType {
        let cmd = DeleteCommand(key: key)
        return try cmd.sendTo(self)
Loading