mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-18 12:56:29 +00:00
Add Swift keyring client API with tests
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.
This commit is contained in:
parent
f2eb2bf9ab
commit
3ffa4b10af
4
.gitignore
vendored
4
.gitignore
vendored
@ -7,6 +7,7 @@
|
||||
/objs
|
||||
/objs_lib
|
||||
/objs_servald
|
||||
*.o
|
||||
*.a
|
||||
*.suo
|
||||
.*.sw?
|
||||
@ -36,3 +37,6 @@ test.*.log
|
||||
/java-api/Makefile
|
||||
/java-api/classes/
|
||||
/java-api/testclasses/
|
||||
/swift-client-api/Makefile
|
||||
/swift-client-api/build/
|
||||
/swift-client-api/swift-client-util
|
||||
|
15
INSTALL.md
15
INSTALL.md
@ -150,6 +150,14 @@ A successful session should appear something like:
|
||||
Note: Some input files use or override a deprecated API.
|
||||
Note: Recompile with -Xlint:deprecation for details.
|
||||
make[1]: Leaving directory '/home/username/src/serval-dna/java-api'
|
||||
SWIFT MODULE servald.swiftmodule
|
||||
cd swift-api && make SOURCE_PREFIX= all
|
||||
make[1]: Entering directory '/home/username/src/serval-dna/swift-api'
|
||||
swift build --package-path package
|
||||
Compile Swift Module 'ServalClient' (5 sources)
|
||||
Archiving /home/username/src/serval-dna/swift-api/package/.build/x86_64-unknown-linux/debug/libServalClient.a
|
||||
SWIFT test-swift
|
||||
make[1]: Leaving directory '/home/username/src/serval-dna/swift-api'
|
||||
rm _servalclient.a _monitorclient.a _servald.a
|
||||
$
|
||||
|
||||
@ -251,6 +259,11 @@ present][Swift development]:
|
||||
Swift language's run-time support and resultant library dependencies, so is
|
||||
not suitable for deployment.
|
||||
|
||||
* **swift-client-api/build/debug/ServalClient.swiftmodule**
|
||||
**swift-client-api/build/debug/ServalClient.swiftdoc**
|
||||
**swift-client-api/build/debug/libServalClient.a**
|
||||
are the [Swift Client API module][].
|
||||
|
||||
Test scripts
|
||||
------------
|
||||
|
||||
@ -317,6 +330,7 @@ This document is available under the [Creative Commons Attribution 4.0 Internati
|
||||
[gcc 6]: http://gcc.gnu.org/gcc-6/
|
||||
[Notes for Developers]: ./doc/Development.md
|
||||
[Swift development]: ./doc/Development.md#swift
|
||||
[Swift Client API module]: ./doc/Development.md#swift-client-api
|
||||
[OpenWRT]: ./doc/OpenWRT.md
|
||||
[Serval Infrastructure]: ./doc/Serval-Infrastructure.md
|
||||
[Serval Mesh Extender]: http://developer.servalproject.org/dokuwiki/doku.php?id=content:meshextender:
|
||||
@ -329,6 +343,7 @@ This document is available under the [Creative Commons Attribution 4.0 Internati
|
||||
[CLI API]: ./doc/CLI-API.md
|
||||
[JNI]: http://en.wikipedia.org/wiki/Java_Native_Interface
|
||||
[Swift]: https://en.wikipedia.org/wiki/Swift_(programming_language)
|
||||
[dlopen(3)]: http://man7.org/linux/man-pages/man3/dlopen.3.html
|
||||
[Bash]: http://en.wikipedia.org/wiki/Bash_(Unix_shell)
|
||||
[GNU make]: http://www.gnu.org/software/make/
|
||||
[Git]: http://git-scm.com/
|
||||
|
30
Makefile.in
30
Makefile.in
@ -1,4 +1,4 @@
|
||||
# Makefile.in for Serval DNA
|
||||
# Makefile.in for Serval DNA daemon and libraries
|
||||
# vim: noet ts=8 sts=0 sw=8
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
@ -88,6 +88,7 @@ CFLAGS+=-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_OMIT_VIRTUALTABLE \
|
||||
-DSQLITE_OMIT_AUTHORIZATION
|
||||
CFLAGS+=-fPIC -DSERVAL_ENABLE_DEBUG=1 -Wall -Werror -Wextra -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2
|
||||
CFLAGS+=@CFLAGS_TARGET@
|
||||
|
||||
# Solaris magic
|
||||
CFLAGS+=-DSHA2_USE_INTTYPES_H -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D__EXTENSIONS__=1
|
||||
@ -163,6 +164,25 @@ java-api-clean:
|
||||
|
||||
endif # $(JAVAC)
|
||||
|
||||
ifneq ($(SWIFTC),) # Only provide Swift targets if the Swift compiler is available.
|
||||
|
||||
all: swift-client-api
|
||||
|
||||
test: servaldswift
|
||||
|
||||
clean: swift-client-api-clean
|
||||
|
||||
.PHONY: swift-client-api swift-client-api-clean
|
||||
|
||||
swift-client-api:
|
||||
@mkdir -p swift-client-api
|
||||
cd swift-client-api && $(MAKE) all
|
||||
|
||||
swift-client-api-clean:
|
||||
cd swift-client-api 2>/dev/null && $(MAKE) clean
|
||||
|
||||
endif # $(SWIFTC)
|
||||
|
||||
# Build the Sodium elliptic curve encryption library within its 'libsodium'
|
||||
# subtree, and install its development files (headers and libraries) into our
|
||||
# $(LIBSODIUM_DEV) subdirectory. Then use the contents of this subdirectory to
|
||||
@ -186,7 +206,11 @@ $(LIBSODIUM_DEV)/.installed:
|
||||
@mkdir -p $(LIBSODIUM_DEV)
|
||||
@$(RM) $@
|
||||
@touch $@.in-progress
|
||||
@cd $(LIBSODIUM_SUBDIR) && $(MAKE) CFLAGS+=-prefer-pic prefix=$(abspath $(LIBSODIUM_DEV)) install
|
||||
@cd $(LIBSODIUM_SUBDIR) && $(MAKE) \
|
||||
CFLAGS+="-prefer-pic @CFLAGS_TARGET@" \
|
||||
CCASFLAGS+="@CFLAGS_TARGET@" \
|
||||
prefix=$(abspath $(LIBSODIUM_DEV)) \
|
||||
install
|
||||
@mv -f $@.in-progress $@
|
||||
|
||||
# Source code test coverage support -- see doc/Testing.md
|
||||
@ -338,8 +362,6 @@ servald: $(OBJSDIR_SERVALD)/servald_features.o \
|
||||
|
||||
ifneq ($(SWIFTC),) # Only provide Swift targets if the Swift compiler is available.
|
||||
|
||||
test: servaldswift
|
||||
|
||||
# A servald equivalent whose main entry point and logging output is implemented
|
||||
# in the Swift language, rather than the C entry point in main.c. This exists
|
||||
# mainly to ensure that the Serval daemon library can be linked into a Swift
|
||||
|
105
configure.ac
105
configure.ac
@ -6,11 +6,11 @@ AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AC_ARG_VAR([AR], [Library archiver])
|
||||
AC_ARG_VAR([RANLIB], [Archive indexer])
|
||||
|
||||
dnl Specify Swift compiler
|
||||
AC_ARG_VAR([SWIFTC], [Swift compiler])
|
||||
AC_ARG_VAR([SWIFTCFLAGS], [Swift compiler flags])
|
||||
|
||||
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
|
||||
|
||||
dnl Specify default instance path
|
||||
AC_ARG_VAR([INSTANCE_PATH], [default instance path for servald])
|
||||
AS_IF([test "x$INSTANCE_PATH" != x], [AC_DEFINE_UNQUOTED([INSTANCE_PATH], ["$INSTANCE_PATH"], [default instance path])])
|
||||
@ -39,23 +39,61 @@ dnl Specify default Rhizome store directory
|
||||
AC_ARG_VAR([RHIZOME_STORE_PATH], [default Rhizome store directory])
|
||||
AS_IF([test "x$RHIZOME_STORE_PATH" != x], [AC_DEFINE_UNQUOTED([RHIZOME_STORE_PATH], ["$RHIZOME_STORE_PATH"], [default Rhizome store directory])])
|
||||
|
||||
dnl Set $host_os, which is needed by javac detection.
|
||||
AC_CANONICAL_SYSTEM
|
||||
dnl Set $build, $build_cpu, $build_vendor, $build_os to reflect the native
|
||||
dnl platform (the one on which the build is being performed), either from the
|
||||
dnl --build option, or by running config.guess.
|
||||
AC_CANONICAL_BUILD
|
||||
|
||||
dnl Check for C99 compiler and other tools.
|
||||
dnl Set $host, $host_cpu, $host_vendor, $host_os, either from --host option
|
||||
dnl (cross compilation), or falling back to $build (native compilation).
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
dnl $CFLAGS_TARGET is used in the Serval DNA Makefile and also passed in CFLAGS to all
|
||||
dnl sub-Makefiles, such as libsodium.
|
||||
CFLAGS_TARGET=''
|
||||
|
||||
dnl Check for C99 compiler, preprocessor and assembler.
|
||||
AC_PROG_CC_C99
|
||||
AC_PROG_CPP
|
||||
AM_PROG_AS
|
||||
|
||||
dnl Check for library creation tools.
|
||||
AC_CHECK_TOOL([AR], [ar], [:])
|
||||
AS_IF([test "x$AR" = x:], [AC_MSG_ERROR([Library archiver not found: ar])])
|
||||
|
||||
AC_CHECK_TOOL([RANLIB], [ranlib], [:])
|
||||
AS_IF([test "x$RANLIB" = x:], [AC_MSG_ERROR([Archive indexer not found: ranlib])])
|
||||
|
||||
dnl C preprocessor option to support cross-compiling.
|
||||
AX_APPEND_COMPILE_FLAGS(["-arch $host_cpu"], [CPPFLAGS])
|
||||
|
||||
dnl Check for a Swift 3 or 4 compiler; set SWIFTC if found.
|
||||
AC_PROG_SWIFTC
|
||||
|
||||
AS_IF([test "x$SWIFTC" != x], [ dnl
|
||||
dnl Discover the Swift compiler's target, which is determined by the --host option
|
||||
dnl in an Xcode cross build, and is its default target for a native build (which
|
||||
dnl may be affected by $SWIFTCFLAGS).
|
||||
AC_MSG_CHECKING([Swift target])
|
||||
|
||||
dnl Swift SDK names differ a little from Xcode names: iPhoneOS and iPhoneSimulator
|
||||
dnl are both represented as ios.
|
||||
swiftc_target=`$SWIFTC $SWIFTCFLAGS -version 2>&1 | sed -n -e 's/^Target: *//p'`
|
||||
AS_IF([test "x$swiftc_target" = x], [AC_MSG_ERROR([Swift compiler does not report its target: $SWIFTC $SWIFTCFLAGS -version])])
|
||||
|
||||
dnl In a build for Mac OSX (native or cross), ensure that the Swift target is high
|
||||
dnl enough to create a Swift package, which were not supported before Mac OSX 10.10.
|
||||
macosx_min_version=10.10
|
||||
AS_CASE([$swiftc_target],
|
||||
[[*-apple-macosx*]], [ dnl
|
||||
swiftc_target_version=[`echo "$swiftc_target" | sed -n -e 's/^.*-macosx//p'`]
|
||||
AS_VERSION_COMPARE([$swiftc_target_version], [$macosx_min_version], [ dnl
|
||||
CFLAGS_TARGET="-mmacosx-version-min=$macosx_min_version"
|
||||
swiftc_target=[`echo "$swiftc_target" | sed -n -e 's/-macosx.*$//p'`-macosx$macosx_min_version]
|
||||
])
|
||||
]
|
||||
)
|
||||
AC_MSG_RESULT([$swiftc_target])
|
||||
|
||||
dnl Check whether the Swift compiler will compile a simple Swift 4 program with the supplied flags.
|
||||
dnl If not, report failure but keep going.
|
||||
AC_PROG_SWIFTC_IS_SWIFT4
|
||||
@ -67,11 +105,31 @@ AS_IF([test "x$SWIFTC" != x], [ dnl
|
||||
SWIFTC=
|
||||
])
|
||||
])
|
||||
|
||||
dnl Add the -target option to SWIFTCFLAGS (if the user has already supplied a -target option in
|
||||
dnl SWIFTCFLAGS, then this prepended one will take precedence).
|
||||
SWIFTCFLAGS="-target $swiftc_target $SWIFTCFLAGS"
|
||||
])
|
||||
|
||||
dnl Check for a working Swift package manager, keep going if unsuccessful.
|
||||
AS_IF([test "x$SWIFTC" != x && test "x$SWIFT_BUILD" = x], [
|
||||
AC_PROG_SWIFT_PACKAGE_MANAGER
|
||||
])
|
||||
|
||||
dnl The C compilation flags used in all Serval-DNA Makefiles.
|
||||
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
|
||||
CFLAGS_TARGET="$CFLAGS_TARGET"
|
||||
CFLAGS="$CFLAGS_TARGET $CFLAGS"
|
||||
|
||||
export CPPFLAGS
|
||||
export CFLAGS
|
||||
|
||||
AC_SUBST([WRAPPER])
|
||||
AC_SUBST([CFLAGS_TARGET])
|
||||
AC_SUBST([SWIFTC])
|
||||
AC_SUBST([SWIFTCFLAGS])
|
||||
AC_SUBST([SWIFT_VERSION])
|
||||
AC_SUBST([SWIFT_BUILD])
|
||||
|
||||
dnl Various GCC function and variable attributes
|
||||
AX_GCC_FUNC_ATTRIBUTE(aligned)
|
||||
@ -90,8 +148,16 @@ dnl Swift compiler, so the gold linker is used to create dynamic libraries.
|
||||
dnl See doc/Development.md for details.
|
||||
AX_APPEND_LINK_FLAGS(-fuse-ld=gold)
|
||||
|
||||
dnl Check compiler options for compiling SQLite.
|
||||
AX_APPEND_COMPILE_FLAGS(
|
||||
dnl Early versions of GCC on Mac OS-X would fail without this flag, which soon
|
||||
dnl became deprecated and eventually removed some time around 2015.
|
||||
AX_APPEND_COMPILE_FLAGS([-no-cpp-precomp], [CFLAGS])
|
||||
|
||||
dnl Cause GCC to use pipes to connect the compilation stages using pipes instead
|
||||
dnl of temporary files.
|
||||
AX_APPEND_COMPILE_FLAGS([-pipe], [CFLAGS])
|
||||
|
||||
dnl Suppress certain compiler warnings when compiling SQLite.
|
||||
AX_APPEND_COMPILE_FLAGS([ \
|
||||
-Wno-empty-body \
|
||||
-Wno-unused-value \
|
||||
-Wno-unused-function \
|
||||
@ -99,8 +165,12 @@ AX_APPEND_COMPILE_FLAGS(
|
||||
-Wno-unused-variable \
|
||||
-Wno-unused-but-set-variable \
|
||||
-Wno-missing-field-initializers \
|
||||
-Wno-deprecated-declarations,
|
||||
[CFLAGS_SQLITE], [-Werror])
|
||||
-Wno-deprecated-declarations \
|
||||
'-Wno-#warnings' \
|
||||
],
|
||||
[CFLAGS_SQLITE], [-Werror])
|
||||
dnl Put a backslash before any '#' characters so it expands correctly in Makefile.in.
|
||||
CFLAGS_SQLITE="`echo "$CFLAGS_SQLITE" | sed 's/#/\\\\#/g'`"
|
||||
AC_SUBST([CFLAGS_SQLITE])
|
||||
|
||||
dnl Math library functions for spandsp
|
||||
@ -158,7 +228,7 @@ AC_CHECK_TYPES([off64_t], [have_off64_t=1], [have_off64_t=0])
|
||||
AC_CHECK_SIZEOF([off_t])
|
||||
|
||||
dnl There must be a 64-bit seek(2) system call of some kind
|
||||
AS_IF([test "x$have_lseek64_t" = "xno" -a "x$ac_cv_sizeof_off_t" != x8 ], [
|
||||
AS_IF([test "x$have_lseek64_t" = "xno" && test "x$ac_cv_sizeof_off_t" != x8 ], [
|
||||
AC_MSG_ERROR([Missing lseek64(2) system call])
|
||||
])
|
||||
|
||||
@ -205,11 +275,6 @@ AC_CHECK_HEADERS(
|
||||
|
||||
AC_SUBST([HAVE_JNI_H], [$ac_cv_header_jni_h])
|
||||
|
||||
dnl The entire libsodium source is in a subdirectory, and has its own configure
|
||||
dnl script.
|
||||
|
||||
AC_CONFIG_SUBDIRS([libsodium])
|
||||
|
||||
dnl Check if the Linux gettid() and tgkill() system calls are supported.
|
||||
AC_CHECK_FUNCS([gettid tgkill])
|
||||
AC_CACHE_CHECK([Linux thread system calls], ac_cv_have_linux_threads, [
|
||||
@ -284,8 +349,16 @@ dnl them in @DEFS@ on the command-line of every compilation invoked by make.
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_SUBST([CONFIG_H], [config.h])
|
||||
|
||||
dnl The entire libsodium source is in a subdirectory, and has its own configure
|
||||
dnl script.
|
||||
|
||||
AC_CONFIG_SUBDIRS([libsodium])
|
||||
|
||||
ac_configure_args="$ac_configure_args CC='$CC' CCAS='$CCAS' LD='$LD'"
|
||||
|
||||
AC_OUTPUT([
|
||||
Makefile
|
||||
testconfig.sh
|
||||
java-api/Makefile
|
||||
swift-client-api/Makefile
|
||||
])
|
||||
|
@ -159,9 +159,9 @@ Apple Mac OS X
|
||||
### Test utilities
|
||||
|
||||
The [OS X grep(1)][] , [OS X sed(1)][] and [OS X awk(1)][] tools provided by
|
||||
Apple Mac OS X are the BSD variants. The test scripts require the GNU variants
|
||||
with the names *ggrep*, *gsed* and *gawk*, which can be installed on Mac OS X
|
||||
using the [homebrew][] package manager:
|
||||
Apple Mac OS X are the BSD variants. The [test scripts][] require the GNU
|
||||
variants with the names *ggrep*, *gsed* and *gawk*, which can be installed on
|
||||
Mac OS X using the [homebrew][] package manager:
|
||||
|
||||
$ brew tap homebrew/dupes
|
||||
==> Tapping homebrew/dupes
|
||||
@ -255,6 +255,34 @@ environment variables or using the `VARNAME=value` syntax on its command line:
|
||||
* `SWIFTCFLAGS` extra command-line arguments to pass to the Swift compiler;
|
||||
analogous to `CFLAGS` for the C compiler
|
||||
|
||||
Swift Client API
|
||||
----------------
|
||||
|
||||
Serval DNA provides a *Swift Client API* as a [Swift module][] called
|
||||
**ServalClient**, which provides access to the services of the Serval DNA
|
||||
daemon through its [REST API][].
|
||||
|
||||
The Swift client API is written entirely in [Swift][] using the [URLSession][]
|
||||
Foundation class and related classes as the HTTP client. The API is covered
|
||||
by its own [test scripts][]. To date only the following parts of the [REST
|
||||
API][] are supported:
|
||||
|
||||
* [Keyring REST API][], test script is [keyringswift](../tests/keyringswift)
|
||||
|
||||
Using Swift modules
|
||||
-------------------
|
||||
|
||||
To use a [Swift module][] in your Swift program:
|
||||
|
||||
* add the directory containing the *ModuleName.swiftmodule* and
|
||||
*ModuleName.swiftdoc* files to your Swift import path, so the Swift source
|
||||
code can use `import ModuleName` to access the API definition;
|
||||
|
||||
* include the `libModuleName.a` static library in the link command line, either
|
||||
by giving its path explicitly as an argument, or by adding its containing
|
||||
directory to the link search path with the `-L` option and giving the
|
||||
`-lModuleName` option on the link command line.
|
||||
|
||||
About the examples
|
||||
------------------
|
||||
|
||||
@ -279,6 +307,9 @@ Available under the [Creative Commons Attribution 4.0 International licence][CC
|
||||
[CC BY 4.0]: ../LICENSE-DOCUMENTATION.md
|
||||
[Serval DNA]: ../README.md
|
||||
[build]: ../INSTALL.md
|
||||
[REST API]: ./REST-API.md
|
||||
[Keyring REST API]: ./REST-API-Keyring.md
|
||||
[test scripts]: ./Testing.md
|
||||
[configure.ac]: ../configure.ac
|
||||
[autoconf]: http://www.gnu.org/software/autoconf/autoconf.html
|
||||
[autoconf macro archive]: http://www.gnu.org/software/autoconf-archive/
|
||||
@ -307,5 +338,6 @@ Available under the [Creative Commons Attribution 4.0 International licence][CC
|
||||
[Swift module]: https://swift.org/package-manager/#modules
|
||||
[Swift 3]: https://swift.org/blog/swift-3-0-released/
|
||||
[Swift 4]: https://swift.org/blog/swift-4-0-released/
|
||||
[URLSession]: https://developer.apple.com/documentation/foundation/urlsession
|
||||
[gold]: https://en.wikipedia.org/wiki/Gold_(linker)
|
||||
[Bourne shell]: http://en.wikipedia.org/wiki/Bourne_shell
|
||||
|
@ -210,6 +210,10 @@ recognised:
|
||||
* **name**: the name; empty to clear the name, otherwise must conform to the
|
||||
rules for [Name](#name)
|
||||
|
||||
If a parameter is missing, then the corresponding field of the identity is left
|
||||
unchanged. If a parameter is set to an empty string, then the corresponding
|
||||
field of the identity is erased.
|
||||
|
||||
If any parameter contains an invalid value then the request returns [400 Bad
|
||||
Request][400]. If there is no unlocked identity with the given SID, this
|
||||
request returns [404 Not Found][404].
|
||||
|
14
keyring.c
14
keyring.c
@ -1612,6 +1612,10 @@ int keyring_commit(keyring_file *k)
|
||||
|
||||
int keyring_set_did_name(keyring_identity *id, const char *did, const char *name)
|
||||
{
|
||||
/* Do nothing if not changing either field. */
|
||||
if (!did && !name)
|
||||
return 0;
|
||||
|
||||
/* Find where to put it */
|
||||
keypair *kp = id->keypairs;
|
||||
while(kp){
|
||||
@ -1628,26 +1632,28 @@ int keyring_set_did_name(keyring_identity *id, const char *did, const char *name
|
||||
return -1;
|
||||
keyring_identity_add_keypair(id, kp);
|
||||
DEBUG(keyring, "Created DID/Name record for identity");
|
||||
bzero(kp->private_key, kp->private_key_len);
|
||||
bzero(kp->public_key, kp->public_key_len);
|
||||
}
|
||||
|
||||
/* Store DID as nul-terminated string. */
|
||||
{
|
||||
if (did) {
|
||||
size_t len = strlen(did);
|
||||
assert(len < kp->private_key_len);
|
||||
bcopy(did, &kp->private_key[0], len);
|
||||
bzero(&kp->private_key[len], kp->private_key_len - len);
|
||||
DEBUG_dump(keyring, "storing DID", &kp->private_key[0], kp->private_key_len);
|
||||
}
|
||||
|
||||
/* Store Name as nul-terminated string. */
|
||||
{
|
||||
if (name) {
|
||||
size_t len = strlen(name);
|
||||
assert(len < kp->public_key_len);
|
||||
bcopy(name, &kp->public_key[0], len);
|
||||
bzero(&kp->public_key[len], kp->public_key_len - len);
|
||||
DEBUG_dump(keyring, "storing Name", &kp->public_key[0], kp->public_key_len);
|
||||
}
|
||||
|
||||
DEBUG_dump(keyring, "storing DID",&kp->private_key[0],32);
|
||||
DEBUG_dump(keyring, "storing Name",&kp->public_key[0],64);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -272,7 +272,7 @@ static int restful_keyring_set(httpd_request *r, const char *remainder)
|
||||
keyring_identity *id = keyring_find_identity_sid(keyring, &r->sid1);
|
||||
if (!id)
|
||||
return http_request_keyring_response(r, 404, "Identity not found");
|
||||
if (keyring_set_did_name(id, did ? did : "", name ? name : "") == -1)
|
||||
if (keyring_set_did_name(id, did, name) == -1)
|
||||
return http_request_keyring_response(r, 500, "Could not set identity DID/Name");
|
||||
if (keyring_commit(keyring) == -1)
|
||||
return http_request_keyring_response(r, 500, "Could not store new identity");
|
||||
|
96
m4/ax_prog_swift_build_works.m4
Normal file
96
m4/ax_prog_swift_build_works.m4
Normal file
@ -0,0 +1,96 @@
|
||||
# Serval Project Swift language support
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_PROG_SWIFT_BUILD_WORKS
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# AX_PROG_SWIFT_BUILD_WORKS tests whether the Swift package manager "build"
|
||||
# command works.
|
||||
#
|
||||
# Requires the SWIFT shell variable to contain the path of the Swift package
|
||||
# manager executable (not the Swift compiler!), either relative to $PATH or
|
||||
# absolute; this will usually be just "swift". Expands the SWIFTCFLAGS shell
|
||||
# variable on the build command-line with -Xswiftc preceding each word.
|
||||
#
|
||||
# Sets the SWIFT_BUILD variable to the command to invoke the build-package
|
||||
# command, usually "$SWIFT build".
|
||||
#
|
||||
# To force a specific swift executable, either:
|
||||
#
|
||||
# - in configure.ac, set SWIFT=yourswift before calling
|
||||
# AX_PROG_SWIFT_PACKAGE_MANAGER, or
|
||||
#
|
||||
# - before invoking ./configure, export SWIFT=yourswift
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (C) 2016 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, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
AU_ALIAS([AC_PROG_SWIFT_BUILD_WORKS], [AX_PROG_SWIFT_BUILD_WORKS])
|
||||
AC_DEFUN([AX_PROG_SWIFT_BUILD_WORKS],[
|
||||
AC_REQUIRE([AX_TMPDIR_SWIFT])
|
||||
SWIFT_BUILD="$SWIFT build"
|
||||
AC_CACHE_CHECK([if $SWIFT_BUILD works], ac_cv_prog_swift_build_works, [
|
||||
AS_MKDIR_P(["$ax_tmpdir_swift/swift_package/Sources"])
|
||||
cat << EOF > "$ax_tmpdir_swift/swift_package/Package.swift"
|
||||
/* [#]line __oline__ "configure" */
|
||||
import PackageDescription
|
||||
let package = Package(name: "test")
|
||||
EOF
|
||||
cat << EOF > "$ax_tmpdir_swift/swift_package/Sources/test.swift"
|
||||
/* [#]line __oline__ "configure" */
|
||||
public func test() {
|
||||
test1()
|
||||
}
|
||||
fileprivate func test1() {}
|
||||
EOF
|
||||
ac_cv_prog_swift_build_works=no
|
||||
SWIFTBUILDFLAGS=
|
||||
for flag in $SWIFTCFLAGS; do
|
||||
AS_VAR_APPEND([SWIFTBUILDFLAGS], [" -Xswiftc $flag"])
|
||||
done
|
||||
AS_IF([AC_TRY_COMMAND(cd "$ax_tmpdir_swift/swift_package" && $SWIFT_BUILD $SWIFTBUILDFLAGS) >/dev/null 2>&1], [
|
||||
AS_IF([test -e "$ax_tmpdir_swift/swift_package/.build/debug/test.swiftmodule"], [
|
||||
ac_cv_prog_swift_build_works=yes
|
||||
])
|
||||
])
|
||||
AS_IF([test "x$ac_cv_prog_swift_build_works" != xyes], [
|
||||
echo "Package.swift:" >&AS_MESSAGE_LOG_FD
|
||||
cat "$ax_tmpdir_swift/swift_package/Package.swift" >&AS_MESSAGE_LOG_FD
|
||||
echo "failed program was:" >&AS_MESSAGE_LOG_FD
|
||||
cat "$ax_tmpdir_swift/swift_package/Sources/test.swift" >&AS_MESSAGE_LOG_FD
|
||||
])
|
||||
])
|
||||
AS_IF([test "x$ac_cv_prog_swift_build_works" != xyes], [
|
||||
AS_UNSET([SWIFT_BUILD])
|
||||
])
|
||||
AC_PROVIDE([$0])dnl
|
||||
])
|
70
m4/ax_prog_swift_package_manager.m4
Normal file
70
m4/ax_prog_swift_package_manager.m4
Normal file
@ -0,0 +1,70 @@
|
||||
# Serval Project Swift language support
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_PROG_SWIFT_PACKAGE_MANAGER
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# AX_PROG_SWIFT_PACKAGE_MANAGER tests for the presence of a Swift package
|
||||
# manager, ie, a "swift" executable that supports the "swift build" and
|
||||
# "swift package" commands.
|
||||
#
|
||||
# Sets the SWIFT shell variable to the name of the Swift executable (not the
|
||||
# Swift compiler!) either relative to $PATH or an absolute path if necessary;
|
||||
# this is usually just "swift".
|
||||
#
|
||||
# Sets the SWIFT_BUILD shell variable to the command to invoke the
|
||||
# build-package command, usually "$SWIFT build".
|
||||
#
|
||||
# Sets the SWIFT_PACKAGE variable to the command to invoke the package
|
||||
# management command, usually "$SWIFT package".
|
||||
#
|
||||
# To force a specific swift executable, either:
|
||||
#
|
||||
# - in configure.ac, set SWIFT=yourswift before calling
|
||||
# AX_PROG_SWIFT_PACKAGE_MANAGER, or
|
||||
#
|
||||
# - before invoking ./configure, export SWIFT=yourswift
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (C) 2016 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, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
AU_ALIAS([AC_PROG_SWIFT_PACKAGE_MANAGER], [AX_PROG_SWIFT_PACKAGE_MANAGER])
|
||||
AC_DEFUN([AX_PROG_SWIFT_PACKAGE_MANAGER],[
|
||||
AS_IF([test "x$SWIFT" = x], [AC_CHECK_PROGS([SWIFT], [swift])])
|
||||
AS_IF([test "x$SWIFT" = x], [
|
||||
echo "no Swift executable found in \$PATH" >&AS_MESSAGE_LOG_FD
|
||||
], [
|
||||
AX_PROG_SWIFT_BUILD_WORKS
|
||||
AX_PROG_SWIFT_PACKAGE_WORKS
|
||||
])
|
||||
AC_PROVIDE([$0])dnl
|
||||
])
|
86
m4/ax_prog_swift_package_works.m4
Normal file
86
m4/ax_prog_swift_package_works.m4
Normal file
@ -0,0 +1,86 @@
|
||||
# Serval Project Swift language support
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_PROG_SWIFT_PACKAGE_WORKS
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# AX_PROG_SWIFT_BUILD_WORKS tests whether the Swift package manager "package"
|
||||
# command works.
|
||||
#
|
||||
# Requires the SWIFT shell variable to contain the path of the Swift package
|
||||
# manager executable (not the Swift compiler!), either relative to $PATH or
|
||||
# absolute; this will usually be just "swift".
|
||||
#
|
||||
# Sets the SWIFT_PACKAGE variable to the command to invoke the manage-package
|
||||
# command, usually "swift package".
|
||||
#
|
||||
# To force a specific swift executable, either:
|
||||
#
|
||||
# - in configure.ac, set SWIFT=yourswift before calling
|
||||
# AX_PROG_SWIFT_PACKAGE_MANAGER, or
|
||||
#
|
||||
# - before invoking ./configure, export SWIFT=yourswift
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (C) 2016 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, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
AU_ALIAS([AC_PROG_SWIFT_PACKAGE_WORKS], [AX_PROG_SWIFT_PACKAGE_WORKS])
|
||||
AC_DEFUN([AX_PROG_SWIFT_PACKAGE_WORKS],[
|
||||
AC_REQUIRE([AC_PROG_SED])
|
||||
AC_REQUIRE([AX_TMPDIR_SWIFT])
|
||||
SWIFT_PACKAGE="$SWIFT package"
|
||||
AC_CACHE_CHECK([if $SWIFT_PACKAGE works], ac_cv_prog_swift_package_works, [
|
||||
AS_MKDIR_P(["$ax_tmpdir_swift/swift_package/Sources"])
|
||||
cat << \EOF > "$ax_tmpdir_swift/swift_package/Package.swift"
|
||||
/* [#]line __oline__ "configure" */
|
||||
import PackageDescription
|
||||
let package = Package(name: "test")
|
||||
EOF
|
||||
ac_cv_prog_swift_package_works=no
|
||||
AS_IF([AC_TRY_COMMAND(cd "$ax_tmpdir_swift/swift_package" >/dev/null && $SWIFT_PACKAGE dump-package) > "$ax_tmpdir_swift/swift_package_info.json"], [
|
||||
ac_swift_package_info=`$SED -e ':a;$!N;s/\n//;ta;s/ //g' "$ax_tmpdir_swift/swift_package_info.json"`
|
||||
AS_IF([test "x$ac_swift_package_info" = ['x{"dependencies":[],"exclude":[],"name":"test","targets":[]}']], [
|
||||
ac_cv_prog_swift_package_works=yes
|
||||
])
|
||||
])
|
||||
AS_IF([test "x$ac_cv_prog_swift_package_works" != xyes], [
|
||||
echo "Package.swift:" >&AS_MESSAGE_LOG_FD
|
||||
cat "$ax_tmpdir_swift/swift_package/Package.swift" >&AS_MESSAGE_LOG_FD
|
||||
echo "failed output was:" >&AS_MESSAGE_LOG_FD
|
||||
echo "$ac_swift_package_info" >&AS_MESSAGE_LOG_FD
|
||||
])
|
||||
])
|
||||
AS_IF([test "x$ac_cv_prog_swift_package_works" != xyes], [
|
||||
AS_UNSET([SWIFT_PACKAGE])
|
||||
])
|
||||
AC_PROVIDE([$0])dnl
|
||||
])
|
56
swift-client-api/Makefile.in
Normal file
56
swift-client-api/Makefile.in
Normal file
@ -0,0 +1,56 @@
|
||||
# Makefile.in for Serval DNA Swift API
|
||||
# vim: noet ts=8 sts=0 sw=8
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
bindir=@bindir@
|
||||
sbindir=@sbindir@
|
||||
sysconfdir=@sysconfdir@
|
||||
localstatedir=@localstatedir@
|
||||
srcdir=@srcdir@
|
||||
abs_builddir=@abs_builddir@
|
||||
|
||||
SWIFT_MODULE_NAME= ServalClient
|
||||
SWIFT_PACKAGE_DIR= $(srcdir)/package
|
||||
SWIFT_BUILD_DIR= $(abs_builddir)/build
|
||||
|
||||
SWIFTC= @SWIFTC@
|
||||
SWIFTCFLAGS= @SWIFTCFLAGS@
|
||||
SWIFTCFLAGS+= -I $(srcdir)
|
||||
|
||||
SWIFT_BUILD= @SWIFT_BUILD@
|
||||
SWIFT_BUILD_FLAGS= $(addprefix -Xswiftc , $(SWIFTCFLAGS))
|
||||
|
||||
DEFS= @DEFS@
|
||||
SWIFTDEFS= $(addprefix -Xcc , $(DEFS))
|
||||
|
||||
.PHONY: all check check_swiftc check_swift_build swiftmodule clean
|
||||
|
||||
all: check swiftmodule swift-client-util
|
||||
|
||||
check: check_swiftc check_swift_build
|
||||
|
||||
check_swiftc:
|
||||
@if [ -z "$(SWIFTC)" ]; then echo "No swift compiler configured" >&2; exit 1; fi
|
||||
@if ! $(SWIFTC) -version >/dev/null; then echo "Swift compiler not executable" >&2; exit 1; fi
|
||||
|
||||
check_swift_build:
|
||||
@if [ -z "$(SWIFT_BUILD)" ]; then echo "No swift package manager configured" >&2; exit 1; fi
|
||||
@if ! $(SWIFT_BUILD) -h >/dev/null; then echo "Swift package manager not executable" >&2; exit 1; fi
|
||||
|
||||
# The Swift 3 package manager --chdir option was replaced with --package-path
|
||||
# in Swift 4, so to support both, avoid the options altogether and use "cd
|
||||
# package-dir && swift build" instead.
|
||||
swiftmodule:
|
||||
mkdir -p $(SWIFT_BUILD_DIR) && \
|
||||
cd $(SWIFT_PACKAGE_DIR) && \
|
||||
$(SWIFT_BUILD) --build-path $(SWIFT_BUILD_DIR) $(SWIFT_BUILD_FLAGS) $(SWIFTDEFS)
|
||||
|
||||
$(SWIFT_BUILD_DIR)/debug/libServalClient.a: swiftmodule
|
||||
|
||||
swift-client-util: $(srcdir)/client_util.swift $(SWIFT_BUILD_DIR)/debug/libServalClient.a
|
||||
@echo SWIFT $@
|
||||
@$(SWIFTC) -emit-executable $(SWIFTCFLAGS) $(SWIFTDEFS) -I $(SWIFT_BUILD_DIR)/debug -o $@ $^
|
||||
|
||||
clean:
|
||||
$(RM) -r $(SWIFT_BUILD_DIR)
|
||||
$(RM) swift-client-util
|
218
swift-client-api/client_util.swift
Normal file
218
swift-client-api/client_util.swift
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
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()
|
7
swift-client-api/package/Package.swift
Normal file
7
swift-client-api/package/Package.swift
Normal file
@ -0,0 +1,7 @@
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "ServalClient"
|
||||
)
|
||||
|
||||
products.append(Product(name: "ServalClient", type: .Library(.Static), modules: "ServalClient"))
|
109
swift-client-api/package/Sources/abstract_id.swift
Normal file
109
swift-client-api/package/Sources/abstract_id.swift
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
Serval DNA Swift API
|
||||
Copyright (C) 2016 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 Foundation
|
||||
|
||||
/* All the Serval Id types (SID, BundleId, etc.) are binary blobs that are
|
||||
* typically represented in hexadecimal text format. Some also have an
|
||||
* "abbreviated" format.
|
||||
*/
|
||||
|
||||
public protocol AbstractId : Hashable, CustomStringConvertible {
|
||||
init(fromBinary: [UInt8])
|
||||
init?(fromHex: String)
|
||||
var binary : [UInt8] { get }
|
||||
var hexUpper : String { get }
|
||||
}
|
||||
|
||||
public protocol AbbreviatedId : AbstractId {
|
||||
var abbreviation : String { get }
|
||||
}
|
||||
|
||||
/* Implementations of AbstractId that specialise GenericIdImplementation must
|
||||
* also implement the ConcreteId protocol, which allows users to discover
|
||||
* properties of the specialised type without instantiating it.
|
||||
*/
|
||||
|
||||
public protocol ConcreteId {
|
||||
static var byteCount : Int { get }
|
||||
static var mimeType : String { get }
|
||||
}
|
||||
|
||||
/* All Serval Id types are specialisations of this generic implementation,
|
||||
* which stores the Id's value as an array of bytes, and derives all other
|
||||
* properties from that representation.
|
||||
*/
|
||||
|
||||
public class GenericIdImplementation : AbstractId {
|
||||
public let binary : [UInt8]
|
||||
|
||||
public static func == (lhs: GenericIdImplementation, rhs: GenericIdImplementation) -> Bool {
|
||||
return lhs.binary == rhs.binary
|
||||
}
|
||||
|
||||
public var hashValue : Int {
|
||||
return self.binary.map { $0.hashValue }.reduce(0) {
|
||||
(($0 << 8) | Int(UInt($0) >> UInt((MemoryLayout<Int>.size - 1) * 8))) ^ $1
|
||||
}
|
||||
}
|
||||
|
||||
internal init(fill: UInt8) {
|
||||
self.binary = Array(repeating: fill, count: (type(of:self) as! ConcreteId.Type).byteCount)
|
||||
}
|
||||
|
||||
public required init(fromBinary binary: [UInt8]) {
|
||||
self.binary = binary
|
||||
assert(self.binary.count == (type(of:self) as! ConcreteId.Type).byteCount)
|
||||
}
|
||||
|
||||
public required init?(fromHex hex: String) {
|
||||
var binary = Array(repeating: UInt8(0), count: (type(of:self) as! ConcreteId.Type).byteCount)
|
||||
var index = hex.startIndex
|
||||
for i in 0 ..< binary.count {
|
||||
guard let next = hex.index(index, offsetBy: 2, limitedBy: hex.endIndex) else {
|
||||
return nil
|
||||
}
|
||||
let digits = hex.substring(with: index ..< next)
|
||||
guard let byte = UInt8(digits, radix: 16) else {
|
||||
return nil
|
||||
}
|
||||
binary[i] = byte
|
||||
index = next
|
||||
}
|
||||
guard index == hex.endIndex else {
|
||||
return nil
|
||||
}
|
||||
self.binary = binary
|
||||
}
|
||||
|
||||
public var hexUpper : String {
|
||||
return self.binary.map { String(format: "%02hhX", $0) }.joined()
|
||||
}
|
||||
|
||||
internal func hexUpper(digitCount: Int) -> String {
|
||||
let byteCount = (digitCount + 1) / 2
|
||||
assert(byteCount <= self.binary.count)
|
||||
let hex = self.binary[0 ..< byteCount].map { String(format: "%02hhX", $0) }.joined()
|
||||
return digitCount == byteCount * 2 ? hex : hex.substring(with: hex.startIndex ..< hex.index(hex.endIndex, offsetBy: -1))
|
||||
}
|
||||
|
||||
public var description : String {
|
||||
return "\(type(of:self))(fromHex: \"\(self.hexUpper)\")"
|
||||
}
|
||||
}
|
31
swift-client-api/package/Sources/debug.swift
Normal file
31
swift-client-api/package/Sources/debug.swift
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Serval DNA Swift API
|
||||
Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#if os(Linux)
|
||||
import Glibc
|
||||
#else
|
||||
import Darwin
|
||||
#endif
|
||||
|
||||
public struct ErrorOutputStream: TextOutputStream {
|
||||
public mutating func write(_ string: String) { fputs(string, stderr) }
|
||||
}
|
||||
|
||||
public var errorStream = ErrorOutputStream()
|
||||
public var debugStream = errorStream
|
240
swift-client-api/package/Sources/keyring.swift
Normal file
240
swift-client-api/package/Sources/keyring.swift
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
Serval DNA Swift API
|
||||
Copyright (C) 2016 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 Foundation
|
||||
|
||||
public class ServalKeyring {
|
||||
|
||||
public struct Identity {
|
||||
public let sid : SubscriberId
|
||||
public let identity : SubscriberId
|
||||
public let did : String?
|
||||
public let name : String?
|
||||
}
|
||||
|
||||
public static func listIdentities(client: ServalRestfulClient = ServalRestfulClient(),
|
||||
pin: String? = nil,
|
||||
completionHandler: @escaping ([Identity]?, Error?) -> Void)
|
||||
-> ServalRestfulClient.Request
|
||||
{
|
||||
var param = [String: String]()
|
||||
if pin != nil { param["pin"] = pin }
|
||||
return client.createRequest(path: "restful/keyring/identities.json",
|
||||
query: param) { (statusCode, json, error) in
|
||||
if let error = error {
|
||||
completionHandler(nil, error)
|
||||
return
|
||||
}
|
||||
guard statusCode! == 200 else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.requestFailed(statusCode: statusCode!))
|
||||
return
|
||||
}
|
||||
guard let json_top = json as? [String: Any] else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "root is not JSON object"))
|
||||
return
|
||||
}
|
||||
var column_count = 0
|
||||
var sid_index = -1
|
||||
var identity_index = -1
|
||||
var did_index = -1
|
||||
var name_index = -1
|
||||
guard let header = json_top["header"] as? [String] else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "missing 'header' element"))
|
||||
return
|
||||
}
|
||||
for text in header {
|
||||
if text == "sid" {
|
||||
sid_index = column_count
|
||||
}
|
||||
else if text == "identity" {
|
||||
identity_index = column_count
|
||||
}
|
||||
else if text == "did" {
|
||||
did_index = column_count
|
||||
}
|
||||
else if text == "name" {
|
||||
name_index = column_count
|
||||
}
|
||||
column_count += 1
|
||||
}
|
||||
guard sid_index != -1 else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "missing 'sid' column"))
|
||||
return
|
||||
}
|
||||
guard identity_index != -1 else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "missing 'identity' column"))
|
||||
return
|
||||
}
|
||||
guard let rows = json_top["rows"] as? [[Any]] else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "missing 'rows' element"))
|
||||
return
|
||||
}
|
||||
var identities : [Identity] = []
|
||||
for row in rows {
|
||||
guard row.count == column_count else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "row has \(row.count) elements; should be \(column_count)"))
|
||||
return
|
||||
}
|
||||
var opt_sid : SubscriberId?
|
||||
var opt_identity : SubscriberId?
|
||||
var did : String?
|
||||
var name : String?
|
||||
if sid_index != -1 {
|
||||
guard let hex = row[sid_index] as? String else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "sid value is not String"))
|
||||
return
|
||||
}
|
||||
opt_sid = SubscriberId(fromHex: hex)
|
||||
guard opt_sid != nil else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "sid value is not hex: \(hex)"))
|
||||
return
|
||||
}
|
||||
}
|
||||
if identity_index != -1 {
|
||||
guard let hex = row[identity_index] as? String else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "identity value is not String"))
|
||||
return
|
||||
}
|
||||
opt_identity = SubscriberId(fromHex: hex)
|
||||
guard opt_sid != nil else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "identity value is not hex: \(hex)"))
|
||||
return
|
||||
}
|
||||
}
|
||||
if did_index != -1 {
|
||||
let value = row[did_index]
|
||||
if value as? NSNull == nil {
|
||||
guard let text = value as? String else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "did value is not String: \(value)"))
|
||||
return
|
||||
}
|
||||
if !text.isEmpty {
|
||||
did = text
|
||||
}
|
||||
}
|
||||
}
|
||||
if name_index != -1 {
|
||||
let value = row[name_index]
|
||||
if value as? NSNull == nil {
|
||||
guard let text = value as? String else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "name value is not String: \(value)"))
|
||||
return
|
||||
}
|
||||
if !text.isEmpty {
|
||||
name = text
|
||||
}
|
||||
}
|
||||
}
|
||||
identities.append(Identity(sid: opt_sid!, identity: opt_identity!, did: did, name: name))
|
||||
}
|
||||
completionHandler(identities, nil)
|
||||
}!
|
||||
}
|
||||
|
||||
private static func singleIdentityRequest(client: ServalRestfulClient = ServalRestfulClient(),
|
||||
path: String,
|
||||
query: [String: String] = [:],
|
||||
successStatusCodes: Set<Int> = [200],
|
||||
completionHandler: @escaping (Identity?, Error?) -> Void)
|
||||
-> ServalRestfulClient.Request
|
||||
{
|
||||
return client.createRequest(path: path, query: query) { (statusCode, json, error) in
|
||||
if let error = error {
|
||||
completionHandler(nil, error)
|
||||
return
|
||||
}
|
||||
guard successStatusCodes.contains(statusCode!) else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.requestFailed(statusCode: statusCode!))
|
||||
return
|
||||
}
|
||||
guard let json_top = json as? [String: Any] else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "root is not JSON object"))
|
||||
return
|
||||
}
|
||||
guard let json_identity = json_top["identity"] as? [String: Any] else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "'identity' is not JSON object"))
|
||||
return
|
||||
}
|
||||
guard let sid_hex = json_identity["sid"] as? String else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "'sid' is not String"))
|
||||
return
|
||||
}
|
||||
guard let identity_hex = json_identity["identity"] as? String else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "'identity' is not String"))
|
||||
return
|
||||
}
|
||||
guard let sid = SubscriberId(fromHex: sid_hex) else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "invalid 'sid': \(sid_hex)"))
|
||||
return
|
||||
}
|
||||
guard let identity = SubscriberId(fromHex: identity_hex) else {
|
||||
completionHandler(nil, ServalRestfulClient.Exception.invalidJson(reason: "invalid 'identity': \(identity_hex)"))
|
||||
return
|
||||
}
|
||||
let did = json_identity["did"] as? String ?? ""
|
||||
let name = json_identity["name"] as? String ?? ""
|
||||
completionHandler(Identity(sid: sid, identity: identity, did: did, name: name), nil)
|
||||
}!
|
||||
}
|
||||
|
||||
public static func addIdentity(client: ServalRestfulClient = ServalRestfulClient(),
|
||||
did: String? = nil,
|
||||
name: String? = nil,
|
||||
pin: String? = nil,
|
||||
completionHandler: @escaping (Identity?, Error?) -> Void)
|
||||
-> ServalRestfulClient.Request
|
||||
{
|
||||
var param = [String: String]()
|
||||
if did != nil { param["did"] = did }
|
||||
if name != nil { param["name"] = name }
|
||||
if pin != nil { param["pin"] = pin }
|
||||
return self.singleIdentityRequest(client: client,
|
||||
path: "restful/keyring/add",
|
||||
query: param,
|
||||
successStatusCodes: [201],
|
||||
completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
public static func removeIdentity(client: ServalRestfulClient = ServalRestfulClient(),
|
||||
sid: SubscriberId,
|
||||
pin: String? = nil,
|
||||
completionHandler: @escaping (Identity?, Error?) -> Void)
|
||||
-> ServalRestfulClient.Request
|
||||
{
|
||||
var param = [String: String]()
|
||||
if pin != nil { param["pin"] = pin }
|
||||
return self.singleIdentityRequest(client: client, path: "restful/keyring/\(sid.hexUpper)/remove", query: param, completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
public static func setIdentity(client: ServalRestfulClient = ServalRestfulClient(),
|
||||
sid: SubscriberId,
|
||||
did: String? = nil,
|
||||
name: String? = nil,
|
||||
pin: String? = nil,
|
||||
completionHandler: @escaping (Identity?, Error?) -> Void)
|
||||
-> ServalRestfulClient.Request
|
||||
{
|
||||
var param = [String: String]()
|
||||
if did != nil { param["did"] = did }
|
||||
if name != nil { param["name"] = name }
|
||||
if pin != nil { param["pin"] = pin }
|
||||
return self.singleIdentityRequest(client: client, path: "restful/keyring/\(sid.hexUpper)/set", query: param, completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
}
|
119
swift-client-api/package/Sources/restful_client.swift
Normal file
119
swift-client-api/package/Sources/restful_client.swift
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
Serval DNA Swift API
|
||||
Copyright (C) 2016 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 Foundation
|
||||
|
||||
public class ServalRestfulClient {
|
||||
|
||||
public struct Configuration {
|
||||
public let host : String
|
||||
public let port : Int16
|
||||
public let username : String
|
||||
public let password : String
|
||||
|
||||
public func with(host: String? = nil, port: Int16? = nil, username: String? = nil, password: String? = nil) -> Configuration {
|
||||
return Configuration(host: host ?? type(of:self).default.host,
|
||||
port: port ?? type(of:self).default.port,
|
||||
username: username ?? type(of:self).default.username,
|
||||
password: password ?? type(of:self).default.password)
|
||||
}
|
||||
|
||||
public static let `default` = Configuration(
|
||||
host: "127.0.0.1",
|
||||
port : 4110,
|
||||
username: "",
|
||||
password: ""
|
||||
)
|
||||
}
|
||||
|
||||
public let configuration : Configuration
|
||||
|
||||
public enum Exception : Error {
|
||||
case requestFailed(statusCode: Int)
|
||||
case missingContentType
|
||||
case invalidContentType(mimeType: String)
|
||||
case malformedJson
|
||||
case invalidJson(reason: String)
|
||||
}
|
||||
|
||||
public struct Request {
|
||||
fileprivate let urlSession : URLSession
|
||||
fileprivate let dataTask : URLSessionDataTask
|
||||
public func close() {
|
||||
print("TODO: close", to: &debugStream) // TODO
|
||||
}
|
||||
}
|
||||
|
||||
public init(configuration: Configuration = Configuration.default) {
|
||||
self.configuration = configuration
|
||||
}
|
||||
|
||||
public func createRequest(path: String,
|
||||
query: [String: String] = [:],
|
||||
completionHandler: @escaping (Int?, Any?, Error?) -> Void)
|
||||
-> Request?
|
||||
{
|
||||
var urlComponents = URLComponents()
|
||||
urlComponents.scheme = "http"
|
||||
urlComponents.host = self.configuration.host
|
||||
urlComponents.port = Int(self.configuration.port)
|
||||
urlComponents.path = "/\(path)"
|
||||
var items : [URLQueryItem] = []
|
||||
for (name, value) in query {
|
||||
items.append(URLQueryItem(name: name, value: value))
|
||||
}
|
||||
urlComponents.queryItems = items
|
||||
if !query.isEmpty {
|
||||
precondition(urlComponents.percentEncodedQuery != nil)
|
||||
}
|
||||
let url = urlComponents.url!
|
||||
let session = URLSession(configuration: URLSessionConfiguration.default)
|
||||
debugPrint(url, to: &debugStream)
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "GET"
|
||||
if !self.configuration.username.isEmpty {
|
||||
let data = (self.configuration.username + ":" + self.configuration.password).data(using: String.Encoding.utf8)
|
||||
if let base64 = data?.base64EncodedString() {
|
||||
request.setValue("Basic \(base64)", forHTTPHeaderField: "Authorization")
|
||||
}
|
||||
}
|
||||
let dataTask = session.dataTask(with: request) { (data, response, error) in
|
||||
if let error = error {
|
||||
completionHandler(nil, nil, error)
|
||||
return
|
||||
}
|
||||
let httpResponse = response as! HTTPURLResponse
|
||||
guard let mimeType = httpResponse.mimeType else {
|
||||
completionHandler(nil, nil, ServalRestfulClient.Exception.missingContentType)
|
||||
return
|
||||
}
|
||||
guard mimeType == "application/json" else {
|
||||
completionHandler(nil, nil, ServalRestfulClient.Exception.invalidContentType(mimeType: mimeType))
|
||||
return
|
||||
}
|
||||
guard let json = try? JSONSerialization.jsonObject(with: data!, options: []) else {
|
||||
completionHandler(nil, nil, ServalRestfulClient.Exception.malformedJson)
|
||||
return
|
||||
}
|
||||
completionHandler(httpResponse.statusCode, json, nil)
|
||||
}
|
||||
dataTask.resume()
|
||||
return Request(urlSession: session, dataTask: dataTask)
|
||||
}
|
||||
}
|
32
swift-client-api/package/Sources/subscriber_id.swift
Normal file
32
swift-client-api/package/Sources/subscriber_id.swift
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
Serval DNA Swift API
|
||||
Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
public class SubscriberId : GenericIdImplementation, ConcreteId, AbbreviatedId {
|
||||
public static let byteCount = 32
|
||||
|
||||
public static let mimeType = "serval-mesh/sid"
|
||||
|
||||
public var abbreviation : String {
|
||||
return "sid:\(self.hexUpper(digitCount: 6))*"
|
||||
}
|
||||
|
||||
public static let any = SubscriberId(fill: 0)
|
||||
|
||||
public static let broadcast = SubscriberId(fill: 0xff)
|
||||
}
|
@ -2,3 +2,4 @@
|
||||
# This file is sourced by some of the test scripts in ./tests.
|
||||
# It defines some settings that were established by ./configure.
|
||||
JAVAC="@JAVAC@"
|
||||
SWIFTC="@SWIFTC@"
|
||||
|
12
testdefs.sh
12
testdefs.sh
@ -83,7 +83,7 @@ extract_stdout_keyvalue_optional() {
|
||||
esac
|
||||
local _label_re=$(escape_grep_basic "$_label")
|
||||
local _delim_re=$(escape_grep_basic "$_delim")
|
||||
local _line=$($GREP "^$_label_re$_delim_re" "$TFWSTDOUT")
|
||||
local _line=$($GREP "^$_label_re$_delim_re$_rexp" "$TFWSTDOUT")
|
||||
local _value=
|
||||
local _return=1
|
||||
if [ -n "$_line" ]; then
|
||||
@ -104,6 +104,16 @@ extract_stdout_keyvalue() {
|
||||
assert --message="stdout of ($TFWEXECUTED) contains valid '$_label:' line" --stdout extract_stdout_keyvalue_optional "$@"
|
||||
}
|
||||
|
||||
# Assert function for the output of servald commands that return "key:value\n"
|
||||
# pairs.
|
||||
assert_stdout_keyvalue() {
|
||||
local _label="$1"
|
||||
local _value="$2"
|
||||
local _extracted
|
||||
extract_stdout_keyvalue _extracted "$_label" '.*'
|
||||
assert --message="stdout of ($executed) '$_label:' line does not equal '$_value'" --stdout test "$_extracted" = "$_value"
|
||||
}
|
||||
|
||||
# Parse the standard result set output produced by the immediately preceding command
|
||||
# command into the following shell variables:
|
||||
# NCOLS the number of columns
|
||||
|
34
testdefs_swift.sh
Normal file
34
testdefs_swift.sh
Normal file
@ -0,0 +1,34 @@
|
||||
# Definitions for test suites using Swift
|
||||
# Copyright 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.
|
||||
|
||||
swift_client_util="$servald_build_root/swift-client-api/swift-client-util"
|
||||
|
||||
SWIFT_TEST_USER="steve"
|
||||
SWIFT_TEST_PASSWORD="jobs"
|
||||
|
||||
assert_swift_executable_exists() {
|
||||
executeSwiftOk help
|
||||
}
|
||||
|
||||
executeSwiftOk() {
|
||||
executeOk --stdout --stderr --core-backtrace \
|
||||
--executable="$swift_client_util" \
|
||||
-- \
|
||||
--port "${SWIFT_TEST_PORT?}" \
|
||||
${SWIFT_TEST_USER:+--user "$SWIFT_TEST_USER" --password "$SWIFT_TEST_PASSWORD"} \
|
||||
"$@"
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
# Aggregation of all tests except high-load stress tests.
|
||||
#
|
||||
# Copyright 2012-2014 Serval Project Inc.
|
||||
# Copyright 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
|
||||
@ -43,5 +44,8 @@ includeTests meshmbrestful
|
||||
if type -p "$JAVAC" >/dev/null; then
|
||||
includeTests alljava
|
||||
fi
|
||||
if type -p "$SWIFTC" >/dev/null; then
|
||||
includeTests keyringswift
|
||||
fi
|
||||
|
||||
runTests "$@"
|
||||
|
155
tests/keyringswift
Executable file
155
tests/keyringswift
Executable file
@ -0,0 +1,155 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Tests for Keyring Swift API.
|
||||
#
|
||||
# Copyright 2015 Serval Project Inc.
|
||||
# Copyright 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.
|
||||
|
||||
source "${0%/*}/../testframework.sh"
|
||||
source "${0%/*}/../testdefs.sh"
|
||||
source "${0%/*}/../testdefs_swift.sh"
|
||||
|
||||
setup() {
|
||||
setup_servald
|
||||
set_instance +A
|
||||
set_keyring_config
|
||||
set_extra_config
|
||||
executeOk_servald config \
|
||||
set "api.restful.users.$SWIFT_TEST_USER.password" "$SWIFT_TEST_PASSWORD"
|
||||
if [ -z "$IDENTITY_COUNT" ]; then
|
||||
create_single_identity
|
||||
else
|
||||
create_identities $IDENTITY_COUNT
|
||||
fi
|
||||
export SERVALD_RHIZOME_DB_RETRY_LIMIT_MS=60000
|
||||
start_servald_server
|
||||
wait_until servald_restful_http_server_started +A
|
||||
get_servald_restful_http_server_port SWIFT_TEST_PORT +A
|
||||
}
|
||||
|
||||
teardown() {
|
||||
stop_all_servald_servers
|
||||
kill_all_servald_processes
|
||||
assert_no_servald_processes
|
||||
report_all_servald_servers
|
||||
}
|
||||
|
||||
set_keyring_config() {
|
||||
executeOk_servald config \
|
||||
set log.console.level debug \
|
||||
set debug.httpd on \
|
||||
set debug.keyring on \
|
||||
set debug.verbose on
|
||||
}
|
||||
|
||||
set_extra_config() {
|
||||
:
|
||||
}
|
||||
|
||||
doc_keyringList="Swift API list keyring identities"
|
||||
setup_keyringList() {
|
||||
IDENTITY_COUNT=10
|
||||
DIDA1=123123123
|
||||
NAMEA1='Joe Bloggs'
|
||||
DIDA5=567567567
|
||||
setup
|
||||
}
|
||||
test_keyringList() {
|
||||
executeSwiftOk keyring list
|
||||
tfw_cat --stdout --stderr
|
||||
assert_keyring_list $IDENTITY_COUNT
|
||||
}
|
||||
|
||||
doc_keyringListPin="Swift API list keyring identities, with PIN"
|
||||
setup_keyringListPin() {
|
||||
IDENTITY_COUNT=3
|
||||
PINA1='wif waf'
|
||||
setup
|
||||
}
|
||||
test_keyringListPin() {
|
||||
# First, list without supplying the PIN
|
||||
executeSwiftOk keyring list
|
||||
tfw_cat --stdout --stderr
|
||||
assert_keyring_list $((IDENTITY_COUNT - 1))
|
||||
# Then, list supplying the PIN
|
||||
executeSwiftOk keyring list --pin "$PINA1"
|
||||
tfw_cat --stdout --stderr
|
||||
assert_keyring_list $IDENTITY_COUNT
|
||||
}
|
||||
|
||||
doc_keyringAddDidName="Swift API add new keyring identity"
|
||||
setup_keyringAddDidName() {
|
||||
IDENTITY_COUNT=1
|
||||
DIDA2=123123123
|
||||
NAMEA2='Joe Bloggs'
|
||||
setup
|
||||
}
|
||||
test_keyringAddDidName() {
|
||||
executeSwiftOk keyring add did "$DIDA2" name "$NAMEA2"
|
||||
tfw_cat --stdout --stderr
|
||||
assert_stdout_keyvalue did "$DIDA2"
|
||||
assert_stdout_keyvalue name "$NAMEA2"
|
||||
extract_stdout_keyvalue SID sid "$rexp_sid"
|
||||
extract_stdout_keyvalue ID identity "$rexp_id"
|
||||
executeOk_servald keyring list
|
||||
assert_keyring_list 2
|
||||
assertStdoutGrep --stderr --matches=1 "^$SID:$ID:$DIDA2:$NAMEA2\$"
|
||||
}
|
||||
|
||||
doc_keyringRemove="Swift API remove keyring identity"
|
||||
setup_keyringRemove() {
|
||||
IDENTITY_COUNT=2
|
||||
setup
|
||||
}
|
||||
test_keyringRemove() {
|
||||
executeSwiftOk keyring remove "$SIDA1"
|
||||
assert_stdout_keyvalue sid "$SIDA1"
|
||||
executeOk_servald keyring list
|
||||
assert_keyring_list 1
|
||||
assertStdoutGrep --matches=0 "^$SIDA1:"
|
||||
assertStdoutGrep --matches=1 "^$SIDA2:"
|
||||
executeSwiftOk keyring remove "$SIDA2"
|
||||
assert_stdout_keyvalue sid "$SIDA2"
|
||||
executeOk_servald keyring list
|
||||
assert_keyring_list 0
|
||||
}
|
||||
|
||||
doc_keyringSetDidName="Swift API set DID and Name of keyring identity"
|
||||
setup_keyringSetDidName() {
|
||||
IDENTITY_COUNT=1
|
||||
setup
|
||||
}
|
||||
test_keyringSetDidName() {
|
||||
executeSwiftOk keyring set "$SIDA1" did '123456'
|
||||
assert_stdout_keyvalue sid "$SIDA1"
|
||||
assert_stdout_keyvalue identity "$IDA1"
|
||||
assert_stdout_keyvalue did "123456"
|
||||
assert_stdout_keyvalue name ""
|
||||
executeOk_servald keyring list
|
||||
assert_keyring_list 1
|
||||
assertStdoutGrep --stderr --matches=1 "^$SIDA1:$IDA1:123456:\$"
|
||||
executeSwiftOk keyring set "$SIDA1" name 'Display Name'
|
||||
assert_stdout_keyvalue sid "$SIDA1"
|
||||
assert_stdout_keyvalue identity "$IDA1"
|
||||
assert_stdout_keyvalue did "123456"
|
||||
assert_stdout_keyvalue name "Display Name"
|
||||
executeOk_servald keyring list
|
||||
assert_keyring_list 1
|
||||
assertStdoutGrep --stderr --matches=1 "^$SIDA1:$IDA1:123456:Display Name\$"
|
||||
}
|
||||
|
||||
runTests "$@"
|
Loading…
Reference in New Issue
Block a user