intruder 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -12,27 +12,45 @@ Want to try?
12
12
  the test script makes an rpc call to a rabbitmq server and queries for its status.
13
13
 
14
14
  * checkout the source
15
- * `./configure`
15
+ * `ruby extconf.rb`
16
16
  * start your rabbitmq server `sudo rabbitmq-server`
17
- * `ruby test.rb`
17
+ * `ruby examples/rabbitmq_status_rpc.rb`
18
18
 
19
19
  the script should print something similar to this:
20
- rabbit call
20
+ --- rabbit call ---
21
21
  sending params: []
22
22
  rpc call to rabbit:status
23
- rpc response: [{running_applications, [{rabbit, "RabbitMQ", "1.7.2"}, {mnesia, "MNESIA CXC 138 12", "4.4.13"}, {os_mon, "CPO CXC 138 46", "2.2.5"}, {sasl, "SASL CXC 138 11", "2.1.9"}, {stdlib, "ERTS CXC 138 10", "1.16.5"}, {kernel, "ERTS CXC 138 10", "2.13.5"}]}, {nodes, [rabbit@codeslave]}, {running_nodes, [rabbit@codeslave]}]
23
+ [{running_applications, [{rabbit, "RabbitMQ", "1.7.2"}, {mnesia, "MNESIA CXC 138 12", "4.4.13"}, {os_mon, "CPO CXC 138 46", "2.2.5"}, {sasl, "SASL CXC 138 11", "2.1.9"}, {stdlib, "ERTS CXC 138 10", "1.16.5"}, {kernel, "ERTS CXC 138 10", "2.13.5"}]}, {nodes, ['rabbit@codeslave']}, {running_nodes, ['rabbit@codeslave']}]
24
+ Intruder::List
25
+
26
+ --- length of the response ---
27
+ Members: 3
28
+
29
+ --- print every member with its class ---
30
+ {running_applications, [{rabbit, "RabbitMQ", "1.7.2"}, {mnesia, "MNESIA CXC 138 12", "4.4.13"}, {os_mon, "CPO CXC 138 46", "2.2.5"}, {sasl, "SASL CXC 138 11", "2.1.9"}, {stdlib, "ERTS CXC 138 10", "1.16.5"}, {kernel, "ERTS CXC 138 10", "2.13.5"}]} class: Intruder::Tuple
31
+ {nodes, ['rabbit@codeslave']} class: Intruder::Tuple
32
+ {running_nodes, ['rabbit@codeslave']} class: Intruder::Tuple
33
+
34
+ --- access the second element and print its size ---
35
+ {running_nodes, ['rabbit@codeslave']} has size 2
36
+
37
+ --- access the first element of the second member ---
38
+ nodes
39
+
40
+ --- which is a ---
41
+ Intruder::Atom
24
42
 
25
43
  Why that?
26
44
  =========
27
45
 
28
- because thats a fun project to learn c :)
46
+ because thats a fun project to learn c and I need it for another project of mine (namely: paukul/humpty)
29
47
 
30
48
  What works already?
31
49
  ===================
32
50
 
33
- not much
51
+ description missing... yet :)
34
52
 
35
53
  Erlix?
36
54
  ======
37
55
 
38
- is great, took some stuff from there, as I said, thats a fun project for me to learn more about c and c ruby extensions
56
+ is great, I also took some stuff from them. Afaik, Erlix uses erl_interface for most of its operations. erl_interface is limited to one connection only, I needed something to open multiple connections to multiple queues. Erlix is able to do a LOT more than Intruder at the moment, make sure to check it out as well!
data/extconf.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'mkmf'
2
+
3
+ extension_name = 'intruder_ext'
4
+ src_dir = File.expand_path('../src', __FILE__)
5
+ findei = File.expand_path("../findei.erl", __FILE__)
6
+
7
+ dir_config(extension_name)
8
+ File.chmod(0755, findei)
9
+
10
+ ei_dir = `#{findei}`.chomp
11
+ include_dir = ei_dir + '/include/'
12
+ lib_dir = ei_dir + '/lib/'
13
+
14
+ $LDFLAGS << " -L#{lib_dir} -lei -lerl_interface"
15
+ $CPPFLAGS << ' -D_REENTRANT -g -g3 -gdwarf-2'
16
+
17
+ if find_header('ei.h', include_dir)
18
+ create_makefile(extension_name, src_dir)
19
+ else
20
+ puts "error: erl_interface not found!"
21
+ end
data/findei.erl ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env escript
2
+ %%% Author : KDr2
3
+ %%% Find the location of erl_interface.
4
+
5
+ main(_) ->
6
+ io:format("~s~n", [code:lib_dir(erl_interface)]).
data/lib/intruder.rb ADDED
@@ -0,0 +1,20 @@
1
+ require File.expand_path('../../intruder_ext', __FILE__)
2
+
3
+ module Intruder
4
+
5
+ class Node
6
+ def mod(mod_name)
7
+ Mod.new(mod_name, self)
8
+ end
9
+ end
10
+
11
+ class Mod
12
+
13
+ private
14
+
15
+ def method_missing(method, *args)
16
+ rpc(method.to_s, *args)
17
+ end
18
+ end
19
+
20
+ end
data/src/atom.c ADDED
@@ -0,0 +1,7 @@
1
+ #include "atom.h"
2
+
3
+ VALUE IntruderAtom = Qnil;
4
+
5
+ void Init_intruder_atom() {
6
+ IntruderAtom = rb_define_class_under(IntruderModule, "Atom", IntruderTerm);
7
+ }
data/src/atom.h ADDED
@@ -0,0 +1,12 @@
1
+ #ifndef INTRUDER_ATOM_H
2
+ #define INTRUDER_ATOM_H
3
+
4
+ #include "ruby.h"
5
+ #include "term.h"
6
+
7
+ extern VALUE IntruderModule;
8
+ extern VALUE IntruderTerm;
9
+
10
+ void Init_intruder_atom();
11
+
12
+ #endif
data/src/binary.c ADDED
@@ -0,0 +1,20 @@
1
+ #include "binary.h"
2
+
3
+ VALUE IntruderBinary = Qnil;
4
+
5
+ void Init_intruder_binary() {
6
+ IntruderBinary = rb_define_class_under(IntruderModule, "Binary", IntruderTerm);
7
+
8
+ /* class methods */
9
+ rb_define_method(IntruderBinary, "initialize", intruder_binary_init, 1);
10
+ }
11
+
12
+ VALUE intruder_binary_init(VALUE self, VALUE str) {
13
+ ETERM *eterm;
14
+ INTRUDER_TERM *iterm;
15
+ Data_Get_Struct(self, INTRUDER_TERM, iterm);
16
+
17
+ eterm = erl_mk_binary(RSTRING_PTR(str), RSTRING_LEN(str));
18
+ iterm->eterm = eterm;
19
+ return self;
20
+ }
data/src/binary.h ADDED
@@ -0,0 +1,13 @@
1
+ #ifndef INTRUDER_BINARY_H
2
+ #define INTRUDER_BINARY_H
3
+
4
+ #include "ruby.h"
5
+ #include "term.h"
6
+
7
+ extern VALUE IntruderModule;
8
+ extern VALUE IntruderTerm;
9
+
10
+ void Init_intruder_binary();
11
+ VALUE intruder_binary_init(VALUE self, VALUE str);
12
+
13
+ #endif /* INTRUDER_BINARY_H */
@@ -0,0 +1,165 @@
1
+ /*
2
+ * taken from erlix erlix
3
+ * http://github.com/KDr2/erlix
4
+ */
5
+
6
+ #include "erlix_helper.h"
7
+
8
+ static int is_printable_list(const ETERM* term);
9
+ static void fill_printable_list(VALUE *str, const ETERM* ep);
10
+
11
+ static int is_printable_list(const ETERM* term)
12
+ {
13
+ while (ERL_TYPE(term) == ERL_LIST) {
14
+ ETERM* head = (ETERM*)(ERL_CONS_HEAD(term));
15
+ if (ERL_INT_VALUE(head) < 0 || ERL_INT_VALUE(head) > 255) {
16
+ return 0;
17
+ }
18
+ if (ERL_INT_VALUE(head) < ' ') {
19
+ switch (ERL_INT_VALUE(head)) {
20
+ case '\n':
21
+ case '\r':
22
+ case '\t':
23
+ case '\v':
24
+ case '\b':
25
+ case '\f':
26
+ break;
27
+ default:
28
+ return 0;
29
+ }
30
+ }
31
+ term = (ETERM*)(ERL_CONS_TAIL(term));
32
+ }
33
+ return ERL_IS_EMPTY_LIST(term);
34
+ }
35
+
36
+ static void fill_printable_list(VALUE *str, const ETERM* ep){
37
+ ID concat=rb_intern("concat");
38
+ /* rb_funcall(*str,concat,1,rb_str_new2("\"")); */
39
+
40
+ while (ERL_IS_CONS(ep)) {
41
+ int c = ERL_INT_VALUE((ETERM*)ERL_CONS_HEAD(ep));
42
+ if (c >= ' ') {
43
+ char tmp_buf[2];
44
+ tmp_buf[0]=c;
45
+ tmp_buf[1]=0;
46
+ rb_funcall(*str,concat,1,rb_str_new2(tmp_buf));
47
+ }
48
+ else {
49
+ if(c=='\n'){
50
+ rb_funcall(*str,concat,1,rb_str_new2("\\n"));
51
+ }else if(c=='\r'){
52
+ rb_funcall(*str,concat,1,rb_str_new2("\\r"));
53
+ }else if(c=='\t'){
54
+ rb_funcall(*str,concat,1,rb_str_new2("\\t"));
55
+ }else if(c=='\v'){
56
+ rb_funcall(*str,concat,1,rb_str_new2("\\v"));
57
+ }else if(c=='\b'){
58
+ rb_funcall(*str,concat,1,rb_str_new2("\\b"));
59
+ }else if(c=='\f'){
60
+ rb_funcall(*str,concat,1,rb_str_new2("\\f"));
61
+ }else{
62
+ char tmp_buf[8];
63
+ memset(tmp_buf,0,8);
64
+ sprintf(tmp_buf,"\\%o",c);
65
+ rb_funcall(*str,concat,1,rb_str_new2(tmp_buf));
66
+ }
67
+ }
68
+ ep = (ETERM*)ERL_CONS_TAIL(ep);
69
+ }
70
+ /* rb_funcall(*str,concat,1,rb_str_new2("\"")); */
71
+ }
72
+
73
+ void fill_string(VALUE *str,ETERM *ep){
74
+ ID concat=rb_intern("concat");
75
+
76
+ int j,i,doquote;
77
+ if (!ep) return;
78
+
79
+ j = i = doquote = 0;
80
+
81
+ if(ERL_IS_ATOM(ep)){
82
+ /* FIXME: what if some weird locale is in use? */
83
+ if (!islower((int)ERL_ATOM_PTR(ep)[0]))
84
+ doquote = 1;
85
+ for (i = 0; !doquote && i < ERL_ATOM_SIZE(ep); i++){
86
+ doquote = !(isalnum((int)ERL_ATOM_PTR(ep)[i])
87
+ || (ERL_ATOM_PTR(ep)[i] == '_'));
88
+ }
89
+ if (doquote) {
90
+ rb_funcall(*str,concat,1,rb_str_new2("\'"));
91
+ }
92
+ rb_funcall(*str,concat,1,rb_str_new2(ERL_ATOM_PTR(ep)));
93
+ if(doquote){
94
+ rb_funcall(*str,concat,1,rb_str_new2("\'"));
95
+ }
96
+ }else if(ERL_IS_PID(ep)){
97
+ int buffsize = 9 + strlen(ERL_PID_NODE(ep));
98
+ char tmp_buf_pid[buffsize];
99
+ memset(tmp_buf_pid,0,buffsize);
100
+ sprintf(tmp_buf_pid,"<%s.%d.%d>",ERL_PID_NODE(ep),ERL_PID_NUMBER(ep), ERL_PID_SERIAL(ep));
101
+ rb_funcall(*str,concat,1,rb_str_new2(tmp_buf_pid));
102
+ }else if(ERL_IS_PORT(ep)){
103
+ rb_funcall(*str,concat,1,rb_str_new2("#Port"));
104
+ }else if(ERL_IS_REF(ep)){
105
+ rb_funcall(*str,concat,1,rb_str_new2("#Ref"));
106
+ }else if(ERL_IS_EMPTY_LIST(ep)){
107
+ rb_funcall(*str,concat,1,rb_str_new2("[]"));
108
+ }else if(ERL_IS_LIST(ep)){
109
+ if (is_printable_list(ep)) {
110
+ fill_printable_list(str,ep);
111
+ } else {
112
+ rb_funcall(*str,concat,1,rb_str_new2("["));
113
+ ETERM *tl=ep,*hd,*tmp;
114
+ while (ERL_IS_CONS(tl)){
115
+ hd=erl_hd(tl);
116
+ fill_string(str,hd);
117
+ //erl_free_term(hd);
118
+ tmp = erl_tl(tl);
119
+ //if(tl!=ep)erl_free_term(tl);
120
+ tl=tmp;
121
+ if (ERL_IS_CONS(tl)) {
122
+ rb_funcall(*str,concat,1,rb_str_new2(", "));
123
+ }
124
+ }
125
+ if (!ERL_IS_EMPTY_LIST(tl)) {
126
+ rb_funcall(*str,concat,1,rb_str_new2("|"));
127
+ fill_string(str, tl);
128
+ }else{
129
+ //erl_free_term(tl);
130
+ }
131
+ rb_funcall(*str,concat,1,rb_str_new2("]"));
132
+ }
133
+ }else if(ERL_IS_TUPLE(ep)){
134
+ rb_funcall(*str,concat,1,rb_str_new2("{"));
135
+ for (i=0; i < ERL_TUPLE_SIZE(ep); i++) {
136
+ ETERM *e=erl_element(i+1,ep);
137
+ fill_string(str,e);
138
+ //erl_free_term(e);
139
+ if (i != ERL_TUPLE_SIZE(ep)-1) {
140
+ rb_funcall(*str,concat,1,rb_str_new2(", "));
141
+ }
142
+ }
143
+ rb_funcall(*str,concat,1,rb_str_new2("}"));
144
+ }else if(ERL_IS_BINARY(ep)){
145
+ rb_funcall(*str,concat,1,rb_str_new2(ERL_BIN_PTR(ep)));
146
+ }else if(ERL_IS_INTEGER(ep)){
147
+ char tmp_buf_num[24];
148
+ memset(tmp_buf_num,0,24);
149
+ sprintf(tmp_buf_num,"%d", ERL_INT_VALUE(ep));
150
+ rb_funcall(*str,concat,1,rb_str_new2(tmp_buf_num));
151
+ }else if(ERL_IS_UNSIGNED_INTEGER(ep)){
152
+ char tmp_buf_unum[24];
153
+ memset(tmp_buf_unum, 0, 24);
154
+ sprintf(tmp_buf_unum, "%u", ERL_INT_UVALUE(ep));
155
+ rb_funcall(*str,concat, 1, rb_str_new2(tmp_buf_unum));
156
+ }else if(ERL_IS_FLOAT(ep)){
157
+ char tmp_buf_float[24];
158
+ memset(tmp_buf_float, 0, 24);
159
+ sprintf(tmp_buf_float, "%f", ERL_FLOAT_VALUE(ep));
160
+ rb_funcall(*str,concat, 1, rb_str_new2(tmp_buf_float));
161
+ }else{
162
+ rb_funcall(*str,concat, 1, rb_str_new2("*Unknow*"));
163
+ //rb_raise(rb_eException,"ErlixTerm.to_s: Bad type of term !");
164
+ }
165
+ }
@@ -0,0 +1,13 @@
1
+ #ifndef ERLIX_HELPER_H
2
+ #define ERLIX_HELPER_H
3
+
4
+ #include "ruby.h"
5
+ #include "erl_interface.h"
6
+ #include "ei.h"
7
+
8
+ #include <ctype.h>
9
+ #include <string.h>
10
+
11
+ void fill_string(VALUE *str, ETERM *ep);
12
+
13
+ #endif
@@ -0,0 +1,48 @@
1
+ #include "intruder_ext.h"
2
+
3
+ /* common imports */
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+ #include <errno.h>
7
+
8
+ /* TODO in den header*/
9
+ VALUE IntruderModule = Qnil;
10
+ VALUE IntruderException = Qnil;
11
+ extern VALUE IntruderNodeException;
12
+
13
+ void Init_intruder_ext(){
14
+ erl_init(NULL, 0);
15
+ IntruderModule = rb_define_module("Intruder");
16
+ IntruderException = rb_define_class_under(IntruderModule, "Error", rb_eRuntimeError);
17
+
18
+ Init_intruder_term();
19
+ Init_intruder_list();
20
+ Init_intruder_tuple();
21
+ Init_intruder_atom();
22
+ Init_intruder_binary();
23
+ Init_intruder_node();
24
+ Init_intruder_mod();
25
+ }
26
+
27
+ void raise_rException_for_erl_errno(){
28
+ /* DEBUG("Result: %d\n", erl_errno); */
29
+ /* DEBUG("ERHOSTUNREACH: %d\n", EHOSTUNREACH); */
30
+ /* DEBUG("ENOMEM: %d\n", ENOMEM); */
31
+ /* DEBUG("EIO: %d\n", EIO); */
32
+
33
+ switch( erl_errno )
34
+ {
35
+ case EHOSTUNREACH :
36
+ rb_raise(IntruderNodeException, "Host unreachable");
37
+ break;
38
+ case ENOMEM :
39
+ rb_raise(IntruderNodeException, "Memory Error");
40
+ break;
41
+ case EIO :
42
+ rb_raise(IntruderNodeException, "IO error");
43
+ break;
44
+ default :
45
+ rb_raise(IntruderNodeException, strerror(erl_errno));
46
+ break;
47
+ }
48
+ }
@@ -0,0 +1,28 @@
1
+ #ifndef INTRUDER_EXT_H_
2
+ #define INTRUDER_EXT_H_
3
+
4
+ #include "ruby.h"
5
+ #include "node.h"
6
+ #include "mod.h"
7
+ #include "term.h"
8
+ #include "list.h"
9
+ #include "atom.h"
10
+ #include "binary.h"
11
+
12
+ #ifndef RSTRING_PTR
13
+ #define RSTRING_PTR(s) (RSTRING(s)->ptr)
14
+ #define RSTRING_LEN(s) (RSTRING(s)->len)
15
+ #define RARRAY_LEN(a) (RARRAY(a)->len)
16
+ #endif
17
+
18
+ extern void raise_rException_for_erl_errno();
19
+ #endif /* #ifndef INTRUDER_EXT_H */
20
+
21
+ /*
22
+ * TODO: Add Check_Type checks for every method that needs a specific argument type
23
+ * TODO: macros for retrival of the class structs like:
24
+ * #define GetDBM(obj, dbmp) {\
25
+ * Data_Get_Struct(obj, struct dbmdata, dbmp);\
26
+ * if (dbmp->di_dbm == 0) closed_dbm();\
27
+ * }
28
+ */
data/src/list.c ADDED
@@ -0,0 +1,70 @@
1
+ #include "list.h"
2
+
3
+ VALUE IntruderList = Qnil;
4
+
5
+ void Init_intruder_list()
6
+ {
7
+ IntruderList = rb_define_class_under(IntruderModule, "List", IntruderTerm);
8
+
9
+ rb_include_module(IntruderList, rb_mEnumerable);
10
+ rb_define_method(IntruderList, "each", intruder_list_each, 0);
11
+ rb_define_method(IntruderList, "[]", intruder_list_member_at, 1);
12
+ rb_define_method(IntruderList, "length", intruder_list_length, 0);
13
+ rb_define_alias(IntruderList, "size", "length");
14
+ }
15
+
16
+ /* lenght and size */
17
+ VALUE intruder_list_length(VALUE self){
18
+ INTRUDER_TERM *term;
19
+ Data_Get_Struct(self, INTRUDER_TERM, term);
20
+
21
+ return INT2FIX(erl_length(term->eterm));
22
+ }
23
+
24
+ /* [] */
25
+ VALUE intruder_list_member_at(VALUE self, VALUE pos)
26
+ {
27
+ int position = NUM2INT(pos) + 1;
28
+ if (position <= 0 || NUM2INT(intruder_list_length(self)) < position)
29
+ return Qnil;
30
+
31
+ INTRUDER_TERM *term;
32
+ Data_Get_Struct(self, INTRUDER_TERM, term);
33
+
34
+ int i;
35
+ ETERM *member, *list;
36
+ list = erl_copy_term(term->eterm);
37
+
38
+ for(i = 1; i <= position; i++)
39
+ {
40
+ member = erl_hd(list);
41
+ list = erl_tl(list);
42
+ }
43
+
44
+ erl_free_compound(list);
45
+ return rb_value_from_eterm(member);
46
+ }
47
+
48
+ /* Enumerable */
49
+ VALUE intruder_list_each(VALUE self)
50
+ {
51
+ INTRUDER_TERM *term;
52
+ ETERM *member, *list;
53
+ VALUE rMember;
54
+ int i;
55
+
56
+ Data_Get_Struct(self, INTRUDER_TERM, term);
57
+ list = erl_copy_term(term->eterm);
58
+ int length = erl_length(list);
59
+
60
+ for(i = 1; i <= length; i++)
61
+ {
62
+ member = erl_hd(list);
63
+ list = erl_tl(list);
64
+ rMember = rb_value_from_eterm(member);
65
+ rb_yield(rMember);
66
+ }
67
+
68
+ erl_free_compound(list);
69
+ return Qnil;
70
+ }
data/src/list.h ADDED
@@ -0,0 +1,19 @@
1
+ #ifndef INTRUDER_LIST_H
2
+ #define INTRUDER_LIST_H
3
+
4
+ #include "ruby.h"
5
+
6
+ #include "term.h"
7
+
8
+ extern VALUE IntruderModule;
9
+ extern VALUE IntruderTerm;
10
+
11
+ void Init_intruder_list();
12
+
13
+ /* Enumerable */
14
+ VALUE intruder_list_each(VALUE self);
15
+
16
+ VALUE intruder_list_member_at(VALUE self, VALUE position);
17
+ VALUE intruder_list_length(VALUE self);
18
+
19
+ #endif /* ifndef INTRUDER_LIST_H */
data/src/mod.c ADDED
@@ -0,0 +1,74 @@
1
+ #include "mod.h"
2
+
3
+ VALUE IntruderMod = Qnil;
4
+ extern VALUE IntruderModule;
5
+ extern VALUE IntruderTerm;
6
+
7
+ VALUE intruder_mod_init(VALUE self, VALUE modname, VALUE node) {
8
+ rb_iv_set(self, "@node", node);
9
+ rb_iv_set(self, "@modname", modname);
10
+ return self;
11
+ }
12
+
13
+ VALUE intruder_mod_alloc(VALUE class) {
14
+ INTRUDER_MOD *im = (INTRUDER_MOD*)malloc(sizeof(INTRUDER_MOD));
15
+ VALUE obj;
16
+ obj = Data_Wrap_Struct(class, 0, free, im);
17
+ return obj;
18
+ }
19
+
20
+ VALUE intruder_mod_rpc(VALUE self, VALUE args) {
21
+ /* get the data struct of the Intruder::Node in the Intruder::Mod */
22
+ INTRUDER_NODE *inode;
23
+ Data_Get_Struct(rb_iv_get(self, "@node"), INTRUDER_NODE, inode);
24
+ if (inode->status == INTRUDER_DISCONNECTED) {
25
+ rb_raise(IntruderException, "node not connected");
26
+ }
27
+
28
+ VALUE fun = rb_ary_shift(args);
29
+ VALUE params = rb_ary_shift(args);
30
+
31
+ /* get the intruder term struct from the args array */
32
+ INTRUDER_TERM *iterm;
33
+ Data_Get_Struct(params, INTRUDER_TERM, iterm);
34
+
35
+ /* name of the module to call is set in a ruby ivar */
36
+ char *mod = RSTRING_PTR(rb_iv_get(self, "@modname"));
37
+ int ret;
38
+
39
+ /* prepare the erlang stuff */
40
+ int index = 0;
41
+ ei_x_buff rpcargs, result;
42
+ ei_x_new(&result);
43
+ ei_x_new(&rpcargs);
44
+ ei_x_encode_term(&rpcargs, iterm->eterm);
45
+
46
+ /* ei_print_term(stdout, rpcargs.buff, &index); */
47
+ /* fflush(stdout); */
48
+
49
+ /* RPC call */
50
+ pthread_mutex_lock(inode->mutex);
51
+ ret = ei_rpc(inode->cnode, inode->fd, mod, RSTRING_PTR(fun), rpcargs.buff, rpcargs.index, &result);
52
+ if (ret < 0) {
53
+ raise_rException_for_erl_errno();
54
+ return Qnil;
55
+ } else {
56
+ ETERM *tuplep;
57
+ tuplep = erl_decode(result.buff);
58
+ ei_x_free(&rpcargs);
59
+ ei_x_free(&result);
60
+ pthread_mutex_unlock(inode->mutex);
61
+ return rb_value_from_eterm(tuplep);
62
+ }
63
+ }
64
+
65
+ void Init_intruder_mod() {
66
+ IntruderMod = rb_define_class_under(IntruderModule, "Mod", rb_cObject);
67
+
68
+ /* class methods */
69
+ rb_define_alloc_func(IntruderMod, intruder_mod_alloc);
70
+
71
+ /* instance methods */
72
+ rb_define_method(IntruderMod, "initialize", intruder_mod_init, 2);
73
+ rb_define_method(IntruderMod, "rpc", intruder_mod_rpc, -2);
74
+ }
data/src/mod.h ADDED
@@ -0,0 +1,25 @@
1
+ #ifndef INTRUDER_MOD_H_
2
+ #define INTRUDER_MOD_H_
3
+
4
+ #include "ruby.h"
5
+ #include "ei.h"
6
+ #include "erl_interface.h"
7
+ #include <stdio.h>
8
+ #include <pthread.h>
9
+
10
+ #include "intruder_ext.h"
11
+ #include "node.h"
12
+ #include "term.h"
13
+
14
+ typedef struct intruder_mod
15
+ {
16
+ ei_cnode *node;
17
+ } INTRUDER_MOD;
18
+
19
+ void Init_intruder_mod();
20
+
21
+ VALUE intruder_mod_init(VALUE self, VALUE modname, VALUE node);
22
+ VALUE intruder_mod_alloc(VALUE self);
23
+ VALUE private_intruder_mod_rpc(VALUE self, VALUE args);
24
+
25
+ #endif
data/src/node.c ADDED
@@ -0,0 +1,217 @@
1
+ /*
2
+ * Helpfull stuff:
3
+ * Erl_interface doku: http://erlang.mirror.su.se/doc/man/ei_connect.html
4
+ * http://erlang.org/pipermail/erlang-questions/2003-August/009536.html
5
+ * Erlix discussion: http://www.mentby.com/Group/ruby-talk/ruby-interface-of-erlang.html
6
+ * Extending ruby (german): http://home.vrweb.de/~juergen.katins/ruby/buch/ext_ruby.html
7
+ * http://www.eqqon.com/index.php/Ruby_C_Extension#debug
8
+ */
9
+ #include "node.h"
10
+
11
+ #define STOSYM(string) ID2SYM(rb_intern(string))
12
+
13
+ VALUE IntruderNode = Qnil;
14
+ VALUE IntruderNodeException = Qnil;
15
+ int node_count = 0;
16
+ pthread_t alive_thread;
17
+ pthread_mutex_t **mutexes_locked_for_keep_alive;
18
+ INTRUDER_NODE **connectlist;
19
+ fd_set socks;
20
+ int highsock;
21
+ int readsocks;
22
+ int connectlist_inited = 0;
23
+ unsigned int tmo = 1;
24
+
25
+ /* internal methods */
26
+ static void declare_attr_accessors();
27
+ static void free_class_struct(void *class_struct);
28
+ static void release_locks();
29
+
30
+ void lock_node(INTRUDER_NODE *node);
31
+ void unlock_node(INTRUDER_NODE *node);
32
+ void read_socks();
33
+ void *aliveloop();
34
+ void build_select_list();
35
+
36
+ /* implementation */
37
+ VALUE intruder_node_alloc(VALUE class){
38
+ INTRUDER_NODE *class_struct = malloc(sizeof(INTRUDER_NODE));
39
+ class_struct->cnode = malloc(sizeof(ei_cnode));
40
+ class_struct->status = INTRUDER_DISCONNECTED;
41
+ class_struct->mutex = malloc(sizeof(pthread_mutex_t));
42
+ pthread_mutex_init(class_struct->mutex, NULL);
43
+
44
+ VALUE obj = Data_Wrap_Struct(class, 0, free_class_struct, class_struct);
45
+ return obj;
46
+ }
47
+
48
+ static void free_class_struct(void *class_struct)
49
+ {
50
+ pthread_mutex_destroy(((INTRUDER_NODE *)class_struct)->mutex);
51
+ free(((INTRUDER_NODE *)class_struct)->cnode);
52
+ free(class_struct);
53
+ }
54
+
55
+ VALUE intruder_node_init(VALUE self, VALUE sname, VALUE cookie){
56
+ CLASS_STRUCT;
57
+
58
+ rb_iv_set(self, "@sname", sname);
59
+ rb_iv_set(self, "@cookie", cookie);
60
+
61
+ if (!connectlist_inited) {
62
+ connectlist = (INTRUDER_NODE **)calloc(CONBUFFSIZE, sizeof(INTRUDER_NODE*));
63
+ mutexes_locked_for_keep_alive = (pthread_mutex_t **)calloc(CONBUFFSIZE, sizeof(pthread_mutex_t *));
64
+ connectlist_inited = 1;
65
+ }
66
+
67
+ /* initialize the node */
68
+ if(ei_connect_init(class_struct->cnode, RSTRING_PTR(sname), RSTRING_PTR(cookie), node_count) < 0){
69
+ free(class_struct->cnode);
70
+ rb_raise(rb_eRuntimeError, "Error initializing the node");
71
+ }
72
+
73
+ return self;
74
+ }
75
+
76
+ VALUE intruder_node_status(VALUE self){
77
+ CLASS_STRUCT;
78
+ if (class_struct->status == INTRUDER_CONNECTED)
79
+ return STOSYM("connected");
80
+ else
81
+ return STOSYM("disconnected");
82
+ }
83
+
84
+ VALUE intruder_node_pid(VALUE self){
85
+ CLASS_STRUCT;
86
+ erlang_pid *pid = ei_self(class_struct->cnode);
87
+ return INT2FIX(pid->num);
88
+ }
89
+
90
+ VALUE intruder_node_connect(VALUE self, VALUE remote_node){
91
+ INTRUDER_NODE *class_struct;
92
+ Data_Get_Struct(self, INTRUDER_NODE, class_struct);
93
+
94
+ if((class_struct->fd = ei_connect_tmo(class_struct->cnode, RSTRING_PTR(remote_node), tmo)) < 0)
95
+ raise_rException_for_erl_errno();
96
+
97
+ class_struct->status = INTRUDER_CONNECTED;
98
+ connectlist[node_count] = class_struct;
99
+ node_count++;
100
+
101
+ if (alive_thread == NULL) {
102
+ pthread_create(&alive_thread, NULL, aliveloop, NULL);
103
+ }
104
+ return Qtrue;
105
+ }
106
+
107
+ void Init_intruder_node(){
108
+ IntruderNode = rb_define_class_under(IntruderModule, "Node", rb_cObject);
109
+ declare_attr_accessors();
110
+
111
+ /* class methods */
112
+ rb_define_alloc_func(IntruderNode, intruder_node_alloc);
113
+
114
+ /* instance methods */
115
+ rb_define_method(IntruderNode, "initialize", intruder_node_init, 2);
116
+ rb_define_method(IntruderNode, "connect", intruder_node_connect, 1);
117
+ rb_define_method(IntruderNode, "pid", intruder_node_pid, 0);
118
+ rb_define_method(IntruderNode, "status", intruder_node_status, 0);
119
+
120
+ /* exceptions */
121
+ IntruderNodeException = rb_define_class_under(IntruderModule, "NodeError", IntruderException);
122
+ }
123
+
124
+ static void declare_attr_accessors(){
125
+ ID attr_accessor = rb_intern("attr_reader");
126
+
127
+ char *i_vars[2] = {"cookie", "sname"};
128
+ VALUE params[2];
129
+
130
+ int i = 0;
131
+ for(; i <= 1; i++){
132
+ params[i] = STOSYM(i_vars[i]);
133
+ }
134
+ rb_funcall2(IntruderNode, attr_accessor, 2, params);
135
+ }
136
+
137
+ void build_select_list() {
138
+ int listnum, locks = 0;
139
+ FD_ZERO(&socks);
140
+
141
+ for (listnum = 0; listnum < node_count; listnum++) {
142
+ if (connectlist[listnum] != NULL) {
143
+ if (!pthread_mutex_trylock(connectlist[listnum]->mutex)) {
144
+ mutexes_locked_for_keep_alive[locks++] = connectlist[listnum]->mutex;
145
+ FD_SET(connectlist[listnum]->fd, &socks);
146
+ if (connectlist[listnum]->fd > highsock)
147
+ highsock = connectlist[listnum]->fd;
148
+ }
149
+ else {
150
+ /* printf("fd %d is already locked, skipping\n", connectlist[listnum]->fd); */
151
+ }
152
+ }
153
+ }
154
+ }
155
+
156
+ void read_socks() {
157
+ int listnum;
158
+ int got;
159
+ char buf[400];
160
+
161
+ for (listnum = 0; listnum < node_count; listnum++) {
162
+ /* printf("checking socket %d (%d)\n", connectlist[listnum]->fd, listnum); */
163
+ if (connectlist[listnum] != 0 && FD_ISSET(connectlist[listnum]->fd, &socks)) {
164
+ got = erl_receive(connectlist[listnum]->fd, buf, 400);
165
+ if (got == ERL_TICK) { /* keeping the node alive */
166
+ continue;
167
+ } else {
168
+ rb_raise(rb_eRuntimeError, "Keep Alive thread cought a message other than ERL_TICK");
169
+ }
170
+ }
171
+ }
172
+ }
173
+
174
+ void *aliveloop() {
175
+ struct timeval timeout;
176
+
177
+ while(1) {
178
+ timeout.tv_sec = 1;
179
+ timeout.tv_usec = 0;
180
+
181
+ build_select_list();
182
+ /* printf("waiting for sockets\n"); */
183
+ readsocks = select(highsock+1, &socks, (fd_set *) 0, (fd_set *) 0, &timeout);
184
+
185
+ if (readsocks < 0) {
186
+ perror("select");
187
+ exit(EXIT_FAILURE);
188
+ }
189
+ if (readsocks != 0)
190
+ read_socks();
191
+ release_locks(); /* TODO: maybe return the locklist from build_select_list and pass in as an argument here */
192
+ }
193
+ }
194
+
195
+ static void release_locks() {
196
+ int i;
197
+ pthread_mutex_t *mutex;
198
+ /* printf("cleaning up locks"); */
199
+ for (i = 0; i < CONBUFFSIZE; i++) {
200
+ if ((mutex = mutexes_locked_for_keep_alive[i]) != NULL) {
201
+ /* printf(" %d", i); */
202
+ pthread_mutex_unlock(mutex);
203
+ mutexes_locked_for_keep_alive[i] = NULL;
204
+ } else {
205
+ /* printf("\n"); */
206
+ break;
207
+ }
208
+ }
209
+ }
210
+
211
+ void lock_node(INTRUDER_NODE *node) {
212
+ pthread_mutex_lock(node->mutex);
213
+ }
214
+
215
+ void unlock_node(INTRUDER_NODE *node) {
216
+ pthread_mutex_unlock(node->mutex);
217
+ }
data/src/node.h ADDED
@@ -0,0 +1,49 @@
1
+ /* FIXME node.h =schlechte idee, umbenennen */
2
+ #ifndef INTRUDER_NODE_H
3
+ #define INTRUDER_NODE_H
4
+
5
+ #include "ruby.h"
6
+ #include "erl_interface.h"
7
+ #include "ei.h"
8
+
9
+ #include "intruder_ext.h"
10
+
11
+ #include <stdio.h>
12
+
13
+ #define INTRUDER_DEBUG
14
+
15
+ #ifdef INTRUDER_DEBUG
16
+ #define DEBUG(fmt, args...) printf(fmt, ##args)
17
+ #else
18
+ #define DEBUG(fmt, args...)
19
+ #endif
20
+
21
+ #define INTRUDER_CONNECTED 0
22
+ #define INTRUDER_DISCONNECTED 1
23
+
24
+ #define CONBUFFSIZE 20
25
+
26
+ #define CLASS_STRUCT struct intruder_node *class_struct; Data_Get_Struct(self, struct intruder_node, class_struct)
27
+
28
+ typedef struct intruder_node
29
+ {
30
+ ei_cnode *cnode;
31
+ int fd; /* file descriptor for the communication with the epmd */
32
+ int status;
33
+ pthread_mutex_t *mutex; /* mutex on the fd */
34
+ } INTRUDER_NODE;
35
+
36
+ extern VALUE IntruderModule;
37
+ extern VALUE IntruderException;
38
+
39
+ /* prototypes */
40
+ void Init_intruder_node();
41
+
42
+ /* ruby instance methods */
43
+ VALUE intruder_node_init(VALUE self, VALUE sname, VALUE cookie);
44
+ VALUE intruder_node_connect(VALUE self, VALUE remote_node);
45
+ /* VALUE intruder_node_mod(VALUE self, VALUE mod_name); */
46
+
47
+ /* ruby class methods */
48
+ VALUE intruder_node_new(VALUE class, VALUE host, VALUE sname, VALUE cookie);
49
+ #endif
data/src/term.c ADDED
@@ -0,0 +1,168 @@
1
+ #include "term.h"
2
+
3
+ VALUE IntruderTerm = Qnil;
4
+
5
+ /* internal methods */
6
+ void free_intruder_term(void *term) {
7
+ INTRUDER_TERM *iterm = term;
8
+ erl_free_compound(iterm->eterm);
9
+ free(term);
10
+ }
11
+
12
+ INTRUDER_TERM * new_intruder_term() {
13
+ INTRUDER_TERM *iterm = malloc(sizeof(INTRUDER_TERM));
14
+ return iterm;
15
+ }
16
+
17
+ /* instance methods */
18
+
19
+ VALUE intruder_term_to_s(VALUE self) {
20
+ INTRUDER_TERM *iterm;
21
+ Data_Get_Struct(self, INTRUDER_TERM, iterm);
22
+ ETERM *eterm = iterm->eterm;
23
+ VALUE ret = rb_str_new2("");
24
+ /* int ei_s_print_term(char** s, const char* buf, int* index) */
25
+ /* int index = 0; */
26
+ /* char *buff; */
27
+ /* int ei_s_print_term(&buff, , int* index); */
28
+ fill_string(&ret, eterm);
29
+ return ret;
30
+ }
31
+
32
+ VALUE rb_value_from_eterm(ETERM *eterm)
33
+ {
34
+ VALUE rubyObject;
35
+ INTRUDER_TERM *iterm = new_intruder_term();
36
+ iterm->eterm = eterm;
37
+ if (ERL_IS_LIST(eterm))
38
+ rubyObject = rb_value_from_list(iterm);
39
+ else if (ERL_IS_TUPLE(eterm))
40
+ rubyObject = rb_value_from_tuple(iterm);
41
+ else if (ERL_IS_ATOM(eterm))
42
+ rubyObject = rb_value_from_atom(iterm);
43
+ else if (ERL_IS_BINARY(eterm))
44
+ rubyObject = rb_value_from_binary(iterm);
45
+ else
46
+ rubyObject = Data_Wrap_Struct(IntruderTerm, 0, free_intruder_term, iterm);
47
+
48
+ return rubyObject;
49
+
50
+ /* figure out the type of the eterm (more to come) */
51
+ /* erl_free_compound(eterm); */
52
+ /* return Qnil; */
53
+ }
54
+
55
+ VALUE rb_value_from_list(INTRUDER_TERM *iterm) {
56
+ VALUE rValue;
57
+ iterm->type = INTRUDER_TYPE_LIST;
58
+ rValue = Data_Wrap_Struct(IntruderList, 0, free_intruder_term, iterm);
59
+ return rValue;
60
+ }
61
+
62
+ VALUE rb_value_from_tuple(INTRUDER_TERM *iterm) {
63
+ VALUE rValue;
64
+ iterm->type = INTRUDER_TYPE_TUPLE;
65
+ rValue = Data_Wrap_Struct(IntruderTuple, 0, free_intruder_term, iterm);
66
+ return rValue;
67
+ }
68
+
69
+ VALUE rb_value_from_atom(INTRUDER_TERM *iterm) {
70
+ VALUE rValue;
71
+ iterm->type = INTRUDER_TYPE_ATOM;
72
+ rValue = Data_Wrap_Struct(IntruderAtom, 0, free_intruder_term, iterm);
73
+ return rValue;
74
+ }
75
+
76
+ VALUE rb_value_from_binary(INTRUDER_TERM *iterm) {
77
+ VALUE rValue;
78
+ iterm->type = INTRUDER_TYPE_BINARY;
79
+ rValue = Data_Wrap_Struct(IntruderBinary, 0, free_intruder_term, iterm);
80
+ return Qnil;
81
+ }
82
+
83
+ static ETERM *intruder_eterm_from_array(VALUE obj);
84
+ VALUE intruder_term_encode(VALUE self, VALUE obj) {
85
+ VALUE ret = Qnil;
86
+
87
+ ETERM *eterm = intruder_eterm_from_value(obj);
88
+ if (eterm == NULL) {
89
+ erl_free(eterm);
90
+ rb_raise(IntruderException, "unable to convert that ruby object to an erlang term");
91
+ return Qnil;
92
+ }
93
+
94
+ ret = rb_value_from_eterm(eterm);
95
+ return ret;
96
+ }
97
+
98
+ /* Create an ETERM from a Ruby VALUE
99
+ * currently it knows how to handle Strings, Symbols and Arrays (of strings, symbols or arrays)
100
+ */
101
+ ETERM *intruder_eterm_from_value(VALUE obj) {
102
+ ETERM *eterm;
103
+ if (rb_obj_is_kind_of(obj, IntruderTerm)) {
104
+ INTRUDER_TERM *iterm;
105
+ Data_Get_Struct(obj, INTRUDER_TERM, iterm);
106
+ eterm = iterm->eterm;
107
+ } else {
108
+ switch(TYPE(obj)) {
109
+ case T_SYMBOL :
110
+ eterm = erl_mk_atom(rb_id2name(SYM2ID(obj)));
111
+ break;
112
+ case T_ARRAY :
113
+ eterm = intruder_eterm_from_array(obj);
114
+ break;
115
+ case T_STRING :
116
+ eterm = erl_mk_estring(RSTRING_PTR(obj), RSTRING_LEN(obj));
117
+ break;
118
+ default :
119
+ eterm = NULL;
120
+ }
121
+ }
122
+ return eterm;
123
+ }
124
+
125
+ /* creates an ETERM from a ruby array of symbols, strings or arrays again */
126
+ static ETERM *intruder_eterm_from_array(VALUE obj) {
127
+ int size = RARRAY_LEN(obj);
128
+
129
+ if (size == 0)
130
+ return erl_format("[]");
131
+
132
+ ETERM **list = (ETERM **)malloc(sizeof(ETERM*) * size);
133
+ ETERM *element, *eterm;
134
+ INTRUDER_TERM *iterm;
135
+ VALUE rElement;
136
+ int i;
137
+
138
+ for (i = 0; i < size; i++) {
139
+ rElement = rb_ary_shift(obj);
140
+ element = intruder_eterm_from_value(rElement);
141
+ if (element == NULL) { /* it could not be decoded */
142
+ free(list);
143
+ return NULL;
144
+ }
145
+ *(list+i) = element;
146
+ }
147
+
148
+ eterm = erl_mk_list(list, size);
149
+ free(list);
150
+ return eterm;
151
+ }
152
+
153
+ VALUE intruder_term_alloc(VALUE class) {
154
+ INTRUDER_TERM *iterm = new_intruder_term();
155
+ VALUE obj = Data_Wrap_Struct(class, 0, free_intruder_term, iterm);
156
+ return obj;
157
+ }
158
+
159
+ void Init_intruder_term(){
160
+ IntruderTerm = rb_define_class_under(IntruderModule, "Term", rb_cObject);
161
+
162
+ /* instance methods */
163
+ rb_define_method(IntruderTerm, "to_s", intruder_term_to_s, 0);
164
+ rb_define_singleton_method(IntruderTerm, "encode", intruder_term_encode, 1);
165
+
166
+ /* allocation */
167
+ rb_define_alloc_func(IntruderTerm, intruder_term_alloc);
168
+ }
data/src/term.h ADDED
@@ -0,0 +1,58 @@
1
+ #ifndef INTRUDER_TERM_H
2
+ #define INTRUDER_TERM_H
3
+
4
+ #include "ruby.h"
5
+ #include "ei.h"
6
+ #include "erl_interface.h"
7
+
8
+ #include "intruder_ext.h"
9
+ #include "list.h"
10
+ #include "erlix_helper.h"
11
+
12
+ #define INTRUDER_TYPE_ATOM 0
13
+ #define INTRUDER_TYPE_LIST 1
14
+ #define INTRUDER_TYPE_TUPLE 2
15
+ #define INTRUDER_TYPE_INT 3
16
+ #define INTRUDER_TYPE_UINT 4
17
+ #define INTRUDER_TYPE_FLOAT 5
18
+ #define INTRUDER_TYPE_PID 6
19
+ #define INTRUDER_TYPE_PORT 7
20
+ #define INTRUDER_TYPE_REF 8
21
+ #define INTRUDER_TYPE_BIN 9
22
+ #define INTRUDER_TYPE_CON 10
23
+ #define INTRUDER_TYPE_STRING 11
24
+ #define INTRUDER_TYPE_BINARY 12
25
+
26
+ extern VALUE IntruderModule;
27
+ extern VALUE IntruderList;
28
+ extern VALUE IntruderTuple;
29
+ extern VALUE IntruderAtom;
30
+ extern VALUE IntruderException;
31
+ extern VALUE IntruderBinary;
32
+
33
+ typedef struct intruder_term
34
+ {
35
+ ETERM *eterm;
36
+ int type;
37
+ } INTRUDER_TERM;
38
+
39
+ void Init_intruder_term();
40
+
41
+ /* instance methods */
42
+ VALUE intruder_term_to_s(VALUE self);
43
+ VALUE intruder_term_encode(VALUE self, VALUE ruby_object);
44
+
45
+ /* allocation */
46
+ VALUE intruder_term_alloc(VALUE class);
47
+ void free_intruder_term(void *term);
48
+ INTRUDER_TERM *new_intruder_term();
49
+
50
+ /* C Methods */
51
+ VALUE rb_value_from_eterm(ETERM *eterm);
52
+ VALUE rb_value_from_list(INTRUDER_TERM *iterm);
53
+ VALUE rb_value_from_tuple(INTRUDER_TERM *iterm);
54
+ VALUE rb_value_from_atom(INTRUDER_TERM *iterm);
55
+ VALUE rb_value_from_binary(INTRUDER_TERM *iterm);
56
+ ETERM *intruder_eterm_from_value(VALUE obj);
57
+
58
+ #endif /* ifndef INTRUDER_TERM_H */
data/src/tuple.c ADDED
@@ -0,0 +1,55 @@
1
+ #include "tuple.h"
2
+
3
+ VALUE IntruderTuple = Qnil;
4
+
5
+ void Init_intruder_tuple() {
6
+ IntruderTuple = rb_define_class_under(IntruderModule, "Tuple", IntruderTerm);
7
+
8
+ rb_include_module(IntruderTuple, rb_mEnumerable);
9
+ rb_define_method(IntruderTuple, "initialize", intruder_tuple_init, 1);
10
+ rb_define_method(IntruderTuple, "each", intruder_tuple_each, 0);
11
+ rb_define_method(IntruderTuple, "[]", intruder_tuple_member_at, 1);
12
+ rb_define_method(IntruderTuple, "length", intruder_tuple_length, 0);
13
+ rb_define_alias(IntruderTuple, "size", "length");
14
+ }
15
+
16
+ VALUE intruder_tuple_each(VALUE self) {
17
+ INTRUDER_TERM *iterm;
18
+ Data_Get_Struct(self, INTRUDER_TERM, iterm);
19
+ int i;
20
+ for (i = 1; i <= erl_size(iterm->eterm); i++) {
21
+ rb_yield(rb_value_from_eterm(erl_element(i, iterm-> eterm)));
22
+ }
23
+ return Qnil;
24
+ }
25
+
26
+ VALUE intruder_tuple_init(VALUE self, VALUE arr) {
27
+ int i, arrsize = RARRAY_LEN(arr);
28
+ INTRUDER_TERM *iterm;
29
+ ETERM **members = (ETERM**)malloc(sizeof(ETERM*) * arrsize);
30
+
31
+ for (i = 0; i < arrsize; i++) {
32
+ members[i] = intruder_eterm_from_value(rb_ary_shift(arr));
33
+ }
34
+
35
+ Data_Get_Struct(self, INTRUDER_TERM, iterm);
36
+ iterm->eterm = erl_mk_tuple(members, arrsize);
37
+ return self;
38
+ }
39
+
40
+ VALUE intruder_tuple_member_at(VALUE self, VALUE position) {
41
+ INTRUDER_TERM *iterm;
42
+ ETERM *member;
43
+ int iPosition = NUM2INT(position);
44
+ Data_Get_Struct(self, INTRUDER_TERM, iterm);
45
+ member = erl_element(iPosition+1, iterm->eterm);
46
+ return rb_value_from_eterm(member);
47
+ }
48
+
49
+ VALUE intruder_tuple_length(VALUE self) {
50
+ INTRUDER_TERM *iterm;
51
+ Data_Get_Struct(self, INTRUDER_TERM, iterm);
52
+ int iLength;
53
+ iLength = erl_size(iterm->eterm);
54
+ return INT2NUM(iLength);
55
+ }
data/src/tuple.h ADDED
@@ -0,0 +1,17 @@
1
+ #ifndef INTRUDER_TUPLE_H
2
+ #define INTRUDER_TUPLE_H
3
+
4
+ #include "ruby.h"
5
+ #include "term.h"
6
+
7
+ extern VALUE IntruderModule;
8
+ extern VALUE IntruderTerm;
9
+
10
+ void Init_intruder_tuple();
11
+
12
+ VALUE intruder_tuple_each(VALUE self);
13
+ VALUE intruder_tuple_init(VALUE self, VALUE arr);
14
+ VALUE intruder_tuple_member_at(VALUE self, VALUE position);
15
+ VALUE intruder_tuple_length(VALUE self);
16
+
17
+ #endif /* ifndef INTRUDER_TUPLE_H */
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 0.1.0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Pascal Friederich
@@ -14,20 +14,53 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-11 00:00:00 +01:00
17
+ date: 2010-03-11 00:00:00 +00:00
18
18
  default_executable:
19
- dependencies: []
20
-
21
- description: ===========
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: minitest
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 5
30
+ - 0
31
+ version: 1.5.0
32
+ type: :development
33
+ version_requirements: *id001
34
+ description: Communicate with erlang from within ruby natively
22
35
  email: paukul@gmail.com
23
36
  executables: []
24
37
 
25
- extensions: []
26
-
38
+ extensions:
39
+ - extconf.rb
27
40
  extra_rdoc_files:
28
41
  - README.md
29
- files: []
30
-
42
+ files:
43
+ - README.md
44
+ - findei.erl
45
+ - src/atom.c
46
+ - src/atom.h
47
+ - src/binary.c
48
+ - src/binary.h
49
+ - src/erlix_helper.c
50
+ - src/erlix_helper.h
51
+ - src/intruder_ext.c
52
+ - src/intruder_ext.h
53
+ - src/list.c
54
+ - src/list.h
55
+ - src/mod.c
56
+ - src/mod.h
57
+ - src/node.c
58
+ - src/node.h
59
+ - src/term.c
60
+ - src/term.h
61
+ - src/tuple.c
62
+ - src/tuple.h
63
+ - lib/intruder.rb
31
64
  has_rdoc: true
32
65
  homepage: http://github.com/paukul/intruder
33
66
  licenses: []