Latest 0.2.0
Homepage https://github.com/iscriptology/Swamp
License MIT
Platforms ios 8.0, osx 10.10
Dependencies SwiftyJSON, Starscream, CryptoSwift
Authors

Version
License
Platform

Swamp – Swift WAMP implementation

Swamp is a WAMP implementation in Swift.

It currently supports calling remote procedures, subscribing on topics, and publishing events. It also supports authentication using ticket & wampcra authentication.

Swamp utilizes WebSockets as its only available transport, and JSON as its serialization method.

Contributions to support MessagePack & Raw Sockets will be merged gladly!

Swift Versions

Swift Version Swamp Version Requirements
2.x 0.1.x OSX 10.9 or iOS 8.0
3 0.2.0 and above OSX 10.10 or iOS 8.0

Installation

Swamp is available through cocoapods. Add

pod 'Swamp', '~> 0.2.0'

to your Podfile. (use '~> 0.1.0' for Swift 2)

Usage

Connect to router

import Swamp

let swampTransport = WebSocketSwampTransport(wsEndpoint:  NSURL(string: "ws://my-router.com:8080/ws")!)
let swampSession = SwampSession(realm: "router-defined-realm", transport: swampTransport)
// Set delegate for callbacks
// swampSession.delegate = <SwampSessionDelegate implementation>
swampSession.connect()
swampSession.disconnect()
SwampSession constructor parameters
  • realm – which realm to join
  • transport – a SwampTransport implementation
  • authmethods authid authrole authextra – See your router’s documentation and use accordingly
Connection/Disconnection
  • connect() – Establish transport and perform authentication if configured.
  • disconnect() – Opposite.

Now you should wait for your delegate’s callbacks:

SwampSessionDelegate interface

Implement the following methods:

  • func swampSessionHandleChallenge(authMethod: String, extra: [String: AnyObject]) -> String
    • Fired when a challenge request arrives.
    • You can return SwampCraAuthHelper.sign("your-secret", extra["challenge"] as! String) to support wampcra auth method.
  • func swampSessionConnected(session: SwampSession, sessionId: Int)
    • Fired once the session has established and authenticated a session, and has joined the realm successfully. (AKA You may now call, subscribe & publish.)
  • func swampSessionEnded(reason: String)
    • Fired once the connection has ended.
    • reason is usually a WAMP-domain error, but it can also be a textual description of WTF just happened

Let’s get the shit started!

  • General note: Lots of callback functions receive args-kwargs pairs, check your other client implementaion to see which of them is utilized, and act accordingly.
Calling remote procedures

Calling may fire two callbacks:

  • onSuccess – if calling has completed without errors.
  • onError – If the call has failed. (Either in router or in peer client.)
Signature
public func call(proc: String, options: [String: AnyObject]=[:], args: [AnyObject]?=nil, kwargs: [String: AnyObject]?=nil, onSuccess: CallCallback, onError: ErrorCallCallback)
Simple use case:
session.call("wamp.procedure", args: [1, "argument1"],
    onSuccess: { details, results, kwResults in
        // Usually result is in results[0], but do a manual check in your infrastructure
    },
    onError: { details, error, args, kwargs in
        // Handle your error here (You can ignore args kwargs in most cases)
    })
Full use case:
session.call("wamp.procedure", options: ["disclose_me": true], args: [1, "argument1"], kwargs: ["arg1": 1, "arg2": "argument2"], 
    onSuccess: { details, results, kwResults in
        // Usually result is in results[0], but do a manual check in your infrastructure
    },
    onError: { details, error, args, kwargs in
        // Handle your error here (You can ignore args kwargs in most cases)
    })
Subscribing on topics

Subscribing may fire three callbacks:

  • onSuccess – if subscription has succeeded.
  • onError – if it has not.
  • onEvent – if it succeeded, this is fired when the actual event was published.
Signature
public func subscribe(topic: String, options: [String: AnyObject]=[:], onSuccess: SubscribeCallback, onError: ErrorSubscribeCallback, onEvent: EventCallback)
Simple use case:
session.subscribe("wamp.topic", onSuccess: { subscription in 
    // subscription can be stored for subscription.cancel()
    }, onError: { details, error in

    }, onEvent: { details, results, kwResults in
        // Event data is usually in results, but manually check blabla yadayada
    })
Full use case:
session.subscribe("wamp.topic", options: ["disclose_me": true], 
    onSuccess: { subscription in 
        // subscription can be stored for subscription.cancel()
    }, onError: { details, error in
        // handle error                        
    }, onEvent: { details, results, kwResults in
        // Event data is usually in results, but manually check blabla yadayada
    })
Publishing events

Publishing may either be called without callbacks (AKA unacknowledged) or with the following two callbacks:

  • onSuccess – if publishing has succeeded.
  • onError – if it has not.
Signature
// without acknowledging
public func publish(topic: String, options: [String: AnyObject]=[:], args: [AnyObject]?=nil, kwargs: [String: AnyObject]?=nil)
// with acknowledging
public func publish(topic: String, options: [String: AnyObject]=[:], args: [AnyObject]?=nil, kwargs: [String: AnyObject]?=nil, onSuccess: PublishCallback, onError: ErrorPublishCallback) {
Simple use case:
session.publish("wamp.topic", args: [1, "argument2"])
Full use case:
session.publish("wamp.topic", options: ["disclose_me": true],  args: [1, "argument2"], kwargs: ["arg1": 1, "arg2": "argument2"],
    onSuccess: {
        // Publication has been published!
    }, onError: { details, error in
        // Handle error (What can it be except wamp.error.not_authorized?)
    })

Testing

For now, only integration tests against crossbar exist. I plan to add unit tests in the future.

In order to run the tests:

  1. Install Docker for Mac (Easy Peasy)
  2. Open Example/Swamp.xcworkspace with XCode
  3. Select Swamp_Test-iOS or Swamp_Test-OSX
  4. Run the tests! (Product -> Test or ⌘U)

Troubleshooting

If for some reason the tests fail, make sure:

  • You have docker installed and available at /usr/local/bin/docker
  • You have an available port 8080 on your machine

You can also inspect Example/swamp-crossbar-instance.log to find out what happened with the crossbar instance while the tests were executing.

Roadmap

  1. MessagePack & Raw Sockets
  2. Callee role
  3. More robust codebase and error handling
  4. More generic and comfortable API
  5. Advanced profile features

Contributions

License

I don’t care, MIT because it’s pod lib create default and I’m too lazy to tldrlegal.

Latest podspec

{
    "name": "Swamp",
    "version": "0.2.0",
    "summary": "WAMP protocol implementation in swift",
    "description": "the WAMP WebSocket subprotocol implemented purely in Swift using Starscream, SwiftyJSON",
    "homepage": "https://github.com/iscriptology/Swamp",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    },
    "authors": {
        "Yossi Abraham": "[email protected]"
    },
    "source": {
        "git": "https://github.com/iscriptology/Swamp.git",
        "tag": "0.2.0"
    },
    "platforms": {
        "ios": "8.0",
        "osx": "10.10"
    },
    "source_files": "Swamp/**/*",
    "dependencies": {
        "SwiftyJSON": [
            "~>3.1.0"
        ],
        "Starscream": [
            "~>2.0.0"
        ],
        "CryptoSwift": [
            "~>0.6.0"
        ]
    }
}

Pin It on Pinterest

Share This