zyre 0.1.0 → 0.4.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
- checksums.yaml.gz.sig +3 -2
- data.tar.gz.sig +0 -0
- data/Authentication.md +30 -0
- data/History.md +36 -0
- data/README.md +70 -6
- data/ext/zyre_ext/cert.c +504 -0
- data/ext/zyre_ext/event.c +105 -33
- data/ext/zyre_ext/extconf.rb +5 -0
- data/ext/zyre_ext/node.c +283 -38
- data/ext/zyre_ext/poller.c +6 -7
- data/ext/zyre_ext/zyre_ext.c +104 -1
- data/ext/zyre_ext/zyre_ext.h +25 -2
- data/lib/observability/instrumentation/zyre.rb +4 -4
- data/lib/zyre.rb +38 -14
- data/lib/zyre/cert.rb +75 -0
- data/lib/zyre/event.rb +9 -0
- data/lib/zyre/event/leader.rb +18 -0
- data/lib/zyre/event/stop.rb +5 -0
- data/lib/zyre/testing.rb +36 -3
- data/spec/observability/instrumentation/zyre_spec.rb +2 -2
- data/spec/spec_helper.rb +4 -0
- data/spec/zyre/cert_spec.rb +218 -0
- data/spec/zyre/event_spec.rb +62 -0
- data/spec/zyre/node_spec.rb +195 -8
- data/spec/zyre/testing_spec.rb +72 -0
- data/spec/zyre_spec.rb +12 -0
- metadata +22 -17
- metadata.gz.sig +0 -0
data/ext/zyre_ext/poller.c
CHANGED
@@ -15,14 +15,13 @@ VALUE rzyre_cZyrePoller;
|
|
15
15
|
static void rzyre_poller_free( void *ptr );
|
16
16
|
|
17
17
|
static const rb_data_type_t rzyre_poller_t = {
|
18
|
-
"Zyre::Poller",
|
19
|
-
{
|
20
|
-
NULL,
|
21
|
-
rzyre_poller_free
|
18
|
+
.wrap_struct_name = "Zyre::Poller",
|
19
|
+
.function = {
|
20
|
+
.dmark = NULL,
|
21
|
+
.dfree = rzyre_poller_free,
|
22
22
|
},
|
23
|
-
|
24
|
-
|
25
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
23
|
+
.data = NULL,
|
24
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
26
25
|
};
|
27
26
|
|
28
27
|
|
data/ext/zyre_ext/zyre_ext.c
CHANGED
@@ -68,6 +68,67 @@ rzyre_log( const char *level, const char *fmt, va_dcl )
|
|
68
68
|
}
|
69
69
|
|
70
70
|
|
71
|
+
/* --------------------------------------------------------------
|
72
|
+
* Utility functions
|
73
|
+
* -------------------------------------------------------------- */
|
74
|
+
|
75
|
+
// Struct for passing arguments through rb_protect to rzyre_add_frames_to_zmsg()
|
76
|
+
struct add_frames_to_zmsg_call {
|
77
|
+
zmsg_t *msg;
|
78
|
+
VALUE msg_parts;
|
79
|
+
};
|
80
|
+
typedef struct add_frames_to_zmsg_call add_frames_to_zmsg_call_t;
|
81
|
+
|
82
|
+
|
83
|
+
/*
|
84
|
+
* Add a frame for each object in an Array.
|
85
|
+
*/
|
86
|
+
static VALUE
|
87
|
+
rzyre_add_frames_to_zmsg( VALUE call )
|
88
|
+
{
|
89
|
+
add_frames_to_zmsg_call_t *call_ptr = (add_frames_to_zmsg_call_t *)call;
|
90
|
+
VALUE msg_part, msg_str;
|
91
|
+
zframe_t *frame;
|
92
|
+
|
93
|
+
for ( long i = 0 ; i < RARRAY_LEN(call_ptr->msg_parts) ; i++ ) {
|
94
|
+
msg_part = rb_ary_entry(call_ptr->msg_parts, i);
|
95
|
+
msg_str = StringValue( msg_part );
|
96
|
+
frame = zframe_new( RSTRING_PTR(msg_str), RSTRING_LEN(msg_str) );
|
97
|
+
zmsg_append( call_ptr->msg, &frame );
|
98
|
+
}
|
99
|
+
|
100
|
+
return Qtrue;
|
101
|
+
}
|
102
|
+
|
103
|
+
|
104
|
+
/*
|
105
|
+
* Make and return a zmsg, with one frame per object in +messages+. Caller owns the returned
|
106
|
+
* zmsg. Can raise a TypeError if one of the +messages+ can't be stringified.
|
107
|
+
*/
|
108
|
+
zmsg_t *
|
109
|
+
rzyre_make_zmsg_from( VALUE messages )
|
110
|
+
{
|
111
|
+
VALUE msgarray = rb_Array( messages );
|
112
|
+
zmsg_t *msg = zmsg_new();
|
113
|
+
static add_frames_to_zmsg_call_t call;
|
114
|
+
int state;
|
115
|
+
|
116
|
+
call.msg = msg;
|
117
|
+
call.msg_parts = msgarray;
|
118
|
+
|
119
|
+
rb_protect( rzyre_add_frames_to_zmsg, (VALUE)&call, &state );
|
120
|
+
|
121
|
+
if ( state ) {
|
122
|
+
zmsg_destroy( &msg );
|
123
|
+
rb_jump_tag( state );
|
124
|
+
}
|
125
|
+
|
126
|
+
return msg;
|
127
|
+
}
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
|
71
132
|
|
72
133
|
/* --------------------------------------------------------------
|
73
134
|
* Module methods
|
@@ -107,7 +168,7 @@ rzyre_s_zyre_version()
|
|
107
168
|
* }
|
108
169
|
*/
|
109
170
|
static VALUE
|
110
|
-
rzyre_s_interfaces()
|
171
|
+
rzyre_s_interfaces( VALUE module )
|
111
172
|
{
|
112
173
|
ziflist_t *iflist = ziflist_new();
|
113
174
|
const VALUE rval = rb_hash_new();
|
@@ -134,6 +195,30 @@ rzyre_s_interfaces()
|
|
134
195
|
}
|
135
196
|
|
136
197
|
|
198
|
+
/*
|
199
|
+
* call-seq:
|
200
|
+
* Zyre.disable_zsys_handler
|
201
|
+
*
|
202
|
+
* Disable CZMQ's default signal handler, which allows for handling it in Ruby instead.
|
203
|
+
*
|
204
|
+
*/
|
205
|
+
static VALUE
|
206
|
+
rzyre_s_disable_zsys_handler( VALUE module )
|
207
|
+
{
|
208
|
+
rzyre_log( "info", "Disabling zsys INT/TERM handler." );
|
209
|
+
zsys_handler_set( NULL );
|
210
|
+
return Qtrue;
|
211
|
+
}
|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
static VALUE
|
216
|
+
rzyre_s_start_authenticator( VALUE module )
|
217
|
+
{
|
218
|
+
return Qnil;
|
219
|
+
}
|
220
|
+
|
221
|
+
|
137
222
|
/*
|
138
223
|
* Zyre extension init function
|
139
224
|
*/
|
@@ -142,13 +227,31 @@ Init_zyre_ext()
|
|
142
227
|
{
|
143
228
|
rzyre_mZyre = rb_define_module( "Zyre" );
|
144
229
|
|
230
|
+
#ifdef CZMQ_BUILD_DRAFT_API
|
231
|
+
rb_define_const( rzyre_mZyre, "BUILT_WITH_DRAFT_CZMQ_API", Qtrue );
|
232
|
+
#else
|
233
|
+
rb_define_const( rzyre_mZyre, "BUILT_WITH_DRAFT_CZMQ_API", Qfalse );
|
234
|
+
#endif
|
235
|
+
#ifdef ZYRE_BUILD_DRAFT_API
|
236
|
+
rb_define_const( rzyre_mZyre, "BUILT_WITH_DRAFT_API", Qtrue );
|
237
|
+
#else
|
238
|
+
rb_define_const( rzyre_mZyre, "BUILT_WITH_DRAFT_API", Qfalse );
|
239
|
+
#endif
|
240
|
+
|
145
241
|
rb_define_singleton_method( rzyre_mZyre, "zyre_version", rzyre_s_zyre_version, 0 );
|
146
242
|
rb_define_singleton_method( rzyre_mZyre, "interfaces", rzyre_s_interfaces, 0 );
|
243
|
+
rb_define_singleton_method( rzyre_mZyre, "disable_zsys_handler", rzyre_s_disable_zsys_handler, 0 );
|
244
|
+
|
245
|
+
// :TODO: Allow for startup of the zauth agent. This will require enough of a
|
246
|
+
// subset of CZMQ that I hesitate to do it in Zyre. Maybe better to just write a
|
247
|
+
// decent CZMQ library instead?
|
248
|
+
rb_define_singleton_method( rzyre_mZyre, "start_authenticator", rzyre_s_start_authenticator, 0 );
|
147
249
|
|
148
250
|
// :TODO: set up zsys_set_logsender()
|
149
251
|
|
150
252
|
rzyre_init_node();
|
151
253
|
rzyre_init_event();
|
152
254
|
rzyre_init_poller();
|
255
|
+
rzyre_init_cert();
|
153
256
|
}
|
154
257
|
|
data/ext/zyre_ext/zyre_ext.h
CHANGED
@@ -10,13 +10,23 @@
|
|
10
10
|
#ifndef ZYRE_EXT_H_90322ABD
|
11
11
|
#define ZYRE_EXT_H_90322ABD
|
12
12
|
|
13
|
+
#include "extconf.h"
|
14
|
+
|
13
15
|
#include <ruby.h>
|
14
16
|
#include <ruby/intern.h>
|
15
17
|
#include <ruby/thread.h>
|
18
|
+
#include <ruby/encoding.h>
|
19
|
+
#include <ruby/version.h>
|
20
|
+
|
21
|
+
#ifdef HAVE_ZCERT_UNSET_META
|
22
|
+
# define CZMQ_BUILD_DRAFT_API 1
|
23
|
+
#endif
|
24
|
+
#ifdef HAVE_ZYRE_SET_BEACON_PEER_PORT
|
25
|
+
# define ZYRE_BUILD_DRAFT_API 1
|
26
|
+
#endif
|
16
27
|
|
17
28
|
#include "zyre.h"
|
18
29
|
#include "czmq.h"
|
19
|
-
#include "extconf.h"
|
20
30
|
|
21
31
|
#ifndef TRUE
|
22
32
|
# define TRUE 1
|
@@ -27,7 +37,8 @@
|
|
27
37
|
#endif
|
28
38
|
|
29
39
|
|
30
|
-
// For synthesized events
|
40
|
+
// For synthesized events, sizeof calculations, copied from the czmq and zyre
|
41
|
+
// source
|
31
42
|
struct _zyre_event_t {
|
32
43
|
char *type; // Event type as string
|
33
44
|
char *peer_uuid; // Sender UUID as string
|
@@ -39,6 +50,7 @@ struct _zyre_event_t {
|
|
39
50
|
};
|
40
51
|
|
41
52
|
|
53
|
+
|
42
54
|
/* --------------------------------------------------------------
|
43
55
|
* Declarations
|
44
56
|
* -------------------------------------------------------------- */
|
@@ -73,6 +85,9 @@ extern VALUE rzyre_mZyre;
|
|
73
85
|
extern VALUE rzyre_cZyreNode;
|
74
86
|
extern VALUE rzyre_cZyreEvent;
|
75
87
|
extern VALUE rzyre_cZyrePoller;
|
88
|
+
extern VALUE rzyre_cZyreCert;
|
89
|
+
|
90
|
+
extern zactor_t *auth_actor;
|
76
91
|
|
77
92
|
|
78
93
|
/* --------------------------------------------------------------
|
@@ -82,6 +97,12 @@ extern VALUE rzyre_cZyrePoller;
|
|
82
97
|
#define IsZyreNode( obj ) rb_obj_is_kind_of( (obj), rzyre_cZyreNode )
|
83
98
|
#define IsZyreEvent( obj ) rb_obj_is_kind_of( (obj), rzyre_cZyreEvent )
|
84
99
|
#define IsZyrePoller( obj ) rb_obj_is_kind_of( (obj), rzyre_cZyrePoller )
|
100
|
+
#define IsZyreCert( obj ) rb_obj_is_kind_of( (obj), rzyre_cZyreCert )
|
101
|
+
|
102
|
+
/* --------------------------------------------------------------
|
103
|
+
* Utility functions
|
104
|
+
* -------------------------------------------------------------- */
|
105
|
+
extern zmsg_t * rzyre_make_zmsg_from _(( VALUE ));
|
85
106
|
|
86
107
|
|
87
108
|
/* -------------------------------------------------------
|
@@ -92,8 +113,10 @@ extern void Init_zyre_ext _(( void ));
|
|
92
113
|
extern void rzyre_init_node _(( void ));
|
93
114
|
extern void rzyre_init_event _(( void ));
|
94
115
|
extern void rzyre_init_poller _(( void ));
|
116
|
+
extern void rzyre_init_cert _(( void ));
|
95
117
|
|
96
118
|
extern zyre_t * rzyre_get_node _(( VALUE ));
|
119
|
+
extern zcert_t * rzyre_get_cert _(( VALUE ));
|
97
120
|
|
98
121
|
#endif /* end of include guard: ZYRE_EXT_H_90322ABD */
|
99
122
|
|
@@ -38,14 +38,14 @@ module Observability::Instrumentation::Zyre
|
|
38
38
|
###############
|
39
39
|
|
40
40
|
### Observer callback for the #whisper method.
|
41
|
-
def observe_whisper( peer_uuid,
|
42
|
-
Observability.observer.add( peer_uuid: peer_uuid,
|
41
|
+
def observe_whisper( peer_uuid, *msgs )
|
42
|
+
Observability.observer.add( peer_uuid: peer_uuid, messages: msgs )
|
43
43
|
end
|
44
44
|
|
45
45
|
|
46
46
|
### Observer callback for the #shout method.
|
47
|
-
def observe_shout( group,
|
48
|
-
Observability.observer.add( group: group,
|
47
|
+
def observe_shout( group, *msgs )
|
48
|
+
Observability.observer.add( group: group, messages: msgs )
|
49
49
|
end
|
50
50
|
|
51
51
|
end # module Observability::Instrumentation::Zyre
|
data/lib/zyre.rb
CHANGED
@@ -1,35 +1,27 @@
|
|
1
1
|
# -*- ruby -*-
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require 'set'
|
4
5
|
require 'loggability'
|
5
6
|
|
6
7
|
require_relative 'zyre_ext'
|
7
8
|
|
8
9
|
|
9
|
-
|
10
|
+
#--
|
11
|
+
# See also: ext/zyre_ext/zyre_ext.c
|
10
12
|
module Zyre
|
11
13
|
extend Loggability
|
12
14
|
|
13
15
|
|
14
16
|
# Gem version (semver)
|
15
|
-
VERSION = '0.1
|
16
|
-
|
17
|
+
VERSION = '0.4.1'
|
17
18
|
|
18
19
|
# Set up a logger for Zyre classes
|
19
20
|
log_as :zyre
|
20
21
|
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
### Specify a +timeout+ of -1 to wait indefinitely. The timeout is in floating-point
|
25
|
-
### seconds.
|
26
|
-
###
|
27
|
-
### Raises an Interrupt if the call is interrupted or the ZMQ context is destroyed.
|
28
|
-
def self::wait( *nodes, timeout: -1 )
|
29
|
-
nodes = nodes.flatten
|
30
|
-
return nil if nodes.empty?
|
31
|
-
return self.wait2( nodes, timeout )
|
32
|
-
end
|
23
|
+
@whitelisted_ips = Set.new
|
24
|
+
@blacklisted_ips = Set.new
|
33
25
|
|
34
26
|
|
35
27
|
### If the given +key+ is a Symbol, transform it into an RFC822-style header key. If
|
@@ -50,4 +42,36 @@ module Zyre
|
|
50
42
|
transform_values {|v| v.to_s.encode('us-ascii') }
|
51
43
|
end
|
52
44
|
|
45
|
+
|
46
|
+
### Allow (whitelist) a list of IP +addresses+. For NULL, all clients from
|
47
|
+
### these addresses will be accepted. For PLAIN and CURVE, they will be
|
48
|
+
### allowed to continue with authentication. You can call this method
|
49
|
+
### multiple times to whitelist more IP addresses. If you whitelist one
|
50
|
+
### or more addresses, any non-whitelisted addresses are treated as
|
51
|
+
### blacklisted:
|
52
|
+
def self::allow( *addresses )
|
53
|
+
@whitelisted_ips.merge( addresses )
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
### Deny (blacklist) a list of IP +addresses+. For all security mechanisms,
|
58
|
+
### this rejects the connection without any further authentication. Use
|
59
|
+
### either a whitelist, or a blacklist, not not both. If you define both
|
60
|
+
### a whitelist and a blacklist, only the whitelist takes effect:
|
61
|
+
def self::deny( *addresses )
|
62
|
+
@blacklisted_ips.merge( addresses )
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
### Returns +true+ if the underlying Czmq library was built with draft APIs.
|
67
|
+
def self::has_draft_czmq_apis?
|
68
|
+
return Zyre::BUILT_WITH_DRAFT_CZMQ_API ? true : false
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
### Returns +true+ if the underlying Zyre library was built with draft APIs.
|
73
|
+
def self::has_draft_apis?
|
74
|
+
return Zyre::BUILT_WITH_DRAFT_API ? true : false
|
75
|
+
end
|
76
|
+
|
53
77
|
end # module Zyre
|
data/lib/zyre/cert.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'loggability'
|
5
|
+
|
6
|
+
require 'zyre' unless defined?( Zyre )
|
7
|
+
|
8
|
+
|
9
|
+
#--
|
10
|
+
# See also: ext/zyre_ext/cert.c
|
11
|
+
class Zyre::Cert
|
12
|
+
extend Loggability
|
13
|
+
|
14
|
+
|
15
|
+
# The placeholder key that is set as the secret key for a public certificate.
|
16
|
+
EMPTY_KEY = "\x00" * 32
|
17
|
+
|
18
|
+
|
19
|
+
# Use the Zyre module's logger
|
20
|
+
log_to :zyre
|
21
|
+
|
22
|
+
|
23
|
+
# Set up some more Rubyish aliases
|
24
|
+
alias_method :private_key, :secret_key
|
25
|
+
alias_method :==, :eql?
|
26
|
+
|
27
|
+
|
28
|
+
### Fetch the value for the cert metadata with the given +name+.
|
29
|
+
def []( name )
|
30
|
+
return self.meta( name.to_s )
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
### Set the value for the cert metadata with the given +name+ to +value+.
|
35
|
+
def []=( name, value )
|
36
|
+
return self.set_meta( name.to_s, value.to_s )
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
### Return the metadata from the cert as a Hash.
|
41
|
+
def meta_hash
|
42
|
+
hash = self.meta_keys.each_with_object( {} ) do |key, h|
|
43
|
+
h[ key ] = self[ key ]
|
44
|
+
end
|
45
|
+
hash.freeze
|
46
|
+
return hash
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
### Delete the value for the cert metadata with the given +name+. Requires
|
51
|
+
### CZMQ to have been built with Draft APIs.
|
52
|
+
def delete( name )
|
53
|
+
name = name.to_s
|
54
|
+
|
55
|
+
deleted_val = self[ name ]
|
56
|
+
self.unset_meta( name )
|
57
|
+
|
58
|
+
return deleted_val
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
### Returns +true+ if the certificate has a secret key.
|
63
|
+
def have_secret_key?
|
64
|
+
return self.secret_key != EMPTY_KEY
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
### Apply the certificate to the specified +zyre_node+, i.e. use the
|
69
|
+
### cert for CURVE security. If the receiving certificate doesn't have a
|
70
|
+
### private key, an exception will be raised.
|
71
|
+
def apply( zyre_node )
|
72
|
+
return zyre_node.zcert = self
|
73
|
+
end
|
74
|
+
|
75
|
+
end # class Zyre::Cert
|
data/lib/zyre/event.rb
CHANGED
@@ -25,6 +25,7 @@ class Zyre::Event
|
|
25
25
|
autoload :Exit, 'zyre/event/exit'
|
26
26
|
autoload :Join, 'zyre/event/join'
|
27
27
|
autoload :Leave, 'zyre/event/leave'
|
28
|
+
autoload :Leader, 'zyre/event/leader'
|
28
29
|
autoload :Shout, 'zyre/event/shout'
|
29
30
|
autoload :Silent, 'zyre/event/silent'
|
30
31
|
autoload :Stop, 'zyre/event/stop'
|
@@ -60,6 +61,14 @@ class Zyre::Event
|
|
60
61
|
end
|
61
62
|
|
62
63
|
|
64
|
+
### Returns +true+ if the receiving event has a multipart message.
|
65
|
+
def multipart?
|
66
|
+
size = self.msg_size
|
67
|
+
return size && size > 1
|
68
|
+
end
|
69
|
+
alias_method :is_multipart?, :multipart?
|
70
|
+
|
71
|
+
|
63
72
|
### Return a string describing this event, suitable for debugging.
|
64
73
|
def inspect
|
65
74
|
details = self.inspect_details
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'zyre/event' unless defined?( Zyre::Event )
|
5
|
+
|
6
|
+
|
7
|
+
class Zyre::Event::Leader < Zyre::Event
|
8
|
+
|
9
|
+
### Provide the details of the inspect message.
|
10
|
+
def inspect_details
|
11
|
+
return "%s (%s) has been elected leader of «%s»" % [
|
12
|
+
self.peer_uuid,
|
13
|
+
self.peer_name,
|
14
|
+
self.group
|
15
|
+
]
|
16
|
+
end
|
17
|
+
|
18
|
+
end # class Zyre::Event::Leader
|