mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-19 21:27:57 +00:00
Add Swift daemon API, use in 'servaldswift'
The daemon API is built as a Swift module called ServalDNA. The new CliContext class allows easy implementation of CLI output using Swift code. The new CliContextFile subclass is the obvious first implementation, equivalent to cli_stdio.c. The 'servaldswift' executable now uses CliContextFile to print its CLI output to standard output. The new delegated log output support constructs each log line in a buffer and prints it by calling the delegate's 'print' function at end-of-line. The 'servaldswift' executable now provides a log output delegate in Swift that simply prints to standard error, replacing log_output_console.o, which is omitted from its link.
This commit is contained in:
parent
3ffa4b10af
commit
a79156c4d0
3
.gitignore
vendored
3
.gitignore
vendored
@ -11,6 +11,8 @@
|
|||||||
*.a
|
*.a
|
||||||
*.suo
|
*.suo
|
||||||
.*.sw?
|
.*.sw?
|
||||||
|
*.swiftdoc
|
||||||
|
*.swiftmodule
|
||||||
/VERSION.txt
|
/VERSION.txt
|
||||||
/configure
|
/configure
|
||||||
/autom4te.cache
|
/autom4te.cache
|
||||||
@ -37,6 +39,7 @@ test.*.log
|
|||||||
/java-api/Makefile
|
/java-api/Makefile
|
||||||
/java-api/classes/
|
/java-api/classes/
|
||||||
/java-api/testclasses/
|
/java-api/testclasses/
|
||||||
|
/swift-daemon-api/build/
|
||||||
/swift-client-api/Makefile
|
/swift-client-api/Makefile
|
||||||
/swift-client-api/build/
|
/swift-client-api/build/
|
||||||
/swift-client-api/swift-client-util
|
/swift-client-api/swift-client-util
|
||||||
|
@ -259,6 +259,11 @@ present][Swift development]:
|
|||||||
Swift language's run-time support and resultant library dependencies, so is
|
Swift language's run-time support and resultant library dependencies, so is
|
||||||
not suitable for deployment.
|
not suitable for deployment.
|
||||||
|
|
||||||
|
* **ServalDNA.swiftmodule**
|
||||||
|
**ServalDNA.swiftdoc**
|
||||||
|
**libServalDNA.a**
|
||||||
|
are the [Swift Daemon API module][].
|
||||||
|
|
||||||
* **swift-client-api/build/debug/ServalClient.swiftmodule**
|
* **swift-client-api/build/debug/ServalClient.swiftmodule**
|
||||||
**swift-client-api/build/debug/ServalClient.swiftdoc**
|
**swift-client-api/build/debug/ServalClient.swiftdoc**
|
||||||
**swift-client-api/build/debug/libServalClient.a**
|
**swift-client-api/build/debug/libServalClient.a**
|
||||||
@ -330,6 +335,7 @@ This document is available under the [Creative Commons Attribution 4.0 Internati
|
|||||||
[gcc 6]: http://gcc.gnu.org/gcc-6/
|
[gcc 6]: http://gcc.gnu.org/gcc-6/
|
||||||
[Notes for Developers]: ./doc/Development.md
|
[Notes for Developers]: ./doc/Development.md
|
||||||
[Swift development]: ./doc/Development.md#swift
|
[Swift development]: ./doc/Development.md#swift
|
||||||
|
[Swift Daemon API module]: ./doc/Development.md#swift-daemon-api
|
||||||
[Swift Client API module]: ./doc/Development.md#swift-client-api
|
[Swift Client API module]: ./doc/Development.md#swift-client-api
|
||||||
[OpenWRT]: ./doc/OpenWRT.md
|
[OpenWRT]: ./doc/OpenWRT.md
|
||||||
[Serval Infrastructure]: ./doc/Serval-Infrastructure.md
|
[Serval Infrastructure]: ./doc/Serval-Infrastructure.md
|
||||||
|
43
Makefile.in
43
Makefile.in
@ -1,4 +1,5 @@
|
|||||||
# Makefile.in for Serval DNA daemon and libraries
|
# Makefile.in for Serval DNA daemon and libraries
|
||||||
|
# nnnn
|
||||||
# vim: noet ts=8 sts=0 sw=8
|
# vim: noet ts=8 sts=0 sw=8
|
||||||
prefix=@prefix@
|
prefix=@prefix@
|
||||||
exec_prefix=@exec_prefix@
|
exec_prefix=@exec_prefix@
|
||||||
@ -7,16 +8,24 @@ sbindir=@sbindir@
|
|||||||
sysconfdir=@sysconfdir@
|
sysconfdir=@sysconfdir@
|
||||||
localstatedir=@localstatedir@
|
localstatedir=@localstatedir@
|
||||||
srcdir=@srcdir@
|
srcdir=@srcdir@
|
||||||
|
abs_srcdir=@abs_srcdir@
|
||||||
|
abs_builddir=@abs_builddir@
|
||||||
|
|
||||||
CC = @CC@
|
CC = @CC@
|
||||||
AR = @AR@
|
AR = @AR@
|
||||||
RANLIB = @RANLIB@
|
RANLIB = @RANLIB@
|
||||||
JAVAC= @JAVAC@
|
JAVAC= @JAVAC@
|
||||||
SWIFTC= @SWIFTC@
|
|
||||||
|
|
||||||
SWIFTCFLAGS= @SWIFTCFLAGS@ -I. -I $(srcdir)
|
SWIFTC= @SWIFTC@
|
||||||
|
SWIFTCFLAGS= @SWIFTCFLAGS@ -I$(abs_builddir) -I$(abs_srcdir)
|
||||||
SWIFTLIBS= @LIBS@
|
SWIFTLIBS= @LIBS@
|
||||||
|
|
||||||
|
SWIFT_BUILD= @SWIFT_BUILD@
|
||||||
|
SWIFT_BUILD_FLAGS= $(addprefix -Xswiftc , $(SWIFTCFLAGS))
|
||||||
|
|
||||||
SWIFT_MODULE_NAME= ServalDNA
|
SWIFT_MODULE_NAME= ServalDNA
|
||||||
|
SWIFT_PACKAGE_DIR= $(srcdir)/swift-daemon-api
|
||||||
|
SWIFT_BUILD_DIR= $(abs_builddir)/swift-daemon-api/build
|
||||||
|
|
||||||
INSTALL= install
|
INSTALL= install
|
||||||
INSTALL_PROGRAM= $(INSTALL)
|
INSTALL_PROGRAM= $(INSTALL)
|
||||||
@ -166,13 +175,26 @@ endif # $(JAVAC)
|
|||||||
|
|
||||||
ifneq ($(SWIFTC),) # Only provide Swift targets if the Swift compiler is available.
|
ifneq ($(SWIFTC),) # Only provide Swift targets if the Swift compiler is available.
|
||||||
|
|
||||||
all: swift-client-api
|
all: swift-daemon-api swift-client-api
|
||||||
|
|
||||||
test: servaldswift
|
test: servaldswift
|
||||||
|
|
||||||
clean: swift-client-api-clean
|
clean: swift-daemon-api-clean swift-client-api-clean
|
||||||
|
|
||||||
.PHONY: swift-client-api swift-client-api-clean
|
.PHONY: swift-daemon-api swift-daemon-api-clean swift-client-api swift-client-api-clean
|
||||||
|
|
||||||
|
libServalDNA.a $(SWIFT_MODULE_NAME).swiftmodule $(SWIFT_MODULE_NAME).swiftdoc: swift-daemon-api
|
||||||
|
cp $(SWIFT_BUILD_DIR)/debug/$(notdir $@) $@
|
||||||
|
|
||||||
|
swift-daemon-api:
|
||||||
|
mkdir -p $(SWIFT_BUILD_DIR) && \
|
||||||
|
cd $(SWIFT_PACKAGE_DIR) && \
|
||||||
|
$(SWIFT_BUILD) --build-path $(SWIFT_BUILD_DIR) $(SWIFT_BUILD_FLAGS) $(SWIFTDEFS)
|
||||||
|
|
||||||
|
swift-daemon-api-clean:
|
||||||
|
$(RM) -r $(SWIFT_BUILD_DIR) \
|
||||||
|
$(SWIFT_MODULE_NAME).swiftmodule \
|
||||||
|
$(SWIFT_MODULE_NAME).swiftdoc
|
||||||
|
|
||||||
swift-client-api:
|
swift-client-api:
|
||||||
@mkdir -p swift-client-api
|
@mkdir -p swift-client-api
|
||||||
@ -369,12 +391,15 @@ ifneq ($(SWIFTC),) # Only provide Swift targets if the Swift compiler is availab
|
|||||||
# package.
|
# package.
|
||||||
servaldswift: $(srcdir)/servaldswift.swift \
|
servaldswift: $(srcdir)/servaldswift.swift \
|
||||||
$(OBJSDIR_SERVALD)/servald_features.o \
|
$(OBJSDIR_SERVALD)/servald_features.o \
|
||||||
$(OBJSDIR_SERVALD)/log_output_console.o \
|
|
||||||
$(OBJSDIR_SERVALD)/log_output_file.o \
|
$(OBJSDIR_SERVALD)/log_output_file.o \
|
||||||
libservaldaemon.a \
|
libservaldaemon.a \
|
||||||
$(srcdir)/module.modulemap
|
$(SWIFT_MODULE_NAME).swiftmodule \
|
||||||
|
libServalDNA.a
|
||||||
@echo SWIFT $@
|
@echo SWIFT $@
|
||||||
@$(SWIFTC) -emit-executable $(SWIFTCFLAGS) $(SWIFTDEFS) -o $@ $(filter %.swift, $^) $(filter %.o, $^) $(filter %.a, $^) $(SWIFTLIBS)
|
@$(SWIFTC) -emit-executable -o $@ \
|
||||||
|
$(SWIFTCFLAGS) $(SWIFTDEFS) \
|
||||||
|
$(filter %.swift, $^) $(filter %.o, $^) $(filter %.a, $^) \
|
||||||
|
$(SWIFTLIBS)
|
||||||
|
|
||||||
endif # $(SWIFTC)
|
endif # $(SWIFTC)
|
||||||
|
|
||||||
@ -413,7 +438,7 @@ libservalclient.a: _servalclient.a $(LIBSODIUM_A)
|
|||||||
|
|
||||||
libservalclient.so: $(LIB_SERVAL_OBJS) $(OBJSDIR_TOOLS)/version.o $(LIBSODIUM_A)
|
libservalclient.so: $(LIB_SERVAL_OBJS) $(OBJSDIR_TOOLS)/version.o $(LIBSODIUM_A)
|
||||||
@echo LINK $@
|
@echo LINK $@
|
||||||
@$(CC) -Wall -shared -o $@ $(LDFLAGS) $(filter %.o, $^) $(filter %.a, $^)
|
@$(CC) -Wall -shared -o $@ $(LDFLAGS) $(filter %.o %.a, $^) $(filter %.a, $^)
|
||||||
|
|
||||||
.INTERMEDIATE: _monitorclient.a
|
.INTERMEDIATE: _monitorclient.a
|
||||||
_monitorclient.a: $(MONITOR_CLIENT_OBJS) $(OBJSDIR_TOOLS)/version.o
|
_monitorclient.a: $(MONITOR_CLIENT_OBJS) $(OBJSDIR_TOOLS)/version.o
|
||||||
|
@ -28,6 +28,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
|
|
||||||
|
/* An instance of struct cli_vtable that prints all fields to a stdio stream. This is used by the
|
||||||
|
* 'servald' daemon to print its output on stdout.
|
||||||
|
*/
|
||||||
|
|
||||||
static FILE *stdio_fp(struct cli_context *context)
|
static FILE *stdio_fp(struct cli_context *context)
|
||||||
{
|
{
|
||||||
return ((struct cli_context_stdio *)(context->context))->fp;
|
return ((struct cli_context_stdio *)(context->context))->fp;
|
||||||
|
@ -241,10 +241,10 @@ Serval DNA supports [Swift][], the language that Apple recommend for developing
|
|||||||
iOS apps for their mobile devices such as phones and tablets. The
|
iOS apps for their mobile devices such as phones and tablets. The
|
||||||
`./configure` script [generated from configure.ac](#autotools) detects whether
|
`./configure` script [generated from configure.ac](#autotools) detects whether
|
||||||
a [Swift 4][] compiler is present, or failing that, a [Swift 3][] compiler, and
|
a [Swift 4][] compiler is present, or failing that, a [Swift 3][] compiler, and
|
||||||
if so, then produces a Makefile that will compile
|
if so, then produces a Makefile that will compile [servaldswift.swift][] into
|
||||||
[servaldswift.swift](../servaldswift.swift) into the *servaldswift* executable,
|
the *servaldswift* executable, to prove that the Swift [module
|
||||||
to prove that the Swift [module map](../module.modulemap) allows Swift source
|
map](../module.modulemap) allows Swift source code to invoke internal Serval
|
||||||
code to invoke internal Serval DNA functions.
|
DNA functions.
|
||||||
|
|
||||||
The `./configure` script can be passed the following variables, either as
|
The `./configure` script can be passed the following variables, either as
|
||||||
environment variables or using the `VARNAME=value` syntax on its command line:
|
environment variables or using the `VARNAME=value` syntax on its command line:
|
||||||
@ -255,12 +255,45 @@ environment variables or using the `VARNAME=value` syntax on its command line:
|
|||||||
* `SWIFTCFLAGS` extra command-line arguments to pass to the Swift compiler;
|
* `SWIFTCFLAGS` extra command-line arguments to pass to the Swift compiler;
|
||||||
analogous to `CFLAGS` for the C compiler
|
analogous to `CFLAGS` for the C compiler
|
||||||
|
|
||||||
|
Swift Daemon API
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Serval DNA provides a *Swift Daemon API* as a [Swift module][] called
|
||||||
|
**ServalDNA**, which provides access to some of the internal APIs of the Serval
|
||||||
|
DNA daemon by wrapping direct function invocations in Swift classes.
|
||||||
|
|
||||||
|
The Swift daemon API is written as a set of [Swift][] "wrappers" around
|
||||||
|
internal functions and constants that are declared in C header files. Those
|
||||||
|
internals are exposed to Swift by the Swift [module map](../module.modulemap),
|
||||||
|
which defines a [Swift module][] called **servald** that has the following
|
||||||
|
submodules:
|
||||||
|
|
||||||
|
* **servald.log** the Serval DNA logging API, including the log output API
|
||||||
|
|
||||||
|
* **servald.cli** the Serval DNA [CLI API][] and the daemon's command-line
|
||||||
|
entry point
|
||||||
|
|
||||||
|
The [CliContext][] Swift class provides an object-oriented interface to the
|
||||||
|
[CLI API][]. To capture the output from any CLI command, a Swift program can
|
||||||
|
simply subclass [CliContext][] and override its `write()` method and any other
|
||||||
|
methods as needed, then pass an instance of that subclass to the
|
||||||
|
[serval\_commandline\_main][] function. An example of how to do this is in
|
||||||
|
[servaldswift.swift][], which uses an instance of the [CliContextFile][]
|
||||||
|
subclass to print its output on standard output via a buffer.
|
||||||
|
|
||||||
|
[servaldswift.swift][] shows how to capture Serval DNA log output in Swift
|
||||||
|
code, by providing an implementation of the delegate log output `print()`
|
||||||
|
function. This works because [Makefile.in][] includes `log_output_delegate.o`
|
||||||
|
in the link for the *servaldswift* executable, and omits the other log outputs.
|
||||||
|
|
||||||
Swift Client API
|
Swift Client API
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Serval DNA provides a *Swift Client API* as a [Swift module][] called
|
Serval DNA provides a *Swift Client API* as a [Swift module][] called
|
||||||
**ServalClient**, which provides access to the services of the Serval DNA
|
**ServalClient**, which provides access to the services of the Serval DNA
|
||||||
daemon through its [REST API][].
|
daemon through its [REST API][]. Once an iOS app has started a thread that is
|
||||||
|
running the daemon (invoked via the [Swift Daemon API](#swift-daemon-api)), the
|
||||||
|
client API can be used to communicate with the running daemon thread.
|
||||||
|
|
||||||
The Swift client API is written entirely in [Swift][] using the [URLSession][]
|
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
|
Foundation class and related classes as the HTTP client. The API is covered
|
||||||
@ -307,10 +340,16 @@ Available under the [Creative Commons Attribution 4.0 International licence][CC
|
|||||||
[CC BY 4.0]: ../LICENSE-DOCUMENTATION.md
|
[CC BY 4.0]: ../LICENSE-DOCUMENTATION.md
|
||||||
[Serval DNA]: ../README.md
|
[Serval DNA]: ../README.md
|
||||||
[build]: ../INSTALL.md
|
[build]: ../INSTALL.md
|
||||||
|
[CLI API]: ./CLI-API.md
|
||||||
[REST API]: ./REST-API.md
|
[REST API]: ./REST-API.md
|
||||||
[Keyring REST API]: ./REST-API-Keyring.md
|
[Keyring REST API]: ./REST-API-Keyring.md
|
||||||
[test scripts]: ./Testing.md
|
[test scripts]: ./Testing.md
|
||||||
[configure.ac]: ../configure.ac
|
[configure.ac]: ../configure.ac
|
||||||
|
[Makefile.in]: ../Makefile.in
|
||||||
|
[servaldswift.swift]: ../servaldswift.swift
|
||||||
|
[CliContext]: ../swift-daemon-api/Sources/CliContext.swift
|
||||||
|
[CliContextFile]: ../swift-daemon-api/Sources/CliContextFile.swift
|
||||||
|
[serval\_commandline\_main]: ../swift-daemon-api/Sources/commandline.swift
|
||||||
[autoconf]: http://www.gnu.org/software/autoconf/autoconf.html
|
[autoconf]: http://www.gnu.org/software/autoconf/autoconf.html
|
||||||
[autoconf macro archive]: http://www.gnu.org/software/autoconf-archive/
|
[autoconf macro archive]: http://www.gnu.org/software/autoconf-archive/
|
||||||
[GNU M4]: http://www.gnu.org/software/m4/m4.html
|
[GNU M4]: http://www.gnu.org/software/m4/m4.html
|
||||||
|
@ -268,7 +268,8 @@ JNIEXPORT jint JNICALL Java_org_servalproject_servaldna_ServalDCommand_rawComman
|
|||||||
return (jint) status;
|
return (jint) status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output primitives for JNI.
|
/* An instance of struct cli_vtable that passes all output fields to an IJniResults
|
||||||
|
* interface callback.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static struct jni_context *jni_context(struct cli_context *cli_context)
|
static struct jni_context *jni_context(struct cli_context *cli_context)
|
||||||
|
134
log_output_delegate.c
Normal file
134
log_output_delegate.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
Serval DNA logging output to a delegate
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "log_output.h"
|
||||||
|
#include "log_output_delegate.h"
|
||||||
|
#include "strbuf.h"
|
||||||
|
|
||||||
|
/* An implementation of the Serval logging API that constructs log messages in
|
||||||
|
* a buffer then passes the buffer to a delegate.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Private state for delegate log output.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct log_output_delegate_state {
|
||||||
|
bool_t opened;
|
||||||
|
// Buffer to hold log messages before the log file is open and ready for writing:
|
||||||
|
struct strbuf strbuf;
|
||||||
|
char buf[8192];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct log_output_delegate_state static_state = {
|
||||||
|
.opened = 0,
|
||||||
|
.strbuf = STRUCT_STRBUF_EMPTY,
|
||||||
|
.buf = ""
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Functions for querying configuration.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int log_delegate_minimum_level(const struct log_output *UNUSED(out))
|
||||||
|
{
|
||||||
|
return serval_log_delegate.minimum_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool_t log_delegate_show_pid(const struct log_output *UNUSED(out))
|
||||||
|
{
|
||||||
|
return serval_log_delegate.show_pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool_t log_delegate_show_time(const struct log_output *UNUSED(out))
|
||||||
|
{
|
||||||
|
return serval_log_delegate.show_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Log output operations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline struct log_output_delegate_state *_state(struct log_output *out)
|
||||||
|
{
|
||||||
|
assert(out->state);
|
||||||
|
return (struct log_output_delegate_state *)(out->state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool_t is_log_delegate_available(const struct log_output_iterator *UNUSED(it))
|
||||||
|
{
|
||||||
|
return serval_log_delegate.print != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_delegate_open(struct log_output_iterator *it)
|
||||||
|
{
|
||||||
|
struct log_output_delegate_state *state = _state(*it->output);
|
||||||
|
if (!state->opened) {
|
||||||
|
state->opened = 1;
|
||||||
|
if (serval_log_delegate.show_prolog)
|
||||||
|
serval_log_print_prolog(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_delegate_start_line(struct log_output_iterator *it, int UNUSED(level))
|
||||||
|
{
|
||||||
|
struct log_output_delegate_state *state = _state(*it->output);
|
||||||
|
strbuf sb = &state->strbuf;
|
||||||
|
assert(strbuf_len(sb) == 0);
|
||||||
|
strbuf_init(sb, state->buf, sizeof state->buf);
|
||||||
|
it->xpf = XPRINTF_STRBUF(sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_delegate_end_line(struct log_output_iterator *it, int level)
|
||||||
|
{
|
||||||
|
struct log_output_delegate_state *state = _state(*it->output);
|
||||||
|
strbuf sb = &state->strbuf;
|
||||||
|
serval_log_delegate.print(level, strbuf_str(sb), strbuf_overrun(sb));
|
||||||
|
strbuf_reset(sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush_log_delegate(struct log_output_iterator *UNUSED(it))
|
||||||
|
{
|
||||||
|
if (serval_log_delegate.flush)
|
||||||
|
serval_log_delegate.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct log_output static_log_output = {
|
||||||
|
.minimum_level = log_delegate_minimum_level,
|
||||||
|
.show_pid = log_delegate_show_pid,
|
||||||
|
.show_time = log_delegate_show_time,
|
||||||
|
.state = &static_state,
|
||||||
|
.open = log_delegate_open,
|
||||||
|
.capture_fd = NULL,
|
||||||
|
.is_available = is_log_delegate_available,
|
||||||
|
.start_line = log_delegate_start_line,
|
||||||
|
.end_line = log_delegate_end_line,
|
||||||
|
.flush = flush_log_delegate,
|
||||||
|
.close = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_LOG_OUTPUT(&static_log_output);
|
||||||
|
|
||||||
|
// These are defaults only; the delegate fills this in as it wishes.
|
||||||
|
struct log_delegate serval_log_delegate = {
|
||||||
|
.minimum_level = LOG_LEVEL_INFO,
|
||||||
|
.show_prolog = 1,
|
||||||
|
.show_pid = 0,
|
||||||
|
.show_time = 1,
|
||||||
|
.print = NULL,
|
||||||
|
.flush = NULL
|
||||||
|
};
|
36
log_output_delegate.h
Normal file
36
log_output_delegate.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
Serval DNA logging output to a delegate
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SERVAL_DNA__LOG_OUTPUT_DELEGATE_H
|
||||||
|
#define __SERVAL_DNA__LOG_OUTPUT_DELEGATE_H
|
||||||
|
|
||||||
|
#include "lang.h" // for bool_t
|
||||||
|
|
||||||
|
struct log_delegate {
|
||||||
|
bool_t show_prolog;
|
||||||
|
int minimum_level;
|
||||||
|
bool_t show_pid;
|
||||||
|
bool_t show_time;
|
||||||
|
void (*print)(int level, const char *message, bool_t overrun);
|
||||||
|
void (*flush)();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct log_delegate serval_log_delegate;
|
||||||
|
|
||||||
|
#endif // __SERVAL_DNA__LOG_OUTPUT_DELEGATE_H
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Serval DNA module map
|
Serval DNA Swift module map
|
||||||
Copyright (C) 2016-2017 Flinders University
|
Copyright (C) 2016-2017 Flinders University
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
@ -21,7 +21,14 @@ module servald {
|
|||||||
|
|
||||||
requires tls // thread-local storage
|
requires tls // thread-local storage
|
||||||
|
|
||||||
module main {
|
module cli {
|
||||||
header "servald_main.h"
|
header "commandline.h"
|
||||||
|
header "cli.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
module log {
|
||||||
|
header "log.h"
|
||||||
|
header "log_output.h"
|
||||||
|
header "log_output_delegate.h"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,54 @@
|
|||||||
import Foundation
|
/*
|
||||||
import servald.main
|
Serval DNA daemon in Swift
|
||||||
|
Copyright 2017 Flinders University
|
||||||
|
|
||||||
public func serval_daemon_main(args: [String]) -> CInt {
|
This program is free software; you can redistribute it and/or
|
||||||
// print "args = \(args)"
|
modify it under the terms of the GNU General Public License
|
||||||
var argv = args.map { strdup($0) }
|
as published by the Free Software Foundation; either version 2
|
||||||
argv.append(nil)
|
of the License, or (at your option) any later version.
|
||||||
defer {
|
|
||||||
argv.forEach { free($0) }
|
This program is distributed in the hope that it will be useful,
|
||||||
}
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
return servald_main(CInt(argv.count - 1), &argv)
|
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
|
||||||
|
import ServalDNA
|
||||||
|
import servald.log
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
//
|
||||||
|
// A simplistic console log outputter that writes to standard error and is not
|
||||||
|
// configurable. Note that log_output_console.o is not linked into
|
||||||
|
// servaldswift, in order to avoid duplicate log outputs on standard error.
|
||||||
|
|
||||||
|
private func logPrint(_ level: CInt, _ message: UnsafePointer<CChar>?, _ overrun: Int8) {
|
||||||
|
let level_text = String(cString: serval_log_level_prefix_string(level)!)
|
||||||
|
let message_text = String(cString: message!)
|
||||||
|
FileHandle.standardError.write("\(level_text) \(message_text)\n".data(using:.utf8)!)
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(serval_daemon_main(args: CommandLine.arguments))
|
serval_log_delegate.print = logPrint
|
||||||
|
serval_log_delegate.minimum_level = LOG_LEVEL_WARN
|
||||||
|
serval_log_delegate.show_prolog = 1
|
||||||
|
serval_log_delegate.show_pid = 1
|
||||||
|
serval_log_delegate.show_time = 1
|
||||||
|
|
||||||
|
// Output
|
||||||
|
|
||||||
|
var contextFile = CliContextFile(FileHandle.standardOutput)
|
||||||
|
|
||||||
|
// Invocation
|
||||||
|
|
||||||
|
let status = serval_commandline_main(context: contextFile, args: CommandLine.arguments)
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
|
||||||
|
contextFile.flush()
|
||||||
|
|
||||||
|
exit(status)
|
||||||
|
@ -62,6 +62,7 @@ SERVAL_DAEMON_SOURCES = \
|
|||||||
keyring_restful.c \
|
keyring_restful.c \
|
||||||
log_output_console.c \
|
log_output_console.c \
|
||||||
log_output_file.c \
|
log_output_file.c \
|
||||||
|
log_output_delegate.c \
|
||||||
lsif.c \
|
lsif.c \
|
||||||
radio_link.c \
|
radio_link.c \
|
||||||
meshms.c \
|
meshms.c \
|
||||||
@ -131,6 +132,12 @@ SERVAL_DAEMON_JNI_SOURCES = \
|
|||||||
jni_instance.c \
|
jni_instance.c \
|
||||||
jni_server.c
|
jni_server.c
|
||||||
|
|
||||||
|
SERVAL_DAEMON_SWIFT_SOURCES = \
|
||||||
|
swift_main.swift \
|
||||||
|
swift_cli.swift \
|
||||||
|
swift_cli_stdio.swift \
|
||||||
|
swift_log.swift
|
||||||
|
|
||||||
MDP_CLIENT_SOURCES = \
|
MDP_CLIENT_SOURCES = \
|
||||||
mdp_client.c
|
mdp_client.c
|
||||||
|
|
||||||
|
@ -23,16 +23,18 @@ SWIFT_BUILD_FLAGS= $(addprefix -Xswiftc , $(SWIFTCFLAGS))
|
|||||||
DEFS= @DEFS@
|
DEFS= @DEFS@
|
||||||
SWIFTDEFS= $(addprefix -Xcc , $(DEFS))
|
SWIFTDEFS= $(addprefix -Xcc , $(DEFS))
|
||||||
|
|
||||||
.PHONY: all check check_swiftc check_swift_build swiftmodule clean
|
.PHONY: all
|
||||||
|
all: check package swift-client-util
|
||||||
all: check swiftmodule swift-client-util
|
|
||||||
|
|
||||||
|
.PHONY: check
|
||||||
check: check_swiftc check_swift_build
|
check: check_swiftc check_swift_build
|
||||||
|
|
||||||
|
.PHONY: check_swiftc
|
||||||
check_swiftc:
|
check_swiftc:
|
||||||
@if [ -z "$(SWIFTC)" ]; then echo "No swift compiler configured" >&2; exit 1; fi
|
@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
|
@if ! $(SWIFTC) -version >/dev/null; then echo "Swift compiler not executable" >&2; exit 1; fi
|
||||||
|
|
||||||
|
.PHONY: check_swift_build
|
||||||
check_swift_build:
|
check_swift_build:
|
||||||
@if [ -z "$(SWIFT_BUILD)" ]; then echo "No swift package manager configured" >&2; exit 1; fi
|
@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
|
@if ! $(SWIFT_BUILD) -h >/dev/null; then echo "Swift package manager not executable" >&2; exit 1; fi
|
||||||
@ -40,17 +42,19 @@ check_swift_build:
|
|||||||
# The Swift 3 package manager --chdir option was replaced with --package-path
|
# 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
|
# in Swift 4, so to support both, avoid the options altogether and use "cd
|
||||||
# package-dir && swift build" instead.
|
# package-dir && swift build" instead.
|
||||||
swiftmodule:
|
.PHONY: package
|
||||||
|
package:
|
||||||
mkdir -p $(SWIFT_BUILD_DIR) && \
|
mkdir -p $(SWIFT_BUILD_DIR) && \
|
||||||
cd $(SWIFT_PACKAGE_DIR) && \
|
cd $(SWIFT_PACKAGE_DIR) && \
|
||||||
$(SWIFT_BUILD) --build-path $(SWIFT_BUILD_DIR) $(SWIFT_BUILD_FLAGS) $(SWIFTDEFS)
|
$(SWIFT_BUILD) --build-path $(SWIFT_BUILD_DIR) $(SWIFT_BUILD_FLAGS) $(SWIFTDEFS)
|
||||||
|
|
||||||
$(SWIFT_BUILD_DIR)/debug/libServalClient.a: swiftmodule
|
$(SWIFT_BUILD_DIR)/debug/libServalClient.a: package
|
||||||
|
|
||||||
swift-client-util: $(srcdir)/client_util.swift $(SWIFT_BUILD_DIR)/debug/libServalClient.a
|
swift-client-util: $(srcdir)/client_util.swift $(SWIFT_BUILD_DIR)/debug/libServalClient.a
|
||||||
@echo SWIFT $@
|
@echo SWIFT $@
|
||||||
@$(SWIFTC) -emit-executable $(SWIFTCFLAGS) $(SWIFTDEFS) -I $(SWIFT_BUILD_DIR)/debug -o $@ $^
|
@$(SWIFTC) -emit-executable $(SWIFTCFLAGS) $(SWIFTDEFS) -I $(SWIFT_BUILD_DIR)/debug -o $@ $^
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
$(RM) -r $(SWIFT_BUILD_DIR)
|
$(RM) -r $(SWIFT_BUILD_DIR)
|
||||||
$(RM) swift-client-util
|
$(RM) swift-client-util
|
||||||
|
9
swift-daemon-api/Package.swift
Normal file
9
swift-daemon-api/Package.swift
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "ServalDNA"
|
||||||
|
)
|
||||||
|
|
||||||
|
products.append(
|
||||||
|
Product(name: "ServalDNA", type: .Library(.Static), modules: "ServalDNA")
|
||||||
|
)
|
158
swift-daemon-api/Sources/CliContext.swift
Normal file
158
swift-daemon-api/Sources/CliContext.swift
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
Serval DNA Swift CLI output
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import servald.cli
|
||||||
|
|
||||||
|
private extension Data {
|
||||||
|
var hexUpper: String {
|
||||||
|
return map { String(format: "%02hhX", $0) }.joined()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class CliContext {
|
||||||
|
public var cContext: cli_context = cli_context(context: nil, vtable: nil)
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
cContext.context = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
|
||||||
|
cContext.vtable = UnsafeMutablePointer<cli_vtable>(&cliVtable)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subclasses override these as needed:
|
||||||
|
|
||||||
|
func delim(_ opt: String? = nil) {}
|
||||||
|
|
||||||
|
func write(_ data: Data) {}
|
||||||
|
|
||||||
|
func puts(_ str: String) {
|
||||||
|
self.write(str.data(using:.utf8)!)
|
||||||
|
}
|
||||||
|
|
||||||
|
func flush() {}
|
||||||
|
|
||||||
|
func putString(_ str: String, _ delim: String? = nil) {
|
||||||
|
self.puts(str)
|
||||||
|
self.delim(delim)
|
||||||
|
}
|
||||||
|
|
||||||
|
func putLong(_ value: Int64, _ delim: String? = nil) {
|
||||||
|
self.puts("\(value)")
|
||||||
|
self.delim(delim)
|
||||||
|
}
|
||||||
|
|
||||||
|
func putHexData(_ data: Data, _ delim: String? = nil) {
|
||||||
|
self.puts(data.hexUpper)
|
||||||
|
self.delim(delim)
|
||||||
|
}
|
||||||
|
|
||||||
|
func putBlob(_ data: Data, _ delim: String? = nil) {
|
||||||
|
self.write(data)
|
||||||
|
self.delim(delim)
|
||||||
|
}
|
||||||
|
|
||||||
|
func startTable(column_names: [String]) {
|
||||||
|
self.putLong(Int64(column_names.count))
|
||||||
|
for i in 0 ..< column_names.count {
|
||||||
|
self.putString(column_names[i], i == column_names.count - 1 ? nil : ":")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func endTable(row_count: Int) {}
|
||||||
|
|
||||||
|
func fieldName(_ name: String, _ delim: String? = nil) {
|
||||||
|
self.putString(name)
|
||||||
|
self.delim(delim)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func _self(_ context: UnsafeMutablePointer<cli_context>?) -> CliContext {
|
||||||
|
return Unmanaged<CliContext>.fromOpaque(context!.pointee.context).takeUnretainedValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cliDelim(_ context: UnsafeMutablePointer<cli_context>?, _ opt: UnsafePointer<CChar>?) -> Void {
|
||||||
|
_self(context).delim(opt != nil ? String(cString: opt!) : nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cliWrite(_ context: UnsafeMutablePointer<cli_context>?, _ buf: UnsafePointer<CChar>?, _ len: Int) -> Void {
|
||||||
|
if buf != nil {
|
||||||
|
_self(context).write(Data(bytes: buf!, count: len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cliPuts(_ context: UnsafeMutablePointer<cli_context>?, _ str: UnsafePointer<CChar>?) -> Void {
|
||||||
|
if str != nil {
|
||||||
|
_self(context).putString(String(cString: str!))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cliVprintf(_ context: UnsafeMutablePointer<cli_context>?, _ fmt: UnsafePointer<CChar>?, _ ap: CVaListPointer) -> Void {
|
||||||
|
let str = NSString(format: String(cString: fmt!), arguments: ap)
|
||||||
|
_self(context).putString(String(data: str.data(using: String.Encoding.utf16.rawValue)!, encoding:.utf16)!)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cliPutLong(_ context: UnsafeMutablePointer<cli_context>?, _ value: Int64, _ delim: UnsafePointer<CChar>?) -> Void {
|
||||||
|
_self(context).putLong(value, delim != nil ? String(cString: delim!) : nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cliPutString(_ context: UnsafeMutablePointer<cli_context>?, _ value: UnsafePointer<CChar>?, _ delim: UnsafePointer<CChar>?) -> Void {
|
||||||
|
_self(context).putString(value != nil ? String(cString: value!) : "",
|
||||||
|
delim != nil ? String(cString: delim!) : nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cliPutHexvalue(_ context: UnsafeMutablePointer<cli_context>?, _ buf: UnsafePointer<CUnsignedChar>?, _ len: Int, _ delim: UnsafePointer<CChar>?) -> Void {
|
||||||
|
_self(context).putHexData(buf != nil ? Data(bytes: buf!, count: len) : Data(),
|
||||||
|
delim != nil ? String(cString: delim!) : nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cliPutBlob(_ context: UnsafeMutablePointer<cli_context>?, _ blob: UnsafePointer<CUnsignedChar>?, _ len: Int, _ delim: UnsafePointer<CChar>?) -> Void {
|
||||||
|
_self(context).putBlob(blob != nil ? Data(bytes: UnsafeRawPointer(blob!).bindMemory(to: CChar.self, capacity: len), count: len) : Data(),
|
||||||
|
delim != nil ? String(cString: delim!) : nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cliStartTable(_ context: UnsafeMutablePointer<cli_context>?, _ column_count: Int, _ column_names: UnsafeMutablePointer<UnsafePointer<CChar>?>?) -> Void {
|
||||||
|
let names = (0..<column_count).map { String(cString: column_names![$0]!) }
|
||||||
|
_self(context).startTable(column_names: names)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cliEndTable(_ context: UnsafeMutablePointer<cli_context>?, _ row_count: Int) -> Void {
|
||||||
|
_self(context).endTable(row_count: row_count)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cliFieldName(_ context: UnsafeMutablePointer<cli_context>?, _ name: UnsafePointer<CChar>?, _ delim: UnsafePointer<CChar>?) -> Void {
|
||||||
|
_self(context).fieldName(name != nil ? String(cString: name!) : "", delim != nil ? String(cString: delim!) : nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func cliFlush(_ context: UnsafeMutablePointer<cli_context>?) -> Void {
|
||||||
|
_self(context).flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var cliVtable = cli_vtable(
|
||||||
|
delim: cliDelim,
|
||||||
|
write: cliWrite,
|
||||||
|
puts: cliPuts,
|
||||||
|
vprintf: cliVprintf,
|
||||||
|
put_long: cliPutLong,
|
||||||
|
put_string: cliPutString,
|
||||||
|
put_hexvalue: cliPutHexvalue,
|
||||||
|
put_blob: cliPutBlob,
|
||||||
|
start_table: cliStartTable,
|
||||||
|
end_table: cliEndTable,
|
||||||
|
field_name: cliFieldName,
|
||||||
|
flush: cliFlush
|
||||||
|
)
|
54
swift-daemon-api/Sources/CliContextFile.swift
Normal file
54
swift-daemon-api/Sources/CliContextFile.swift
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
Serval DNA Swift CLI output to stdio stream
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
/* An instance of struct cli_vtable that prints all fields to a stdio stream
|
||||||
|
* via a buffer. This is the Swift equivalent of cli_stdio.c. It is used by
|
||||||
|
* the 'servaldswift' daemon to produce its output.
|
||||||
|
*/
|
||||||
|
|
||||||
|
open class CliContextFile: CliContext {
|
||||||
|
private var fileHandle: FileHandle
|
||||||
|
private var buffer: Data
|
||||||
|
private let bufsize: Int? = nil
|
||||||
|
|
||||||
|
public init(_ file: FileHandle) {
|
||||||
|
self.fileHandle = file
|
||||||
|
self.buffer = Data()
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func delim(_ opt: String?) {
|
||||||
|
self.puts(ProcessInfo.processInfo.environment["SERVALD_OUTPUT_DELIMITER"] ?? opt ?? "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func write(_ data: Data) {
|
||||||
|
self.buffer.append(data)
|
||||||
|
if self.bufsize != nil && self.buffer.count >= self.bufsize! {
|
||||||
|
self.flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func flush() {
|
||||||
|
if !self.buffer.isEmpty {
|
||||||
|
self.fileHandle.write(self.buffer)
|
||||||
|
self.buffer.removeAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
swift-daemon-api/Sources/commandline.swift
Normal file
39
swift-daemon-api/Sources/commandline.swift
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
Serval DNA Swift command-line entry point
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import servald.cli
|
||||||
|
|
||||||
|
/* A Swift entry point to the Serval DNA daemon command-line entry point, which takes a
|
||||||
|
* [String] parameter, converts it into an argv array of C strings, and invokes
|
||||||
|
* the C main entry point with argv0, and argc/argv arguments.
|
||||||
|
*/
|
||||||
|
public func serval_commandline_main(context: CliContext, args: [String]) -> CInt {
|
||||||
|
var margv = args.map { strdup($0) }
|
||||||
|
margv.append(nil)
|
||||||
|
defer {
|
||||||
|
margv.forEach { free($0) }
|
||||||
|
}
|
||||||
|
let argv0 = margv[0]
|
||||||
|
margv.remove(at: 0)
|
||||||
|
let argv = margv.map { $0 != nil ? UnsafePointer<CChar>?($0!) : nil }
|
||||||
|
return argv.withUnsafeBufferPointer {
|
||||||
|
return commandline_main(&context.cContext, argv0, CInt(argv.count - 1), $0.baseAddress!)
|
||||||
|
}
|
||||||
|
}
|
39
swift-daemon-api/Sources/log.swift
Normal file
39
swift-daemon-api/Sources/log.swift
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import servald.log
|
||||||
|
|
||||||
|
private func serval_log(level: CInt, format: String, va_list: CVaListPointer) {
|
||||||
|
format.withCString { CString in
|
||||||
|
serval_vlogf(level, __whence, CString, va_list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func serval_log(level: CInt, text: String) {
|
||||||
|
text.withCString { CString in
|
||||||
|
withVaList([CString]) { va_list in
|
||||||
|
serval_log(level: level, format: "%s", va_list: va_list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func serval_log_fatal(_ text: String) {
|
||||||
|
serval_log(level: LOG_LEVEL_FATAL, text: text)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func serval_log_error(_ text: String) {
|
||||||
|
serval_log(level: LOG_LEVEL_ERROR, text: text)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func serval_log_warning(_ text: String) {
|
||||||
|
serval_log(level: LOG_LEVEL_WARN, text: text)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func serval_log_hint(_ text: String) {
|
||||||
|
serval_log(level: LOG_LEVEL_HINT, text: text)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func serval_log_info(_ text: String) {
|
||||||
|
serval_log(level: LOG_LEVEL_INFO, text: text)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func serval_log_debug(_ text: String) {
|
||||||
|
serval_log(level: LOG_LEVEL_DEBUG, text: text)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user