frostbitten 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +20 -0
- data/Gemfile.lock +84 -0
- data/Guardfile +24 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +45 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/ext/.DS_Store +0 -0
- data/ext/frostbitten/.DS_Store +0 -0
- data/ext/frostbitten/Makefile +213 -0
- data/ext/frostbitten/extconf.rb +4 -0
- data/ext/frostbitten/frostbitten.h +13 -0
- data/ext/frostbitten/header.c +194 -0
- data/ext/frostbitten/header.h +30 -0
- data/ext/frostbitten/message.c +202 -0
- data/ext/frostbitten/message.h +17 -0
- data/ext/frostbitten/native.c +15 -0
- data/ext/frostbitten/packet.c +20 -0
- data/ext/frostbitten/packet.h +11 -0
- data/ext/frostbitten/word.c +60 -0
- data/ext/frostbitten/word.h +17 -0
- data/frostbitten.gemspec +106 -0
- data/lib/frostbitten.rb +37 -0
- data/lib/frostbitten/client.rb +50 -0
- data/lib/frostbitten/connection.rb +100 -0
- data/lib/frostbitten/map.rb +38 -0
- data/lib/frostbitten/methods/admin.rb +29 -0
- data/lib/frostbitten/methods/normal.rb +47 -0
- data/lib/frostbitten/player.rb +54 -0
- data/lib/frostbitten/score.rb +21 -0
- data/lib/frostbitten/server.rb +27 -0
- data/lib/frostbitten/version.rb +15 -0
- data/spec/frostbitten_spec.rb +8 -0
- data/spec/lib/frostbitten_client_spec.rb +14 -0
- data/spec/lib/frostbitten_server_spec.rb +48 -0
- data/spec/spec_helper.rb +7 -0
- data/test/helper.rb +15 -0
- data/test/test_frostbitten.rb +7 -0
- metadata +252 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
#ifndef frostbitten_h
|
2
|
+
#define frostbitten_h
|
3
|
+
#include <ruby.h>
|
4
|
+
#include <ruby/io.h>
|
5
|
+
#include <stdint.h>
|
6
|
+
#include <stdbool.h>
|
7
|
+
#include <stdlib.h>
|
8
|
+
extern VALUE m_frostbitten;
|
9
|
+
void Init_frostbitten();
|
10
|
+
#define OVERRIDE_IF_SET(options,name) rb_funcall(options, rb_intern("has_key?"), 1, ID2SYM(rb_intern(#name))) == Qtrue ? \
|
11
|
+
rb_hash_aref(options, ID2SYM(rb_intern(#name))) : name
|
12
|
+
#endif
|
13
|
+
|
@@ -0,0 +1,194 @@
|
|
1
|
+
#include "frostbitten.h"
|
2
|
+
#include "header.h"
|
3
|
+
#include <ruby/io.h>
|
4
|
+
VALUE c_frostbitten_header;
|
5
|
+
|
6
|
+
|
7
|
+
VALUE frostbitten_header_parse_from_buffer(VALUE self, fb_packet_buffer *buffer) {
|
8
|
+
fb_header *header;
|
9
|
+
Data_Get_Struct(self, fb_header, header);
|
10
|
+
frostbitten_header_unpack(header, buffer->header);
|
11
|
+
return self;
|
12
|
+
}
|
13
|
+
|
14
|
+
VALUE frostbitten_header_get_sequence(VALUE self) {
|
15
|
+
fb_header *header;
|
16
|
+
Data_Get_Struct(self, fb_header, header);
|
17
|
+
return INT2NUM(header->sequence);
|
18
|
+
}
|
19
|
+
|
20
|
+
VALUE frostbitten_header_set_sequence(VALUE self, VALUE seq) {
|
21
|
+
fb_header *header;
|
22
|
+
Data_Get_Struct(self, fb_header, header);
|
23
|
+
header->sequence = NUM2INT(seq);
|
24
|
+
return frostbitten_header_get_sequence(self);
|
25
|
+
}
|
26
|
+
|
27
|
+
VALUE frostbitten_header_set_origin(VALUE self, VALUE origin) {
|
28
|
+
fb_header *header;
|
29
|
+
Data_Get_Struct(self, fb_header, header);
|
30
|
+
if ( ID2SYM(rb_intern("client")) == origin ) {
|
31
|
+
header->origin = 1;
|
32
|
+
} else if ID2SYM(rb_intern("server") == origin ) {
|
33
|
+
header->origin = 0;
|
34
|
+
} else {
|
35
|
+
rb_raise(rb_eTypeError, "must be either :client or :server");
|
36
|
+
}
|
37
|
+
return Qfalse;
|
38
|
+
}
|
39
|
+
|
40
|
+
VALUE frostbitten_header_get_origin(VALUE self) {
|
41
|
+
fb_header *header;
|
42
|
+
Data_Get_Struct(self, fb_header, header);
|
43
|
+
switch(header->origin) {
|
44
|
+
case 1:
|
45
|
+
return ID2SYM(rb_intern("client"));
|
46
|
+
break;
|
47
|
+
|
48
|
+
case 0:
|
49
|
+
return ID2SYM(rb_intern("server"));
|
50
|
+
break;
|
51
|
+
}
|
52
|
+
return Qnil;
|
53
|
+
}
|
54
|
+
|
55
|
+
VALUE frostbitten_header_get_response(VALUE self) {
|
56
|
+
fb_header *header;
|
57
|
+
Data_Get_Struct(self, fb_header, header);
|
58
|
+
if ( header->response == 0 ) {
|
59
|
+
return Qtrue;
|
60
|
+
} else {
|
61
|
+
return Qfalse;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
VALUE frostbitten_header_set_response(VALUE self, VALUE response) {
|
66
|
+
if ( TYPE(response) != T_TRUE && TYPE(response) != T_FALSE) {
|
67
|
+
rb_raise(rb_eTypeError, "must be either true or false");
|
68
|
+
}
|
69
|
+
|
70
|
+
fb_header *header;
|
71
|
+
Data_Get_Struct(self, fb_header, header);
|
72
|
+
if ( response == Qtrue )
|
73
|
+
header->response = 1;
|
74
|
+
else {
|
75
|
+
header->response = 0;
|
76
|
+
}
|
77
|
+
return frostbitten_header_get_response(self);
|
78
|
+
}
|
79
|
+
|
80
|
+
uint32_t frostbitten_header_package(fb_header *header) {
|
81
|
+
uint32_t data = header->sequence;
|
82
|
+
if ( header->origin == 0 ) {
|
83
|
+
data |= 1 << 31;
|
84
|
+
} else {
|
85
|
+
data &= ~(1 << 31);
|
86
|
+
}
|
87
|
+
|
88
|
+
if ( header->response != (( 1 << 30 ) & data) ) {
|
89
|
+
data ^= 1 << 30;
|
90
|
+
}
|
91
|
+
|
92
|
+
return data;
|
93
|
+
}
|
94
|
+
|
95
|
+
void frostbitten_header_unpack(fb_header *header, uint32_t val) {
|
96
|
+
header->sequence = (uint32_t)val & 0x3fffffff;
|
97
|
+
header->origin = (val & (1 << 31));
|
98
|
+
header->response = (val & (1 << 30));
|
99
|
+
}
|
100
|
+
|
101
|
+
VALUE frostbitten_header_write_to_io(VALUE self, VALUE io) {
|
102
|
+
fb_header *header;
|
103
|
+
Data_Get_Struct(self, fb_header, header);
|
104
|
+
|
105
|
+
rb_io_t *fptr;
|
106
|
+
GetOpenFile(io, fptr);
|
107
|
+
rb_io_check_writable(fptr);
|
108
|
+
|
109
|
+
FILE *fp = rb_io_stdio_file(fptr);
|
110
|
+
|
111
|
+
uint32_t val = frostbitten_header_package(header);
|
112
|
+
fwrite((const void*)&val,sizeof(uint32_t),1,fp);
|
113
|
+
return self;
|
114
|
+
}
|
115
|
+
|
116
|
+
VALUE frostbitten_header_cls_read_from_io(VALUE self, VALUE io) {
|
117
|
+
VALUE header = rb_obj_alloc(c_frostbitten_header);
|
118
|
+
rb_obj_call_init(header, 0, 0);
|
119
|
+
return frostbitten_header_read_from_io(header, io);
|
120
|
+
}
|
121
|
+
|
122
|
+
VALUE frostbitten_header_read_from_io(VALUE self, VALUE io) {
|
123
|
+
fb_header *header;
|
124
|
+
Data_Get_Struct(self, fb_header, header);
|
125
|
+
|
126
|
+
uint32_t val = 0;
|
127
|
+
|
128
|
+
rb_io_t *fptr;
|
129
|
+
GetOpenFile(io, fptr);
|
130
|
+
rb_io_check_readable(fptr);
|
131
|
+
|
132
|
+
FILE *fp = rb_io_stdio_file(fptr);
|
133
|
+
fread((void*)&val, sizeof(uint32_t),1, fp);
|
134
|
+
|
135
|
+
frostbitten_header_unpack(header, val);
|
136
|
+
return self;
|
137
|
+
}
|
138
|
+
|
139
|
+
void frostbitten_header_deallocate(fb_header *header) {
|
140
|
+
header->sequence = 0;
|
141
|
+
header->origin = 0;
|
142
|
+
header->response = false;
|
143
|
+
ruby_xfree(header);
|
144
|
+
}
|
145
|
+
|
146
|
+
VALUE frostbitten_header_allocate (VALUE klass) {
|
147
|
+
fb_header *header = ruby_xmalloc(sizeof(fb_header));
|
148
|
+
return Data_Wrap_Struct(klass,NULL,frostbitten_header_deallocate, header);
|
149
|
+
}
|
150
|
+
|
151
|
+
VALUE frostbitten_header_init(int argc, VALUE *argv, VALUE self) {
|
152
|
+
|
153
|
+
fb_header *header;
|
154
|
+
Data_Get_Struct(self, fb_header, header);
|
155
|
+
|
156
|
+
VALUE options;
|
157
|
+
if (rb_scan_args(argc, argv, "01", &options) == 0)
|
158
|
+
options = Qnil;
|
159
|
+
|
160
|
+
VALUE sequence = INT2NUM(0);
|
161
|
+
VALUE origin = ID2SYM(rb_intern("client"));
|
162
|
+
VALUE response = Qfalse;
|
163
|
+
|
164
|
+
if (!NIL_P(options) && TYPE(options) == T_HASH) {
|
165
|
+
sequence = OVERRIDE_IF_SET(options,sequence);
|
166
|
+
origin = OVERRIDE_IF_SET(options,origin);
|
167
|
+
response = OVERRIDE_IF_SET(options,response);
|
168
|
+
}
|
169
|
+
frostbitten_header_set_sequence(self,sequence);
|
170
|
+
frostbitten_header_set_origin(self,origin);
|
171
|
+
frostbitten_header_set_response(self,response);
|
172
|
+
|
173
|
+
return self;
|
174
|
+
}
|
175
|
+
|
176
|
+
void header_init() {
|
177
|
+
c_frostbitten_header = rb_define_class_under(m_frostbitten, "Header", rb_cObject);
|
178
|
+
rb_define_alloc_func(c_frostbitten_header, frostbitten_header_allocate);
|
179
|
+
rb_define_method(c_frostbitten_header, "initialize", frostbitten_header_init, -1);
|
180
|
+
|
181
|
+
rb_define_method(c_frostbitten_header,"sequence=", frostbitten_header_set_sequence,1);
|
182
|
+
rb_define_method(c_frostbitten_header,"sequence", frostbitten_header_get_sequence,0);
|
183
|
+
|
184
|
+
rb_define_method(c_frostbitten_header, "origin", frostbitten_header_get_origin,0);
|
185
|
+
rb_define_method(c_frostbitten_header, "origin=", frostbitten_header_set_origin, 1);
|
186
|
+
|
187
|
+
rb_define_method(c_frostbitten_header,"response=", frostbitten_header_set_response, 1);
|
188
|
+
rb_define_method(c_frostbitten_header,"is_response?", frostbitten_header_get_response, 0);
|
189
|
+
|
190
|
+
rb_define_method(c_frostbitten_header, "read", frostbitten_header_read_from_io, 1);
|
191
|
+
rb_define_method(c_frostbitten_header, "write", frostbitten_header_write_to_io, 1);
|
192
|
+
rb_define_singleton_method(c_frostbitten_header, "read", frostbitten_header_cls_read_from_io, 1);
|
193
|
+
|
194
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#include "frostbitten.h"
|
2
|
+
#include "packet.h"
|
3
|
+
#ifndef header_h
|
4
|
+
#define header_h
|
5
|
+
|
6
|
+
extern VALUE c_frostbitten_header;
|
7
|
+
|
8
|
+
typedef struct _fb_header {
|
9
|
+
uint32_t sequence;
|
10
|
+
uint32_t origin;
|
11
|
+
bool response;
|
12
|
+
} fb_header;
|
13
|
+
|
14
|
+
void header_init();
|
15
|
+
VALUE frostbitten_header_parse_from_buffer(VALUE self, fb_packet_buffer *buffer);
|
16
|
+
VALUE frostbitten_header_get_sequence(VALUE self);
|
17
|
+
VALUE frostbitten_header_set_sequence(VALUE self, VALUE seq);
|
18
|
+
uint32_t frostbitten_header_package(fb_header *header);
|
19
|
+
void frostbitten_header_unpack(fb_header *header, uint32_t val);
|
20
|
+
|
21
|
+
VALUE frostbitten_header_cls_read_from_io(VALUE self, VALUE io);
|
22
|
+
VALUE frostbitten_header_read_from_io(VALUE self, VALUE io);
|
23
|
+
VALUE frostbitten_header_write_to_io(VALUE self, VALUE io);
|
24
|
+
// VALUE frostbitten_header_test_write(VALUE self);
|
25
|
+
// VALUE frostbitten_header_test_read(VALUE self);
|
26
|
+
VALUE frostbitten_header_format(VALUE self);
|
27
|
+
void frostbitten_header_deallocate(fb_header *header);
|
28
|
+
VALUE frostbitten_header_allocate (VALUE klass);
|
29
|
+
|
30
|
+
#endif
|
@@ -0,0 +1,202 @@
|
|
1
|
+
#include "frostbitten.h"
|
2
|
+
#include "message.h"
|
3
|
+
|
4
|
+
VALUE c_frostbitten_message;
|
5
|
+
|
6
|
+
void frostbitten_read_words_from_file(fb_message *message, FILE *fp, fb_packet_buffer *buffer) {
|
7
|
+
for(uint32_t i=0; i < buffer->wordCount; i++) {
|
8
|
+
uint32_t wordByteLength = 0;
|
9
|
+
fread(&wordByteLength, sizeof(uint32_t), 1, fp);
|
10
|
+
|
11
|
+
char *word = malloc(wordByteLength+1);
|
12
|
+
fread(word, sizeof(char), wordByteLength+1, fp);
|
13
|
+
rb_ary_push(message->words, rb_str_new2(word));
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
VALUE frostbitten_message_read_from_io(VALUE self, VALUE io) {
|
18
|
+
fb_message *message;
|
19
|
+
Data_Get_Struct(self, fb_message, message);
|
20
|
+
|
21
|
+
rb_io_t *fptr;
|
22
|
+
GetOpenFile(io, fptr);
|
23
|
+
rb_io_check_readable(fptr);
|
24
|
+
FILE *fp = rb_io_stdio_file(fptr);
|
25
|
+
fb_packet_buffer *buffer = read_buffer_from_io(fp);
|
26
|
+
|
27
|
+
if ( !message->header ) {
|
28
|
+
message->header = rb_class_new_instance(0, NULL, c_frostbitten_header);
|
29
|
+
frostbitten_header_parse_from_buffer(message->header, buffer);
|
30
|
+
}
|
31
|
+
|
32
|
+
frostbitten_read_words_from_file(message, fp, buffer);
|
33
|
+
return self;
|
34
|
+
}
|
35
|
+
|
36
|
+
VALUE frostbitten_message_cls_read_from_io(VALUE self, VALUE io) {
|
37
|
+
VALUE msg = rb_obj_alloc(c_frostbitten_message);
|
38
|
+
rb_obj_call_init(msg, 0, 0);
|
39
|
+
return frostbitten_message_read_from_io(msg, io);
|
40
|
+
}
|
41
|
+
|
42
|
+
VALUE frostbitten_message_complete(VALUE self, VALUE io) {
|
43
|
+
rb_io_t *fptr;
|
44
|
+
GetOpenFile(io, fptr);
|
45
|
+
rb_io_check_readable(fptr);
|
46
|
+
FILE *fp = rb_io_stdio_file(fptr);
|
47
|
+
|
48
|
+
fb_packet_buffer *buffer = read_buffer_from_io(fp);
|
49
|
+
if (is_packet_valid(buffer)) {
|
50
|
+
VALUE msg = rb_obj_alloc(c_frostbitten_message);
|
51
|
+
rb_obj_call_init(msg, 0, 0);
|
52
|
+
fb_message *message;
|
53
|
+
Data_Get_Struct(msg, fb_message, message);
|
54
|
+
frostbitten_read_words_from_file(message, fp, buffer);
|
55
|
+
|
56
|
+
if (rb_block_given_p()) {
|
57
|
+
return rb_yield(msg);
|
58
|
+
} else {
|
59
|
+
return msg;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
free(buffer);
|
63
|
+
return Qnil;
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
VALUE frostbitten_message_write_to_io(VALUE self, VALUE io) {
|
70
|
+
fb_message *message;
|
71
|
+
Data_Get_Struct(self, fb_message, message);
|
72
|
+
|
73
|
+
frostbitten_header_write_to_io(message->header, io);
|
74
|
+
|
75
|
+
|
76
|
+
uint32_t arrayLength = (uint32_t)RARRAY_LEN(message->words);
|
77
|
+
uint32_t packetSize = 0;
|
78
|
+
|
79
|
+
char** strings = frostbitten_message_generate(message, &packetSize);
|
80
|
+
packetSize += sizeof(uint32_t); // Header
|
81
|
+
packetSize += sizeof(uint32_t); // packetSize
|
82
|
+
packetSize += sizeof(uint32_t); // wordCount
|
83
|
+
rb_io_t *fptr;
|
84
|
+
GetOpenFile(io, fptr);
|
85
|
+
rb_io_check_readable(fptr);
|
86
|
+
FILE *fp = rb_io_stdio_file(fptr);
|
87
|
+
|
88
|
+
fwrite((const void*)&packetSize,sizeof(uint32_t),1,fp);
|
89
|
+
fwrite((const void*)&arrayLength,sizeof(uint32_t),1,fp);
|
90
|
+
for(uint32_t i=0; i < arrayLength; i++) {
|
91
|
+
char *str = strings[i];
|
92
|
+
uint32_t len = (uint32_t)strlen(str);
|
93
|
+
fwrite((const void*)&len, sizeof(uint32_t), 1, fp);
|
94
|
+
fwrite(str, sizeof(char), strlen(str)+1, fp);
|
95
|
+
}
|
96
|
+
fflush(fp);
|
97
|
+
return self;
|
98
|
+
}
|
99
|
+
|
100
|
+
char** frostbitten_message_generate(fb_message *message, uint32_t *message_size) {
|
101
|
+
uint32_t arrayLength = (uint32_t)RARRAY_LEN(message->words);
|
102
|
+
char **strings = (char **)calloc(arrayLength,sizeof(char *));
|
103
|
+
|
104
|
+
for(uint32_t i=0; i < arrayLength; i++) {
|
105
|
+
VALUE str = rb_ary_entry(message->words, i);
|
106
|
+
if ( !NIL_P(str) && TYPE(str) == T_STRING ) {
|
107
|
+
char *p = StringValueCStr(str);
|
108
|
+
char *p2 = malloc(strlen(p)*sizeof(char)+1);
|
109
|
+
memcpy(p2,p,strlen(p)*sizeof(char)+1);
|
110
|
+
strings[i] = p2;
|
111
|
+
*message_size += sizeof(char)*(strlen(p2)+1)+sizeof(uint32_t);
|
112
|
+
}
|
113
|
+
}
|
114
|
+
return strings;
|
115
|
+
}
|
116
|
+
|
117
|
+
VALUE frostbitten_message_get_words(VALUE self) {
|
118
|
+
fb_message *message;
|
119
|
+
Data_Get_Struct(self, fb_message, message);
|
120
|
+
return message->words;
|
121
|
+
}
|
122
|
+
|
123
|
+
VALUE frostbitten_message_set_words(VALUE self, VALUE words) {
|
124
|
+
Check_Type(words, T_ARRAY);
|
125
|
+
|
126
|
+
fb_message *message;
|
127
|
+
Data_Get_Struct(self, fb_message, message);
|
128
|
+
message->words = words;
|
129
|
+
return message->words;
|
130
|
+
}
|
131
|
+
|
132
|
+
VALUE frostbitten_message_get_header(VALUE self) {
|
133
|
+
fb_message *message;
|
134
|
+
Data_Get_Struct(self, fb_message, message);
|
135
|
+
return message->header;
|
136
|
+
}
|
137
|
+
|
138
|
+
VALUE frostbitten_message_set_header(VALUE self, VALUE header) {
|
139
|
+
if ( NIL_P(header) || CLASS_OF(header) != c_frostbitten_header ) {
|
140
|
+
rb_raise(rb_eTypeError, "Invalid argument header, not a Frostbitten::Header");
|
141
|
+
return Qnil;
|
142
|
+
}
|
143
|
+
fb_message *message;
|
144
|
+
Data_Get_Struct(self, fb_message, message);
|
145
|
+
message->header = header;
|
146
|
+
return message->header;
|
147
|
+
}
|
148
|
+
|
149
|
+
VALUE frostbitten_message_init(int argc, VALUE *argv, VALUE self) {
|
150
|
+
|
151
|
+
fb_message *message;
|
152
|
+
Data_Get_Struct(self, fb_message, message);
|
153
|
+
|
154
|
+
VALUE options;
|
155
|
+
if (rb_scan_args(argc, argv, "01", &options) == 0)
|
156
|
+
options = Qnil;
|
157
|
+
VALUE words = rb_ary_new();
|
158
|
+
VALUE header = rb_obj_alloc(c_frostbitten_header);
|
159
|
+
|
160
|
+
if (!NIL_P(options) && TYPE(options) == T_HASH) {
|
161
|
+
words = OVERRIDE_IF_SET(options,words);
|
162
|
+
header = OVERRIDE_IF_SET(options,header);
|
163
|
+
}
|
164
|
+
|
165
|
+
frostbitten_message_set_header(self,header);
|
166
|
+
frostbitten_message_set_words(self,words);
|
167
|
+
|
168
|
+
return self;
|
169
|
+
}
|
170
|
+
|
171
|
+
void frostbitten_message_deallocate(fb_message *message) {
|
172
|
+
// frostbitten_header_deallocate(message->header);
|
173
|
+
ruby_xfree(message);
|
174
|
+
}
|
175
|
+
|
176
|
+
void frostbitten_message_mark(fb_message *message) {
|
177
|
+
rb_gc_mark(message->header);
|
178
|
+
rb_gc_mark(message->words);
|
179
|
+
}
|
180
|
+
|
181
|
+
|
182
|
+
VALUE frostbitten_message_allocate (VALUE klass) {
|
183
|
+
fb_message *msg = ruby_xmalloc(sizeof(fb_message));
|
184
|
+
return Data_Wrap_Struct(klass, frostbitten_message_mark, frostbitten_message_deallocate, msg);
|
185
|
+
}
|
186
|
+
|
187
|
+
void message_init() {
|
188
|
+
c_frostbitten_message = rb_define_class_under(m_frostbitten, "Message", rb_cObject);
|
189
|
+
rb_define_alloc_func(c_frostbitten_message, frostbitten_message_allocate);
|
190
|
+
rb_define_method(c_frostbitten_message, "initialize", frostbitten_message_init, -1);
|
191
|
+
|
192
|
+
rb_define_method(c_frostbitten_message, "write", frostbitten_message_write_to_io, 1);
|
193
|
+
rb_define_method(c_frostbitten_message, "read", frostbitten_message_read_from_io, 1);
|
194
|
+
|
195
|
+
rb_define_method(c_frostbitten_message, "words", frostbitten_message_get_words, 0);
|
196
|
+
rb_define_method(c_frostbitten_message, "words=", frostbitten_message_set_words, 1);
|
197
|
+
|
198
|
+
rb_define_method(c_frostbitten_message, "header", frostbitten_message_get_header, 0);
|
199
|
+
rb_define_method(c_frostbitten_message, "header=", frostbitten_message_set_header, 1);
|
200
|
+
rb_define_singleton_method(c_frostbitten_message, "read", frostbitten_message_cls_read_from_io, 1);
|
201
|
+
rb_define_singleton_method(c_frostbitten_message, "locate_packet", frostbitten_message_complete, 1);
|
202
|
+
}
|