mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-24 15:26:43 +00:00
3ffa4b10af
Add a swift-client-api subdirectory containing a Swift source package and a Makefile.in that compiles it into the "ServalClient" Swift module using the Swift package manager. The Swift API contains the following classes: - ServalKeyring provides the operations: add, remove, set, list - AbstractId and its specialisation SubscriberId, already in near-final form, are data types for SID and the like - ServalRestfulClient (internal) uses an HTTP client to access the Serval DNA RESTful interface Improve the REST /keyring/set operation to only alter the DID or Name if the corresponding query parameter is supplied. Modify the internal keyring_set_did() function to only assign the DID or Name if the corresponding parameter is not a null pointer. The configure script ensures that the Swift build target version is 10.10 or later when compiling for Mac OS-X, so that the package manager will succeed. Add autoconf macros for the Swift package manager.
219 lines
7.5 KiB
Swift
219 lines
7.5 KiB
Swift
/*
|
|
Serval DNA Client Swift test program
|
|
Copyright (C) 2016-2017 Flinders University
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
import ServalClient
|
|
import Dispatch
|
|
#if os(Linux)
|
|
import Glibc
|
|
#endif
|
|
|
|
var arg0 : String = ""
|
|
|
|
func usage() {
|
|
// Once no longer supporting Swift 3, change this to a multi-line string literal.
|
|
print("Usage: \(arg0) [options] keyring --pin PIN list")
|
|
print(" \(arg0) [options] keyring --pin PIN add [ did DID ] [ name NAME ]")
|
|
print(" \(arg0) [options] keyring --pin PIN remove SID")
|
|
print(" \(arg0) [options] keyring --pin PIN set SID [ did DID ] [ name NAME ]")
|
|
print("Options:")
|
|
print(" --pin PIN")
|
|
print(" --user USER")
|
|
print(" --password PASSWORD")
|
|
}
|
|
|
|
func main() {
|
|
var args = CommandLine.arguments
|
|
arg0 = args.remove(at: 0)
|
|
var port : Int16?
|
|
var username : String?
|
|
var password : String?
|
|
parseOptions(&args, [
|
|
("--port", { port = Int16($0) }),
|
|
("--user", { username = $0 }),
|
|
("--password", { password = $0 })
|
|
])
|
|
let restful_config = ServalRestfulClient.Configuration.default.with(port: port, username: username, password: password)
|
|
let cmd = args.isEmpty ? "" : args.remove(at: 0)
|
|
switch (cmd) {
|
|
case "keyring":
|
|
exit(keyring(&args, configuration: restful_config))
|
|
default:
|
|
usage()
|
|
exit(1)
|
|
}
|
|
}
|
|
|
|
func parseOptions(_ args: inout [String], _ options: [(String, (String) -> Void)]) -> Void {
|
|
argLoop: while (!args.isEmpty) {
|
|
let arg = args[0]
|
|
var opt : String
|
|
var param : String?
|
|
var optrange : Range<Int>
|
|
if let eq = arg.range(of: "=") {
|
|
opt = arg.substring(to: eq.lowerBound)
|
|
param = arg.substring(from: eq.upperBound)
|
|
optrange = 0 ..< 1
|
|
}
|
|
else {
|
|
opt = arg
|
|
param = args.count > 1 ? args[1] : nil
|
|
optrange = 0 ..< 2
|
|
}
|
|
for (label, closure) in options {
|
|
if opt == label && param != nil {
|
|
closure(param!)
|
|
args.removeSubrange(optrange)
|
|
continue argLoop
|
|
}
|
|
}
|
|
break argLoop
|
|
}
|
|
}
|
|
|
|
func printIdentity(identity: ServalKeyring.Identity) {
|
|
print("sid:" + identity.sid.hexUpper)
|
|
print("identity:" + identity.identity.hexUpper)
|
|
if identity.did != nil {
|
|
print("did:" + identity.did!)
|
|
}
|
|
if identity.name != nil {
|
|
print("name:" + identity.name!)
|
|
}
|
|
}
|
|
|
|
func keyring(_ args: inout [String], configuration: ServalRestfulClient.Configuration) -> Int32 {
|
|
let cmd = args.isEmpty ? "" : args.remove(at: 0)
|
|
var pin : String? = nil
|
|
parseOptions(&args, [("--pin", { pin = $0 })])
|
|
var status : Int32 = 0
|
|
switch (cmd) {
|
|
case "list":
|
|
precondition(args.isEmpty)
|
|
print("4")
|
|
print("sid:identity:did:name")
|
|
let semaphore = DispatchSemaphore(value: 0)
|
|
let client = ServalRestfulClient(configuration: configuration)
|
|
let request = ServalKeyring.listIdentities(client: client, pin: pin) { (identities, error) in
|
|
if let error = error {
|
|
print(error, to: &errorStream)
|
|
status = 2
|
|
}
|
|
else if let identities = identities {
|
|
for identity in identities {
|
|
print("\(identity.sid.hexUpper):\(identity.identity.hexUpper):\(identity.did ?? ""):\(identity.name ?? "")")
|
|
}
|
|
}
|
|
semaphore.signal()
|
|
}
|
|
print("Waiting...", to: &debugStream)
|
|
semaphore.wait()
|
|
print("Done", to: &debugStream)
|
|
request.close()
|
|
|
|
case "add":
|
|
var did : String? = nil
|
|
var name : String? = nil
|
|
parseOptions(&args, [("did", { did = $0 }), ("name", { name = $0 })])
|
|
precondition(args.isEmpty)
|
|
var message = "Adding (did="
|
|
debugPrint(did as Any, terminator:"", to:&message)
|
|
message += " name="
|
|
debugPrint(name as Any, terminator:"", to:&message)
|
|
message += " pin="
|
|
debugPrint(pin as Any, terminator:"", to:&message)
|
|
message += ")..."
|
|
print(message, to: &debugStream)
|
|
let semaphore = DispatchSemaphore(value: 0)
|
|
let client = ServalRestfulClient(configuration: configuration)
|
|
let request = ServalKeyring.addIdentity(client: client, did: did, name: name, pin: pin) { (identity, error) in
|
|
if let error = error {
|
|
print(error, to: &errorStream)
|
|
status = 2
|
|
}
|
|
else if let identity = identity {
|
|
printIdentity(identity: identity)
|
|
}
|
|
semaphore.signal()
|
|
}
|
|
print("Waiting...", to: &debugStream)
|
|
semaphore.wait()
|
|
print("Done", to: &debugStream)
|
|
request.close()
|
|
|
|
case "remove":
|
|
let sid = SubscriberId(fromHex: args.remove(at: 0))!
|
|
precondition(args.isEmpty)
|
|
print("Removing (sid=\(sid.hexUpper))...")
|
|
let semaphore = DispatchSemaphore(value: 0)
|
|
let client = ServalRestfulClient(configuration: configuration)
|
|
let request = ServalKeyring.removeIdentity(client: client, sid: sid, pin: pin) { (identity, error) in
|
|
if let error = error {
|
|
print(error, to: &errorStream)
|
|
status = 2
|
|
}
|
|
else if let identity = identity {
|
|
printIdentity(identity: identity)
|
|
}
|
|
semaphore.signal()
|
|
}
|
|
print("Waiting...", to: &debugStream)
|
|
semaphore.wait()
|
|
print("Done", to: &debugStream)
|
|
request.close()
|
|
|
|
case "set":
|
|
let sid = SubscriberId(fromHex: args.remove(at: 0))!
|
|
var did : String? = nil
|
|
var name : String? = nil
|
|
parseOptions(&args, [("did", { did = $0 }), ("name", { name = $0 })])
|
|
precondition(args.isEmpty)
|
|
var message = "Setting (sid=\(sid.hexUpper))..."
|
|
message += " did="
|
|
debugPrint(did as Any, terminator:"", to:&message)
|
|
message += " name="
|
|
debugPrint(name as Any, terminator:"", to:&message)
|
|
message += " pin="
|
|
debugPrint(pin as Any, terminator:"", to:&message)
|
|
print(message, to: &debugStream)
|
|
let semaphore = DispatchSemaphore(value: 0)
|
|
let client = ServalRestfulClient(configuration: configuration)
|
|
let request = ServalKeyring.setIdentity(client: client, sid: sid, did: did, name: name, pin: pin) { (identity, error) in
|
|
if let error = error {
|
|
print(error, to: &errorStream)
|
|
status = 2
|
|
}
|
|
else if let identity = identity {
|
|
printIdentity(identity: identity)
|
|
}
|
|
semaphore.signal()
|
|
}
|
|
print("Waiting...", to: &debugStream)
|
|
semaphore.wait()
|
|
print("Done", to: &debugStream)
|
|
request.close()
|
|
|
|
default:
|
|
usage()
|
|
status = 1
|
|
}
|
|
return status
|
|
}
|
|
|
|
main()
|