From f193b0358d1c5aab7d35b6f7b7612e6c2de7cb8c Mon Sep 17 00:00:00 2001 From: Paulo Faria Date: Mon, 26 Oct 2015 01:25:04 -0200 Subject: [PATCH] init --- .gitignore | 27 + .travis.yml | 26 + Dependencies/ZeroMQ/module.map | 4 + Dependencies/ZeroMQ/zmq_swift.h | 30 + LICENSE | 21 + README.md | 107 +++ SwiftZMQ.h | 24 + SwiftZMQ.xcodeproj/project.pbxproj | 470 ++++++++++ .../contents.xcworkspacedata | 7 + SwiftZMQ/CURVE.swift | 36 + SwiftZMQ/Context.swift | 179 ++++ SwiftZMQ/Error.swift | 34 + SwiftZMQ/Info.plist | 28 + SwiftZMQ/Message.swift | 129 +++ SwiftZMQ/Poller.swift | 76 ++ SwiftZMQ/Proxy.swift | 29 + SwiftZMQ/Socket.swift | 851 ++++++++++++++++++ SwiftZMQTests/Info.plist | 24 + SwiftZMQTests/ZMQTests.swift | 52 ++ 19 files changed, 2154 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 Dependencies/ZeroMQ/module.map create mode 100644 Dependencies/ZeroMQ/zmq_swift.h create mode 100644 LICENSE create mode 100644 README.md create mode 100644 SwiftZMQ.h create mode 100644 SwiftZMQ.xcodeproj/project.pbxproj create mode 100644 SwiftZMQ.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 SwiftZMQ/CURVE.swift create mode 100644 SwiftZMQ/Context.swift create mode 100644 SwiftZMQ/Error.swift create mode 100644 SwiftZMQ/Info.plist create mode 100644 SwiftZMQ/Message.swift create mode 100644 SwiftZMQ/Poller.swift create mode 100644 SwiftZMQ/Proxy.swift create mode 100644 SwiftZMQ/Socket.swift create mode 100644 SwiftZMQTests/Info.plist create mode 100644 SwiftZMQTests/ZMQTests.swift diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5e98e4f --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Created by https://www.gitignore.io/api/xcode + +### Xcode ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData +Carthage/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..caa4fb9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,26 @@ +language: objective-c +osx_image: xcode7 +env: + global: + - LC_CTYPE=en_US.UTF-8 + - LANG=en_US.UTF-8 + matrix: +# - DESTINATION="OS=8.1,name=iPhone 4S" SCHEME="SwiftZMQ iOS" SDK=iphonesimulator9.0 +# - DESTINATION="OS=8.2,name=iPhone 5" SCHEME="SwiftZMQ iOS" SDK=iphonesimulator9.0 + - DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="SwiftZMQ iOS" SDK=iphonesimulator9.0 + - DESTINATION="OS=8.4,name=iPhone 6" SCHEME="SwiftZMQ iOS" SDK=iphonesimulator9.0 + - DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="SwiftZMQ iOS" SDK=iphonesimulator9.0 + - DESTINATION="arch=x86_64" SCHEME="SwiftZMQ OSX" SDK=macosx10.11 +before_install: + - gem install xcpretty --no-rdoc --no-ri --no-document --quiet +script: + - set -o pipefail + - xcodebuild -version + - xcodebuild -project SwiftZMQ.xcodeproj -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" + -configuration Debug ONLY_ACTIVE_ARCH=NO GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES + GCC_GENERATE_TEST_COVERAGE_FILES=YES test | xcpretty -c + - xcodebuild -project SwiftZMQ.xcodeproj -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" + -configuration Release ONLY_ACTIVE_ARCH=NO GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES + GCC_GENERATE_TEST_COVERAGE_FILES=YES test | xcpretty -c +after_success: + - bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/Dependencies/ZeroMQ/module.map b/Dependencies/ZeroMQ/module.map new file mode 100644 index 0000000..a135ff6 --- /dev/null +++ b/Dependencies/ZeroMQ/module.map @@ -0,0 +1,4 @@ +module ZeroMQ [system] { + header "zmq_swift.h" + export * +} \ No newline at end of file diff --git a/Dependencies/ZeroMQ/zmq_swift.h b/Dependencies/ZeroMQ/zmq_swift.h new file mode 100644 index 0000000..0b433c7 --- /dev/null +++ b/Dependencies/ZeroMQ/zmq_swift.h @@ -0,0 +1,30 @@ +// zmq_swift.swift +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Zewo +// +// 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. + +#ifndef zmw_swift_h +#define zmw_swift_h + +#import + +#endif /* zmw_swift_h */ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0befe39 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Zewo + +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. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..6f1dd05 --- /dev/null +++ b/README.md @@ -0,0 +1,107 @@ +SwiftZMQ +======== + +[![Swift 2.0](https://img.shields.io/badge/Swift-2.0-orange.svg?style=flat)](https://developer.apple.com/swift/) +[![Platforms OS X](https://img.shields.io/badge/Platforms-OS%20X%20%7C%20iOS-lightgray.svg?style=flat)](https://developer.apple.com/swift/) +[![Carthage Compatible](https://img.shields.io/badge/Carthage-Compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![License MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Travis](https://img.shields.io/badge/Build-Passing-4BC51D.svg?style=flat)](https://travis-ci.org/Zewo/SwiftZMQ) +[![codecov.io](http://codecov.io/github/Zewo/SwiftZMQ/coverage.svg?branch=master)](http://codecov.io/github/Zewo/SwiftZMQ?branch=master) + +**SwiftZMQ** is a [ZMQ](http://zeromq.org/) binding for **Swift 2**. + +## Features + +- [x] No `Foundation` depency (**Linux ready**) +- [x] Context +- [x] Socket +- [x] Message +- [x] Poller +- [x] Proxy + +##Example + +```swift +import SwiftZMQ + +do { + let context = try Context() + + let inbound = try context.socket(.Pull) + try inbound.bind("tcp://127.0.0.1:5555") + + let outbound = try context.socket(.Push) + try outbound.connect("tcp://127.0.0.1:5555") + + try outbound.sendString("Hello World!") + try outbound.sendString("Bye!") + + while let data = try inbound.receiveString() where data != "Bye!" { + print(data) // "Hello World!" + } +} catch { + // Something bad happened :( +} +``` + +## Installation + +### Carthage + +[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that automates the process of adding frameworks to your Cocoa application. + +You can install Carthage with [Homebrew](http://brew.sh/) using the following command: + +```bash +$ brew update +$ brew install carthage +``` + +To integrate **SwiftZMQ** into your Xcode project using Carthage, specify it in your `Cartfile`: + +```ogdl +github "Zewo/SwiftZMQ" +``` + +### Manually + +If you prefer not to use a dependency manager, you can integrate **SwiftZMQ** into your project manually. + +#### Embedded Framework + +- Open up Terminal, `cd` into your top-level project directory, and run the following command "if" your project is not initialized as a git repository: + +```bash +$ git init +``` + +- Add **SwiftZMQ** as a git [submodule](http://git-scm.com/docs/git-submodule) by running the following command: + +```bash +$ git submodule add https://github.com/Zewo/SwiftZMQ.git +``` + +- Open the new `SwiftZMQ` folder, and drag the `SwiftZMQ.xcodeproj` into the Project Navigator of your application's Xcode project. + + > It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter. + +- Select the `SwiftZMQ.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target. +- Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar. +- In the tab bar at the top of that window, open the "General" panel. +- Click on the `+` button under the "Embedded Binaries" section. +- You will see two different `SwiftZMQ.xcodeproj` folders each with two different versions of the `SwiftZMQ.framework` nested inside a `Products` folder. + + > It does not matter which `Products` folder you choose from, but it does matter whether you choose the top or bottom `SwiftZMQ.framework`. + +- Select the top `SwiftZMQ.framework` for OS X and the bottom one for iOS. + + > You can verify which one you selected by inspecting the build log for your project. The build target for `SwiftZMQ` will be listed as either `SwiftZMQ iOS` or `SwiftZMQ OSX`. + +- And that's it! + +> The `SwiftZMQ.framework` is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device. + +License +------- + +**SwiftZMQ** is released under the MIT license. See LICENSE for details. \ No newline at end of file diff --git a/SwiftZMQ.h b/SwiftZMQ.h new file mode 100644 index 0000000..65edcc8 --- /dev/null +++ b/SwiftZMQ.h @@ -0,0 +1,24 @@ +// SwiftZMQ.h +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Zewo +// +// 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. + diff --git a/SwiftZMQ.xcodeproj/project.pbxproj b/SwiftZMQ.xcodeproj/project.pbxproj new file mode 100644 index 0000000..56b5e20 --- /dev/null +++ b/SwiftZMQ.xcodeproj/project.pbxproj @@ -0,0 +1,470 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + B00ED9EB1BD8A2CD00BBBBAE /* SwiftZMQ.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B00ED9E01BD8A2CD00BBBBAE /* SwiftZMQ.framework */; settings = {ASSET_TAGS = (); }; }; + B00EDA421BDDD1FB00BBBBAE /* Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = B00EDA361BDDD1FB00BBBBAE /* Context.swift */; settings = {ASSET_TAGS = (); }; }; + B00EDA431BDDD1FB00BBBBAE /* CURVE.swift in Sources */ = {isa = PBXBuildFile; fileRef = B00EDA371BDDD1FB00BBBBAE /* CURVE.swift */; settings = {ASSET_TAGS = (); }; }; + B00EDA441BDDD1FB00BBBBAE /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = B00EDA381BDDD1FB00BBBBAE /* Error.swift */; settings = {ASSET_TAGS = (); }; }; + B00EDA461BDDD1FB00BBBBAE /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = B00EDA3A1BDDD1FB00BBBBAE /* Message.swift */; settings = {ASSET_TAGS = (); }; }; + B00EDA471BDDD1FB00BBBBAE /* Poller.swift in Sources */ = {isa = PBXBuildFile; fileRef = B00EDA3B1BDDD1FB00BBBBAE /* Poller.swift */; settings = {ASSET_TAGS = (); }; }; + B00EDA481BDDD1FB00BBBBAE /* Proxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B00EDA3C1BDDD1FB00BBBBAE /* Proxy.swift */; settings = {ASSET_TAGS = (); }; }; + B00EDA491BDDD1FB00BBBBAE /* Socket.swift in Sources */ = {isa = PBXBuildFile; fileRef = B00EDA3D1BDDD1FB00BBBBAE /* Socket.swift */; settings = {ASSET_TAGS = (); }; }; + B00EDA4D1BDDD27000BBBBAE /* ZMQTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B00EDA411BDDD1FB00BBBBAE /* ZMQTests.swift */; settings = {ASSET_TAGS = (); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + B00ED9EC1BD8A2CD00BBBBAE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B00ED9D71BD8A2CD00BBBBAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B00ED9DF1BD8A2CD00BBBBAE; + remoteInfo = swiftzmq; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + B00ED9E01BD8A2CD00BBBBAE /* SwiftZMQ.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftZMQ.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B00ED9EA1BD8A2CD00BBBBAE /* SwiftZMQTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftZMQTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + B00EDA021BD8A34B00BBBBAE /* module.map */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.map; sourceTree = ""; }; + B00EDA131BD9FE3C00BBBBAE /* zmq_swift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = zmq_swift.h; sourceTree = ""; }; + B00EDA361BDDD1FB00BBBBAE /* Context.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Context.swift; sourceTree = ""; }; + B00EDA371BDDD1FB00BBBBAE /* CURVE.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CURVE.swift; sourceTree = ""; }; + B00EDA381BDDD1FB00BBBBAE /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = ""; }; + B00EDA391BDDD1FB00BBBBAE /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B00EDA3A1BDDD1FB00BBBBAE /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = ""; }; + B00EDA3B1BDDD1FB00BBBBAE /* Poller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Poller.swift; sourceTree = ""; }; + B00EDA3C1BDDD1FB00BBBBAE /* Proxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Proxy.swift; sourceTree = ""; }; + B00EDA3D1BDDD1FB00BBBBAE /* Socket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Socket.swift; sourceTree = ""; }; + B00EDA401BDDD1FB00BBBBAE /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B00EDA411BDDD1FB00BBBBAE /* ZMQTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZMQTests.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + B00ED9DC1BD8A2CD00BBBBAE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B00ED9E71BD8A2CD00BBBBAE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B00ED9EB1BD8A2CD00BBBBAE /* SwiftZMQ.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + B00ED9D61BD8A2CD00BBBBAE = { + isa = PBXGroup; + children = ( + B00ED9FA1BD8A2D900BBBBAE /* Dependencies */, + B00EDA351BDDD1FA00BBBBAE /* SwiftZMQ */, + B00EDA3F1BDDD1FB00BBBBAE /* SwiftZMQTests */, + B00ED9E11BD8A2CD00BBBBAE /* Products */, + ); + sourceTree = ""; + }; + B00ED9E11BD8A2CD00BBBBAE /* Products */ = { + isa = PBXGroup; + children = ( + B00ED9E01BD8A2CD00BBBBAE /* SwiftZMQ.framework */, + B00ED9EA1BD8A2CD00BBBBAE /* SwiftZMQTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + B00ED9FA1BD8A2D900BBBBAE /* Dependencies */ = { + isa = PBXGroup; + children = ( + B00EDA001BD8A34B00BBBBAE /* ZeroMQ */, + ); + name = Dependencies; + sourceTree = ""; + }; + B00EDA001BD8A34B00BBBBAE /* ZeroMQ */ = { + isa = PBXGroup; + children = ( + B00EDA021BD8A34B00BBBBAE /* module.map */, + B00EDA131BD9FE3C00BBBBAE /* zmq_swift.h */, + ); + name = ZeroMQ; + path = Dependencies/zeromq; + sourceTree = ""; + }; + B00EDA351BDDD1FA00BBBBAE /* SwiftZMQ */ = { + isa = PBXGroup; + children = ( + B00EDA361BDDD1FB00BBBBAE /* Context.swift */, + B00EDA371BDDD1FB00BBBBAE /* CURVE.swift */, + B00EDA381BDDD1FB00BBBBAE /* Error.swift */, + B00EDA391BDDD1FB00BBBBAE /* Info.plist */, + B00EDA3A1BDDD1FB00BBBBAE /* Message.swift */, + B00EDA3B1BDDD1FB00BBBBAE /* Poller.swift */, + B00EDA3C1BDDD1FB00BBBBAE /* Proxy.swift */, + B00EDA3D1BDDD1FB00BBBBAE /* Socket.swift */, + ); + path = SwiftZMQ; + sourceTree = ""; + }; + B00EDA3F1BDDD1FB00BBBBAE /* SwiftZMQTests */ = { + isa = PBXGroup; + children = ( + B00EDA401BDDD1FB00BBBBAE /* Info.plist */, + B00EDA411BDDD1FB00BBBBAE /* ZMQTests.swift */, + ); + path = SwiftZMQTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + B00ED9DD1BD8A2CD00BBBBAE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + B00ED9DF1BD8A2CD00BBBBAE /* SwiftZMQ */ = { + isa = PBXNativeTarget; + buildConfigurationList = B00ED9F41BD8A2CD00BBBBAE /* Build configuration list for PBXNativeTarget "SwiftZMQ" */; + buildPhases = ( + B00ED9DB1BD8A2CD00BBBBAE /* Sources */, + B00ED9DC1BD8A2CD00BBBBAE /* Frameworks */, + B00ED9DD1BD8A2CD00BBBBAE /* Headers */, + B00ED9DE1BD8A2CD00BBBBAE /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SwiftZMQ; + productName = swiftzmq; + productReference = B00ED9E01BD8A2CD00BBBBAE /* SwiftZMQ.framework */; + productType = "com.apple.product-type.framework"; + }; + B00ED9E91BD8A2CD00BBBBAE /* SwiftZMQTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = B00ED9F71BD8A2CD00BBBBAE /* Build configuration list for PBXNativeTarget "SwiftZMQTests" */; + buildPhases = ( + B00ED9E61BD8A2CD00BBBBAE /* Sources */, + B00ED9E71BD8A2CD00BBBBAE /* Frameworks */, + B00ED9E81BD8A2CD00BBBBAE /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + B00ED9ED1BD8A2CD00BBBBAE /* PBXTargetDependency */, + ); + name = SwiftZMQTests; + productName = swiftzmqTests; + productReference = B00ED9EA1BD8A2CD00BBBBAE /* SwiftZMQTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + B00ED9D71BD8A2CD00BBBBAE /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 0700; + ORGANIZATIONNAME = Zewo; + TargetAttributes = { + B00ED9DF1BD8A2CD00BBBBAE = { + CreatedOnToolsVersion = 7.0; + }; + B00ED9E91BD8A2CD00BBBBAE = { + CreatedOnToolsVersion = 7.0; + }; + }; + }; + buildConfigurationList = B00ED9DA1BD8A2CD00BBBBAE /* Build configuration list for PBXProject "SwiftZMQ" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = B00ED9D61BD8A2CD00BBBBAE; + productRefGroup = B00ED9E11BD8A2CD00BBBBAE /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + B00ED9DF1BD8A2CD00BBBBAE /* SwiftZMQ */, + B00ED9E91BD8A2CD00BBBBAE /* SwiftZMQTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + B00ED9DE1BD8A2CD00BBBBAE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B00ED9E81BD8A2CD00BBBBAE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + B00ED9DB1BD8A2CD00BBBBAE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B00EDA421BDDD1FB00BBBBAE /* Context.swift in Sources */, + B00EDA491BDDD1FB00BBBBAE /* Socket.swift in Sources */, + B00EDA461BDDD1FB00BBBBAE /* Message.swift in Sources */, + B00EDA441BDDD1FB00BBBBAE /* Error.swift in Sources */, + B00EDA431BDDD1FB00BBBBAE /* CURVE.swift in Sources */, + B00EDA481BDDD1FB00BBBBAE /* Proxy.swift in Sources */, + B00EDA471BDDD1FB00BBBBAE /* Poller.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B00ED9E61BD8A2CD00BBBBAE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B00EDA4D1BDDD27000BBBBAE /* ZMQTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + B00ED9ED1BD8A2CD00BBBBAE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B00ED9DF1BD8A2CD00BBBBAE /* SwiftZMQ */; + targetProxy = B00ED9EC1BD8A2CD00BBBBAE /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + B00ED9F21BD8A2CD00BBBBAE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = /usr/local/include; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "-lzmq"; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + B00ED9F31BD8A2CD00BBBBAE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = /usr/local/include; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = "-lzmq"; + SDKROOT = macosx; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + B00ED9F51BD8A2CD00BBBBAE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = SwiftZMQ/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Dependencies/ZeroMQ", + ); + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-L/usr/local/lib", + "-lzmq", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.zewo.SwiftZMQ; + PRODUCT_NAME = SwiftZMQ; + SKIP_INSTALL = YES; + SWIFT_INCLUDE_PATHS = "$(SRCROOT)/Dependencies"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + B00ED9F61BD8A2CD00BBBBAE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = SwiftZMQ/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Dependencies/ZeroMQ", + ); + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-L/usr/local/lib", + "-lzmq", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.zewo.SwiftZMQ; + PRODUCT_NAME = SwiftZMQ; + SKIP_INSTALL = YES; + SWIFT_INCLUDE_PATHS = "$(SRCROOT)/Dependencies"; + }; + name = Release; + }; + B00ED9F81BD8A2CD00BBBBAE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = SwiftZMQ/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.zewo.SwiftZMQTests; + PRODUCT_NAME = SwiftZMQTests; + }; + name = Debug; + }; + B00ED9F91BD8A2CD00BBBBAE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = SwiftZMQ/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.zewo.SwiftZMQTests; + PRODUCT_NAME = SwiftZMQTests; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B00ED9DA1BD8A2CD00BBBBAE /* Build configuration list for PBXProject "SwiftZMQ" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B00ED9F21BD8A2CD00BBBBAE /* Debug */, + B00ED9F31BD8A2CD00BBBBAE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B00ED9F41BD8A2CD00BBBBAE /* Build configuration list for PBXNativeTarget "SwiftZMQ" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B00ED9F51BD8A2CD00BBBBAE /* Debug */, + B00ED9F61BD8A2CD00BBBBAE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B00ED9F71BD8A2CD00BBBBAE /* Build configuration list for PBXNativeTarget "SwiftZMQTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B00ED9F81BD8A2CD00BBBBAE /* Debug */, + B00ED9F91BD8A2CD00BBBBAE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = B00ED9D71BD8A2CD00BBBBAE /* Project object */; +} diff --git a/SwiftZMQ.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/SwiftZMQ.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..5c7aa9f --- /dev/null +++ b/SwiftZMQ.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/SwiftZMQ/CURVE.swift b/SwiftZMQ/CURVE.swift new file mode 100644 index 0000000..7db7018 --- /dev/null +++ b/SwiftZMQ/CURVE.swift @@ -0,0 +1,36 @@ +// CURVE.swift +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Zewo +// +// 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. + +import ZeroMQ + +public func CURVEKeyPair() throws -> (publicKey: String, secretKey: String) { + var publicKey = [Int8](count: 41, repeatedValue: 0) + var secretKey = [Int8](count: 41, repeatedValue: 0) + + if zmq_curve_keypair(&publicKey, &secretKey) == -1 { + throw Error.lastError + } + + return (String.fromCString(publicKey)!, String.fromCString(secretKey)!) +} \ No newline at end of file diff --git a/SwiftZMQ/Context.swift b/SwiftZMQ/Context.swift new file mode 100644 index 0000000..a429657 --- /dev/null +++ b/SwiftZMQ/Context.swift @@ -0,0 +1,179 @@ +// Context.swift +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Zewo +// +// 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. + +import ZeroMQ + +public enum SocketType { + case Req + case Rep + case Dealer + case Router + case Pub + case Sub + case XPub + case XSub + case Push + case Pull + case Pair + case Stream +} + +extension SocketType { + init?(rawValue: Int32) { + switch rawValue { + case ZMQ_REQ: self = Req + case ZMQ_REP: self = Rep + case ZMQ_DEALER: self = Dealer + case ZMQ_ROUTER: self = Router + case ZMQ_PUB: self = Pub + case ZMQ_SUB: self = Sub + case ZMQ_XPUB: self = XPub + case ZMQ_XSUB: self = XSub + case ZMQ_PUSH: self = Push + case ZMQ_PULL: self = Pull + case ZMQ_PAIR: self = Pair + case ZMQ_STREAM: self = Stream + default: return nil + } + } +} + +extension SocketType { + var rawValue: Int32 { + switch self { + case .Req: return ZMQ_REQ + case .Rep: return ZMQ_REP + case .Dealer: return ZMQ_DEALER + case .Router: return ZMQ_ROUTER + case .Pub: return ZMQ_PUB + case .Sub: return ZMQ_SUB + case .XPub: return ZMQ_XPUB + case .XSub: return ZMQ_XSUB + case .Push: return ZMQ_PUSH + case .Pull: return ZMQ_PULL + case .Pair: return ZMQ_PAIR + case .Stream: return ZMQ_STREAM + } + } +} + +public final class Context { + let context: UnsafeMutablePointer + + public init() throws { + context = zmq_ctx_new() + + if context == nil { + throw Error.lastError + } + } + + public init(IOThreads: Int32) throws { + context = zmq_ctx_new() + + if context == nil { + throw Error.lastError + } + + self.IOThreads = IOThreads + } + + deinit { + let _ = try? terminate() + } + + public func terminate() throws { + if zmq_ctx_term(context) == -1 { + throw Error.lastError + } + } + + func setOption(option: Int32, value: Int32) { + zmq_ctx_set(context, option, value) + } + + func getOption(option: Int32) -> Int32 { + return zmq_ctx_get(context, option) + } + + public func socket(type: SocketType) throws -> Socket { + let socket = zmq_socket(context, type.rawValue) + + if socket == nil { + throw Error.lastError + } + + return Socket(socket: socket) + } +} + +extension Context { + public var blocky: Bool { + set { + setOption(ZMQ_BLOCKY, value: newValue ? 1 : 0) + } + get { + return getOption(ZMQ_BLOCKY) != 0 + } + } + + public var IOThreads: Int32 { + set { + setOption(ZMQ_IO_THREADS, value: newValue) + } + get { + return getOption(ZMQ_IO_THREADS) + } + } + + public var maxSockets: Int32 { + set { + setOption(ZMQ_MAX_SOCKETS, value: newValue) + } + get { + return getOption(ZMQ_MAX_SOCKETS) + } + } + + public var IPV6: Bool { + set { + setOption(ZMQ_IPV6, value: newValue ? 1 : 0) + } + get { + return getOption(ZMQ_IPV6) != 0 + } + } + + public var socketLimit: Int32 { + return getOption(ZMQ_SOCKET_LIMIT) + } + + public func setThreadSchedulingPolicy(value: Int32) { + setOption(ZMQ_THREAD_SCHED_POLICY, value: value) + } + + public func setThreadPriority(value: Int32) { + setOption(ZMQ_THREAD_PRIORITY, value: value) + } +} \ No newline at end of file diff --git a/SwiftZMQ/Error.swift b/SwiftZMQ/Error.swift new file mode 100644 index 0000000..ac88e4f --- /dev/null +++ b/SwiftZMQ/Error.swift @@ -0,0 +1,34 @@ +// Error.swift +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Zewo +// +// 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. + +import ZeroMQ + +public struct Error : ErrorType, CustomStringConvertible { + public let description: String + + static var lastError: Error { + let description = String.fromCString(zmq_strerror(zmq_errno()))! + return Error(description: description) + } +} \ No newline at end of file diff --git a/SwiftZMQ/Info.plist b/SwiftZMQ/Info.plist new file mode 100644 index 0000000..61facdc --- /dev/null +++ b/SwiftZMQ/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2015 Zewo. All rights reserved. + NSPrincipalClass + + + diff --git a/SwiftZMQ/Message.swift b/SwiftZMQ/Message.swift new file mode 100644 index 0000000..3407f8f --- /dev/null +++ b/SwiftZMQ/Message.swift @@ -0,0 +1,129 @@ +// Message.swift +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Zewo +// +// 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. + +import ZeroMQ + +public final class Message { + var message: zmq_msg_t + + public init() throws { + message = zmq_msg_t() + + if zmq_msg_init(&message) == -1 { + throw Error.lastError + } + } + + public init(size: Int) throws { + message = zmq_msg_t() + + if zmq_msg_init_size(&message, size) == -1 { + throw Error.lastError + } + } + + public init(data: UnsafeMutablePointer, size: Int, hint: UnsafeMutablePointer = nil, ffn: @convention(c) (UnsafeMutablePointer, UnsafeMutablePointer) -> Void) throws { + message = zmq_msg_t() + + if zmq_msg_init_data(&message, data, size, ffn, hint) == -1 { + throw Error.lastError + } + } + + public init(data: UnsafeMutablePointer, size: Int) throws { + message = zmq_msg_t() + + if zmq_msg_init_data(&message, data, size, nil, nil) == -1 { + throw Error.lastError + } + } + + deinit { + let _ = try? close() + } + + func setProperty(property: Int32, value: Int32) { + zmq_msg_set(&message, property, value) + } + + func getProperty(property: Int32) -> Int32 { + return zmq_msg_get(&message, property) + } + + public func getProperty(property: String) throws -> String { + let result = zmq_msg_gets(&message, property) + + if result == nil { + throw Error.lastError + } + + return String.fromCString(result)! + } + + public func close() throws { + if zmq_msg_close(&message) == -1 { + throw Error.lastError + } + } + + public var data: UnsafeMutablePointer { + return zmq_msg_data(&message) + } + + public var size: Int { + return zmq_msg_size(&message) + } + + public var more: Bool { + return zmq_msg_more(&message) != 0 + } + + public func copy() throws -> Message { + let message = try Message() + + if zmq_msg_copy(&message.message, &self.message) == -1 { + throw Error.lastError + } + + return message + } + + public func move(inout message: Message) throws { + let message = try Message() + + if zmq_msg_move(&message.message, &self.message) == -1 { + throw Error.lastError + } + } +} + +extension Message { + public var sourceFileDescriptor: Int32 { + return getProperty(ZMQ_SRCFD) + } + + public var shared: Bool { + return getProperty(ZMQ_SHARED) != 0 + } +} \ No newline at end of file diff --git a/SwiftZMQ/Poller.swift b/SwiftZMQ/Poller.swift new file mode 100644 index 0000000..c4d58b0 --- /dev/null +++ b/SwiftZMQ/Poller.swift @@ -0,0 +1,76 @@ +// Poller.swift +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Zewo +// +// 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. + +import ZeroMQ + +public struct PollEvent : OptionSetType { + public let rawValue: Int16 + + public init(rawValue: Int16) { + self.rawValue = rawValue + } + + public static let In = PollEvent(rawValue: Int16(ZMQ_POLLIN)) + public static let Out = PollEvent(rawValue: Int16(ZMQ_POLLOUT)) + public static let Error = PollEvent(rawValue: Int16(ZMQ_POLLERR)) + public static let Priority = PollEvent(rawValue: Int16(ZMQ_POLLPRI)) +} + +public enum PollItemEvent { + case Socket(socket: UnsafeMutablePointer, events: PollEvent) + case FileDescriptor(fileDescriptor: Int32, events: PollEvent) + + var pollItem: zmq_pollitem_t { + switch self { + case Socket(let socket, let events): + return zmq_pollitem_t(socket: socket, fd: 0, events: events.rawValue, revents: 0) + case FileDescriptor(let fileDescriptor, let events): + return zmq_pollitem_t(socket: nil, fd: fileDescriptor, events: events.rawValue, revents: 0) + } + } + + init(pollItem: zmq_pollitem_t) { + if pollItem.socket != nil { + self = Socket( + socket: pollItem.socket, + events: PollEvent(rawValue: pollItem.revents) + ) + } else { + self = FileDescriptor( + fileDescriptor: pollItem.fd, + events: PollEvent(rawValue: pollItem.revents) + ) + } + } +} + +public func poll(items: PollItemEvent..., timeout: Int) throws -> [PollItemEvent] { + var pollItems = items.map { $0.pollItem } + + if zmq_poll(&pollItems, Int32(pollItems.count), timeout) == -1 { + throw Error.lastError + } + + return pollItems.map(PollItemEvent.init) +} \ No newline at end of file diff --git a/SwiftZMQ/Proxy.swift b/SwiftZMQ/Proxy.swift new file mode 100644 index 0000000..faacf10 --- /dev/null +++ b/SwiftZMQ/Proxy.swift @@ -0,0 +1,29 @@ +// Proxy.swift +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Zewo +// +// 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. + +import ZeroMQ + +public func proxy(frontend: Socket, backend: Socket, capture: Socket? = nil) { + zmq_proxy(frontend.socket, backend.socket, capture?.socket ?? nil) +} \ No newline at end of file diff --git a/SwiftZMQ/Socket.swift b/SwiftZMQ/Socket.swift new file mode 100644 index 0000000..ab99837 --- /dev/null +++ b/SwiftZMQ/Socket.swift @@ -0,0 +1,851 @@ +// Socket.swift +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Zewo +// +// 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. + +import ZeroMQ + +public struct SendMode : OptionSetType { + public let rawValue: Int + + public init(rawValue: Int) { + self.rawValue = rawValue + } + + public static let DontWait = SendMode(rawValue: Int(ZMQ_DONTWAIT)) + public static let SendMore = SendMode(rawValue: Int(ZMQ_SNDMORE)) +} + +public struct ReceiveMode : OptionSetType { + public let rawValue: Int + + public init(rawValue: Int) { + self.rawValue = rawValue + } + + public static let DontWait = ReceiveMode(rawValue: Int(ZMQ_DONTWAIT)) +} + +public final class Socket { + let socket: UnsafeMutablePointer + + init(socket: UnsafeMutablePointer) { + self.socket = socket + } + + deinit { + let _ = try? close() + } + + func setOption(option: Int32, value: UnsafePointer, length: Int) throws { + if zmq_setsockopt(socket, option, value, length) == -1 { + throw Error.lastError + } + } + + func getOption(option: Int32, value: UnsafeMutablePointer, length: UnsafeMutablePointer) throws { + if zmq_getsockopt(socket, option, value, length) == -1 { + throw Error.lastError + } + } + + public func bind(endpoint: String) throws { + if zmq_bind(socket, endpoint) == -1 { + throw Error.lastError + } + } + + public func connect(endpoint: String) throws { + if zmq_connect(socket, endpoint) == -1 { + throw Error.lastError + } + } + + public func sendMessage(message: Message, mode: SendMode = []) throws -> Bool { + let result = zmq_msg_send(&message.message, socket, Int32(mode.rawValue)) + + if result == -1 && zmq_errno() == EAGAIN { + return false + } + + if result == -1 { + throw Error.lastError + } + + return true + } + + func send(buffer: UnsafeMutablePointer, length: Int, mode: SendMode = []) throws -> Bool { + let result = zmq_send(socket, buffer, length, Int32(mode.rawValue)) + + if result == -1 && zmq_errno() == EAGAIN { + return false + } + + if result == -1 { + throw Error.lastError + } + + return true + } + + func sendImmutable(buffer: UnsafePointer, length: Int, mode: SendMode = []) throws -> Bool { + let result = zmq_send_const(socket, buffer, length, Int32(mode.rawValue)) + + if result == -1 && zmq_errno() == EAGAIN { + return false + } + + if result == -1 { + throw Error.lastError + } + + return true + } + + public func receiveMessage(mode: ReceiveMode = []) throws -> Message? { + let message = try Message() + let result = zmq_msg_recv(&message.message, socket, Int32(mode.rawValue)) + + if result == -1 && zmq_errno() == EAGAIN { + return nil + } + + if result == -1 { + throw Error.lastError + } + + return message + } + + public func receive(bufferSize bufferSize: Int = 256, mode: ReceiveMode = []) throws -> [Int8]? { + var buffer = [Int8](count: bufferSize, repeatedValue: 0) + let result = zmq_recv(socket, &buffer, bufferSize, Int32(mode.rawValue)) + + if result == -1 && zmq_errno() == EAGAIN { + return nil + } + + if result == -1 { + throw Error.lastError + } + + let bufferEnd = min(Int(result), bufferSize) + return Array(buffer[0 ..< bufferEnd]) + } + + public func close() throws { + if zmq_close(socket) == -1 { + throw Error.lastError + } + } + + public func monitor(endpoint: String, events: SocketEvent) throws { + if zmq_socket_monitor(socket, endpoint, events.rawValue) == -1 { + throw Error.lastError + } + } +} + +public struct SocketEvent : OptionSetType { + public let rawValue: Int32 + + public init(rawValue: Int32) { + self.rawValue = rawValue + } + + public static let All = SocketEvent(rawValue: ZMQ_EVENT_ALL) + public static let Connected = SocketEvent(rawValue: ZMQ_EVENT_CONNECTED) + public static let Delayed = SocketEvent(rawValue: ZMQ_EVENT_CONNECT_DELAYED) + public static let Retried = SocketEvent(rawValue: ZMQ_EVENT_CONNECT_RETRIED) + public static let Listening = SocketEvent(rawValue: ZMQ_EVENT_LISTENING) + public static let BindFailed = SocketEvent(rawValue: ZMQ_EVENT_BIND_FAILED) + public static let Accepted = SocketEvent(rawValue: ZMQ_EVENT_ACCEPTED) + public static let AcceptFailed = SocketEvent(rawValue: ZMQ_EVENT_ACCEPT_FAILED) + public static let Closed = SocketEvent(rawValue: ZMQ_EVENT_CLOSED) + public static let CloseFailed = SocketEvent(rawValue: ZMQ_EVENT_CLOSE_FAILED) + public static let Disconnected = SocketEvent(rawValue: ZMQ_EVENT_DISCONNECTED) + public static let MonitorStopped = SocketEvent(rawValue: ZMQ_EVENT_MONITOR_STOPPED) +} + +extension Socket { + public func setAffinity(var value: UInt64) throws { + try setOption(ZMQ_AFFINITY, value: &value, length: strideof(UInt64)) + } + + public func setBacklog(var value: Int32) throws { + try setOption(ZMQ_BACKLOG, value: &value, length: strideof(Int32)) + } + + public func setConnectRID(value: String) throws { + try value.withCString { v in + try setOption(ZMQ_CONNECT_RID, value: v, length: value.utf8.count) + } + } + + public func setConflate(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_CONFLATE, value: &v, length: strideof(Int32)) + } + + public func setConnectTimeout(var value: Int32) throws { + try setOption(ZMQ_CONNECT_TIMEOUT, value: &value, length: strideof(Int32)) + } + + public func setCURVEPublicKey(value: String?) throws { + if let value = value { + try value.withCString { v in + try setOption(ZMQ_CURVE_PUBLICKEY, value: v, length: value.utf8.count) + } + } else { + try setOption(ZMQ_CURVE_PUBLICKEY, value: nil, length: 0) + } + } + + public func setCURVESecretKey(value: String?) throws { + if let value = value { + try value.withCString { v in + try setOption(ZMQ_CURVE_SECRETKEY, value: v, length: value.utf8.count) + } + } else { + try setOption(ZMQ_CURVE_SECRETKEY, value: nil, length: 0) + } + } + + public func setCURVEServer(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_CURVE_SERVER, value: &v, length: strideof(Int32)) + } + + public func setCURVEServerKey(value: String?) throws { + if let value = value { + try value.withCString { v in + try setOption(ZMQ_CURVE_SERVERKEY, value: v, length: value.utf8.count) + } + } else { + try setOption(ZMQ_CURVE_SERVERKEY, value: nil, length: 0) + } + } + + public func setGSSAPIPlainText(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_GSSAPI_PLAINTEXT, value: &v, length: strideof(Int32)) + } + + public func setGSSAPIPrincipal(value: String) throws { + try value.withCString { v in + try setOption(ZMQ_GSSAPI_PRINCIPAL, value: v, length: value.utf8.count) + } + } + + public func setGSSAPIServer(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_GSSAPI_SERVER, value: &v, length: strideof(Int32)) + } + + public func setGSSAPIServicePrincipal(value: String) throws { + try value.withCString { v in + try setOption(ZMQ_GSSAPI_SERVICE_PRINCIPAL, value: v, length: value.utf8.count) + } + } + + public func setHandshakeInterval(var value: Int32) throws { + try setOption(ZMQ_HANDSHAKE_IVL, value: &value, length: strideof(Int32)) + } + + public func setHeartbeatInterval(var value: Int32) throws { + try setOption(ZMQ_HEARTBEAT_IVL, value: &value, length: strideof(Int32)) + } + + public func setHeartbeatTimeout(var value: Int32) throws { + try setOption(ZMQ_HEARTBEAT_TIMEOUT, value: &value, length: strideof(Int32)) + } + + public func setHeartbeatTTTL(var value: Int32) throws { + try setOption(ZMQ_HEARTBEAT_TTL, value: &value, length: strideof(Int32)) + } + + public func setIdentity(value: String) throws { + try value.withCString { v in + try setOption(ZMQ_IDENTITY, value: v, length: value.utf8.count) + } + } + + public func setImmediate(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_IMMEDIATE, value: &v, length: strideof(Int32)) + } + + public func setInvertMatching(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_INVERT_MATCHING, value: &v, length: strideof(Int32)) + } + + public func setIPV6(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_IPV6, value: &v, length: strideof(Int32)) + } + + public func setLinger(var value: Int32) throws { + try setOption(ZMQ_LINGER, value: &value, length: strideof(Int32)) + } + + public func setMaxMessageSize(var value: Int64) throws { + try setOption(ZMQ_MAXMSGSIZE, value: &value, length: strideof(Int64)) + } + + public func setMulticastHops(var value: Int32) throws { + try setOption(ZMQ_MULTICAST_HOPS, value: &value, length: strideof(Int32)) + } + + public func setPlainPassword(value: String?) throws { + if let value = value { + try value.withCString { v in + try setOption(ZMQ_PLAIN_PASSWORD, value: v, length: value.utf8.count) + } + } else { + try setOption(ZMQ_PLAIN_PASSWORD, value: nil, length: 0) + } + } + + public func setPlainServer(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_PLAIN_SERVER, value: &v, length: strideof(Int32)) + } + + public func setPlainUsername(value: String?) throws { + if let value = value { + try value.withCString { v in + try setOption(ZMQ_PLAIN_USERNAME, value: v, length: value.utf8.count) + } + } else { + try setOption(ZMQ_PLAIN_USERNAME, value: nil, length: 0) + } + } + + public func setProbeRouter(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_PROBE_ROUTER, value: &v, length: strideof(Int32)) + } + + public func setRate(var value: Int32) throws { + try setOption(ZMQ_RATE, value: &value, length: strideof(Int32)) + } + + public func setReceiveBuffer(var value: Int32) throws { + try setOption(ZMQ_RCVBUF, value: &value, length: strideof(Int32)) + } + + public func setReceiveHighWaterMark(var value: Int32) throws { + try setOption(ZMQ_RCVHWM, value: &value, length: strideof(Int32)) + } + + public func setReceiveTimeout(var value: Int32) throws { + try setOption(ZMQ_RCVTIMEO, value: &value, length: strideof(Int32)) + } + + public func setReconnectInterval(var value: Int32) throws { + try setOption(ZMQ_RECONNECT_IVL, value: &value, length: strideof(Int32)) + } + + public func setReconnectIntervalMax(var value: Int32) throws { + try setOption(ZMQ_RECONNECT_IVL_MAX, value: &value, length: strideof(Int32)) + } + + public func setRecoveryInterval(var value: Int32) throws { + try setOption(ZMQ_RECOVERY_IVL, value: &value, length: strideof(Int32)) + } + + public func setReqCorrelate(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_REQ_CORRELATE, value: &v, length: strideof(Int32)) + } + + public func setReqRelaxed(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_REQ_RELAXED, value: &v, length: strideof(Int32)) + } + + public func setRouterHandover(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_ROUTER_HANDOVER, value: &v, length: strideof(Int32)) + } + + public func setRouterMandatory(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_ROUTER_MANDATORY, value: &v, length: strideof(Int32)) + } + + public func setRouterRaw(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_ROUTER_RAW, value: &v, length: strideof(Int32)) + } + + public func setSendBuffer(var value: Int32) throws { + try setOption(ZMQ_SNDBUF, value: &value, length: strideof(Int32)) + } + + public func setSendHighWaterMark(var value: Int32) throws { + try setOption(ZMQ_SNDHWM, value: &value, length: strideof(Int32)) + } + + public func setSendTimeout(var value: Int32) throws { + try setOption(ZMQ_SNDTIMEO, value: &value, length: strideof(Int32)) + } + + public func setStreamNotify(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_STREAM_NOTIFY, value: &v, length: strideof(Int32)) + } + + public func setSubscribe(value: String) throws { + try value.withCString { v in + try setOption(ZMQ_SUBSCRIBE, value: v, length: value.utf8.count) + } + } + + public func setTCPKeepAlive(var value: Int32) throws { + try setOption(ZMQ_TCP_KEEPALIVE, value: &value, length: strideof(Int32)) + } + + public func setTCPKeepAliveCount(var value: Int32) throws { + try setOption(ZMQ_TCP_KEEPALIVE_CNT, value: &value, length: strideof(Int32)) + } + + public func setTCPKeepAliveIdle(var value: Int32) throws { + try setOption(ZMQ_TCP_KEEPALIVE_IDLE, value: &value, length: strideof(Int32)) + } + + public func setTCPKeepAliveInterval(var value: Int32) throws { + try setOption(ZMQ_TCP_KEEPALIVE_INTVL, value: &value, length: strideof(Int32)) + } + + public func setTCPRetransmitTimeout(var value: Int32) throws { + try setOption(ZMQ_TCP_RETRANSMIT_TIMEOUT, value: &value, length: strideof(Int32)) + } + + public func setTypeOfService(var value: Int32) throws { + try setOption(ZMQ_TOS, value: &value, length: strideof(Int32)) + } + + public func setUnsubscribe(value: String) throws { + try value.withCString { v in + try setOption(ZMQ_UNSUBSCRIBE, value: v, length: value.utf8.count) + } + } + + public func setXPubVerbose(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_XPUB_VERBOSE, value: &v, length: strideof(Int32)) + } + + public func setXPubVerboseUnsubscribe(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_XPUB_VERBOSE_UNSUBSCRIBE, value: &v, length: strideof(Int32)) + } + + public func setXPubManual(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_XPUB_MANUAL, value: &v, length: strideof(Int32)) + } + + public func setXPubNoDrop(value: Bool) throws { + var v = value ? 1 : 0 + try setOption(ZMQ_XPUB_NODROP, value: &v, length: strideof(Int32)) + } + + public func setXPubWelcomeMessage(value: String) throws { + try value.withCString { v in + try setOption(ZMQ_XPUB_WELCOME_MSG, value: v, length: value.utf8.count) + } + } + + public func setZAPDomain(value: String?) throws { + if let value = value { + try value.withCString { v in + try setOption(ZMQ_ZAP_DOMAIN, value: v, length: value.utf8.count) + } + } else { + try setOption(ZMQ_ZAP_DOMAIN, value: nil, length: 0) + } + } +} + +extension Socket { + public func getAffinity() throws -> UInt64 { + var value: UInt64 = 0 + var length = strideof(UInt64) + try getOption(ZMQ_AFFINITY, value: &value, length: &length) + return value + } + + public func getBacklog() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_BACKLOG, value: &value, length: &length) + return value + } + + public func getConnectTimeout() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_CONNECT_TIMEOUT, value: &value, length: &length) + return value + } + + public func getCURVEPublicKey() throws -> String { + var value = [Int8](count: 41, repeatedValue: 0) + var length = value.count + try getOption(ZMQ_CURVE_PUBLICKEY, value: &value, length: &length) + return String.fromCString(Array(value[0 ..< length]))! + } + + public func getCURVESecretKey() throws -> String { + var value = [Int8](count: 42, repeatedValue: 0) + var length = value.count + try getOption(ZMQ_CURVE_SECRETKEY, value: &value, length: &length) + return String.fromCString(Array(value[0 ..< length]))! + } + + public func getCURVEServerKey() throws -> String { + var value = [Int8](count: 42, repeatedValue: 0) + var length = value.count + try getOption(ZMQ_CURVE_SERVERKEY, value: &value, length: &length) + return String.fromCString(Array(value[0 ..< length]))! + } + + public func getEvents() throws -> PollEvent? { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_TCP_KEEPALIVE, value: &value, length: &length) + return Int(value) == -1 ? nil : PollEvent(rawValue: Int16(value)) + } + + public func getFileDescriptor() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_FD, value: &value, length: &length) + return value + } + + public func getGSSAPIPlainText() throws -> Bool { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_GSSAPI_PLAINTEXT, value: &value, length: &length) + return value != 0 + } + + public func getGSSAPIPrincipal() throws -> String { + var value = [Int8](count: 256, repeatedValue: 0) + var length = value.count + try getOption(ZMQ_GSSAPI_PRINCIPAL, value: &value, length: &length) + return String.fromCString(Array(value[0 ..< length]))! + } + + public func getGSSAPIServer() throws -> Bool { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_GSSAPI_SERVER, value: &value, length: &length) + return value != 0 + } + + public func getGSSAPIServicePrincipal() throws -> String { + var value = [Int8](count: 256, repeatedValue: 0) + var length = value.count + try getOption(ZMQ_GSSAPI_SERVICE_PRINCIPAL, value: &value, length: &length) + return String.fromCString(Array(value[0 ..< length]))! + } + + public func getHandshakeInterval() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_HANDSHAKE_IVL, value: &value, length: &length) + return value + } + + public func getIdentity() throws -> String { + var value = [Int8](count: 256, repeatedValue: 0) + var length = value.count + try getOption(ZMQ_IDENTITY, value: &value, length: &length) + return String.fromCString(Array(value[0 ..< length])) ?? "" + } + + public func getImmediate() throws -> Bool { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_IMMEDIATE, value: &value, length: &length) + return value != 0 + } + + public func getInvertMatching() throws -> Bool { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_INVERT_MATCHING, value: &value, length: &length) + return value != 0 + } + + public func getIPV4Only() throws -> Bool { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_IPV4ONLY, value: &value, length: &length) + return value != 0 + } + + public func getIPV6() throws -> Bool { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_IPV6, value: &value, length: &length) + return value != 0 + } + + public func getLastEndpoint() throws -> String { + var value = [Int8](count: 256, repeatedValue: 0) + var length = value.count + try getOption(ZMQ_LAST_ENDPOINT, value: &value, length: &length) + return String.fromCString(Array(value[0 ..< length]))! + } + + public func getLinger() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_LINGER, value: &value, length: &length) + return value + } + + public func getMaxMessageSize() throws -> Int64 { + var value: Int64 = 0 + var length = strideof(Int64) + try getOption(ZMQ_MAXMSGSIZE, value: &value, length: &length) + return value + } + + public func getMechanism() throws -> SecurityMechanism { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_MECHANISM, value: &value, length: &length) + return SecurityMechanism(rawValue: value)! + } + + public func getMulticastHops() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_MULTICAST_HOPS, value: &value, length: &length) + return value + } + + public func getPlainPassword() throws -> String { + var value = [Int8](count: 256, repeatedValue: 0) + var length = value.count + try getOption(ZMQ_PLAIN_PASSWORD, value: &value, length: &length) + return String.fromCString(Array(value[0 ..< length]))! + } + + public func getPlainServer() throws -> Bool { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_PLAIN_SERVER, value: &value, length: &length) + return value != 0 + } + + public func getPlainUsername() throws -> String { + var value = [Int8](count: 256, repeatedValue: 0) + var length = value.count + try getOption(ZMQ_PLAIN_USERNAME, value: &value, length: &length) + return String.fromCString(Array(value[0 ..< length]))! + } + + public func getRate() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_RATE, value: &value, length: &length) + return value + } + + public func getReceiveBuffer() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_RCVBUF, value: &value, length: &length) + return value + } + + public func getReceiveHighWaterMark() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_RCVHWM, value: &value, length: &length) + return value + } + + public func getReceiveMore() throws -> Bool { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_RCVMORE, value: &value, length: &length) + return value != 0 + } + + public func getReceiveTimeout() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_RCVTIMEO, value: &value, length: &length) + return value + } + + public func getReconnectInterval() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_RECONNECT_IVL, value: &value, length: &length) + return value + } + + public func getReconnectIntervalMax() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_RECONNECT_IVL_MAX, value: &value, length: &length) + return value + } + + public func getRecoveryInterval() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_RECOVERY_IVL, value: &value, length: &length) + return value + } + + public func getSendBuffer() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_SNDBUF, value: &value, length: &length) + return value + } + + public func getSendHighWaterMark() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_SNDHWM, value: &value, length: &length) + return value + } + + public func getSendTimeout() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_SNDTIMEO, value: &value, length: &length) + return value + } + + public func getTCPKeepAlive() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_TCP_KEEPALIVE, value: &value, length: &length) + return value + } + + public func getTCPKeepAliveCount() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_TCP_KEEPALIVE_CNT, value: &value, length: &length) + return value + } + + public func getTCPKeepAliveIdle() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_TCP_KEEPALIVE_IDLE, value: &value, length: &length) + return value + } + + public func getTCPKeepAliveInterval() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_TCP_KEEPALIVE_INTVL, value: &value, length: &length) + return value + } + + public func getTCPRetransmitTimeout() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_TCP_RETRANSMIT_TIMEOUT, value: &value, length: &length) + return value + } + + public func getThreadSafe() throws -> Bool { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_THREAD_SAFE, value: &value, length: &length) + return value != 0 + } + + public func getTypeOfService() throws -> Int32 { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_TOS, value: &value, length: &length) + return value + } + + public func getType() throws -> SocketType { + var value: Int32 = 0 + var length = strideof(Int32) + try getOption(ZMQ_TYPE, value: &value, length: &length) + return SocketType(rawValue: value)! + } + + public func getZAPDomain() throws -> String { + var value = [Int8](count: 256, repeatedValue: 0) + var length = value.count + try getOption(ZMQ_ZAP_DOMAIN, value: &value, length: &length) + return String.fromCString(Array(value[0 ..< length]))! + } +} + +public enum SecurityMechanism { + case Null + case Plain + case CURVE +} + +extension SecurityMechanism { + init?(rawValue: Int32) { + switch rawValue { + case ZMQ_NULL: self = Null + case ZMQ_PLAIN: self = Plain + case ZMQ_CURVE: self = CURVE + default: return nil + } + } +} + +extension Socket { + public func send(var buffer: [Int8], mode: SendMode = []) throws -> Bool { + return try send(&buffer, length: buffer.count, mode: mode) + } + + public func sendString(string: String, mode: SendMode = []) throws -> Bool { + var buffer = string.utf8.map { Int8($0) } + return try send(&buffer, length: buffer.count, mode: mode) + } + + public func receiveString(mode: ReceiveMode = []) throws -> String? { + guard var buffer = try receive(mode: mode) else { + return nil + } + buffer.append(0) + return String.fromCString(buffer) + } +} \ No newline at end of file diff --git a/SwiftZMQTests/Info.plist b/SwiftZMQTests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/SwiftZMQTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/SwiftZMQTests/ZMQTests.swift b/SwiftZMQTests/ZMQTests.swift new file mode 100644 index 0000000..75816aa --- /dev/null +++ b/SwiftZMQTests/ZMQTests.swift @@ -0,0 +1,52 @@ +// ZMQTests.swift +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Zewo +// +// 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. + +import XCTest +import SwiftZMQ + +class ZMQTests: XCTestCase { + func testExample() { + var called = false + do { + let context = try Context() + + let inbound = try context.socket(.Pull) + try inbound.bind("tcp://127.0.0.1:5555") + + let outbound = try context.socket(.Push) + try outbound.connect("tcp://127.0.0.1:5555") + + try outbound.sendString("Hello World!") + try outbound.sendString("Bye!") + + while let data = try inbound.receiveString() where data != "Bye!" { + called = true + XCTAssert(data == "Hello World!") + } + } catch { + XCTAssert(false) + } + XCTAssert(called) + } +}