zyre 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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