ffi-nats-core 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ffi-nats-core.gemspec +8 -0
- data/lib/ffi/nats/core/version.rb +1 -1
- data/vendor/cnats/CMakeLists.txt +137 -0
- data/vendor/cnats/adapters/libevent.h +220 -0
- data/vendor/cnats/adapters/libuv.h +472 -0
- data/vendor/cnats/examples/CMakeLists.txt +56 -0
- data/vendor/cnats/examples/asynctimeout.c +83 -0
- data/vendor/cnats/examples/examples.h +322 -0
- data/vendor/cnats/examples/libevent-pub.c +136 -0
- data/vendor/cnats/examples/libevent-sub.c +104 -0
- data/vendor/cnats/examples/libuv-pub.c +120 -0
- data/vendor/cnats/examples/libuv-sub.c +114 -0
- data/vendor/cnats/examples/publisher.c +62 -0
- data/vendor/cnats/examples/queuegroup.c +132 -0
- data/vendor/cnats/examples/replier.c +149 -0
- data/vendor/cnats/examples/requestor.c +75 -0
- data/vendor/cnats/examples/subscriber.c +133 -0
- data/vendor/cnats/src/CMakeLists.txt +31 -0
- data/vendor/cnats/src/asynccb.c +66 -0
- data/vendor/cnats/src/asynccb.h +42 -0
- data/vendor/cnats/src/buf.c +246 -0
- data/vendor/cnats/src/buf.h +116 -0
- data/vendor/cnats/src/comsock.c +474 -0
- data/vendor/cnats/src/comsock.h +81 -0
- data/vendor/cnats/src/conn.c +2725 -0
- data/vendor/cnats/src/conn.h +75 -0
- data/vendor/cnats/src/err.h +31 -0
- data/vendor/cnats/src/gc.h +27 -0
- data/vendor/cnats/src/hash.c +725 -0
- data/vendor/cnats/src/hash.h +141 -0
- data/vendor/cnats/src/include/n-unix.h +56 -0
- data/vendor/cnats/src/include/n-win.h +59 -0
- data/vendor/cnats/src/mem.h +20 -0
- data/vendor/cnats/src/msg.c +155 -0
- data/vendor/cnats/src/msg.h +43 -0
- data/vendor/cnats/src/nats.c +1734 -0
- data/vendor/cnats/src/nats.h +2024 -0
- data/vendor/cnats/src/natsp.h +518 -0
- data/vendor/cnats/src/natstime.c +79 -0
- data/vendor/cnats/src/natstime.h +27 -0
- data/vendor/cnats/src/nuid.c +265 -0
- data/vendor/cnats/src/nuid.h +21 -0
- data/vendor/cnats/src/opts.c +1030 -0
- data/vendor/cnats/src/opts.h +19 -0
- data/vendor/cnats/src/parser.c +869 -0
- data/vendor/cnats/src/parser.h +87 -0
- data/vendor/cnats/src/pub.c +293 -0
- data/vendor/cnats/src/srvpool.c +380 -0
- data/vendor/cnats/src/srvpool.h +71 -0
- data/vendor/cnats/src/stats.c +54 -0
- data/vendor/cnats/src/stats.h +21 -0
- data/vendor/cnats/src/status.c +60 -0
- data/vendor/cnats/src/status.h +95 -0
- data/vendor/cnats/src/sub.c +956 -0
- data/vendor/cnats/src/sub.h +34 -0
- data/vendor/cnats/src/timer.c +86 -0
- data/vendor/cnats/src/timer.h +57 -0
- data/vendor/cnats/src/unix/cond.c +103 -0
- data/vendor/cnats/src/unix/mutex.c +107 -0
- data/vendor/cnats/src/unix/sock.c +105 -0
- data/vendor/cnats/src/unix/thread.c +162 -0
- data/vendor/cnats/src/url.c +134 -0
- data/vendor/cnats/src/url.h +24 -0
- data/vendor/cnats/src/util.c +823 -0
- data/vendor/cnats/src/util.h +75 -0
- data/vendor/cnats/src/version.h +29 -0
- data/vendor/cnats/src/version.h.in +29 -0
- data/vendor/cnats/src/win/cond.c +86 -0
- data/vendor/cnats/src/win/mutex.c +54 -0
- data/vendor/cnats/src/win/sock.c +158 -0
- data/vendor/cnats/src/win/strings.c +108 -0
- data/vendor/cnats/src/win/thread.c +180 -0
- data/vendor/cnats/test/CMakeLists.txt +35 -0
- data/vendor/cnats/test/certs/ca.pem +38 -0
- data/vendor/cnats/test/certs/client-cert.pem +30 -0
- data/vendor/cnats/test/certs/client-key.pem +51 -0
- data/vendor/cnats/test/certs/server-cert.pem +31 -0
- data/vendor/cnats/test/certs/server-key.pem +51 -0
- data/vendor/cnats/test/dylib/CMakeLists.txt +10 -0
- data/vendor/cnats/test/dylib/nonats.c +13 -0
- data/vendor/cnats/test/list.txt +125 -0
- data/vendor/cnats/test/test.c +11655 -0
- data/vendor/cnats/test/tls.conf +15 -0
- data/vendor/cnats/test/tlsverify.conf +19 -0
- metadata +83 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 329ed5a98e503504856fb08d3eb7ad5339ef9460
|
4
|
+
data.tar.gz: b853d48d011a9510ee6003823687153b3afff86f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36f22cd210b091b727ca62f11c39764c4d9473b3cebb79880a112c38f0fbb7dd8558ccbbec92e4b48e2831adbab2883a915fa8784f61a5e5fa2c47280213e6d0
|
7
|
+
data.tar.gz: 1e6102bf76d582972363e3cdc520d3ff6f15e0e9d14cde4c3200c9867a61f2a9074ec42cb0c56bb84f91d57db64d14b36114af3e5e5af311747d2fecd7dd9766
|
data/ffi-nats-core.gemspec
CHANGED
@@ -16,6 +16,14 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
17
|
f.match(%r{^(test|spec|features)/})
|
18
18
|
end
|
19
|
+
|
20
|
+
# cnats files
|
21
|
+
spec.files += Dir.glob("vendor/cnats/CMakeLists.txt")
|
22
|
+
spec.files += Dir.glob("vendor/cnats/adapters/**/*")
|
23
|
+
spec.files += Dir.glob("vendor/cnats/src/**/*")
|
24
|
+
spec.files += Dir.glob("vendor/cnats/test/**/*")
|
25
|
+
spec.files += Dir.glob("vendor/cnats/examples/**/*")
|
26
|
+
|
19
27
|
spec.bindir = "exe"
|
20
28
|
spec.extensions = "ext/ffi/nats/core/Rakefile"
|
21
29
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
@@ -0,0 +1,137 @@
|
|
1
|
+
cmake_minimum_required(VERSION 2.8)
|
2
|
+
|
3
|
+
project(cnats)
|
4
|
+
include(CTest)
|
5
|
+
|
6
|
+
# Uncomment to have the build process verbose
|
7
|
+
#set(CMAKE_VERBOSE_MAKEFILE TRUE)
|
8
|
+
|
9
|
+
# Uncomment to have the executable moved to 'build' instead of their respective 'build/xxx' directories
|
10
|
+
#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
11
|
+
|
12
|
+
set(NATS_INSTALL_PREFIX ../install CACHE PATH "Install prefix")
|
13
|
+
set(CMAKE_INSTALL_PREFIX ${NATS_INSTALL_PREFIX} CACHE INTERNAL "")
|
14
|
+
|
15
|
+
option(NATS_UPDATE_VERSION "Update the version file" OFF)
|
16
|
+
option(NATS_COVERAGE "Code coverage" OFF)
|
17
|
+
option(NATS_BUILD_WITH_TLS "Build with TLS support" ON)
|
18
|
+
option(NATS_BUILD_WITH_TLS_CLIENT_METHOD "Use TLS_client_method()" OFF)
|
19
|
+
option(NATS_BUILD_LIBUV_EXAMPLE "Compile libuv example" OFF)
|
20
|
+
option(NATS_BUILD_LIBEVENT_EXAMPLE "Compile libevent example" OFF)
|
21
|
+
|
22
|
+
if(NATS_BUILD_WITH_TLS)
|
23
|
+
find_package(OpenSSL REQUIRED)
|
24
|
+
endif(NATS_BUILD_WITH_TLS)
|
25
|
+
|
26
|
+
set(LIBUV_DIR "/usr/local/" CACHE PATH "Libuv install directory")
|
27
|
+
set(LIBEVENT_DIR "/usr/local/" CACHE PATH "Libevent install directory")
|
28
|
+
|
29
|
+
# Platform specific settings
|
30
|
+
if(UNIX)
|
31
|
+
#---------------------------------------------------------------------------
|
32
|
+
# Define NATS cache variables that override the CMAKE and MEMCHECK variables
|
33
|
+
#---------------------------------------------------------------------------
|
34
|
+
set(NATS_BUILD_TYPE Release CACHE STRING "Build type: Release, Debug, RelWithDebInfo, MinRelSize")
|
35
|
+
set(CMAKE_BUILD_TYPE ${NATS_BUILD_TYPE} CACHE INTERNAL "")
|
36
|
+
|
37
|
+
set(NATS_BUILD_ARCH "64" CACHE STRING "32 for 32bits builds")
|
38
|
+
|
39
|
+
set(NATS_MEMCHECK_CMD "/usr/bin/valgrind" CACHE FILE "Memcheck tool")
|
40
|
+
set(MEMORYCHECK_COMMAND ${NATS_MEMCHECK_CMD} CACHE INTERNAL "")
|
41
|
+
|
42
|
+
set(NATS_MEMCHECK_CMD_OPTS "--leak-check=full --track-fds=yes --show-reachable=yes --num-callers=50" CACHE STRING "Memcheck options")
|
43
|
+
set(MEMORYCHECK_COMMAND_OPTIONS ${NATS_MEMCHECK_CMD_OPTS} CACHE INTERNAL "")
|
44
|
+
|
45
|
+
set(NATS_COMMON_C_FLAGS "-std=c99 -pedantic")
|
46
|
+
|
47
|
+
if(NATS_BUILD_TYPE MATCHES "Debug")
|
48
|
+
set(NATS_COMMON_C_FLAGS "${NATS_COMMON_C_FLAGS} -ggdb")
|
49
|
+
endif(NATS_BUILD_TYPE MATCHES "Debug")
|
50
|
+
|
51
|
+
set(NATS_WARNINGS "-Wall -W -Wno-unused-variable -Wno-unused-parameter -Wno-unused-function -Wstrict-prototypes -Wwrite-strings")
|
52
|
+
set(NATS_PLATFORM_INCLUDE "unix")
|
53
|
+
|
54
|
+
if(APPLE)
|
55
|
+
set(CMAKE_MACOSX_RPATH OFF)
|
56
|
+
set(NATS_OS "DARWIN")
|
57
|
+
else(APPLE)
|
58
|
+
set(NATS_OS "LINUX")
|
59
|
+
set(NATS_USE_PTHREAD "-pthread")
|
60
|
+
set(NATS_EXTRA_LIB "rt")
|
61
|
+
if(NATS_COVERAGE)
|
62
|
+
set(NATS_CODE_COVERAGE "--coverage")
|
63
|
+
endif()
|
64
|
+
endif(APPLE)
|
65
|
+
|
66
|
+
if (${NATS_BUILD_ARCH} MATCHES "32")
|
67
|
+
if(NOT APPLE)
|
68
|
+
message("-----------------------------------------------------------")
|
69
|
+
message("If build fails, you probably need to install libc6-dev-i386")
|
70
|
+
message("apt-get install libc6-dev-i386")
|
71
|
+
message("-----------------------------------------------------------")
|
72
|
+
endif(NOT APPLE)
|
73
|
+
|
74
|
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
|
75
|
+
set(CMAKE_C_LINKER_FLAGS "${CMAKE_C_LINKER_FLAGS} -m32")
|
76
|
+
endif(${NATS_BUILD_ARCH} MATCHES "32")
|
77
|
+
|
78
|
+
elseif(WIN32)
|
79
|
+
set(NATS_OS "_WIN32")
|
80
|
+
set(NATS_PLATFORM_INCLUDE "win")
|
81
|
+
endif(UNIX)
|
82
|
+
|
83
|
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NATS_CODE_COVERAGE} ${NATS_COMMON_C_FLAGS} ${NATS_USE_PTHREAD} ${NATS_WARNINGS}")
|
84
|
+
|
85
|
+
add_definitions(-D${NATS_OS})
|
86
|
+
add_definitions(-D_REENTRANT)
|
87
|
+
if(NATS_BUILD_WITH_TLS)
|
88
|
+
add_definitions(-DNATS_HAS_TLS)
|
89
|
+
if(NATS_BUILD_WITH_TLS_CLIENT_METHOD)
|
90
|
+
add_definitions(-DNATS_USE_TLS_CLIENT_METHOD)
|
91
|
+
endif(NATS_BUILD_WITH_TLS_CLIENT_METHOD)
|
92
|
+
endif(NATS_BUILD_WITH_TLS)
|
93
|
+
|
94
|
+
#---------------------------------------------------------------------
|
95
|
+
# Add to the 'clean' target the list (and location) of files to remove
|
96
|
+
|
97
|
+
list(APPEND NATS_INSTALLED_FILES "${CMAKE_INSTALL_PREFIX}/include/nats.h")
|
98
|
+
list(APPEND NATS_INSTALLED_FILES "${CMAKE_INSTALL_PREFIX}/include/status.h")
|
99
|
+
list(APPEND NATS_INSTALLED_FILES "${CMAKE_INSTALL_PREFIX}/include/version.h")
|
100
|
+
list(APPEND NATS_INSTALLED_FILES "${CMAKE_INSTALL_PREFIX}/lib/${nats}")
|
101
|
+
list(APPEND NATS_INSTALLED_FILES "${CMAKE_INSTALL_PREFIX}/lib/${nats_static}")
|
102
|
+
|
103
|
+
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${NATS_INSTALLED_FILES}")
|
104
|
+
#---------------------------------------------------------------------
|
105
|
+
|
106
|
+
if(NATS_UPDATE_VERSION)
|
107
|
+
#------------
|
108
|
+
# Versionning
|
109
|
+
|
110
|
+
set(NATS_VERSION_MAJOR 1)
|
111
|
+
set(NATS_VERSION_MINOR 5)
|
112
|
+
set(NATS_VERSION_PATCH 0)
|
113
|
+
set(NATS_VERSION_SUFFIX "")
|
114
|
+
|
115
|
+
set(NATS_VERSION_REQUIRED_NUMBER 0x010100)
|
116
|
+
|
117
|
+
configure_file(
|
118
|
+
${CMAKE_CURRENT_SOURCE_DIR}/src/version.h.in
|
119
|
+
${CMAKE_CURRENT_SOURCE_DIR}/src/version.h
|
120
|
+
@ONLY)
|
121
|
+
|
122
|
+
configure_file(
|
123
|
+
${CMAKE_SOURCE_DIR}/doc/DoxyFile.NATS.Client.in
|
124
|
+
${CMAKE_SOURCE_DIR}/doc/DoxyFile.NATS.Client
|
125
|
+
@ONLY)
|
126
|
+
#------------
|
127
|
+
endif()
|
128
|
+
|
129
|
+
#----------------------------
|
130
|
+
# Add the project directories
|
131
|
+
|
132
|
+
add_subdirectory(src)
|
133
|
+
add_subdirectory(examples)
|
134
|
+
add_subdirectory(test)
|
135
|
+
add_subdirectory(test/dylib)
|
136
|
+
#----------------------------
|
137
|
+
|
@@ -0,0 +1,220 @@
|
|
1
|
+
// Copyright 2016 Apcera Inc. All rights reserved.
|
2
|
+
|
3
|
+
#ifndef LIBEVENT_H_
|
4
|
+
#define LIBEVENT_H_
|
5
|
+
|
6
|
+
/** \cond
|
7
|
+
*
|
8
|
+
*/
|
9
|
+
#include <event.h>
|
10
|
+
#include <event2/thread.h>
|
11
|
+
#include "nats.h"
|
12
|
+
|
13
|
+
typedef struct
|
14
|
+
{
|
15
|
+
natsConnection *nc;
|
16
|
+
struct event_base *loop;
|
17
|
+
struct event *read;
|
18
|
+
struct event *write;
|
19
|
+
struct event *keepActive;
|
20
|
+
|
21
|
+
} natsLibeventEvents;
|
22
|
+
|
23
|
+
// Forward declarations
|
24
|
+
natsStatus natsLibevent_Read(void *userData, bool add);
|
25
|
+
natsStatus natsLibevent_Detach(void *userData);
|
26
|
+
|
27
|
+
/** \endcond
|
28
|
+
*
|
29
|
+
*/
|
30
|
+
|
31
|
+
|
32
|
+
/** \defgroup libeventFunctions Libevent Adapter
|
33
|
+
*
|
34
|
+
* Adapter to plug a `NATS` connection to a `libevent` event loop.
|
35
|
+
* @{
|
36
|
+
*/
|
37
|
+
|
38
|
+
/** \brief Initialize the adapter.
|
39
|
+
*
|
40
|
+
* Needs to be called once so that the adapter can initialize some state.
|
41
|
+
*/
|
42
|
+
void
|
43
|
+
natsLibevent_Init(void)
|
44
|
+
{
|
45
|
+
#if _WIN32
|
46
|
+
evthread_use_windows_threads();
|
47
|
+
#else
|
48
|
+
evthread_use_pthreads();
|
49
|
+
#endif
|
50
|
+
}
|
51
|
+
|
52
|
+
static void
|
53
|
+
natsLibevent_ProcessEvent(int fd, short event, void *arg)
|
54
|
+
{
|
55
|
+
natsLibeventEvents *nle = (natsLibeventEvents*) arg;
|
56
|
+
|
57
|
+
if (event & EV_READ)
|
58
|
+
natsConnection_ProcessReadEvent(nle->nc);
|
59
|
+
|
60
|
+
if (event & EV_WRITE)
|
61
|
+
natsConnection_ProcessWriteEvent(nle->nc);
|
62
|
+
}
|
63
|
+
|
64
|
+
static void
|
65
|
+
keepAliveCb(evutil_socket_t fd, short flags, void * arg)
|
66
|
+
{
|
67
|
+
// do nothing...
|
68
|
+
}
|
69
|
+
|
70
|
+
/** \brief Attach a connection to the given event loop.
|
71
|
+
*
|
72
|
+
* This callback is invoked after `NATS` library has connected, or reconnected.
|
73
|
+
* For a reconnect event, `*userData` will not be `NULL`. This function will
|
74
|
+
* start polling on READ events for the given `socket`.
|
75
|
+
*
|
76
|
+
* @param userData the location where the adapter stores the user object passed
|
77
|
+
* to the other callbacks.
|
78
|
+
* @param loop the event loop as a generic pointer. Cast to appropriate type.
|
79
|
+
* @param nc the connection to attach to the event loop
|
80
|
+
* @param socket the socket to start polling on.
|
81
|
+
*/
|
82
|
+
natsStatus
|
83
|
+
natsLibevent_Attach(void **userData, void *loop, natsConnection *nc, int socket)
|
84
|
+
{
|
85
|
+
struct event_base *libeventLoop = (struct event_base*) loop;
|
86
|
+
natsLibeventEvents *nle = (natsLibeventEvents*) (*userData);
|
87
|
+
natsStatus s = NATS_OK;
|
88
|
+
|
89
|
+
// This is the first attach (when reconnecting, nle will be non-NULL).
|
90
|
+
if (nle == NULL)
|
91
|
+
{
|
92
|
+
nle = (natsLibeventEvents*) calloc(1, sizeof(natsLibeventEvents));
|
93
|
+
if (nle == NULL)
|
94
|
+
return NATS_NO_MEMORY;
|
95
|
+
|
96
|
+
nle->nc = nc;
|
97
|
+
nle->loop = libeventLoop;
|
98
|
+
|
99
|
+
nle->keepActive = event_new(nle->loop, -1, EV_PERSIST, keepAliveCb, NULL);
|
100
|
+
if (nle->keepActive == NULL)
|
101
|
+
s = NATS_NO_MEMORY;
|
102
|
+
|
103
|
+
if (s == NATS_OK)
|
104
|
+
{
|
105
|
+
struct timeval timeout;
|
106
|
+
|
107
|
+
timeout.tv_sec = 100000;
|
108
|
+
timeout.tv_usec = 0;
|
109
|
+
|
110
|
+
if (event_add(nle->keepActive, &timeout) != 0)
|
111
|
+
s = NATS_ERR;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
else
|
115
|
+
{
|
116
|
+
if (nle->read != NULL)
|
117
|
+
{
|
118
|
+
event_free(nle->read);
|
119
|
+
nle->read = NULL;
|
120
|
+
}
|
121
|
+
if (nle->write != NULL)
|
122
|
+
{
|
123
|
+
event_free(nle->write);
|
124
|
+
nle->write = NULL;
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
if (s == NATS_OK)
|
129
|
+
{
|
130
|
+
nle->read = event_new(nle->loop, socket, EV_READ|EV_PERSIST,
|
131
|
+
natsLibevent_ProcessEvent, (void*) nle);
|
132
|
+
natsLibevent_Read((void*) nle, true);
|
133
|
+
|
134
|
+
nle->write = event_new(nle->loop, socket, EV_WRITE|EV_PERSIST,
|
135
|
+
natsLibevent_ProcessEvent, (void*) nle);
|
136
|
+
}
|
137
|
+
|
138
|
+
if (s == NATS_OK)
|
139
|
+
*userData = (void*) nle;
|
140
|
+
else
|
141
|
+
natsLibevent_Detach((void*) nle);
|
142
|
+
|
143
|
+
return s;
|
144
|
+
}
|
145
|
+
|
146
|
+
/** \brief Start or stop polling on READ events.
|
147
|
+
*
|
148
|
+
* This callback is invoked to notify that the event library should start
|
149
|
+
* or stop polling for READ events.
|
150
|
+
*
|
151
|
+
* @param userData the user object created in #natsLibuv_Attach
|
152
|
+
* @param add `true` if the library needs to start polling, `false` otherwise.
|
153
|
+
*/
|
154
|
+
natsStatus
|
155
|
+
natsLibevent_Read(void *userData, bool add)
|
156
|
+
{
|
157
|
+
natsLibeventEvents *nle = (natsLibeventEvents*) userData;
|
158
|
+
int res;
|
159
|
+
|
160
|
+
if (add)
|
161
|
+
res = event_add(nle->read, NULL);
|
162
|
+
else
|
163
|
+
res = event_del(nle->read);
|
164
|
+
|
165
|
+
return (res == 0 ? NATS_OK : NATS_ERR);
|
166
|
+
}
|
167
|
+
|
168
|
+
/** \brief Start or stop polling on WRITE events.
|
169
|
+
*
|
170
|
+
* This callback is invoked to notify that the event library should start
|
171
|
+
* or stop polling for WRITE events.
|
172
|
+
*
|
173
|
+
* @param userData the user object created in #natsLibuv_Attach
|
174
|
+
* @param add `true` if the library needs to start polling, `false` otherwise.
|
175
|
+
*/
|
176
|
+
natsStatus
|
177
|
+
natsLibevent_Write(void *userData, bool add)
|
178
|
+
{
|
179
|
+
natsLibeventEvents *nle = (natsLibeventEvents*) userData;
|
180
|
+
int res;
|
181
|
+
|
182
|
+
if (add)
|
183
|
+
res = event_add(nle->write, NULL);
|
184
|
+
else
|
185
|
+
res = event_del(nle->write);
|
186
|
+
|
187
|
+
return (res == 0 ? NATS_OK : NATS_ERR);
|
188
|
+
}
|
189
|
+
|
190
|
+
/** \brief The connection is closed, it can be safely detached.
|
191
|
+
*
|
192
|
+
* When a connection is closed (not disconnected, pending a reconnect), this
|
193
|
+
* callback will be invoked. This is the opportunity to cleanup the state
|
194
|
+
* maintained by the adapter for this connection.
|
195
|
+
*
|
196
|
+
* @param userData the user object created in #natsLibuv_Attach
|
197
|
+
*/
|
198
|
+
natsStatus
|
199
|
+
natsLibevent_Detach(void *userData)
|
200
|
+
{
|
201
|
+
natsLibeventEvents *nle = (natsLibeventEvents*) userData;
|
202
|
+
|
203
|
+
if (nle->read != NULL)
|
204
|
+
event_free(nle->read);
|
205
|
+
if (nle->write != NULL)
|
206
|
+
event_free(nle->write);
|
207
|
+
if (nle->keepActive != NULL)
|
208
|
+
{
|
209
|
+
event_active(nle->keepActive, 0, 0);
|
210
|
+
event_free(nle->keepActive);
|
211
|
+
}
|
212
|
+
|
213
|
+
free(nle);
|
214
|
+
|
215
|
+
return NATS_OK;
|
216
|
+
}
|
217
|
+
|
218
|
+
/** @} */ // end of libeventFunctions
|
219
|
+
|
220
|
+
#endif /* LIBEVENT_H_ */
|
@@ -0,0 +1,472 @@
|
|
1
|
+
// Copyright 2016 Apcera Inc. All rights reserved.
|
2
|
+
|
3
|
+
#ifndef LIBUV_H_
|
4
|
+
#define LIBUV_H_
|
5
|
+
|
6
|
+
/** \cond
|
7
|
+
*
|
8
|
+
*/
|
9
|
+
#ifndef _GNU_SOURCE
|
10
|
+
#define _GNU_SOURCE
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#define NATS_LIBUV_INCLUDE
|
14
|
+
|
15
|
+
#include <uv.h>
|
16
|
+
#include "nats.h"
|
17
|
+
|
18
|
+
#define NATS_LIBUV_ATTACH (1)
|
19
|
+
#define NATS_LIBUV_READ (2)
|
20
|
+
#define NATS_LIBUV_WRITE (3)
|
21
|
+
#define NATS_LIBUV_DETACH (4)
|
22
|
+
|
23
|
+
struct __natsLibuvEvent;
|
24
|
+
|
25
|
+
typedef struct __natsLibuvEvent
|
26
|
+
{
|
27
|
+
int type;
|
28
|
+
bool add;
|
29
|
+
struct __natsLibuvEvent *next;
|
30
|
+
|
31
|
+
} natsLibuvEvent;
|
32
|
+
|
33
|
+
typedef struct
|
34
|
+
{
|
35
|
+
natsConnection *nc;
|
36
|
+
uv_loop_t *loop;
|
37
|
+
uv_poll_t *handle;
|
38
|
+
uv_async_t *scheduler;
|
39
|
+
int events;
|
40
|
+
int socket;
|
41
|
+
uv_mutex_t *lock;
|
42
|
+
natsLibuvEvent *head;
|
43
|
+
natsLibuvEvent *tail;
|
44
|
+
|
45
|
+
} natsLibuvEvents;
|
46
|
+
|
47
|
+
// Forward declarations
|
48
|
+
natsStatus natsLibuv_Detach(void *userData);
|
49
|
+
|
50
|
+
/** \endcond
|
51
|
+
*
|
52
|
+
*/
|
53
|
+
|
54
|
+
static uv_once_t uvOnce = UV_ONCE_INIT;
|
55
|
+
static uv_key_t uvLoopThreadKey;
|
56
|
+
|
57
|
+
static void
|
58
|
+
_initOnce(void)
|
59
|
+
{
|
60
|
+
if (uv_key_create(&uvLoopThreadKey) != 0)
|
61
|
+
abort();
|
62
|
+
}
|
63
|
+
|
64
|
+
/** \defgroup libuvFunctions Libuv Adapter
|
65
|
+
*
|
66
|
+
* Adapter to plug a `NATS` connection to a `libuv` event loop.
|
67
|
+
* @{
|
68
|
+
*/
|
69
|
+
|
70
|
+
/** \brief Initialize the adapter.
|
71
|
+
*
|
72
|
+
* Needs to be called once so that the adapter can initialize some state.
|
73
|
+
*/
|
74
|
+
void
|
75
|
+
natsLibuv_Init(void)
|
76
|
+
{
|
77
|
+
uv_once(&uvOnce, _initOnce);
|
78
|
+
}
|
79
|
+
|
80
|
+
/** \brief Register the event loop with the thread running `uv_run()`.
|
81
|
+
*
|
82
|
+
* Since `libuv` is not thread-safe, the adapter needs to know in which
|
83
|
+
* thread `uv_run()` will run for the given `loop`. It allows the adapter
|
84
|
+
* to schedule events so that they are executed in the event loop thread.
|
85
|
+
*
|
86
|
+
* @param loop an event loop.
|
87
|
+
*/
|
88
|
+
void
|
89
|
+
natsLibuv_SetThreadLocalLoop(uv_loop_t *loop)
|
90
|
+
{
|
91
|
+
uv_key_set(&uvLoopThreadKey, (void*) loop);
|
92
|
+
}
|
93
|
+
|
94
|
+
static natsStatus
|
95
|
+
uvScheduleToEventLoop(natsLibuvEvents *nle, int eventType, bool add)
|
96
|
+
{
|
97
|
+
natsLibuvEvent *newEvent = NULL;
|
98
|
+
int res;
|
99
|
+
|
100
|
+
newEvent = (natsLibuvEvent*) malloc(sizeof(natsLibuvEvent));
|
101
|
+
if (newEvent == NULL)
|
102
|
+
return NATS_NO_MEMORY;
|
103
|
+
|
104
|
+
newEvent->type = eventType;
|
105
|
+
newEvent->add = add;
|
106
|
+
newEvent->next = NULL;
|
107
|
+
|
108
|
+
uv_mutex_lock(nle->lock);
|
109
|
+
|
110
|
+
if (nle->head == NULL)
|
111
|
+
nle->head = newEvent;
|
112
|
+
|
113
|
+
if (nle->tail != NULL)
|
114
|
+
nle->tail->next = newEvent;
|
115
|
+
|
116
|
+
nle->tail = newEvent;
|
117
|
+
|
118
|
+
uv_mutex_unlock(nle->lock);
|
119
|
+
|
120
|
+
res = uv_async_send(nle->scheduler);
|
121
|
+
|
122
|
+
return (res == 0 ? NATS_OK : NATS_ERR);
|
123
|
+
}
|
124
|
+
|
125
|
+
static void
|
126
|
+
natsLibuvPoll(uv_poll_t* handle, int status, int events)
|
127
|
+
{
|
128
|
+
natsLibuvEvents *nle = (natsLibuvEvents*)handle->data;
|
129
|
+
|
130
|
+
if (status != 0)
|
131
|
+
return;
|
132
|
+
|
133
|
+
if (events & UV_READABLE)
|
134
|
+
natsConnection_ProcessReadEvent(nle->nc);
|
135
|
+
|
136
|
+
if (events & UV_WRITABLE)
|
137
|
+
natsConnection_ProcessWriteEvent(nle->nc);
|
138
|
+
}
|
139
|
+
|
140
|
+
static natsStatus
|
141
|
+
uvPollUpdate(natsLibuvEvents *nle, int eventType, bool add)
|
142
|
+
{
|
143
|
+
int res;
|
144
|
+
|
145
|
+
if (eventType == NATS_LIBUV_READ)
|
146
|
+
{
|
147
|
+
if (add)
|
148
|
+
nle->events |= UV_READABLE;
|
149
|
+
else
|
150
|
+
nle->events &= ~UV_READABLE;
|
151
|
+
}
|
152
|
+
else
|
153
|
+
{
|
154
|
+
if (add)
|
155
|
+
nle->events |= UV_WRITABLE;
|
156
|
+
else
|
157
|
+
nle->events &= ~UV_WRITABLE;
|
158
|
+
}
|
159
|
+
|
160
|
+
if (nle->events)
|
161
|
+
res = uv_poll_start(nle->handle, nle->events, natsLibuvPoll);
|
162
|
+
else
|
163
|
+
res = uv_poll_stop(nle->handle);
|
164
|
+
|
165
|
+
if (res != 0)
|
166
|
+
return NATS_ERR;
|
167
|
+
|
168
|
+
return NATS_OK;
|
169
|
+
}
|
170
|
+
|
171
|
+
static void
|
172
|
+
uvHandleClosedCb(uv_handle_t *handle)
|
173
|
+
{
|
174
|
+
free(handle);
|
175
|
+
}
|
176
|
+
|
177
|
+
static natsStatus
|
178
|
+
uvAsyncAttach(natsLibuvEvents *nle)
|
179
|
+
{
|
180
|
+
natsStatus s = NATS_OK;
|
181
|
+
|
182
|
+
// We are reconnecting, destroy the old handle, create a new one
|
183
|
+
if (nle->handle != NULL)
|
184
|
+
{
|
185
|
+
uv_close((uv_handle_t*) nle->handle, uvHandleClosedCb);
|
186
|
+
nle->handle = NULL;
|
187
|
+
}
|
188
|
+
|
189
|
+
nle->handle = (uv_poll_t*) malloc(sizeof(uv_poll_t));
|
190
|
+
if (nle->handle == NULL)
|
191
|
+
s = NATS_NO_MEMORY;
|
192
|
+
|
193
|
+
if ((s == NATS_OK)
|
194
|
+
&& (uv_poll_init_socket(nle->loop, nle->handle, nle->socket) != 0))
|
195
|
+
{
|
196
|
+
s = NATS_ERR;
|
197
|
+
}
|
198
|
+
|
199
|
+
if ((s == NATS_OK)
|
200
|
+
&& (nle->handle->data = (void*) nle)
|
201
|
+
&& (uv_poll_start(nle->handle, UV_READABLE, natsLibuvPoll) != 0))
|
202
|
+
{
|
203
|
+
s = NATS_ERR;
|
204
|
+
}
|
205
|
+
|
206
|
+
return s;
|
207
|
+
}
|
208
|
+
|
209
|
+
static void
|
210
|
+
finalCloseCb(uv_handle_t* handle)
|
211
|
+
{
|
212
|
+
natsLibuvEvents *nle = (natsLibuvEvents*)handle->data;
|
213
|
+
natsLibuvEvent *event;
|
214
|
+
|
215
|
+
while ((event = nle->head) != NULL)
|
216
|
+
{
|
217
|
+
nle->head = event->next;
|
218
|
+
free(event);
|
219
|
+
}
|
220
|
+
free(nle->handle);
|
221
|
+
free(nle->scheduler);
|
222
|
+
uv_mutex_destroy(nle->lock);
|
223
|
+
free(nle->lock);
|
224
|
+
free(nle);
|
225
|
+
}
|
226
|
+
|
227
|
+
static void
|
228
|
+
closeSchedulerCb(uv_handle_t* scheduler)
|
229
|
+
{
|
230
|
+
natsLibuvEvents *nle = (natsLibuvEvents*) scheduler->data;
|
231
|
+
|
232
|
+
uv_close((uv_handle_t*) nle->handle, finalCloseCb);
|
233
|
+
}
|
234
|
+
|
235
|
+
static void
|
236
|
+
uvAsyncDetach(natsLibuvEvents *nle)
|
237
|
+
{
|
238
|
+
uv_close((uv_handle_t*) nle->scheduler, closeSchedulerCb);
|
239
|
+
}
|
240
|
+
|
241
|
+
static void
|
242
|
+
uvAsyncCb(uv_async_t *handle)
|
243
|
+
{
|
244
|
+
natsLibuvEvents *nle = (natsLibuvEvents*) handle->data;
|
245
|
+
natsStatus s = NATS_OK;
|
246
|
+
natsLibuvEvent *event = NULL;
|
247
|
+
bool remove = false;
|
248
|
+
bool more = false;
|
249
|
+
|
250
|
+
while (1)
|
251
|
+
{
|
252
|
+
uv_mutex_lock(nle->lock);
|
253
|
+
|
254
|
+
event = nle->head;
|
255
|
+
if (event == NULL)
|
256
|
+
{
|
257
|
+
// This is possible, even on entry of this function because
|
258
|
+
// the callback is called when the handle is initialized.
|
259
|
+
uv_mutex_unlock(nle->lock);
|
260
|
+
return;
|
261
|
+
}
|
262
|
+
|
263
|
+
nle->head = event->next;
|
264
|
+
if (event == nle->tail)
|
265
|
+
nle->tail = NULL;
|
266
|
+
|
267
|
+
more = (nle->head != NULL ? true : false);
|
268
|
+
|
269
|
+
uv_mutex_unlock(nle->lock);
|
270
|
+
|
271
|
+
switch (event->type)
|
272
|
+
{
|
273
|
+
case NATS_LIBUV_ATTACH:
|
274
|
+
{
|
275
|
+
s = uvAsyncAttach(nle);
|
276
|
+
break;
|
277
|
+
}
|
278
|
+
case NATS_LIBUV_READ:
|
279
|
+
case NATS_LIBUV_WRITE:
|
280
|
+
{
|
281
|
+
s = uvPollUpdate(nle, event->type, event->add);
|
282
|
+
break;
|
283
|
+
}
|
284
|
+
case NATS_LIBUV_DETACH:
|
285
|
+
{
|
286
|
+
uvAsyncDetach(nle);
|
287
|
+
break;
|
288
|
+
}
|
289
|
+
default:
|
290
|
+
{
|
291
|
+
s = NATS_ERR;
|
292
|
+
break;
|
293
|
+
}
|
294
|
+
}
|
295
|
+
|
296
|
+
free(event);
|
297
|
+
|
298
|
+
if ((s != NATS_OK) || !more)
|
299
|
+
break;
|
300
|
+
}
|
301
|
+
|
302
|
+
if (s != NATS_OK)
|
303
|
+
natsConnection_Close(nle->nc);
|
304
|
+
}
|
305
|
+
|
306
|
+
/** \brief Attach a connection to the given event loop.
|
307
|
+
*
|
308
|
+
* This callback is invoked after `NATS` library has connected, or reconnected.
|
309
|
+
* For a reconnect event, `*userData` will not be `NULL`. This function will
|
310
|
+
* start polling on READ events for the given `socket`.
|
311
|
+
*
|
312
|
+
* @param userData the location where the adapter stores the user object passed
|
313
|
+
* to the other callbacks.
|
314
|
+
* @param loop the event loop as a generic pointer. Cast to appropriate type.
|
315
|
+
* @param nc the connection to attach to the event loop
|
316
|
+
* @param socket the socket to start polling on.
|
317
|
+
*/
|
318
|
+
natsStatus
|
319
|
+
natsLibuv_Attach(void **userData, void *loop, natsConnection *nc, int socket)
|
320
|
+
{
|
321
|
+
uv_loop_t *uvLoop = (uv_loop_t*) loop;
|
322
|
+
bool sched = false;
|
323
|
+
natsLibuvEvents *nle = (natsLibuvEvents*) (*userData);
|
324
|
+
natsStatus s = NATS_OK;
|
325
|
+
|
326
|
+
sched = ((uv_key_get(&uvLoopThreadKey) != loop) ? true : false);
|
327
|
+
|
328
|
+
// This is the first attach (when reconnecting, nle will be non-NULL).
|
329
|
+
if (nle == NULL)
|
330
|
+
{
|
331
|
+
// This has to run from the event loop!
|
332
|
+
if (sched)
|
333
|
+
return NATS_ILLEGAL_STATE;
|
334
|
+
|
335
|
+
nle = (natsLibuvEvents*) calloc(1, sizeof(natsLibuvEvents));
|
336
|
+
if (nle == NULL)
|
337
|
+
return NATS_NO_MEMORY;
|
338
|
+
|
339
|
+
nle->lock = (uv_mutex_t*) malloc(sizeof(uv_mutex_t));
|
340
|
+
if (nle->lock == NULL)
|
341
|
+
s = NATS_NO_MEMORY;
|
342
|
+
|
343
|
+
if ((s == NATS_OK) && (uv_mutex_init(nle->lock) != 0))
|
344
|
+
s = NATS_ERR;
|
345
|
+
|
346
|
+
if ((s == NATS_OK)
|
347
|
+
&& ((nle->scheduler = (uv_async_t*) malloc(sizeof(uv_async_t))) == NULL))
|
348
|
+
{
|
349
|
+
s = NATS_NO_MEMORY;
|
350
|
+
}
|
351
|
+
|
352
|
+
if ((s == NATS_OK)
|
353
|
+
&& (uv_async_init(uvLoop, nle->scheduler, uvAsyncCb) != 0))
|
354
|
+
{
|
355
|
+
s = NATS_ERR;
|
356
|
+
}
|
357
|
+
|
358
|
+
if (s == NATS_OK)
|
359
|
+
{
|
360
|
+
nle->nc = nc;
|
361
|
+
nle->loop = uvLoop;
|
362
|
+
nle->scheduler->data = (void*) nle;
|
363
|
+
}
|
364
|
+
}
|
365
|
+
|
366
|
+
if (s == NATS_OK)
|
367
|
+
{
|
368
|
+
nle->socket = socket;
|
369
|
+
nle->events = UV_READABLE;
|
370
|
+
|
371
|
+
if (sched)
|
372
|
+
s = uvScheduleToEventLoop(nle, NATS_LIBUV_ATTACH, true);
|
373
|
+
else
|
374
|
+
s = uvAsyncAttach(nle);
|
375
|
+
}
|
376
|
+
|
377
|
+
if (s == NATS_OK)
|
378
|
+
*userData = (void*) nle;
|
379
|
+
else
|
380
|
+
natsLibuv_Detach((void*) nle);
|
381
|
+
|
382
|
+
return s;
|
383
|
+
}
|
384
|
+
|
385
|
+
/** \brief Start or stop polling on READ events.
|
386
|
+
*
|
387
|
+
* This callback is invoked to notify that the event library should start
|
388
|
+
* or stop polling for READ events.
|
389
|
+
*
|
390
|
+
* @param userData the user object created in #natsLibuv_Attach
|
391
|
+
* @param add `true` if the library needs to start polling, `false` otherwise.
|
392
|
+
*/
|
393
|
+
natsStatus
|
394
|
+
natsLibuv_Read(void *userData, bool add)
|
395
|
+
{
|
396
|
+
natsLibuvEvents *nle = (natsLibuvEvents*) userData;
|
397
|
+
natsStatus s = NATS_OK;
|
398
|
+
bool sched;
|
399
|
+
|
400
|
+
sched = ((uv_key_get(&uvLoopThreadKey) != nle->loop) ? true : false);
|
401
|
+
|
402
|
+
// If this call is made from a different thread than the event loop's
|
403
|
+
// thread, or if there are already scheduled events, then schedule
|
404
|
+
// this new event.
|
405
|
+
|
406
|
+
// We don't need to get the lock for nle->head because if sched is
|
407
|
+
// false, we are in the event loop thread, which is the thread removing
|
408
|
+
// events from the list. Also, all calls to the read/write/etc.. callbacks
|
409
|
+
// are protected by the connection's lock in the NATS library.
|
410
|
+
if (sched || (nle->head != NULL))
|
411
|
+
s = uvScheduleToEventLoop(nle, NATS_LIBUV_READ, add);
|
412
|
+
else
|
413
|
+
s = uvPollUpdate(nle, NATS_LIBUV_READ, add);
|
414
|
+
|
415
|
+
return s;
|
416
|
+
}
|
417
|
+
|
418
|
+
/** \brief Start or stop polling on WRITE events.
|
419
|
+
*
|
420
|
+
* This callback is invoked to notify that the event library should start
|
421
|
+
* or stop polling for WRITE events.
|
422
|
+
*
|
423
|
+
* @param userData the user object created in #natsLibuv_Attach
|
424
|
+
* @param add `true` if the library needs to start polling, `false` otherwise.
|
425
|
+
*/
|
426
|
+
natsStatus
|
427
|
+
natsLibuv_Write(void *userData, bool add)
|
428
|
+
{
|
429
|
+
natsLibuvEvents *nle = (natsLibuvEvents*) userData;
|
430
|
+
natsStatus s = NATS_OK;
|
431
|
+
bool sched;
|
432
|
+
|
433
|
+
sched = ((uv_key_get(&uvLoopThreadKey) != nle->loop) ? true : false);
|
434
|
+
|
435
|
+
// See comment in natsLibuvRead
|
436
|
+
if (sched || (nle->head != NULL))
|
437
|
+
s = uvScheduleToEventLoop(nle, NATS_LIBUV_WRITE, add);
|
438
|
+
else
|
439
|
+
s = uvPollUpdate(nle, NATS_LIBUV_WRITE, add);
|
440
|
+
|
441
|
+
return s;
|
442
|
+
}
|
443
|
+
|
444
|
+
/** \brief The connection is closed, it can be safely detached.
|
445
|
+
*
|
446
|
+
* When a connection is closed (not disconnected, pending a reconnect), this
|
447
|
+
* callback will be invoked. This is the opportunity to cleanup the state
|
448
|
+
* maintained by the adapter for this connection.
|
449
|
+
*
|
450
|
+
* @param userData the user object created in #natsLibuv_Attach
|
451
|
+
*/
|
452
|
+
natsStatus
|
453
|
+
natsLibuv_Detach(void *userData)
|
454
|
+
{
|
455
|
+
natsLibuvEvents *nle = (natsLibuvEvents*) userData;
|
456
|
+
natsStatus s = NATS_OK;
|
457
|
+
bool sched;
|
458
|
+
|
459
|
+
sched = ((uv_key_get(&uvLoopThreadKey) != nle->loop) ? true : false);
|
460
|
+
|
461
|
+
// See comment in natsLibuvRead
|
462
|
+
if (sched || (nle->head != NULL))
|
463
|
+
s = uvScheduleToEventLoop(nle, NATS_LIBUV_DETACH, true);
|
464
|
+
else
|
465
|
+
uvAsyncDetach(nle);
|
466
|
+
|
467
|
+
return s;
|
468
|
+
}
|
469
|
+
|
470
|
+
/** @} */ // end of libuvFunctions
|
471
|
+
|
472
|
+
#endif /* LIBUV_H_ */
|