ffi-nats-core 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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_ */
|