1 /*************************************************************************/
2 /* networked_multiplayer_enet.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30
31 #include "networked_multiplayer_enet.h"
32 #include "core/io/ip.h"
33 #include "core/io/marshalls.h"
34 #include "core/os/os.h"
35
set_transfer_mode(TransferMode p_mode)36 void NetworkedMultiplayerENet::set_transfer_mode(TransferMode p_mode) {
37
38 transfer_mode = p_mode;
39 }
get_transfer_mode() const40 NetworkedMultiplayerPeer::TransferMode NetworkedMultiplayerENet::get_transfer_mode() const {
41
42 return transfer_mode;
43 }
44
set_target_peer(int p_peer)45 void NetworkedMultiplayerENet::set_target_peer(int p_peer) {
46
47 target_peer = p_peer;
48 }
49
get_packet_peer() const50 int NetworkedMultiplayerENet::get_packet_peer() const {
51
52 ERR_FAIL_COND_V_MSG(!active, 1, "The multiplayer instance isn't currently active.");
53 ERR_FAIL_COND_V(incoming_packets.size() == 0, 1);
54
55 return incoming_packets.front()->get().from;
56 }
57
get_packet_channel() const58 int NetworkedMultiplayerENet::get_packet_channel() const {
59
60 ERR_FAIL_COND_V_MSG(!active, -1, "The multiplayer instance isn't currently active.");
61 ERR_FAIL_COND_V(incoming_packets.size() == 0, -1);
62
63 return incoming_packets.front()->get().channel;
64 }
65
get_last_packet_channel() const66 int NetworkedMultiplayerENet::get_last_packet_channel() const {
67
68 ERR_FAIL_COND_V_MSG(!active, -1, "The multiplayer instance isn't currently active.");
69 ERR_FAIL_COND_V(!current_packet.packet, -1);
70
71 return current_packet.channel;
72 }
73
create_server(int p_port,int p_max_clients,int p_in_bandwidth,int p_out_bandwidth)74 Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int p_in_bandwidth, int p_out_bandwidth) {
75
76 ERR_FAIL_COND_V_MSG(active, ERR_ALREADY_IN_USE, "The multiplayer instance is already active.");
77 ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The port number must be set between 0 and 65535 (inclusive).");
78 ERR_FAIL_COND_V_MSG(p_max_clients < 1 || p_max_clients > 4095, ERR_INVALID_PARAMETER, "The number of clients must be set between 1 and 4095 (inclusive).");
79 ERR_FAIL_COND_V_MSG(p_in_bandwidth < 0, ERR_INVALID_PARAMETER, "The incoming bandwidth limit must be greater than or equal to 0 (0 disables the limit).");
80 ERR_FAIL_COND_V_MSG(p_out_bandwidth < 0, ERR_INVALID_PARAMETER, "The outgoing bandwidth limit must be greater than or equal to 0 (0 disables the limit).");
81 ERR_FAIL_COND_V(dtls_enabled && (dtls_key.is_null() || dtls_cert.is_null()), ERR_INVALID_PARAMETER);
82
83 ENetAddress address;
84 memset(&address, 0, sizeof(address));
85
86 #ifdef GODOT_ENET
87 if (bind_ip.is_wildcard()) {
88 address.wildcard = 1;
89 } else {
90 enet_address_set_ip(&address, bind_ip.get_ipv6(), 16);
91 }
92 #else
93 if (bind_ip.is_wildcard()) {
94 address.host = 0;
95 } else {
96 ERR_FAIL_COND_V(!bind_ip.is_ipv4(), ERR_INVALID_PARAMETER);
97 address.host = *(uint32_t *)bind_ip.get_ipv4();
98 }
99 #endif
100 address.port = p_port;
101
102 host = enet_host_create(&address /* the address to bind the server host to */,
103 p_max_clients /* allow up to 32 clients and/or outgoing connections */,
104 channel_count /* allow up to channel_count to be used */,
105 p_in_bandwidth /* limit incoming bandwidth if > 0 */,
106 p_out_bandwidth /* limit outgoing bandwidth if > 0 */);
107
108 ERR_FAIL_COND_V_MSG(!host, ERR_CANT_CREATE, "Couldn't create an ENet multiplayer server.");
109 #ifdef GODOT_ENET
110 if (dtls_enabled) {
111 enet_host_dtls_server_setup(host, dtls_key.ptr(), dtls_cert.ptr());
112 }
113 enet_host_refuse_new_connections(host, refuse_connections);
114 #endif
115
116 _setup_compressor();
117 active = true;
118 server = true;
119 refuse_connections = false;
120 unique_id = 1;
121 connection_status = CONNECTION_CONNECTED;
122 return OK;
123 }
create_client(const String & p_address,int p_port,int p_in_bandwidth,int p_out_bandwidth,int p_client_port)124 Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_port, int p_in_bandwidth, int p_out_bandwidth, int p_client_port) {
125
126 ERR_FAIL_COND_V_MSG(active, ERR_ALREADY_IN_USE, "The multiplayer instance is already active.");
127 ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The server port number must be set between 0 and 65535 (inclusive).");
128 ERR_FAIL_COND_V_MSG(p_client_port < 0 || p_client_port > 65535, ERR_INVALID_PARAMETER, "The client port number must be set between 0 and 65535 (inclusive).");
129 ERR_FAIL_COND_V_MSG(p_in_bandwidth < 0, ERR_INVALID_PARAMETER, "The incoming bandwidth limit must be greater than or equal to 0 (0 disables the limit).");
130 ERR_FAIL_COND_V_MSG(p_out_bandwidth < 0, ERR_INVALID_PARAMETER, "The outgoing bandwidth limit must be greater than or equal to 0 (0 disables the limit).");
131
132 if (p_client_port != 0) {
133 ENetAddress c_client;
134
135 #ifdef GODOT_ENET
136 if (bind_ip.is_wildcard()) {
137 c_client.wildcard = 1;
138 } else {
139 enet_address_set_ip(&c_client, bind_ip.get_ipv6(), 16);
140 }
141 #else
142 if (bind_ip.is_wildcard()) {
143 c_client.host = 0;
144 } else {
145 ERR_FAIL_COND_V_MSG(!bind_ip.is_ipv4(), ERR_INVALID_PARAMETER, "Wildcard IP addresses are only permitted in IPv4, not IPv6.");
146 c_client.host = *(uint32_t *)bind_ip.get_ipv4();
147 }
148 #endif
149
150 c_client.port = p_client_port;
151
152 host = enet_host_create(&c_client /* create a client host */,
153 1 /* only allow 1 outgoing connection */,
154 channel_count /* allow up to channel_count to be used */,
155 p_in_bandwidth /* limit incoming bandwidth if > 0 */,
156 p_out_bandwidth /* limit outgoing bandwidth if > 0 */);
157 } else {
158 host = enet_host_create(NULL /* create a client host */,
159 1 /* only allow 1 outgoing connection */,
160 channel_count /* allow up to channel_count to be used */,
161 p_in_bandwidth /* limit incoming bandwidth if > 0 */,
162 p_out_bandwidth /* limit outgoing bandwidth if > 0 */);
163 }
164
165 ERR_FAIL_COND_V_MSG(!host, ERR_CANT_CREATE, "Couldn't create the ENet client host.");
166 #ifdef GODOT_ENET
167 if (dtls_enabled) {
168 enet_host_dtls_client_setup(host, dtls_cert.ptr(), dtls_verify, p_address.utf8().get_data());
169 }
170 enet_host_refuse_new_connections(host, refuse_connections);
171 #endif
172
173 _setup_compressor();
174
175 IP_Address ip;
176 if (p_address.is_valid_ip_address()) {
177 ip = p_address;
178 } else {
179 #ifdef GODOT_ENET
180 ip = IP::get_singleton()->resolve_hostname(p_address);
181 #else
182 ip = IP::get_singleton()->resolve_hostname(p_address, IP::TYPE_IPV4);
183 #endif
184
185 ERR_FAIL_COND_V_MSG(!ip.is_valid(), ERR_CANT_RESOLVE, "Couldn't resolve the server IP address or domain name.");
186 }
187
188 ENetAddress address;
189 #ifdef GODOT_ENET
190 enet_address_set_ip(&address, ip.get_ipv6(), 16);
191 #else
192 ERR_FAIL_COND_V_MSG(!ip.is_ipv4(), ERR_INVALID_PARAMETER, "Connecting to an IPv6 server isn't supported when using vanilla ENet. Recompile Godot with the bundled ENet library.");
193 address.host = *(uint32_t *)ip.get_ipv4();
194 #endif
195 address.port = p_port;
196
197 unique_id = _gen_unique_id();
198
199 // Initiate connection, allocating enough channels
200 ENetPeer *peer = enet_host_connect(host, &address, channel_count, unique_id);
201
202 if (peer == NULL) {
203 enet_host_destroy(host);
204 ERR_FAIL_COND_V_MSG(!peer, ERR_CANT_CREATE, "Couldn't connect to the ENet multiplayer server.");
205 }
206
207 // Technically safe to ignore the peer or anything else.
208
209 connection_status = CONNECTION_CONNECTING;
210 active = true;
211 server = false;
212 refuse_connections = false;
213
214 return OK;
215 }
216
poll()217 void NetworkedMultiplayerENet::poll() {
218
219 ERR_FAIL_COND_MSG(!active, "The multiplayer instance isn't currently active.");
220
221 _pop_current_packet();
222
223 ENetEvent event;
224 /* Keep servicing until there are no available events left in queue. */
225 while (true) {
226
227 if (!host || !active) // Might have been disconnected while emitting a notification
228 return;
229
230 int ret = enet_host_service(host, &event, 0);
231
232 if (ret < 0) {
233 // Error, do something?
234 break;
235 } else if (ret == 0) {
236 break;
237 }
238
239 switch (event.type) {
240 case ENET_EVENT_TYPE_CONNECT: {
241 // Store any relevant client information here.
242
243 if (server && refuse_connections) {
244 enet_peer_reset(event.peer);
245 break;
246 }
247
248 // A client joined with an invalid ID (negative values, 0, and 1 are reserved).
249 // Probably trying to exploit us.
250 if (server && ((int)event.data < 2 || peer_map.has((int)event.data))) {
251 enet_peer_reset(event.peer);
252 ERR_CONTINUE(true);
253 }
254
255 int *new_id = memnew(int);
256 *new_id = event.data;
257
258 if (*new_id == 0) { // Data zero is sent by server (enet won't let you configure this). Server is always 1.
259 *new_id = 1;
260 }
261
262 event.peer->data = new_id;
263
264 peer_map[*new_id] = event.peer;
265
266 connection_status = CONNECTION_CONNECTED; // If connecting, this means it connected to something!
267
268 emit_signal("peer_connected", *new_id);
269
270 if (server) {
271 // Do not notify other peers when server_relay is disabled.
272 if (!server_relay)
273 break;
274
275 // Someone connected, notify all the peers available
276 for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) {
277
278 if (E->key() == *new_id)
279 continue;
280 // Send existing peers to new peer
281 ENetPacket *packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE);
282 encode_uint32(SYSMSG_ADD_PEER, &packet->data[0]);
283 encode_uint32(E->key(), &packet->data[4]);
284 enet_peer_send(event.peer, SYSCH_CONFIG, packet);
285 // Send the new peer to existing peers
286 packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE);
287 encode_uint32(SYSMSG_ADD_PEER, &packet->data[0]);
288 encode_uint32(*new_id, &packet->data[4]);
289 enet_peer_send(E->get(), SYSCH_CONFIG, packet);
290 }
291 } else {
292
293 emit_signal("connection_succeeded");
294 }
295
296 } break;
297 case ENET_EVENT_TYPE_DISCONNECT: {
298
299 // Reset the peer's client information.
300
301 int *id = (int *)event.peer->data;
302
303 if (!id) {
304 if (!server) {
305 emit_signal("connection_failed");
306 }
307 // Never fully connected.
308 break;
309 }
310
311 if (!server) {
312
313 // Client just disconnected from server.
314 emit_signal("server_disconnected");
315 close_connection();
316 return;
317 } else if (server_relay) {
318
319 // Server just received a client disconnect and is in relay mode, notify everyone else.
320 for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) {
321
322 if (E->key() == *id)
323 continue;
324
325 ENetPacket *packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE);
326 encode_uint32(SYSMSG_REMOVE_PEER, &packet->data[0]);
327 encode_uint32(*id, &packet->data[4]);
328 enet_peer_send(E->get(), SYSCH_CONFIG, packet);
329 }
330 }
331
332 emit_signal("peer_disconnected", *id);
333 peer_map.erase(*id);
334 memdelete(id);
335 } break;
336 case ENET_EVENT_TYPE_RECEIVE: {
337
338 if (event.channelID == SYSCH_CONFIG) {
339 // Some config message
340 ERR_CONTINUE(event.packet->dataLength < 8);
341
342 // Only server can send config messages
343 ERR_CONTINUE(server);
344
345 int msg = decode_uint32(&event.packet->data[0]);
346 int id = decode_uint32(&event.packet->data[4]);
347
348 switch (msg) {
349 case SYSMSG_ADD_PEER: {
350
351 peer_map[id] = NULL;
352 emit_signal("peer_connected", id);
353
354 } break;
355 case SYSMSG_REMOVE_PEER: {
356
357 peer_map.erase(id);
358 emit_signal("peer_disconnected", id);
359 } break;
360 }
361
362 enet_packet_destroy(event.packet);
363 } else if (event.channelID < channel_count) {
364
365 Packet packet;
366 packet.packet = event.packet;
367
368 uint32_t *id = (uint32_t *)event.peer->data;
369
370 ERR_CONTINUE(event.packet->dataLength < 8);
371
372 uint32_t source = decode_uint32(&event.packet->data[0]);
373 int target = decode_uint32(&event.packet->data[4]);
374
375 packet.from = source;
376 packet.channel = event.channelID;
377
378 if (server) {
379 // Someone is cheating and trying to fake the source!
380 ERR_CONTINUE(source != *id);
381
382 packet.from = *id;
383
384 if (target == 1) {
385 // To myself and only myself
386 incoming_packets.push_back(packet);
387 } else if (!server_relay) {
388 // No other destination is allowed when server is not relaying
389 continue;
390 } else if (target == 0) {
391 // Re-send to everyone but sender :|
392
393 incoming_packets.push_back(packet);
394 // And make copies for sending
395 for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) {
396
397 if (uint32_t(E->key()) == source) // Do not resend to self
398 continue;
399
400 ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, packet.packet->flags);
401
402 enet_peer_send(E->get(), event.channelID, packet2);
403 }
404
405 } else if (target < 0) {
406 // To all but one
407
408 // And make copies for sending
409 for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) {
410
411 if (uint32_t(E->key()) == source || E->key() == -target) // Do not resend to self, also do not send to excluded
412 continue;
413
414 ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, packet.packet->flags);
415
416 enet_peer_send(E->get(), event.channelID, packet2);
417 }
418
419 if (-target != 1) {
420 // Server is not excluded
421 incoming_packets.push_back(packet);
422 } else {
423 // Server is excluded, erase packet
424 enet_packet_destroy(packet.packet);
425 }
426
427 } else {
428 // To someone else, specifically
429 ERR_CONTINUE(!peer_map.has(target));
430 enet_peer_send(peer_map[target], event.channelID, packet.packet);
431 }
432 } else {
433
434 incoming_packets.push_back(packet);
435 }
436
437 // Destroy packet later
438 } else {
439 ERR_CONTINUE(true);
440 }
441
442 } break;
443 case ENET_EVENT_TYPE_NONE: {
444 // Do nothing
445 } break;
446 }
447 }
448 }
449
is_server() const450 bool NetworkedMultiplayerENet::is_server() const {
451 ERR_FAIL_COND_V_MSG(!active, false, "The multiplayer instance isn't currently active.");
452
453 return server;
454 }
455
close_connection(uint32_t wait_usec)456 void NetworkedMultiplayerENet::close_connection(uint32_t wait_usec) {
457
458 ERR_FAIL_COND_MSG(!active, "The multiplayer instance isn't currently active.");
459
460 _pop_current_packet();
461
462 bool peers_disconnected = false;
463 for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) {
464 if (E->get()) {
465 enet_peer_disconnect_now(E->get(), unique_id);
466 int *id = (int *)(E->get()->data);
467 memdelete(id);
468 peers_disconnected = true;
469 }
470 }
471
472 if (peers_disconnected) {
473 enet_host_flush(host);
474
475 if (wait_usec > 0) {
476 OS::get_singleton()->delay_usec(wait_usec); // Wait for disconnection packets to send
477 }
478 }
479
480 enet_host_destroy(host);
481 active = false;
482 incoming_packets.clear();
483 peer_map.clear();
484 unique_id = 1; // Server is 1
485 connection_status = CONNECTION_DISCONNECTED;
486 }
487
disconnect_peer(int p_peer,bool now)488 void NetworkedMultiplayerENet::disconnect_peer(int p_peer, bool now) {
489
490 ERR_FAIL_COND_MSG(!active, "The multiplayer instance isn't currently active.");
491 ERR_FAIL_COND_MSG(!is_server(), "Can't disconnect a peer when not acting as a server.");
492 ERR_FAIL_COND_MSG(!peer_map.has(p_peer), vformat("Peer ID %d not found in the list of peers.", p_peer));
493
494 if (now) {
495 int *id = (int *)peer_map[p_peer]->data;
496 enet_peer_disconnect_now(peer_map[p_peer], 0);
497
498 // enet_peer_disconnect_now doesn't generate ENET_EVENT_TYPE_DISCONNECT,
499 // notify everyone else, send disconnect signal & remove from peer_map like in poll()
500 if (server_relay) {
501 for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) {
502
503 if (E->key() == p_peer) {
504 continue;
505 }
506
507 ENetPacket *packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE);
508 encode_uint32(SYSMSG_REMOVE_PEER, &packet->data[0]);
509 encode_uint32(p_peer, &packet->data[4]);
510 enet_peer_send(E->get(), SYSCH_CONFIG, packet);
511 }
512 }
513
514 if (id)
515 memdelete(id);
516
517 emit_signal("peer_disconnected", p_peer);
518 peer_map.erase(p_peer);
519 } else {
520 enet_peer_disconnect_later(peer_map[p_peer], 0);
521 }
522 }
523
get_available_packet_count() const524 int NetworkedMultiplayerENet::get_available_packet_count() const {
525
526 return incoming_packets.size();
527 }
528
get_packet(const uint8_t ** r_buffer,int & r_buffer_size)529 Error NetworkedMultiplayerENet::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
530
531 ERR_FAIL_COND_V_MSG(incoming_packets.size() == 0, ERR_UNAVAILABLE, "No incoming packets available.");
532
533 _pop_current_packet();
534
535 current_packet = incoming_packets.front()->get();
536 incoming_packets.pop_front();
537
538 *r_buffer = (const uint8_t *)(¤t_packet.packet->data[8]);
539 r_buffer_size = current_packet.packet->dataLength - 8;
540
541 return OK;
542 }
543
put_packet(const uint8_t * p_buffer,int p_buffer_size)544 Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
545
546 ERR_FAIL_COND_V_MSG(!active, ERR_UNCONFIGURED, "The multiplayer instance isn't currently active.");
547 ERR_FAIL_COND_V_MSG(connection_status != CONNECTION_CONNECTED, ERR_UNCONFIGURED, "The multiplayer instance isn't currently connected to any server or client.");
548
549 int packet_flags = 0;
550 int channel = SYSCH_RELIABLE;
551
552 switch (transfer_mode) {
553 case TRANSFER_MODE_UNRELIABLE: {
554 if (always_ordered)
555 packet_flags = 0;
556 else
557 packet_flags = ENET_PACKET_FLAG_UNSEQUENCED;
558 channel = SYSCH_UNRELIABLE;
559 } break;
560 case TRANSFER_MODE_UNRELIABLE_ORDERED: {
561 packet_flags = 0;
562 channel = SYSCH_UNRELIABLE;
563 } break;
564 case TRANSFER_MODE_RELIABLE: {
565 packet_flags = ENET_PACKET_FLAG_RELIABLE;
566 channel = SYSCH_RELIABLE;
567 } break;
568 }
569
570 if (transfer_channel > SYSCH_CONFIG)
571 channel = transfer_channel;
572
573 Map<int, ENetPeer *>::Element *E = NULL;
574
575 if (target_peer != 0) {
576
577 E = peer_map.find(ABS(target_peer));
578 ERR_FAIL_COND_V_MSG(!E, ERR_INVALID_PARAMETER, vformat("Invalid target peer: %d", target_peer));
579 }
580
581 ENetPacket *packet = enet_packet_create(NULL, p_buffer_size + 8, packet_flags);
582 encode_uint32(unique_id, &packet->data[0]); // Source ID
583 encode_uint32(target_peer, &packet->data[4]); // Dest ID
584 copymem(&packet->data[8], p_buffer, p_buffer_size);
585
586 if (server) {
587
588 if (target_peer == 0) {
589 enet_host_broadcast(host, channel, packet);
590 } else if (target_peer < 0) {
591 // Send to all but one
592 // and make copies for sending
593
594 int exclude = -target_peer;
595
596 for (Map<int, ENetPeer *>::Element *F = peer_map.front(); F; F = F->next()) {
597
598 if (F->key() == exclude) // Exclude packet
599 continue;
600
601 ENetPacket *packet2 = enet_packet_create(packet->data, packet->dataLength, packet_flags);
602
603 enet_peer_send(F->get(), channel, packet2);
604 }
605
606 enet_packet_destroy(packet); // Original packet no longer needed
607 } else {
608 enet_peer_send(E->get(), channel, packet);
609 }
610 } else {
611
612 ERR_FAIL_COND_V(!peer_map.has(1), ERR_BUG);
613 enet_peer_send(peer_map[1], channel, packet); // Send to server for broadcast
614 }
615
616 enet_host_flush(host);
617
618 return OK;
619 }
620
get_max_packet_size() const621 int NetworkedMultiplayerENet::get_max_packet_size() const {
622
623 return 1 << 24; // Anything is good
624 }
625
_pop_current_packet()626 void NetworkedMultiplayerENet::_pop_current_packet() {
627
628 if (current_packet.packet) {
629 enet_packet_destroy(current_packet.packet);
630 current_packet.packet = NULL;
631 current_packet.from = 0;
632 current_packet.channel = -1;
633 }
634 }
635
get_connection_status() const636 NetworkedMultiplayerPeer::ConnectionStatus NetworkedMultiplayerENet::get_connection_status() const {
637
638 return connection_status;
639 }
640
_gen_unique_id() const641 uint32_t NetworkedMultiplayerENet::_gen_unique_id() const {
642
643 uint32_t hash = 0;
644
645 while (hash == 0 || hash == 1) {
646
647 hash = hash_djb2_one_32(
648 (uint32_t)OS::get_singleton()->get_ticks_usec());
649 hash = hash_djb2_one_32(
650 (uint32_t)OS::get_singleton()->get_unix_time(), hash);
651 hash = hash_djb2_one_32(
652 (uint32_t)OS::get_singleton()->get_user_data_dir().hash64(), hash);
653 hash = hash_djb2_one_32(
654 (uint32_t)((uint64_t)this), hash); // Rely on ASLR heap
655 hash = hash_djb2_one_32(
656 (uint32_t)((uint64_t)&hash), hash); // Rely on ASLR stack
657
658 hash = hash & 0x7FFFFFFF; // Make it compatible with unsigned, since negative ID is used for exclusion
659 }
660
661 return hash;
662 }
663
get_unique_id() const664 int NetworkedMultiplayerENet::get_unique_id() const {
665
666 ERR_FAIL_COND_V_MSG(!active, 0, "The multiplayer instance isn't currently active.");
667 return unique_id;
668 }
669
set_refuse_new_connections(bool p_enable)670 void NetworkedMultiplayerENet::set_refuse_new_connections(bool p_enable) {
671
672 refuse_connections = p_enable;
673 #ifdef GODOT_ENET
674 if (active) {
675 enet_host_refuse_new_connections(host, p_enable);
676 }
677 #endif
678 }
679
is_refusing_new_connections() const680 bool NetworkedMultiplayerENet::is_refusing_new_connections() const {
681
682 return refuse_connections;
683 }
684
set_compression_mode(CompressionMode p_mode)685 void NetworkedMultiplayerENet::set_compression_mode(CompressionMode p_mode) {
686
687 compression_mode = p_mode;
688 }
689
get_compression_mode() const690 NetworkedMultiplayerENet::CompressionMode NetworkedMultiplayerENet::get_compression_mode() const {
691
692 return compression_mode;
693 }
694
enet_compress(void * context,const ENetBuffer * inBuffers,size_t inBufferCount,size_t inLimit,enet_uint8 * outData,size_t outLimit)695 size_t NetworkedMultiplayerENet::enet_compress(void *context, const ENetBuffer *inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 *outData, size_t outLimit) {
696
697 NetworkedMultiplayerENet *enet = (NetworkedMultiplayerENet *)(context);
698
699 if (size_t(enet->src_compressor_mem.size()) < inLimit) {
700 enet->src_compressor_mem.resize(inLimit);
701 }
702
703 int total = inLimit;
704 int ofs = 0;
705 while (total) {
706 for (size_t i = 0; i < inBufferCount; i++) {
707 int to_copy = MIN(total, int(inBuffers[i].dataLength));
708 copymem(&enet->src_compressor_mem.write[ofs], inBuffers[i].data, to_copy);
709 ofs += to_copy;
710 total -= to_copy;
711 }
712 }
713
714 Compression::Mode mode;
715
716 switch (enet->compression_mode) {
717 case COMPRESS_FASTLZ: {
718 mode = Compression::MODE_FASTLZ;
719 } break;
720 case COMPRESS_ZLIB: {
721 mode = Compression::MODE_DEFLATE;
722 } break;
723 case COMPRESS_ZSTD: {
724 mode = Compression::MODE_ZSTD;
725 } break;
726 default: {
727 ERR_FAIL_V_MSG(0, vformat("Invalid ENet compression mode: %d", enet->compression_mode));
728 }
729 }
730
731 int req_size = Compression::get_max_compressed_buffer_size(ofs, mode);
732 if (enet->dst_compressor_mem.size() < req_size) {
733 enet->dst_compressor_mem.resize(req_size);
734 }
735 int ret = Compression::compress(enet->dst_compressor_mem.ptrw(), enet->src_compressor_mem.ptr(), ofs, mode);
736
737 if (ret < 0)
738 return 0;
739
740 if (ret > int(outLimit))
741 return 0; // Do not bother
742
743 copymem(outData, enet->dst_compressor_mem.ptr(), ret);
744
745 return ret;
746 }
747
enet_decompress(void * context,const enet_uint8 * inData,size_t inLimit,enet_uint8 * outData,size_t outLimit)748 size_t NetworkedMultiplayerENet::enet_decompress(void *context, const enet_uint8 *inData, size_t inLimit, enet_uint8 *outData, size_t outLimit) {
749
750 NetworkedMultiplayerENet *enet = (NetworkedMultiplayerENet *)(context);
751 int ret = -1;
752 switch (enet->compression_mode) {
753 case COMPRESS_FASTLZ: {
754
755 ret = Compression::decompress(outData, outLimit, inData, inLimit, Compression::MODE_FASTLZ);
756 } break;
757 case COMPRESS_ZLIB: {
758
759 ret = Compression::decompress(outData, outLimit, inData, inLimit, Compression::MODE_DEFLATE);
760 } break;
761 case COMPRESS_ZSTD: {
762
763 ret = Compression::decompress(outData, outLimit, inData, inLimit, Compression::MODE_ZSTD);
764 } break;
765 default: {
766 }
767 }
768 if (ret < 0) {
769 return 0;
770 } else {
771 return ret;
772 }
773 }
774
_setup_compressor()775 void NetworkedMultiplayerENet::_setup_compressor() {
776
777 switch (compression_mode) {
778
779 case COMPRESS_NONE: {
780
781 enet_host_compress(host, NULL);
782 } break;
783 case COMPRESS_RANGE_CODER: {
784 enet_host_compress_with_range_coder(host);
785 } break;
786 case COMPRESS_FASTLZ:
787 case COMPRESS_ZLIB:
788 case COMPRESS_ZSTD: {
789
790 enet_host_compress(host, &enet_compressor);
791 } break;
792 }
793 }
794
enet_compressor_destroy(void * context)795 void NetworkedMultiplayerENet::enet_compressor_destroy(void *context) {
796
797 // Nothing to do
798 }
799
get_peer_address(int p_peer_id) const800 IP_Address NetworkedMultiplayerENet::get_peer_address(int p_peer_id) const {
801
802 ERR_FAIL_COND_V_MSG(!peer_map.has(p_peer_id), IP_Address(), vformat("Peer ID %d not found in the list of peers.", p_peer_id));
803 ERR_FAIL_COND_V_MSG(!is_server() && p_peer_id != 1, IP_Address(), "Can't get the address of peers other than the server (ID -1) when acting as a client.");
804 ERR_FAIL_COND_V_MSG(peer_map[p_peer_id] == NULL, IP_Address(), vformat("Peer ID %d found in the list of peers, but is null.", p_peer_id));
805
806 IP_Address out;
807 #ifdef GODOT_ENET
808 out.set_ipv6((uint8_t *)&(peer_map[p_peer_id]->address.host));
809 #else
810 out.set_ipv4((uint8_t *)&(peer_map[p_peer_id]->address.host));
811 #endif
812
813 return out;
814 }
815
get_peer_port(int p_peer_id) const816 int NetworkedMultiplayerENet::get_peer_port(int p_peer_id) const {
817
818 ERR_FAIL_COND_V_MSG(!peer_map.has(p_peer_id), 0, vformat("Peer ID %d not found in the list of peers.", p_peer_id));
819 ERR_FAIL_COND_V_MSG(!is_server() && p_peer_id != 1, 0, "Can't get the address of peers other than the server (ID -1) when acting as a client.");
820 ERR_FAIL_COND_V_MSG(peer_map[p_peer_id] == NULL, 0, vformat("Peer ID %d found in the list of peers, but is null.", p_peer_id));
821 #ifdef GODOT_ENET
822 return peer_map[p_peer_id]->address.port;
823 #else
824 return peer_map[p_peer_id]->address.port;
825 #endif
826 }
827
set_transfer_channel(int p_channel)828 void NetworkedMultiplayerENet::set_transfer_channel(int p_channel) {
829
830 ERR_FAIL_COND_MSG(p_channel < -1 || p_channel >= channel_count, vformat("The transfer channel must be set between 0 and %d, inclusive (got %d).", channel_count - 1, p_channel));
831 ERR_FAIL_COND_MSG(p_channel == SYSCH_CONFIG, vformat("The channel %d is reserved.", SYSCH_CONFIG));
832 transfer_channel = p_channel;
833 }
834
get_transfer_channel() const835 int NetworkedMultiplayerENet::get_transfer_channel() const {
836 return transfer_channel;
837 }
838
set_channel_count(int p_channel)839 void NetworkedMultiplayerENet::set_channel_count(int p_channel) {
840
841 ERR_FAIL_COND_MSG(active, "The channel count can't be set while the multiplayer instance is active.");
842 ERR_FAIL_COND_MSG(p_channel < SYSCH_MAX, vformat("The channel count must be greater than or equal to %d to account for reserved channels (got %d).", SYSCH_MAX, p_channel));
843 channel_count = p_channel;
844 }
845
get_channel_count() const846 int NetworkedMultiplayerENet::get_channel_count() const {
847 return channel_count;
848 }
849
set_always_ordered(bool p_ordered)850 void NetworkedMultiplayerENet::set_always_ordered(bool p_ordered) {
851 always_ordered = p_ordered;
852 }
853
is_always_ordered() const854 bool NetworkedMultiplayerENet::is_always_ordered() const {
855 return always_ordered;
856 }
857
set_server_relay_enabled(bool p_enabled)858 void NetworkedMultiplayerENet::set_server_relay_enabled(bool p_enabled) {
859 ERR_FAIL_COND_MSG(active, "Server relaying can't be toggled while the multiplayer instance is active.");
860
861 server_relay = p_enabled;
862 }
863
is_server_relay_enabled() const864 bool NetworkedMultiplayerENet::is_server_relay_enabled() const {
865 return server_relay;
866 }
867
_bind_methods()868 void NetworkedMultiplayerENet::_bind_methods() {
869
870 ClassDB::bind_method(D_METHOD("create_server", "port", "max_clients", "in_bandwidth", "out_bandwidth"), &NetworkedMultiplayerENet::create_server, DEFVAL(32), DEFVAL(0), DEFVAL(0));
871 ClassDB::bind_method(D_METHOD("create_client", "address", "port", "in_bandwidth", "out_bandwidth", "client_port"), &NetworkedMultiplayerENet::create_client, DEFVAL(0), DEFVAL(0), DEFVAL(0));
872 ClassDB::bind_method(D_METHOD("close_connection", "wait_usec"), &NetworkedMultiplayerENet::close_connection, DEFVAL(100));
873 ClassDB::bind_method(D_METHOD("disconnect_peer", "id", "now"), &NetworkedMultiplayerENet::disconnect_peer, DEFVAL(false));
874 ClassDB::bind_method(D_METHOD("set_compression_mode", "mode"), &NetworkedMultiplayerENet::set_compression_mode);
875 ClassDB::bind_method(D_METHOD("get_compression_mode"), &NetworkedMultiplayerENet::get_compression_mode);
876 ClassDB::bind_method(D_METHOD("set_bind_ip", "ip"), &NetworkedMultiplayerENet::set_bind_ip);
877 ClassDB::bind_method(D_METHOD("set_dtls_enabled", "enabled"), &NetworkedMultiplayerENet::set_dtls_enabled);
878 ClassDB::bind_method(D_METHOD("is_dtls_enabled"), &NetworkedMultiplayerENet::is_dtls_enabled);
879 ClassDB::bind_method(D_METHOD("set_dtls_key", "key"), &NetworkedMultiplayerENet::set_dtls_key);
880 ClassDB::bind_method(D_METHOD("set_dtls_certificate", "certificate"), &NetworkedMultiplayerENet::set_dtls_certificate);
881 ClassDB::bind_method(D_METHOD("set_dtls_verify_enabled", "enabled"), &NetworkedMultiplayerENet::set_dtls_verify_enabled);
882 ClassDB::bind_method(D_METHOD("is_dtls_verify_enabled"), &NetworkedMultiplayerENet::is_dtls_verify_enabled);
883 ClassDB::bind_method(D_METHOD("get_peer_address", "id"), &NetworkedMultiplayerENet::get_peer_address);
884 ClassDB::bind_method(D_METHOD("get_peer_port", "id"), &NetworkedMultiplayerENet::get_peer_port);
885
886 ClassDB::bind_method(D_METHOD("get_packet_channel"), &NetworkedMultiplayerENet::get_packet_channel);
887 ClassDB::bind_method(D_METHOD("get_last_packet_channel"), &NetworkedMultiplayerENet::get_last_packet_channel);
888 ClassDB::bind_method(D_METHOD("set_transfer_channel", "channel"), &NetworkedMultiplayerENet::set_transfer_channel);
889 ClassDB::bind_method(D_METHOD("get_transfer_channel"), &NetworkedMultiplayerENet::get_transfer_channel);
890 ClassDB::bind_method(D_METHOD("set_channel_count", "channels"), &NetworkedMultiplayerENet::set_channel_count);
891 ClassDB::bind_method(D_METHOD("get_channel_count"), &NetworkedMultiplayerENet::get_channel_count);
892 ClassDB::bind_method(D_METHOD("set_always_ordered", "ordered"), &NetworkedMultiplayerENet::set_always_ordered);
893 ClassDB::bind_method(D_METHOD("is_always_ordered"), &NetworkedMultiplayerENet::is_always_ordered);
894 ClassDB::bind_method(D_METHOD("set_server_relay_enabled", "enabled"), &NetworkedMultiplayerENet::set_server_relay_enabled);
895 ClassDB::bind_method(D_METHOD("is_server_relay_enabled"), &NetworkedMultiplayerENet::is_server_relay_enabled);
896
897 ADD_PROPERTY(PropertyInfo(Variant::INT, "compression_mode", PROPERTY_HINT_ENUM, "None,Range Coder,FastLZ,ZLib,ZStd"), "set_compression_mode", "get_compression_mode");
898 ADD_PROPERTY(PropertyInfo(Variant::INT, "transfer_channel"), "set_transfer_channel", "get_transfer_channel");
899 ADD_PROPERTY(PropertyInfo(Variant::INT, "channel_count"), "set_channel_count", "get_channel_count");
900 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "always_ordered"), "set_always_ordered", "is_always_ordered");
901 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "server_relay"), "set_server_relay_enabled", "is_server_relay_enabled");
902 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dtls_verify"), "set_dtls_verify_enabled", "is_dtls_verify_enabled");
903 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_dtls"), "set_dtls_enabled", "is_dtls_enabled");
904
905 BIND_ENUM_CONSTANT(COMPRESS_NONE);
906 BIND_ENUM_CONSTANT(COMPRESS_RANGE_CODER);
907 BIND_ENUM_CONSTANT(COMPRESS_FASTLZ);
908 BIND_ENUM_CONSTANT(COMPRESS_ZLIB);
909 BIND_ENUM_CONSTANT(COMPRESS_ZSTD);
910 }
911
NetworkedMultiplayerENet()912 NetworkedMultiplayerENet::NetworkedMultiplayerENet() {
913
914 active = false;
915 server = false;
916 refuse_connections = false;
917 server_relay = true;
918 unique_id = 0;
919 target_peer = 0;
920 current_packet.packet = NULL;
921 transfer_mode = TRANSFER_MODE_RELIABLE;
922 channel_count = SYSCH_MAX;
923 transfer_channel = -1;
924 always_ordered = false;
925 connection_status = CONNECTION_DISCONNECTED;
926 compression_mode = COMPRESS_NONE;
927 enet_compressor.context = this;
928 enet_compressor.compress = enet_compress;
929 enet_compressor.decompress = enet_decompress;
930 enet_compressor.destroy = enet_compressor_destroy;
931
932 bind_ip = IP_Address("*");
933
934 dtls_enabled = false;
935 dtls_verify = true;
936 }
937
~NetworkedMultiplayerENet()938 NetworkedMultiplayerENet::~NetworkedMultiplayerENet() {
939
940 if (active) {
941 close_connection();
942 }
943 }
944
945 // Sets IP for ENet to bind when using create_server or create_client
946 // if no IP is set, then ENet bind to ENET_HOST_ANY
set_bind_ip(const IP_Address & p_ip)947 void NetworkedMultiplayerENet::set_bind_ip(const IP_Address &p_ip) {
948 ERR_FAIL_COND_MSG(!p_ip.is_valid() && !p_ip.is_wildcard(), vformat("Invalid bind IP address: %s", String(p_ip)));
949
950 bind_ip = p_ip;
951 }
952
set_dtls_enabled(bool p_enabled)953 void NetworkedMultiplayerENet::set_dtls_enabled(bool p_enabled) {
954 ERR_FAIL_COND(active);
955 dtls_enabled = p_enabled;
956 }
957
is_dtls_enabled() const958 bool NetworkedMultiplayerENet::is_dtls_enabled() const {
959 return dtls_enabled;
960 }
961
set_dtls_verify_enabled(bool p_enabled)962 void NetworkedMultiplayerENet::set_dtls_verify_enabled(bool p_enabled) {
963 ERR_FAIL_COND(active);
964 dtls_verify = p_enabled;
965 }
966
is_dtls_verify_enabled() const967 bool NetworkedMultiplayerENet::is_dtls_verify_enabled() const {
968 return dtls_verify;
969 }
970
set_dtls_key(Ref<CryptoKey> p_key)971 void NetworkedMultiplayerENet::set_dtls_key(Ref<CryptoKey> p_key) {
972 ERR_FAIL_COND(active);
973 dtls_key = p_key;
974 }
975
set_dtls_certificate(Ref<X509Certificate> p_cert)976 void NetworkedMultiplayerENet::set_dtls_certificate(Ref<X509Certificate> p_cert) {
977 ERR_FAIL_COND(active);
978 dtls_cert = p_cert;
979 }
980