renet 0.1.14 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -27,7 +27,7 @@ typedef struct {
27
27
  ENetEvent* event;
28
28
  ENetAddress* address;
29
29
  int channels;
30
- int online;
30
+ int online;
31
31
  } Connection;
32
32
 
33
33
  void init_renet_connection();
@@ -48,10 +48,10 @@ void renet_connection_execute_on_connection();
48
48
 
49
49
  VALUE renet_connection_on_packet_receive(VALUE self, VALUE method);
50
50
  /*VALUE renet_connection_on_packet_receive(int argc, VALUE *argv, VALUE self);*/
51
- void renet_connection_execute_on_packet_receive(enet_uint8* data, enet_uint8 channelID);
51
+ void renet_connection_execute_on_packet_receive(VALUE self, ENetPacket * const packet, enet_uint8 channelID);
52
52
 
53
53
  VALUE renet_connection_on_disconnection(VALUE self, VALUE method);
54
- void renet_connection_execute_on_disconnection();
54
+ void renet_connection_execute_on_disconnection(VALUE self);
55
55
 
56
56
  VALUE renet_connection_online(VALUE self);
57
57
 
@@ -18,11 +18,10 @@
18
18
 
19
19
  #include "renet_server.h"
20
20
 
21
- VALUE cENetServer;
22
21
 
23
22
  void init_renet_server()
24
23
  {
25
- cENetServer = rb_define_class_under(mENet, "Server", rb_cObject);
24
+ VALUE cENetServer = rb_define_class_under(mENet, "Server", rb_cObject);
26
25
  rb_define_alloc_func(cENetServer, renet_server_allocate);
27
26
 
28
27
  rb_define_method(cENetServer, "initialize", renet_server_initialize, 5);
@@ -40,6 +39,11 @@ void init_renet_server()
40
39
 
41
40
  rb_define_method(cENetServer, "max_clients", renet_server_max_clients, 0);
42
41
  rb_define_method(cENetServer, "clients_count", renet_server_clients_count, 0);
42
+
43
+ rb_define_attr(cENetServer, "total_sent_data", 1, 1);
44
+ rb_define_attr(cENetServer, "total_received_data", 1, 1);
45
+ rb_define_attr(cENetServer, "total_sent_packets", 1, 1);
46
+ rb_define_attr(cENetServer, "total_received_packets", 1, 1);
43
47
  }
44
48
 
45
49
  VALUE renet_server_allocate(VALUE self)
@@ -54,227 +58,327 @@ VALUE renet_server_allocate(VALUE self)
54
58
 
55
59
  void renet_server_deallocate(void* server)
56
60
  {
57
- free(((Server*)server)->event);
58
- free(((Server*)server)->address);
59
- enet_host_destroy(((Server*)server)->host);
60
- free((Server*)server);
61
+ free(((Server*)server)->event);
62
+ free(((Server*)server)->address);
63
+ enet_host_destroy(((Server*)server)->host);
64
+ free((Server*)server);
61
65
  }
62
66
 
63
67
  VALUE renet_server_initialize(VALUE self, VALUE port, VALUE n_peers, VALUE channels, VALUE download, VALUE upload)
64
68
  {
65
- rb_funcall(mENet, rb_intern("initialize"), 0);
66
- Server* server;
67
- Data_Get_Struct(self, Server, server);
68
-
69
- server->address->host = ENET_HOST_ANY;
70
- server->address->port = NUM2UINT(port);
71
- server->channels = NUM2UINT(channels);
72
- server->host = enet_host_create(server->address, NUM2UINT(n_peers), server->channels, NUM2UINT(download), NUM2UINT(upload));
73
- if (server->host == NULL)
69
+ rb_funcall(mENet, rb_intern("initialize"), 0);
70
+ Server* server;
71
+ Data_Get_Struct(self, Server, server);
72
+
73
+ VALUE lock = rb_mutex_new();
74
+ rb_iv_set(self, "@lock", lock);
75
+ rb_mutex_lock(lock);
76
+
77
+ server->address->host = ENET_HOST_ANY;
78
+ server->address->port = NUM2UINT(port);
79
+ server->channels = NUM2UINT(channels);
80
+ server->host = enet_host_create(server->address, NUM2UINT(n_peers), server->channels, NUM2UINT(download), NUM2UINT(upload));
81
+ if (server->host == NULL)
74
82
  {
75
- rb_raise(rb_eStandardError, "Cannot create server");
76
- }
77
- rb_iv_set(self, "@total_sent_data", INT2FIX(0));
78
- rb_iv_set(self, "@total_received_data", INT2FIX(0));
79
- rb_iv_set(self, "@total_sent_packets", INT2FIX(0));
80
- rb_iv_set(self, "@total_received_packets", INT2FIX(0));
81
-
82
- rb_define_attr(cENetServer, "total_sent_data", 1, 1);
83
- rb_define_attr(cENetServer, "total_received_data", 1, 1);
84
- rb_define_attr(cENetServer, "total_sent_packets", 1, 1);
85
- rb_define_attr(cENetServer, "total_received_packets", 1, 1);
86
-
87
- return self;
83
+ rb_raise(rb_eStandardError, "Cannot create server");
84
+ }
85
+ rb_iv_set(self, "@total_sent_data", INT2FIX(0));
86
+ rb_iv_set(self, "@total_received_data", INT2FIX(0));
87
+ rb_iv_set(self, "@total_sent_packets", INT2FIX(0));
88
+ rb_iv_set(self, "@total_received_packets", INT2FIX(0));
89
+
90
+ rb_mutex_unlock(lock);
91
+
92
+ return self;
88
93
  }
89
94
 
90
95
  VALUE renet_server_disconnect_client(VALUE self, VALUE peer_id)
91
96
  {
92
- Server* server;
93
- Data_Get_Struct(self, Server, server);
94
- enet_peer_disconnect_now(&(server->host->peers[NUM2UINT(peer_id)]), 0);
95
- renet_server_execute_on_disconnection(peer_id);
96
- return Qtrue;
97
+ Server* server;
98
+ Data_Get_Struct(self, Server, server);
99
+ VALUE lock = rb_iv_get(self, "@lock");
100
+ rb_mutex_lock(lock);
101
+ enet_peer_disconnect_now(&(server->host->peers[NUM2UINT(peer_id)]), 0);
102
+ renet_server_execute_on_disconnection(self, peer_id);
103
+ rb_mutex_unlock(lock);
104
+ return Qtrue;
97
105
  }
98
106
 
99
107
  VALUE renet_server_send_packet(VALUE self, VALUE peer_id, VALUE data, VALUE flag, VALUE channel)
100
108
  {
101
- Server* server;
102
- Data_Get_Struct(self, Server, server);
103
- Check_Type(data, T_STRING);
104
- char* cdata = StringValuePtr(data);
105
- ENetPacket* packet;
106
- if (flag == Qtrue)
107
- {
108
- packet = enet_packet_create(cdata, RSTRING_LEN(data) + 1, ENET_PACKET_FLAG_RELIABLE);
109
- }
110
- else
111
- {
112
- packet = enet_packet_create(cdata, RSTRING_LEN(data) + 1, 0);
113
- }
109
+ Server* server;
110
+ Data_Get_Struct(self, Server, server);
111
+ VALUE lock = rb_iv_get(self, "@lock");
112
+ rb_mutex_lock(lock);
113
+ Check_Type(data, T_STRING);
114
+ char* cdata = StringValuePtr(data);
115
+ ENetPacket* packet;
116
+ if (flag == Qtrue)
117
+ {
118
+ packet = enet_packet_create(cdata, RSTRING_LEN(data) + 1, ENET_PACKET_FLAG_RELIABLE);
119
+ }
120
+ else
121
+ {
122
+ packet = enet_packet_create(cdata, RSTRING_LEN(data) + 1, 0);
123
+ }
114
124
  enet_peer_send(&(server->host->peers[NUM2UINT(peer_id)]), NUM2UINT(channel), packet);
115
- return Qnil;
125
+ rb_mutex_unlock(lock);
126
+ return Qnil;
116
127
  }
117
128
 
118
129
  VALUE renet_server_broadcast_packet(VALUE self, VALUE data, VALUE flag, VALUE channel)
119
130
  {
120
- Server* server;
121
- Data_Get_Struct(self, Server, server);
122
- Check_Type(data, T_STRING);
123
- char* cdata = StringValuePtr(data);
124
- ENetPacket* packet;
125
- if (flag == Qtrue)
126
- {
127
- packet = enet_packet_create(cdata, RSTRING_LEN(data) + 1, ENET_PACKET_FLAG_RELIABLE);
128
- }
129
- else
130
- {
131
- packet = enet_packet_create(cdata, RSTRING_LEN(data) + 1, 0);
132
- }
131
+ Server* server;
132
+ Data_Get_Struct(self, Server, server);
133
+ VALUE lock = rb_iv_get(self, "@lock");
134
+ rb_mutex_lock(lock);
135
+ Check_Type(data, T_STRING);
136
+ char* cdata = StringValuePtr(data);
137
+ ENetPacket* packet;
138
+ if (flag == Qtrue)
139
+ {
140
+ packet = enet_packet_create(cdata, RSTRING_LEN(data) + 1, ENET_PACKET_FLAG_RELIABLE);
141
+ }
142
+ else
143
+ {
144
+ packet = enet_packet_create(cdata, RSTRING_LEN(data) + 1, 0);
145
+ }
133
146
  enet_host_broadcast(server->host, NUM2UINT(channel), packet);
134
- return Qnil;
147
+ rb_mutex_unlock(lock);
148
+ return Qnil;
135
149
  }
136
150
 
137
151
  VALUE renet_server_send_queued_packets(VALUE self)
138
152
  {
139
- Server* server;
140
- Data_Get_Struct(self, Server, server);
153
+ Server* server;
154
+ Data_Get_Struct(self, Server, server);
155
+ VALUE lock = rb_iv_get(self, "@lock");
156
+ rb_mutex_lock(lock);
141
157
  enet_host_flush(server->host);
158
+ rb_mutex_unlock(lock);
142
159
  return Qnil;
143
160
  }
144
161
 
162
+ /* These let us release the global interpreter lock if while we're waiting for
163
+ enet_host_service to finish:
164
+
165
+ CallbackData
166
+ do_service
167
+ service
168
+ */
169
+ typedef struct
170
+ {
171
+ Server * server;
172
+ enet_uint32 timeout;
173
+ } CallbackData;
174
+
175
+ static VALUE do_service(void *data)
176
+ {
177
+ CallbackData* temp_data = data;
178
+ int result = enet_host_service(temp_data->server->host, temp_data->server->event, temp_data->timeout);
179
+ // this will do weird things with the negative numbers but we'll undo it on the other side
180
+ return (unsigned int)result;
181
+ }
182
+
183
+ static int service(VALUE self, Server* server, enet_uint32 timeout)
184
+ {
185
+ CallbackData data = {server, timeout};
186
+ VALUE result;
187
+ if (timeout > 0)
188
+ {
189
+ result = rb_thread_blocking_region(do_service, &data, RUBY_UBF_IO, 0);
190
+ }
191
+ else
192
+ {
193
+ result = do_service(&data);
194
+ }
195
+ // undo our cast to VALUE in a way that will properly restore negative numbers
196
+ unsigned int fix_negatives = (unsigned int)result;
197
+ return (int)fix_negatives;
198
+ }
199
+
145
200
  VALUE renet_server_update(VALUE self, VALUE timeout)
146
201
  {
147
- Server* server;
148
- Data_Get_Struct(self, Server, server);
149
- int peer_id;
150
-
151
- while (enet_host_service(server->host, server->event, NUM2UINT(timeout)) > 0)
202
+ Server* server;
203
+ Data_Get_Struct(self, Server, server);
204
+ VALUE lock = rb_iv_get(self, "@lock");
205
+ rb_mutex_lock(lock);
206
+ int peer_id;
207
+
208
+ /* wait up to timeout milliseconds for a packet */
209
+ if (service(self, server, NUM2UINT(timeout)) > 0)
210
+ {
211
+ do
152
212
  {
153
- switch (server->event->type)
154
- {
155
- case ENET_EVENT_TYPE_NONE:
156
-
157
- break;
158
-
159
- case ENET_EVENT_TYPE_CONNECT:
160
- server->n_clients += 1;
161
- enet_address_get_host_ip(&(server->event->peer->address), server->conn_ip, 20);
162
- peer_id = (int)(server->event->peer - server->host->peers);
163
- renet_server_execute_on_connection(INT2NUM(peer_id), rb_str_new2(server->conn_ip));
164
- break;
165
-
166
- case ENET_EVENT_TYPE_RECEIVE:
167
- peer_id = (int)(server->event->peer - server->host->peers);
168
- renet_server_execute_on_packet_receive(INT2NUM(peer_id), server->event->packet->data, server->event->channelID);
169
- enet_packet_destroy(server->event->packet);
170
- break;
171
-
172
- case ENET_EVENT_TYPE_DISCONNECT:
173
- server->n_clients -= 1;
174
- peer_id = (int)(server->event->peer - server->host->peers);
175
- renet_server_execute_on_disconnection(INT2NUM(peer_id));
176
- }
213
+ switch (server->event->type)
214
+ {
215
+ case ENET_EVENT_TYPE_NONE:
216
+ break;
217
+
218
+ case ENET_EVENT_TYPE_CONNECT:
219
+ server->n_clients += 1;
220
+ enet_address_get_host_ip(&(server->event->peer->address), server->conn_ip, 20);
221
+ peer_id = (int)(server->event->peer - server->host->peers);
222
+ renet_server_execute_on_connection(self, INT2NUM(peer_id), rb_str_new2(server->conn_ip));
223
+ break;
224
+
225
+ case ENET_EVENT_TYPE_RECEIVE:
226
+ peer_id = (int)(server->event->peer - server->host->peers);
227
+ renet_server_execute_on_packet_receive(self, INT2NUM(peer_id), server->event->packet, server->event->channelID);
228
+ break;
229
+
230
+ case ENET_EVENT_TYPE_DISCONNECT:
231
+ server->n_clients -= 1;
232
+ peer_id = (int)(server->event->peer - server->host->peers);
233
+ server->event->peer->data = NULL;
234
+ renet_server_execute_on_disconnection(self, INT2NUM(peer_id));
235
+ break;
236
+ }
177
237
  }
238
+ while (service(self, server, 0) > 0);
239
+ }
240
+
241
+ /* we are unlocking now because it's important to unlock before going
242
+ back into ruby land (which rb_funcall will do). If we don't then an
243
+ exception can leave the locks in an inconsistent state */
244
+ rb_mutex_unlock(lock);
245
+
246
+ {
247
+ VALUE total = rb_iv_get(self, "@total_sent_data");
248
+ VALUE result = rb_funcall( total
249
+ , rb_intern("+")
250
+ , 1
251
+ , UINT2NUM(server->host->totalSentData));
252
+ rb_iv_set(self, "@total_sent_data", result);
253
+ server->host->totalSentData = 0;
254
+ }
255
+
256
+ {
257
+ VALUE total = rb_iv_get(self, "@total_received_data");
258
+ VALUE result = rb_funcall( total
259
+ , rb_intern("+")
260
+ , 1
261
+ , UINT2NUM(server->host->totalReceivedData));
262
+ rb_iv_set(self, "@total_received_data", result);
263
+ server->host->totalReceivedData = 0;
264
+ }
178
265
 
179
- int tmp;
180
- tmp = NUM2INT(rb_iv_get(self, "@total_sent_data"));
181
- tmp = tmp + server->host->totalSentData;
182
- server->host->totalSentData = 0;
183
- rb_iv_set(self, "@total_sent_data", UINT2NUM(tmp));
184
-
185
- tmp = NUM2INT(rb_iv_get(self, "@total_received_data"));
186
- tmp = tmp + server->host->totalReceivedData;
187
- server->host->totalReceivedData = 0;
188
- rb_iv_set(self, "@total_received_data", UINT2NUM(tmp));
189
-
190
- tmp = NUM2INT(rb_iv_get(self, "@total_sent_packets"));
191
- tmp = tmp + server->host->totalSentPackets;
192
- server->host->totalSentPackets = 0;
193
- rb_iv_set(self, "@total_sent_packets", UINT2NUM(tmp));
194
-
195
- tmp = NUM2INT(rb_iv_get(self, "@total_received_packets"));
196
- tmp = tmp + server->host->totalReceivedPackets;
197
- server->host->totalReceivedPackets = 0;
198
- rb_iv_set(self, "@total_received_packets", UINT2NUM(tmp));
199
-
200
- return Qtrue;
266
+ {
267
+ VALUE total = rb_iv_get(self, "@total_sent_packets");
268
+ VALUE result = rb_funcall( total
269
+ , rb_intern("+")
270
+ , 1
271
+ , UINT2NUM(server->host->totalSentPackets));
272
+ rb_iv_set(self, "@total_sent_packets", result);
273
+ server->host->totalSentPackets = 0;
274
+ }
275
+
276
+ {
277
+ VALUE total = rb_iv_get(self, "@total_received_packets");
278
+ VALUE result = rb_funcall( total
279
+ , rb_intern("+")
280
+ , 1
281
+ , UINT2NUM(server->host->totalReceivedPackets));
282
+ rb_iv_set(self, "@total_received_packets", result);
283
+ server->host->totalReceivedPackets = 0;
284
+ }
285
+
286
+ return Qtrue;
201
287
  }
202
288
 
203
289
  VALUE renet_server_use_compression(VALUE self, VALUE flag)
204
290
  {
205
- Server* server;
206
- Data_Get_Struct(self, Server, server);
207
- if (flag == Qtrue)
208
- {
209
- enet_host_compress_with_range_coder(server->host);
210
- }
211
- else
212
- {
213
- enet_host_compress(server->host, NULL);
214
- }
215
- return Qnil;
291
+ Server* server;
292
+ Data_Get_Struct(self, Server, server);
293
+ VALUE lock = rb_iv_get(self, "@lock");
294
+ rb_mutex_lock(lock);
295
+ if (flag == Qtrue)
296
+ {
297
+ enet_host_compress_with_range_coder(server->host);
298
+ }
299
+ else
300
+ {
301
+ enet_host_compress(server->host, NULL);
302
+ }
303
+ rb_mutex_unlock(lock);
304
+ return Qnil;
216
305
  }
217
306
 
218
307
  VALUE renet_server_on_connection(VALUE self, VALUE method)
219
308
  {
220
- /*VALUE method = rb_funcall(rb_cObject, rb_intern("method"), 1, symbol);*/
221
- rb_iv_set(cENetServer, "@on_connection", method);
222
- return Qnil;
309
+ /*VALUE method = rb_funcall(rb_cObject, rb_intern("method"), 1, symbol);*/
310
+ rb_iv_set(self, "@on_connection", method);
311
+ return Qnil;
223
312
  }
224
313
 
225
- void renet_server_execute_on_connection(VALUE peer_id, VALUE ip)
314
+ void renet_server_execute_on_connection(VALUE self, VALUE peer_id, VALUE ip)
226
315
  {
227
- VALUE method = rb_iv_get(cENetServer, "@on_connection");
228
- if (method != Qnil)
229
- {
230
- rb_funcall(method, rb_intern("call"), 2, peer_id, ip);
231
- }
316
+ VALUE method = rb_iv_get(self, "@on_connection");
317
+ if (method != Qnil)
318
+ {
319
+ VALUE lock = rb_iv_get(self, "@lock");
320
+ rb_mutex_unlock(lock);
321
+ rb_funcall(method, rb_intern("call"), 2, peer_id, ip);
322
+ rb_mutex_lock(lock);
323
+ }
232
324
  }
233
325
 
234
326
  VALUE renet_server_on_packet_receive(VALUE self, VALUE method)
235
327
  {
236
-
237
- /*VALUE method = rb_funcall(rb_cObject, rb_intern("method"), 1, symbol);*/
238
- rb_iv_set(cENetServer, "@on_packet_receive", method);
239
- return Qnil;
328
+
329
+ /*VALUE method = rb_funcall(rb_cObject, rb_intern("method"), 1, symbol);*/
330
+ rb_iv_set(self, "@on_packet_receive", method);
331
+ return Qnil;
240
332
  }
241
333
 
242
- void renet_server_execute_on_packet_receive(VALUE peer_id, enet_uint8* data, enet_uint8 channelID)
334
+ void renet_server_execute_on_packet_receive(VALUE self, VALUE peer_id, ENetPacket * const packet, enet_uint8 channelID)
243
335
  {
244
- VALUE method = rb_iv_get(cENetServer, "@on_packet_receive");
245
- if (method != Qnil)
246
- {
247
- rb_funcall(method, rb_intern("call"), 3, peer_id, rb_str_new2(data), UINT2NUM(channelID));
248
- }
336
+ VALUE method = rb_iv_get(self, "@on_packet_receive");
337
+ VALUE data = rb_str_new((char const *)packet->data, packet->dataLength);
338
+ /* marshal data and then destroy packet
339
+ if we don't do this now the packet might become invalid before we get
340
+ back and we'd get a segfault when we attempt to destroy */
341
+ enet_packet_destroy(packet);
342
+
343
+ if (method != Qnil)
344
+ {
345
+ VALUE lock = rb_iv_get(self, "@lock");
346
+ rb_mutex_unlock(lock);
347
+ rb_funcall(method, rb_intern("call"), 3, peer_id, data, UINT2NUM(channelID));
348
+ rb_mutex_lock(lock);
349
+ }
249
350
  }
250
351
 
251
352
  VALUE renet_server_on_disconnection(VALUE self, VALUE method)
252
353
  {
253
- /*VALUE method = rb_funcall(rb_cObject, rb_intern("method"), 1, symbol);*/
254
- rb_iv_set(cENetServer, "@on_disconnection", method);
255
- return Qnil;
354
+ /*VALUE method = rb_funcall(rb_cObject, rb_intern("method"), 1, symbol);*/
355
+ rb_iv_set(self, "@on_disconnection", method);
356
+ return Qnil;
256
357
  }
257
358
 
258
- void renet_server_execute_on_disconnection(VALUE peer_id)
359
+ void renet_server_execute_on_disconnection(VALUE self, VALUE peer_id)
259
360
  {
260
- VALUE method = rb_iv_get(cENetServer, "@on_disconnection");
261
- if (method != Qnil)
262
- {
263
- rb_funcall(method, rb_intern("call"), 1, peer_id);
264
- }
361
+ VALUE method = rb_iv_get(self, "@on_disconnection");
362
+ if (method != Qnil)
363
+ {
364
+ VALUE lock = rb_iv_get(self, "@lock");
365
+ rb_mutex_unlock(lock);
366
+ rb_funcall(method, rb_intern("call"), 1, peer_id);
367
+ rb_mutex_lock(lock);
368
+ }
265
369
  }
266
370
 
267
371
  VALUE renet_server_max_clients(VALUE self)
268
372
  {
269
- Server* server;
270
- Data_Get_Struct(self, Server, server);
271
- return UINT2NUM(server->host->peerCount);
373
+ Server* server;
374
+ Data_Get_Struct(self, Server, server);
375
+ return UINT2NUM(server->host->peerCount);
272
376
  }
273
377
 
274
378
  VALUE renet_server_clients_count(VALUE self)
275
379
  {
276
- Server* server;
277
- Data_Get_Struct(self, Server, server);
278
- return UINT2NUM(server->n_clients);
380
+ Server* server;
381
+ Data_Get_Struct(self, Server, server);
382
+ return UINT2NUM(server->n_clients);
279
383
  }
280
384