intruder 0.1.0 → 0.2.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/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: []