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 +25 -7
- data/extconf.rb +21 -0
- data/findei.erl +6 -0
- data/lib/intruder.rb +20 -0
- data/src/atom.c +7 -0
- data/src/atom.h +12 -0
- data/src/binary.c +20 -0
- data/src/binary.h +13 -0
- data/src/erlix_helper.c +165 -0
- data/src/erlix_helper.h +13 -0
- data/src/intruder_ext.c +48 -0
- data/src/intruder_ext.h +28 -0
- data/src/list.c +70 -0
- data/src/list.h +19 -0
- data/src/mod.c +74 -0
- data/src/mod.h +25 -0
- data/src/node.c +217 -0
- data/src/node.h +49 -0
- data/src/term.c +168 -0
- data/src/term.h +58 -0
- data/src/tuple.c +55 -0
- data/src/tuple.h +17 -0
- metadata +43 -10
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
|
-
*
|
15
|
+
* `ruby extconf.rb`
|
16
16
|
* start your rabbitmq server `sudo rabbitmq-server`
|
17
|
-
* `ruby
|
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
|
-
|
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
|
-
|
51
|
+
description missing... yet :)
|
34
52
|
|
35
53
|
Erlix?
|
36
54
|
======
|
37
55
|
|
38
|
-
is great, took some stuff from
|
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
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
data/src/atom.h
ADDED
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 */
|
data/src/erlix_helper.c
ADDED
@@ -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
|
+
}
|
data/src/erlix_helper.h
ADDED
data/src/intruder_ext.c
ADDED
@@ -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
|
+
}
|
data/src/intruder_ext.h
ADDED
@@ -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
|
-
-
|
7
|
+
- 2
|
8
8
|
- 0
|
9
|
-
version: 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 +
|
17
|
+
date: 2010-03-11 00:00:00 +00:00
|
18
18
|
default_executable:
|
19
|
-
dependencies:
|
20
|
-
|
21
|
-
|
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: []
|