diff --git a/components/nng/Kconfig b/components/nng/Kconfig new file mode 100644 index 0000000..1360349 --- /dev/null +++ b/components/nng/Kconfig @@ -0,0 +1,114 @@ +menuconfig LNNG_ENABLED + bool "Enable nng" + default n + + config NNG_HAVE_BUS0 + bool "compile bus0" + default y + depends on LNNG_ENABLED + + config NNG_HAVE_PAIR0 + bool "compile pair0" + default y + depends on LNNG_ENABLED + + config NNG_HAVE_PAIR1 + bool "compile pair1" + default y + depends on LNNG_ENABLED + + config NNG_HAVE_SURVEYOR0 + bool "compile surveyor0" + default y + depends on LNNG_ENABLED + + config NNG_HAVE_PUBSUB0 + bool "compile pubsub0" + default y + depends on LNNG_ENABLED + + config NNG_HAVE_PULLPUSH0 + bool "compile pullpush0" + default y + depends on LNNG_ENABLED + + config NNG_HAVE_REPREQ0 + bool "compile repreq" + default y + depends on LNNG_ENABLED + + config NNG_TRANSPORT_FDC + bool "compile fdc" + default n + depends on LNNG_ENABLED + + config NNG_TRANSPORT_INPROC + bool "compile inproc" + default y + depends on LNNG_ENABLED + + config NNG_TRANSPORT_IPC + bool "compile ipc" + default y + depends on LNNG_ENABLED + + config NNG_TRANSPORT_TCP + bool "compile tcp" + default y + depends on LNNG_ENABLED + + config NNG_TRANSPORT_TLS + bool "compile tls" + default n + depends on LNNG_ENABLED + + choice + prompt "choice TLS engine" + default TLS_MBEDTLS_ENABLED + depends on NNG_TRANSPORT_TLS + config TLS_MBEDTLS_ENABLED + bool "enable mbedtls" + config TLS_WOLFSSL_ENABLED + bool "enable wolfssl" + endchoice + + config NNG_TRANSPORT_UDP + bool "compile udp" + default y + depends on LNNG_ENABLED + + config NNG_TRANSPORT_WS + bool "compile ws" + default n + depends on LNNG_ENABLED + + config NNG_SUPP_HTTP + bool "compile http" + default n + depends on LNNG_ENABLED + + config NNG_MAX_EXPIRE_THREADS + int "nng max expire threads" + default 2 + depends on LNNG_ENABLED + + config NNG_MAX_POLLER_THREADS + int "nng max poller threads" + default 2 + depends on LNNG_ENABLED + + config NNG_MAX_TASKQ_THREADS + int "nng max taskq threads" + default 4 + depends on LNNG_ENABLED + + config NNG_ENABLE_IPV6 + bool "enable ipv6" + default y + depends on LNNG_ENABLED + + config LNNG_DYNAMIC + bool "compile component as dynamic(shared) lib" + default n + depends on LNNG_ENABLED + diff --git a/components/nng/SConstruct b/components/nng/SConstruct new file mode 100644 index 0000000..97374a0 --- /dev/null +++ b/components/nng/SConstruct @@ -0,0 +1,119 @@ +# component2/SConscript +Import('env') +import os +with open(env['PROJECT_TOOL_S']) as f: + exec(f.read()) + +if 'CONFIG_LNNG_ENABLED' in os.environ: + check_component('nng') + SRCS=[] + INCLUDE=[] + PRIVATE_INCLUDE=[] + REQUIREMENTS=[] + STATIC_LIB=[] + DYNAMIC_LIB=[] + DEFINITIONS=[] + DEFINITIONS_PRIVATE=['-w'] + LDFLAGS=[] + LINK_SEARCH_PATH=[] + + COMPONENT_PATH = os.path.join(os.environ['GIT_REPO_PATH'], 'nng') + INCLUDE.append(os.path.join(COMPONENT_PATH, 'include')) + PRIVATE_INCLUDE.append(os.path.join(COMPONENT_PATH, 'src')) + DEFINITIONS_PRIVATE += ['-DNNG_LITTLE_ENDIAN=1', '-DNNG_HIDDEN_VISIBILITY'] + DEFINITIONS_PRIVATE += ['-D_GNU_SOURCE', '-D_POSIX_PTHREAD_SEMANTICS', '-DNNG_USE_EVENTFD', '-D_THREAD_SAFE'] + DEFINITIONS_PRIVATE += ['-DNNG_STATIC_LIB', '-DNNG_ENABLE_STATS'] + DEFINITIONS_PRIVATE += ['-DNNG_HAVE_ABSTRACT_SOCKETS', '-DNNG_HAVE_BACKTRACE=1'] + DEFINITIONS_PRIVATE += ['-DNNG_HAVE_CLOCK_GETTIME', '-DNNG_HAVE_EPOLL=1', '-DNNG_HAVE_EPOLL_CREATE1=1', + '-DNNG_HAVE_FLOCK', '-DNNG_HAVE_GETENTROPY=1', '-DNNG_HAVE_GETRANDOM=1', + '-DNNG_HAVE_LANGINFO=1', '-DNNG_HAVE_LIBATOMIC=1', + '-DNNG_HAVE_LIBNSL=1', '-DNNG_HAVE_LOCALTIME_R=1', '-DNNG_HAVE_LOCKF=1', + '-DNNG_HAVE_MSG_CONTROL=1', '-DNNG_RESOLV_CONCURRENCY=4'] + + _SRCS = [] + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/*.c')) + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/core/*.c')) + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/*.c')) + + DEFINITIONS_PRIVATE.append('-DNNG_MAX_EXPIRE_THREADS={}'.format(os.environ['CONFIG_NNG_MAX_EXPIRE_THREADS'])) + DEFINITIONS_PRIVATE.append('-DNNG_MAX_POLLER_THREADS={}'.format(os.environ['CONFIG_NNG_MAX_POLLER_THREADS'])) + DEFINITIONS_PRIVATE.append('-DNNG_MAX_TASKQ_THREADS={}'.format(os.environ['CONFIG_NNG_MAX_TASKQ_THREADS'])) + + if 'CONFIG_TOOLCHAIN_SYSTEM_UNIX' in os.environ: + DEFINITIONS_PRIVATE += ['-DNNG_PLATFORM_LINUX', '-DNNG_PLATFORM_POSIX', '-DNNG_USE_EVENTFD', '-DNNG_HAVE_ABSTRACT_SOCKETS'] + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/platform/posix/*.c')) + elif 'CONFIG_TOOLCHAIN_SYSTEM_WIN' in os.environ: + DEFINITIONS_PRIVATE += ['-DNNG_PLATFORM_WINDOWS', '-D_CRT_SECURE_NO_WARNINGS', '-D_CRT_RAND_S', '-D_WIN32_WINNT=0x0600'] + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/platform/windows/*.c')) + + if 'CONFIG_NNG_HAVE_BUS0' in os.environ: + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/protocol/bus0/*.c')) + if 'CONFIG_NNG_HAVE_PAIR0' in os.environ: + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/protocol/pair0/*.c')) + if 'CONFIG_NNG_HAVE_PAIR1' in os.environ: + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/protocol/pair1/*.c')) + if 'CONFIG_NNG_HAVE_SURVEYOR0' in os.environ: + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/protocol/survey0/*.c')) + if 'CONFIG_NNG_HAVE_PUBSUB0' in os.environ: + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/protocol/pubsub0/*.c')) + if 'CONFIG_NNG_HAVE_PULLPUSH0' in os.environ: + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/protocol/pipeline0/*.c')) + if 'CONFIG_NNG_HAVE_REPREQ0' in os.environ: + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/protocol/reqrep0/*.c')) + if 'CONFIG_NNG_TRANSPORT_FDC' in os.environ: + DEFINITIONS_PRIVATE += ['-DNNG_TRANSPORT_FDC'] + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/transport/socket/*.c')) + DEFINITIONS_PRIVATE += ['-DNNG_HAVE_SOCKETPAIR=1'] + if 'CONFIG_NNG_TRANSPORT_INPROC' in os.environ: + DEFINITIONS_PRIVATE += ['-DNNG_TRANSPORT_INPROC'] + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/transport/inproc/*.c')) + if 'CONFIG_NNG_TRANSPORT_IPC' in os.environ: + DEFINITIONS_PRIVATE += ['-DNNG_TRANSPORT_IPC'] + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/transport/ipc/*.c')) + if 'CONFIG_NNG_TRANSPORT_TCP' in os.environ: + DEFINITIONS_PRIVATE += ['-DNNG_TRANSPORT_TCP'] + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/transport/tcp/*.c')) + if 'CONFIG_NNG_TRANSPORT_TLS' in os.environ: + DEFINITIONS_PRIVATE += ['-DNNG_TRANSPORT_TLS'] + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/transport/tls/*.c')) + if 'CONFIG_TLS_MBEDTLS_ENABLED' in os.environ: + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/supplemental/tls/mbedtls/*.c')) + if 'CONFIG_TLS_WOLFSSL_ENABLED' in os.environ: + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/supplemental/tls/wolfssl/*.c')) + + if 'CONFIG_NNG_TRANSPORT_UDP' in os.environ: + DEFINITIONS_PRIVATE += ['-DNNG_TRANSPORT_UDP'] + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/transport/udp/*.c')) + if 'CONFIG_NNG_TRANSPORT_WS' in os.environ: + DEFINITIONS_PRIVATE += ['-DNNG_TRANSPORT_WS'] + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/sp/transport/ws/*.c')) + if 'CONFIG_NNG_SUPP_HTTP' in os.environ: + DEFINITIONS_PRIVATE += ['-DNNG_SUPP_HTTP'] + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/supplemental/http/*.c')) + + if 'CONFIG_NNG_ENABLE_IPV6' in os.environ: + DEFINITIONS_PRIVATE += ['-DNNG_ENABLE_IPV6', '-DNNG_HAVE_INET6=1'] + + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/supplemental/websocket/*.c')) + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/supplemental/tls/*.c')) + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/supplemental/base64/*.c')) + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/supplemental/sha1/*.c')) + _SRCS += AGlob(os.path.join(COMPONENT_PATH,'src/supplemental/util/*.c')) + + for src in _SRCS: + if not str(src).endswith('test.c'): + SRCS.append(src) + + env['COMPONENTS'].append({'target':os.path.basename(env['component_dir']), + 'SRCS':SRCS, + 'INCLUDE':INCLUDE, + 'PRIVATE_INCLUDE':PRIVATE_INCLUDE, + 'REQUIREMENTS':REQUIREMENTS, + 'STATIC_LIB':STATIC_LIB, + 'DYNAMIC_LIB':DYNAMIC_LIB, + 'DEFINITIONS':DEFINITIONS, + 'DEFINITIONS_PRIVATE':DEFINITIONS_PRIVATE, + 'LDFLAGS':LDFLAGS, + 'LINK_SEARCH_PATH':LINK_SEARCH_PATH, + 'REGISTER':'shared' if 'CONFIG_LNNG_DYNAMIC' in os.environ else 'static' + }) diff --git a/examples/nng_demo/.gdb_history b/examples/nng_demo/.gdb_history new file mode 100644 index 0000000..a0c044d --- /dev/null +++ b/examples/nng_demo/.gdb_history @@ -0,0 +1,139 @@ +set args ipc:///tmp.nng +b main +r +l +l +n +r +q +set args ipc:///tmp.nng +b main +r +n +r +n +s +n +s +n +locals +backtrace +info locals +bt +info frame +l +bt +s +bt +r +b nni_aio_init +r +n +c +bt +l +bt +n +print nni_aio_expire_q_cnt +q +q +q +b main +set args ipc:///tmp.nng +r +n +r +n +b 181 +c +s +s +q +b nng_listen +c +bt +s +q +set args ipc:///tmp.nng +b nng_listen +r +q +set args async_server ipc:///tmp.nng +r +r +r +set argsipc:///tmp.nng +set args ipc:///tmp.nng +infs +info +info variables +r +b main +r +n +s +n +info i +info variables +info locals +n +n +info i +info locals +print PARALLEL +info PARALLEL +bt +n +b 158 +c +s +n +s +n +q +set args ipc:///tmp/tmp.nng +b main +r +b nng_listen +c +tui disable thread-info +l +bt +s +q +set args ipc:///tmp/tmp.nng +b nng_listen +r +n +r +b nni_listener_create +c +r +c +n +s +n +f +finish +n +n +info locals +n +r +n +r +n +s +n +s +n +q +r +c +n +s +n +s +q +r +q diff --git a/examples/nng_demo/.gitignore b/examples/nng_demo/.gitignore new file mode 100644 index 0000000..76b743d --- /dev/null +++ b/examples/nng_demo/.gitignore @@ -0,0 +1,6 @@ + +dist +build +.config.mk +.flash.conf.json + diff --git a/examples/nng_demo/SConstruct b/examples/nng_demo/SConstruct new file mode 100644 index 0000000..076d65c --- /dev/null +++ b/examples/nng_demo/SConstruct @@ -0,0 +1,4 @@ +from pathlib import Path +import os +with open(str(Path(os.getcwd())/'..'/'..'/'tools'/'scons'/'project.py')) as f: + exec(f.read()) diff --git a/examples/nng_demo/config_defaults.mk b/examples/nng_demo/config_defaults.mk new file mode 100644 index 0000000..8033ba7 --- /dev/null +++ b/examples/nng_demo/config_defaults.mk @@ -0,0 +1,4 @@ +# CONFIG_TOOLCHAIN_PATH="/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin" +# CONFIG_TOOLCHAIN_PREFIX="arm-linux-gnueabihf-" + +CONFIG_LNNG_ENABLED=y diff --git a/examples/nng_demo/main/Kconfig b/examples/nng_demo/main/Kconfig new file mode 100644 index 0000000..e69de29 diff --git a/examples/nng_demo/main/SConstruct b/examples/nng_demo/main/SConstruct new file mode 100644 index 0000000..85a3e99 --- /dev/null +++ b/examples/nng_demo/main/SConstruct @@ -0,0 +1,42 @@ +# project_root/src/SConscript +import os +# Import the environment from the SConstruct file +Import('env') +with open(env['PROJECT_TOOL_S']) as f: + exec(f.read()) + +SRCS = [] +INCLUDE = [ADir('include'), ADir('.')] +PRIVATE_INCLUDE = [] +REQUIREMENTS = ['nng', 'pthread'] +STATIC_LIB = [] +DYNAMIC_LIB = [] +DEFINITIONS = [] +DEFINITIONS_PRIVATE = [] +LDFLAGS = [] +LINK_SEARCH_PATH = [] + +LDFLAGS += ['-Wl,-rpath=./'] + +all_src_files = Glob('src/*.c*') + +for src in all_src_files: + SRCS = [src] + if str(src).endswith('.cpp'): + target_name = os.path.basename(str(src)[:-4]) + elif str(src).endswith('.c'): + target_name = os.path.basename(str(src)[:-2]) + + env['COMPONENTS'].append({'target':target_name, + 'SRCS':SRCS, + 'INCLUDE':INCLUDE, + 'PRIVATE_INCLUDE':PRIVATE_INCLUDE, + 'REQUIREMENTS':REQUIREMENTS, + 'STATIC_LIB':STATIC_LIB, + 'DYNAMIC_LIB':DYNAMIC_LIB, + 'DEFINITIONS':DEFINITIONS, + 'DEFINITIONS_PRIVATE':DEFINITIONS_PRIVATE, + 'LDFLAGS':LDFLAGS, + 'LINK_SEARCH_PATH':LINK_SEARCH_PATH, + 'REGISTER':'project' + }) \ No newline at end of file diff --git a/examples/nng_demo/main/include/main.h b/examples/nng_demo/main/include/main.h new file mode 100644 index 0000000..e69de29 diff --git a/examples/nng_demo/main/src/async_client.cpp b/examples/nng_demo/main/src/async_client.cpp new file mode 100644 index 0000000..7270ddb --- /dev/null +++ b/examples/nng_demo/main/src/async_client.cpp @@ -0,0 +1,104 @@ +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +// This program is just a simple client application for our demo server. +// It is in a separate file to keep the server code clearer to understand. +// +// Our demonstration application layer protocol is simple. The client sends +// a number of milliseconds to wait before responding. The server just gives +// back an empty reply after waiting that long. + +// For example: +// +// % ./server tcp://127.0.0.1:5555 & +// % ./client tcp://127.0.0.1:5555 323 +// Request took 324 milliseconds. + +#include +#include +#include +#include + +#include +#include +#include + +#define CONFIG_SAMPLE_LOG_LEVEL_ SAMPLE_LOG_DEBUG_ +#include "../../../../components/utilities/include/sample_log.h" + + +void +fatal(const char *func, int rv) +{ + fprintf(stderr, "%s: %s\n", func, nng_strerror(rv)); + exit(1); +} + +/* The client runs just once, and then returns. */ +int +client(const char *url, const char *msecstr) +{ + nng_socket sock; + int rv; + nng_msg * msg; + nng_time start; + nng_time end; + unsigned msec; + SLOGD("3"); + msec = atoi(msecstr); + SLOGD("3"); + if ((rv = nng_req0_open(&sock)) != 0) { + fatal("nng_req0_open", rv); + } + SLOGD("3"); + if ((rv = nng_dial(sock, url, NULL, 0)) != 0) { + fatal("nng_dial", rv); + } + SLOGD("3"); + start = nng_clock(); + SLOGD("3"); + if ((rv = nng_msg_alloc(&msg, 0)) != 0) { + fatal("nng_msg_alloc", rv); + } + SLOGD("3"); + if ((rv = nng_msg_append_u32(msg, msec)) != 0) { + fatal("nng_msg_append_u32", rv); + } + SLOGD("3"); + if ((rv = nng_sendmsg(sock, msg, 0)) != 0) { + fatal("nng_sendmsg", rv); + } + SLOGD("3"); + if ((rv = nng_recvmsg(sock, &msg, 0)) != 0) { + fatal("nng_recvmsg", rv); + } + SLOGD("3"); + end = nng_clock(); + SLOGD("3"); + nng_msg_free(msg); + SLOGD("3"); + nng_close(sock); + SLOGD("3"); + printf("Request took %u milliseconds.\n", (uint32_t)(end - start)); + return (0); +} + +int +main(int argc, char **argv) +{ + int rc; + + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + nng_init(NULL); + rc = client(argv[1], argv[2]); + exit(rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE); +} diff --git a/examples/nng_demo/main/src/async_server.cpp b/examples/nng_demo/main/src/async_server.cpp new file mode 100644 index 0000000..5db98a2 --- /dev/null +++ b/examples/nng_demo/main/src/async_server.cpp @@ -0,0 +1,191 @@ +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +// This program serves as an example for how to write an async RPC service, +// using the request/reply pattern and contexts (nng_ctx(5)). The server +// allocates a number of contexts up front, which determines the amount of +// parallelism possible. The callbacks are handled asynchronously, so +// this could be done by threads, or something similar. For our uses we +// make use of an event driven architecture that we already have available. + +// Our demonstration application layer protocol is simple. The client sends +// a number of milliseconds to wait before responding. The server just gives +// back an empty reply after waiting that long. + +// To run this program, start the server as async_demo -s +// Then connect to it with the client as async_client . +// +// For example: +// +// % ./server tcp://127.0.0.1:5555 & +// % ./client tcp://127.0.0.1:5555 323 +// Request took 324 milliseconds. + +#include +#include +#include +#include + +#include +#include +#include + +#define CONFIG_SAMPLE_LOG_LEVEL_ SAMPLE_LOG_DEBUG_ +#include "../../../../components/utilities/include/sample_log.h" + + +// Parallel is the maximum number of outstanding requests we can handle. +// This is *NOT* the number of threads in use, but instead represents +// outstanding work items. Select a small number to reduce memory size. +// (Each one of these can be thought of as a request-reply loop.) Note +// that you will probably run into limitations on the number of open file +// descriptors if you set this too high. (If not for that limit, this could +// be set in the thousands, each context consumes a couple of KB.) +#ifndef PARALLEL +#define PARALLEL 8 +#endif + +// The server keeps a list of work items, sorted by expiration time, +// so that we can use this to set the timeout to the correct value for +// use in poll. +struct work { + enum { INIT, RECV, WAIT, SEND } state; + nng_aio *aio; + nng_msg *msg; + nng_ctx ctx; +}; + +void +fatal(const char *func, int rv) +{ + fprintf(stderr, "%s: %s\n", func, nng_strerror(rv)); + exit(1); +} + +void +server_cb(void *arg) +{ + struct work *work = (struct work *)arg; + nng_msg * msg; + int rv; + uint32_t when; + SLOGD(""); + switch (work->state) { + case work::INIT: + SLOGD("1"); + work->state = work::RECV; + nng_ctx_recv(work->ctx, work->aio); + SLOGD("2"); + break; + case work::RECV: + SLOGD("3"); + if ((rv = nng_aio_result(work->aio)) != 0) { + fatal("nng_ctx_recv", rv); + } + msg = nng_aio_get_msg(work->aio); + if ((rv = nng_msg_trim_u32(msg, &when)) != 0) { + // bad message, just ignore it. + nng_msg_free(msg); + nng_ctx_recv(work->ctx, work->aio); + return; + } + work->msg = msg; + work->state = work::WAIT; + nng_sleep_aio(100, work->aio); + SLOGD("4"); + break; + case work::WAIT: + SLOGD("5"); + // We could add more data to the message here. + nng_aio_set_msg(work->aio, work->msg); + work->msg = NULL; + work->state = work::SEND; + nng_ctx_send(work->ctx, work->aio); + SLOGD("6"); + break; + case work::SEND: + SLOGD("7"); + if ((rv = nng_aio_result(work->aio)) != 0) { + nng_msg_free(work->msg); + fatal("nng_ctx_send", rv); + } + work->state = work::RECV; + nng_ctx_recv(work->ctx, work->aio); + SLOGD("8"); + break; + default: + fatal("bad state!", NNG_ESTATE); + break; + } +} + +struct work * +alloc_work(nng_socket sock) +{ + struct work *w; + int rv; + + if ((w = (struct work *)nng_alloc(sizeof(*w))) == NULL) { + fatal("nng_alloc", NNG_ENOMEM); + } + if ((rv = nng_aio_alloc(&w->aio, server_cb, w)) != 0) { + fatal("nng_aio_alloc", rv); + } + if ((rv = nng_ctx_open(&w->ctx, sock)) != 0) { + fatal("nng_ctx_open", rv); + } + w->state = work::INIT; + return (w); +} + +// The server runs forever. +int +server(const char *url) +{ + nng_socket sock; + struct work *works[PARALLEL]; + int rv; + int i; + + /* Create the socket. */ + rv = nng_rep0_open(&sock); + if (rv != 0) { + fatal("nng_rep0_open", rv); + } + + for (i = 0; i < PARALLEL; i++) { + works[i] = alloc_work(sock); + } + + if ((rv = nng_listen(sock, url, NULL, 0)) != 0) { + fatal("nng_listen", rv); + } + + for (i = 0; i < PARALLEL; i++) { + server_cb(works[i]); // this starts them going (INIT state) + } + + for (;;) { + nng_msleep(1000); // neither pause() nor sleep() portable + } +} + +int +main(int argc, char **argv) +{ + int rc; + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + nng_init(NULL); + rc = server(argv[1]); + exit(rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE); +} diff --git a/github_source/source-list.sh b/github_source/source-list.sh index 49bff82..88eb882 100755 --- a/github_source/source-list.sh +++ b/github_source/source-list.sh @@ -45,7 +45,7 @@ git_clone_and_checkout_commit https://github.com/libjpeg-turbo/libjpeg-turbo.git git_clone_and_checkout_commit https://github.com/wqking/eventpp.git c472fb22e71ead0e58ff7df89e12c66b0bdfb533 git_clone_and_checkout_commit https://github.com/DaveGamble/cJSON.git 078c4e6c53f13dff15f0eaac1611abb6379e0206 git_clone_and_checkout_commit https://github.com/zpl-c/zpl.git 7e4d5889e9fc7c67251e627d30b7673c915fab0d - +git_clone_and_checkout_commit https://github.com/nanomsg/nng.git 9ea51a5bd5828648c68dbfbc43b2edcde65e5262 # opencv-mobile-2.4.13.7-armlinux https://github.com/nihui/opencv-mobile/releases/download/v26/opencv-mobile-2.4.13.7-armlinux.zip