zyre 0.3.1 → 0.4.0

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.
data/ext/zyre_ext/event.c CHANGED
@@ -15,14 +15,13 @@ VALUE rzyre_cZyreEvent;
15
15
  static void rzyre_event_free( void *ptr );
16
16
 
17
17
  static const rb_data_type_t rzyre_event_t = {
18
- "Zyre::Event",
19
- {
20
- NULL,
21
- rzyre_event_free
18
+ .wrap_struct_name = "Zyre::Event",
19
+ .function = {
20
+ .dmark = NULL,
21
+ .dfree = rzyre_event_free,
22
22
  },
23
- 0,
24
- 0,
25
- RUBY_TYPED_FREE_IMMEDIATELY,
23
+ .data = NULL,
24
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
26
25
  };
27
26
 
28
27
 
@@ -78,7 +77,7 @@ rzyre_read_event( void *node_ptr )
78
77
  assert( node_ptr );
79
78
 
80
79
  event_ptr = zyre_event_new( (zyre_t *)node_ptr );
81
- assert( event_ptr );
80
+
82
81
  return (void *)event_ptr;
83
82
  }
84
83
 
@@ -104,7 +103,13 @@ rzyre_event_s_from_node( VALUE klass, VALUE node )
104
103
  const char *event_type = zyre_event_type( event );
105
104
  VALUE event_type_s = rb_utf8_str_new_cstr( event_type );
106
105
  VALUE event_class = rb_funcall( klass, rb_intern("type_by_name"), 1, event_type_s );
107
- VALUE event_instance = rb_class_new_instance( 0, NULL, event_class );
106
+ VALUE event_instance;
107
+
108
+ if ( !RTEST(event_class) ) {
109
+ rb_raise( rb_eRuntimeError, "Unhandled event type '%s'", event_type );
110
+ }
111
+
112
+ event_instance = rb_class_new_instance( 0, NULL, event_class );
108
113
 
109
114
  RTYPEDDATA_DATA( event_instance ) = event;
110
115
 
@@ -263,6 +268,9 @@ rzyre_event_s_synthesize( int argc, VALUE *argv, VALUE klass )
263
268
  ptr->group = rzyre_copy_required_string( kwvals[3], "group" );
264
269
  ptr->msg = rzyre_make_zmsg_from( kwvals[4] );
265
270
  }
271
+ else if ( streq(ptr->type, "LEADER") ) {
272
+ ptr->group = rzyre_copy_required_string( kwvals[3], "group" );
273
+ }
266
274
 
267
275
  rzyre_log_obj( rval, "debug", "Synthesized a %s event.", ptr->type );
268
276
 
@@ -19,6 +19,11 @@ have_header( 'ruby/thread.h' ) or
19
19
 
20
20
  have_func( 'zyre_set_name', 'zyre.h' )
21
21
  have_func( 'zyre_set_silent_timeout', 'zyre.h' )
22
+ have_func( 'zyre_set_beacon_peer_port', 'zyre.h' )
23
+ have_func( 'zyre_set_contest_in_group', 'zyre.h' )
24
+ have_func( 'zyre_set_zcert', 'zyre.h' )
25
+
26
+ have_func( 'zcert_unset_meta', 'czmq.h' )
22
27
 
23
28
  create_header()
24
29
  create_makefile( 'zyre_ext' )
data/ext/zyre_ext/node.c CHANGED
@@ -8,21 +8,26 @@
8
8
  */
9
9
 
10
10
  #include "zyre_ext.h"
11
+ #include "extconf.h"
11
12
 
12
13
 
13
14
  VALUE rzyre_cZyreNode;
14
15
 
16
+ // Null key; means curve isn't available or the secret side of a public cert.
17
+ #define FORTY_ZEROES "0000000000000000000000000000000000000000"
18
+
19
+
15
20
  static void rzyre_node_free( void *ptr );
16
21
 
22
+
17
23
  static const rb_data_type_t rzyre_node_t = {
18
- "Zyre::Node",
19
- {
20
- NULL,
21
- rzyre_node_free
24
+ .wrap_struct_name = "Zyre::Node",
25
+ .function = {
26
+ .dmark = NULL,
27
+ .dfree = rzyre_node_free,
22
28
  },
23
- 0,
24
- 0,
25
- RUBY_TYPED_FREE_IMMEDIATELY,
29
+ .data = NULL,
30
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
26
31
  };
27
32
 
28
33
 
@@ -38,6 +43,7 @@ rzyre_node_free( void *ptr )
38
43
  }
39
44
 
40
45
 
46
+
41
47
  /*
42
48
  * Alloc function
43
49
  */
@@ -512,9 +518,7 @@ rzyre_node_leave( VALUE self, VALUE group )
512
518
  * call-seq:
513
519
  * node.recv -> zyre_event
514
520
  *
515
- * Receive the next event from the network; the message may be a control
516
- * message (ENTER, EXIT, JOIN, LEAVE) or data (WHISPER, SHOUT).
517
- * Returns a Zyre::Event.
521
+ * Receive the next event from the network as a Zyre::Event.
518
522
  *
519
523
  */
520
524
  static VALUE
@@ -771,6 +775,241 @@ rzyre_node_print( VALUE self )
771
775
  }
772
776
 
773
777
 
778
+ /* --------------------------------------------------------------
779
+ * Draft API
780
+ * -------------------------------------------------------------- */
781
+
782
+
783
+ #define RAISE_NO_DRAFT_APIS()\
784
+ rb_raise( rb_eNotImpError, "Zyre was not built with Draft APIs!" ); \
785
+ return Qnil;
786
+
787
+ /*
788
+ * call-seq:
789
+ * node.beacon_peer_port = 16668
790
+ *
791
+ * Set the TCP port bound by the ROUTER peer-to-peer socket (beacon mode).
792
+ * Defaults to * (the port is randomly assigned by the system).
793
+ * This call overrides this, to bypass some firewall issues when ports are
794
+ * random. Has no effect after #start.
795
+ *
796
+ * Note: this is part of the ZRE 43 Draft API, and may be changed or
797
+ * removed at any time.
798
+ */
799
+ static VALUE
800
+ rzyre_node_beacon_peer_port_eq( VALUE self, VALUE port_number )
801
+ {
802
+ #ifdef ZYRE_BUILD_DRAFT_API
803
+ zyre_t *ptr = rzyre_get_node( self );
804
+
805
+ zyre_set_beacon_peer_port( ptr, FIX2INT(port_number) );
806
+
807
+ return port_number;
808
+ #else
809
+ RAISE_NO_DRAFT_APIS();
810
+ #endif // ZYRE_BUILD_DRAFT_API
811
+ }
812
+
813
+
814
+ /*
815
+ * call-seq:
816
+ * node.set_contest_in_group( group )
817
+ *
818
+ * This options enables a peer to actively contest for leadership in the
819
+ * given +group+. If this option is not set the peer will still participate in
820
+ * elections but never gets elected. This ensures that a consent for a leader
821
+ * is reached within a group even though not every peer is contesting for
822
+ * leadership.
823
+ *
824
+ * Note: this is part of the ZRE 43 Draft API, and may be changed or
825
+ * removed at any time.
826
+ */
827
+ static VALUE
828
+ rzyre_node_set_contest_in_group( VALUE self, VALUE group_name )
829
+ {
830
+ #ifdef ZYRE_BUILD_DRAFT_API
831
+ zyre_t *ptr = rzyre_get_node( self );
832
+ const char *group_str = StringValueCStr( group_name );
833
+
834
+ zyre_set_contest_in_group( ptr, group_str );
835
+
836
+ return group_name;
837
+ #else
838
+ RAISE_NO_DRAFT_APIS();
839
+ #endif // ZYRE_BUILD_DRAFT_API
840
+ }
841
+
842
+
843
+ /*
844
+ * call-seq:
845
+ * node.advertised_endpoint = endpoint
846
+ *
847
+ * Set an alternative +endpoint+ value when using GOSSIP ONLY. This is useful
848
+ * if you're advertising an endpoint behind a NAT.
849
+ *
850
+ * Note: this is part of the ZRE 43 Draft API, and may be changed or
851
+ * removed at any time.
852
+ */
853
+ static VALUE
854
+ rzyre_node_advertised_endpoint_eq( VALUE self, VALUE endpoint )
855
+ {
856
+ #ifdef ZYRE_BUILD_DRAFT_API
857
+ zyre_t *ptr = rzyre_get_node( self );
858
+ const char *endpoint_str = StringValueCStr( endpoint );
859
+
860
+ zyre_set_advertised_endpoint( ptr, endpoint_str );
861
+
862
+ return endpoint;
863
+ #else
864
+ RAISE_NO_DRAFT_APIS();
865
+ #endif // ZYRE_BUILD_DRAFT_API
866
+ }
867
+
868
+
869
+ /*
870
+ * call-seq:
871
+ * node.zcert = zcert
872
+ *
873
+ * Apply a +zcert+ to a Zyre node. See Zyre::Cert#apply and
874
+ * Authentication[rdoc-ref:Authentication].
875
+ *
876
+ * Note: this is part of the ZRE 43 Draft API, and may be changed or
877
+ * removed at any time.
878
+ */
879
+ static VALUE
880
+ rzyre_node_zcert_eq( VALUE self, VALUE cert )
881
+ {
882
+ #ifdef ZYRE_BUILD_DRAFT_API
883
+ zyre_t *ptr = rzyre_get_node( self );
884
+ zcert_t *zcert = rzyre_get_cert( cert );
885
+
886
+ if ( streq(zcert_secret_txt(zcert), FORTY_ZEROES) ) {
887
+ rb_raise( rb_eArgError,
888
+ "can't use this cert for authentication (no curve or missing secret key)" );
889
+ }
890
+
891
+ zyre_set_zcert( ptr, zcert );
892
+
893
+ return Qtrue;
894
+ #else
895
+ RAISE_NO_DRAFT_APIS();
896
+ #endif // ZYRE_BUILD_DRAFT_API
897
+ }
898
+
899
+
900
+ /*
901
+ * call-seq:
902
+ * node.zap_domain = domain
903
+ *
904
+ * Specify the ZAP domain (for use with CURVE authentication). See
905
+ * Authentication[rdoc-ref:Authentication].
906
+ *
907
+ * Note: this is part of the ZRE 43 Draft API, and may be changed or
908
+ * removed at any time.
909
+ */
910
+ static VALUE
911
+ rzyre_node_zap_domain_eq( VALUE self, VALUE domain )
912
+ {
913
+ #ifdef ZYRE_BUILD_DRAFT_API
914
+ zyre_t *ptr = rzyre_get_node( self );
915
+ const char *domain_str = StringValueCStr( domain );
916
+
917
+ zyre_set_zap_domain( ptr, domain_str );
918
+
919
+ return Qtrue;
920
+ #else
921
+ RAISE_NO_DRAFT_APIS();
922
+ #endif // ZYRE_BUILD_DRAFT_API
923
+ }
924
+
925
+
926
+ /*
927
+ * call-seq:
928
+ * node.gossip_connect_curve( public_key, endpoint )
929
+ *
930
+ * Connect to the gossip discovery endpoint with CURVE enabled. The +public_key+ is the
931
+ * Z85-armored public key of the connecting node's cert/
932
+ *
933
+ * Note: this is part of the ZRE 43 Draft API, and may be changed or
934
+ * removed at any time.
935
+ */
936
+ static VALUE
937
+ rzyre_node_gossip_connect_curve( VALUE self, VALUE public_key, VALUE endpoint )
938
+ {
939
+ #ifdef ZYRE_BUILD_DRAFT_API
940
+ zyre_t *ptr = rzyre_get_node( self );
941
+ const char *endpoint_str = StringValueCStr( endpoint );
942
+ const char *key = StringValueCStr( public_key );
943
+
944
+ assert( endpoint_str );
945
+ assert( key );
946
+
947
+ rzyre_log_obj( self, "debug", "Connecting to gossip endpoint %s (CURVE enabled).", endpoint_str );
948
+ zyre_gossip_connect_curve( ptr, key, "%s", endpoint_str );
949
+
950
+ return Qtrue;
951
+ #else
952
+ RAISE_NO_DRAFT_APIS();
953
+ #endif // ZYRE_BUILD_DRAFT_API
954
+ }
955
+
956
+
957
+ /*
958
+ * call-seq:
959
+ * node.gossip_unpublish( node_uuid )
960
+ *
961
+ * Unpublish a GOSSIP node from local list, useful in removing nodes from list
962
+ * when they EXIT.
963
+ *
964
+ * Note: this is part of the ZRE 43 Draft API, and may be changed or
965
+ * removed at any time.
966
+ */
967
+ static VALUE
968
+ rzyre_node_gossip_unpublish( VALUE self, VALUE node_uuid )
969
+ {
970
+ #ifdef ZYRE_BUILD_DRAFT_API
971
+ zyre_t *ptr = rzyre_get_node( self );
972
+ const char *node = StringValueCStr( node_uuid );
973
+
974
+ zyre_gossip_unpublish( ptr, node );
975
+
976
+ return Qtrue;
977
+ #else
978
+ RAISE_NO_DRAFT_APIS();
979
+ #endif // ZYRE_BUILD_DRAFT_API
980
+ }
981
+
982
+
983
+ /*
984
+ * call-seq:
985
+ * node.require_peer( node_uuid, router_endpoint, public_key )
986
+ *
987
+ * Explicitly connect to a peer with the given +node_uuid+ via the specified
988
+ * +router_endpoint+, using the given +public_key+ to authenticate.
989
+ *
990
+ * Note: this is part of the ZRE 43 Draft API, and may be changed or
991
+ * removed at any time.
992
+ */
993
+ static VALUE
994
+ rzyre_node_require_peer( VALUE self, VALUE uuid, VALUE endpoint, VALUE public_key )
995
+ {
996
+ #ifdef ZYRE_BUILD_DRAFT_API
997
+ zyre_t *ptr = rzyre_get_node( self );
998
+ const char *uuid_str = StringValueCStr( uuid ),
999
+ *endpoint_str = StringValueCStr( endpoint ),
1000
+ *key_str = StringValueCStr( public_key );
1001
+ int rval;
1002
+
1003
+ rval = zyre_require_peer( ptr, uuid_str, endpoint_str, key_str );
1004
+
1005
+ return rval == 0 ? Qtrue : Qfalse;
1006
+ #else
1007
+ RAISE_NO_DRAFT_APIS();
1008
+ #endif // ZYRE_BUILD_DRAFT_API
1009
+ }
1010
+
1011
+
1012
+
774
1013
  /*
775
1014
  * Node class init
776
1015
  */
@@ -791,7 +1030,11 @@ rzyre_init_node( void )
791
1030
  * Refs:
792
1031
  * - https://github.com/zeromq/zyre#readme
793
1032
  */
1033
+ #if RUBY_API_VERSION_MAJOR >= 3
1034
+ rzyre_cZyreNode = rb_define_class_under( rzyre_mZyre, "Node", rb_cObject );
1035
+ #else
794
1036
  rzyre_cZyreNode = rb_define_class_under( rzyre_mZyre, "Node", rb_cData );
1037
+ #endif
795
1038
 
796
1039
  rb_define_alloc_func( rzyre_cZyreNode, rzyre_node_alloc );
797
1040
 
@@ -838,18 +1081,14 @@ rzyre_init_node( void )
838
1081
  rb_define_method( rzyre_cZyreNode, "verbose!", rzyre_node_verbose_bang, 0 );
839
1082
  rb_define_method( rzyre_cZyreNode, "print", rzyre_node_print, 0 );
840
1083
 
841
- #ifdef ZYRE_BUILD_DRAFT_API
842
-
843
- rb_define_method( rzyre_cZyreNode, "set_beacon_peer_port", rzyre_node_set_beacon_peer_port, -1 );
844
- rb_define_method( rzyre_cZyreNode, "set_contest_in_group", rzyre_node_set_contest_in_group, -1 );
845
- rb_define_method( rzyre_cZyreNode, "set_advertised_endpoint", rzyre_node_set_advertised_endpoint, -1 );
846
- rb_define_method( rzyre_cZyreNode, "set_zcert", rzyre_node_set_zcert, -1 );
847
- rb_define_method( rzyre_cZyreNode, "set_zap_domain", rzyre_node_set_zap_domain, -1 );
848
- rb_define_method( rzyre_cZyreNode, "gossip_connect_curve", rzyre_node_gossip_connect_curve, -1 );
849
- rb_define_method( rzyre_cZyreNode, "gossip_unpublish", rzyre_node_gossip_unpublish, -1 );
850
- rb_define_method( rzyre_cZyreNode, "require_peer", rzyre_node_require_peer, -1 );
851
-
852
- #endif // ZYRE_BUILD_DRAFT_API
1084
+ rb_define_method( rzyre_cZyreNode, "beacon_peer_port=", rzyre_node_beacon_peer_port_eq, 1 );
1085
+ rb_define_method( rzyre_cZyreNode, "set_contest_in_group", rzyre_node_set_contest_in_group, 1 );
1086
+ rb_define_method( rzyre_cZyreNode, "advertised_endpoint=", rzyre_node_advertised_endpoint_eq, 1 );
1087
+ rb_define_method( rzyre_cZyreNode, "zcert=", rzyre_node_zcert_eq, 1 );
1088
+ rb_define_method( rzyre_cZyreNode, "zap_domain=", rzyre_node_zap_domain_eq, 1 );
1089
+ rb_define_method( rzyre_cZyreNode, "gossip_connect_curve", rzyre_node_gossip_connect_curve, 2 );
1090
+ rb_define_method( rzyre_cZyreNode, "gossip_unpublish", rzyre_node_gossip_unpublish, 1 );
1091
+ rb_define_method( rzyre_cZyreNode, "require_peer", rzyre_node_require_peer, 3 );
853
1092
 
854
1093
  rb_require( "zyre/node" );
855
1094
  }
@@ -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
- 0,
24
- 0,
25
- RUBY_TYPED_FREE_IMMEDIATELY,
23
+ .data = NULL,
24
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
26
25
  };
27
26
 
28
27
 
@@ -168,7 +168,7 @@ rzyre_s_zyre_version()
168
168
  * }
169
169
  */
170
170
  static VALUE
171
- rzyre_s_interfaces()
171
+ rzyre_s_interfaces( VALUE module )
172
172
  {
173
173
  ziflist_t *iflist = ziflist_new();
174
174
  const VALUE rval = rb_hash_new();
@@ -195,6 +195,30 @@ rzyre_s_interfaces()
195
195
  }
196
196
 
197
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
+
198
222
  /*
199
223
  * Zyre extension init function
200
224
  */
@@ -203,13 +227,31 @@ Init_zyre_ext()
203
227
  {
204
228
  rzyre_mZyre = rb_define_module( "Zyre" );
205
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
+
206
241
  rb_define_singleton_method( rzyre_mZyre, "zyre_version", rzyre_s_zyre_version, 0 );
207
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 );
208
249
 
209
250
  // :TODO: set up zsys_set_logsender()
210
251
 
211
252
  rzyre_init_node();
212
253
  rzyre_init_event();
213
254
  rzyre_init_poller();
255
+ rzyre_init_cert();
214
256
  }
215
257