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
cocoapods
To use Swamp through cocoapods, add
pod 'Swamp', '~> 0.2.0'
to your Podfile. (use '~> 0.1.0'
for Swift 2)
Swift Package Manager
To use Swamp through Swift Package Manager, create a Package.swift file:
import PackageDescription
let package = Package(
name: "SwampTestProject",
targets: [],
dependencies: [
.Package(url: "https://github.com/RadarBee/swamp.git", majorVersion: 0, minor: 2)
]
)
$ swift build
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 jointransport
- aSwampTransport
implementationauthmethods
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 supportwampcra
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:
- Install Docker for Mac (Easy Peasy)
- Open
Example/Swamp.xcworkspace
with XCode - Select
Swamp_Test-iOS
orSwamp_Test-OSX
- 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
- MessagePack & Raw Sockets
- Callee role
- More robust codebase and error handling
- More generic and comfortable API
- Advanced profile features
Contributions
- Yossi Abraham, yo.ab@outlook.com (Author)
- Dany Sousa, @danysousa (Swift 3 support
- Kevin Lanik, @MPKevin (Swift Package Manager support)
License
I don't care, MIT because it's pod lib create
default and I'm too lazy to tldrlegal.