Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/enet/enet_godot.cpp
9898 views
1
/**************************************************************************/
2
/* enet_godot.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
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
/**
32
@file enet_godot.cpp
33
@brief ENet Godot specific functions
34
*/
35
36
#include "core/io/dtls_server.h"
37
#include "core/io/ip.h"
38
#include "core/io/net_socket.h"
39
#include "core/io/packet_peer_dtls.h"
40
#include "core/io/udp_server.h"
41
#include "core/os/os.h"
42
43
// This must be last for windows to compile (tested with MinGW)
44
#include "enet/enet.h"
45
46
/// Abstract ENet interface for UDP/DTLS.
47
class ENetGodotSocket {
48
public:
49
virtual Error bind(IPAddress p_ip, uint16_t p_port) = 0;
50
virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) = 0;
51
virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) = 0;
52
virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port) = 0;
53
virtual int set_option(ENetSocketOption p_option, int p_value) = 0;
54
virtual void close() = 0;
55
virtual void set_refuse_new_connections(bool p_enable) {} /* Only used by dtls server */
56
virtual bool can_upgrade() { return false; } /* Only true in ENetUDP */
57
virtual ~ENetGodotSocket() {}
58
};
59
60
class ENetDTLSClient;
61
class ENetDTLSServer;
62
63
/// NetSocket interface
64
class ENetUDP : public ENetGodotSocket {
65
friend class ENetDTLSClient;
66
friend class ENetDTLSServer;
67
68
private:
69
Ref<NetSocket> sock;
70
IPAddress local_address;
71
bool bound = false;
72
73
public:
74
ENetUDP() {
75
sock = Ref<NetSocket>(NetSocket::create());
76
IP::Type ip_type = IP::TYPE_ANY;
77
sock->open(NetSocket::TYPE_UDP, ip_type);
78
}
79
80
~ENetUDP() {
81
sock->close();
82
}
83
84
bool can_upgrade() {
85
return true;
86
}
87
88
Error bind(IPAddress p_ip, uint16_t p_port) {
89
local_address = p_ip;
90
bound = true;
91
return sock->bind(p_ip, p_port);
92
}
93
94
Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) {
95
Error err = sock->get_socket_address(r_ip, r_port);
96
if (bound) {
97
*r_ip = local_address;
98
}
99
return err;
100
}
101
102
Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) {
103
return sock->sendto(p_buffer, p_len, r_sent, p_ip, p_port);
104
}
105
106
Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port) {
107
Error err = sock->poll(NetSocket::POLL_TYPE_IN, 0);
108
if (err != OK) {
109
return err;
110
}
111
return sock->recvfrom(p_buffer, p_len, r_read, r_ip, r_port);
112
}
113
114
int set_option(ENetSocketOption p_option, int p_value) {
115
switch (p_option) {
116
case ENET_SOCKOPT_NONBLOCK: {
117
sock->set_blocking_enabled(p_value ? false : true);
118
return 0;
119
} break;
120
121
case ENET_SOCKOPT_BROADCAST: {
122
sock->set_broadcasting_enabled(p_value ? true : false);
123
return 0;
124
} break;
125
126
case ENET_SOCKOPT_REUSEADDR: {
127
sock->set_reuse_address_enabled(p_value ? true : false);
128
return 0;
129
} break;
130
131
case ENET_SOCKOPT_RCVBUF: {
132
return -1;
133
} break;
134
135
case ENET_SOCKOPT_SNDBUF: {
136
return -1;
137
} break;
138
139
case ENET_SOCKOPT_RCVTIMEO: {
140
return -1;
141
} break;
142
143
case ENET_SOCKOPT_SNDTIMEO: {
144
return -1;
145
} break;
146
147
case ENET_SOCKOPT_NODELAY: {
148
sock->set_tcp_no_delay_enabled(p_value ? true : false);
149
return 0;
150
} break;
151
}
152
153
return -1;
154
}
155
156
void close() {
157
sock->close();
158
local_address.clear();
159
}
160
};
161
162
/// DTLS Client ENet interface
163
class ENetDTLSClient : public ENetGodotSocket {
164
bool connected = false;
165
Ref<PacketPeerUDP> udp;
166
Ref<PacketPeerDTLS> dtls;
167
Ref<TLSOptions> tls_options;
168
String for_hostname;
169
IPAddress local_address;
170
171
public:
172
ENetDTLSClient(ENetUDP *p_base, String p_for_hostname, Ref<TLSOptions> p_options) {
173
for_hostname = p_for_hostname;
174
tls_options = p_options;
175
udp.instantiate();
176
dtls = Ref<PacketPeerDTLS>(PacketPeerDTLS::create());
177
if (p_base->bound) {
178
uint16_t port;
179
p_base->get_socket_address(&local_address, &port);
180
p_base->close();
181
bind(local_address, port);
182
}
183
}
184
185
~ENetDTLSClient() {
186
close();
187
}
188
189
Error bind(IPAddress p_ip, uint16_t p_port) {
190
local_address = p_ip;
191
return udp->bind(p_port, p_ip);
192
}
193
194
Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) {
195
if (!udp->is_bound()) {
196
return ERR_UNCONFIGURED;
197
}
198
*r_ip = local_address;
199
*r_port = udp->get_local_port();
200
return OK;
201
}
202
203
Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) {
204
if (!connected) {
205
udp->connect_to_host(p_ip, p_port);
206
if (dtls->connect_to_peer(udp, for_hostname, tls_options)) {
207
return FAILED;
208
}
209
connected = true;
210
}
211
dtls->poll();
212
if (dtls->get_status() == PacketPeerDTLS::STATUS_HANDSHAKING) {
213
return ERR_BUSY;
214
} else if (dtls->get_status() != PacketPeerDTLS::STATUS_CONNECTED) {
215
return FAILED;
216
}
217
r_sent = p_len;
218
return dtls->put_packet(p_buffer, p_len);
219
}
220
221
Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port) {
222
dtls->poll();
223
if (dtls->get_status() == PacketPeerDTLS::STATUS_HANDSHAKING) {
224
return ERR_BUSY;
225
}
226
if (dtls->get_status() != PacketPeerDTLS::STATUS_CONNECTED) {
227
return FAILED;
228
}
229
int pc = dtls->get_available_packet_count();
230
if (pc == 0) {
231
return ERR_BUSY;
232
} else if (pc < 0) {
233
return FAILED;
234
}
235
236
const uint8_t *buffer;
237
Error err = dtls->get_packet(&buffer, r_read);
238
ERR_FAIL_COND_V(err != OK, err);
239
ERR_FAIL_COND_V(p_len < r_read, ERR_OUT_OF_MEMORY);
240
241
memcpy(p_buffer, buffer, r_read);
242
r_ip = udp->get_packet_address();
243
r_port = udp->get_packet_port();
244
return err;
245
}
246
247
int set_option(ENetSocketOption p_option, int p_value) {
248
return -1;
249
}
250
251
void close() {
252
dtls->disconnect_from_peer();
253
udp->close();
254
}
255
};
256
257
/// DTLSServer - ENet interface
258
class ENetDTLSServer : public ENetGodotSocket {
259
Ref<DTLSServer> server;
260
Ref<UDPServer> udp_server;
261
HashMap<String, Ref<PacketPeerDTLS>> peers;
262
int last_service = 0;
263
IPAddress local_address;
264
265
public:
266
ENetDTLSServer(ENetUDP *p_base, Ref<TLSOptions> p_options) {
267
udp_server.instantiate();
268
if (p_base->bound) {
269
uint16_t port;
270
p_base->get_socket_address(&local_address, &port);
271
p_base->close();
272
bind(local_address, port);
273
}
274
server = Ref<DTLSServer>(DTLSServer::create());
275
server->setup(p_options);
276
}
277
278
~ENetDTLSServer() {
279
close();
280
}
281
282
void set_refuse_new_connections(bool p_refuse) {
283
udp_server->set_max_pending_connections(p_refuse ? 0 : 16);
284
}
285
286
Error bind(IPAddress p_ip, uint16_t p_port) {
287
local_address = p_ip;
288
return udp_server->listen(p_port, p_ip);
289
}
290
291
Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) {
292
if (!udp_server->is_listening()) {
293
return ERR_UNCONFIGURED;
294
}
295
*r_ip = local_address;
296
*r_port = udp_server->get_local_port();
297
return OK;
298
}
299
300
Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) {
301
String key = String(p_ip) + ":" + itos(p_port);
302
if (unlikely(!peers.has(key))) {
303
// The peer might have been disconnected due to a DTLS error.
304
// We need to wait for it to time out, just mark the packet as sent.
305
r_sent = p_len;
306
return OK;
307
}
308
Ref<PacketPeerDTLS> peer = peers[key];
309
Error err = peer->put_packet(p_buffer, p_len);
310
if (err == OK) {
311
r_sent = p_len;
312
} else if (err == ERR_BUSY) {
313
r_sent = 0;
314
} else {
315
// The peer might have been disconnected due to a DTLS error.
316
// We need to wait for it to time out, just mark the packet as sent.
317
r_sent = p_len;
318
return OK;
319
}
320
return err;
321
}
322
323
Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port) {
324
udp_server->poll();
325
// TODO limits? Maybe we can better enforce allowed connections!
326
if (udp_server->is_connection_available()) {
327
Ref<PacketPeerUDP> udp = udp_server->take_connection();
328
IPAddress peer_ip = udp->get_packet_address();
329
int peer_port = udp->get_packet_port();
330
Ref<PacketPeerDTLS> peer = server->take_connection(udp);
331
PacketPeerDTLS::Status status = peer->get_status();
332
if (status == PacketPeerDTLS::STATUS_HANDSHAKING || status == PacketPeerDTLS::STATUS_CONNECTED) {
333
String key = String(peer_ip) + ":" + itos(peer_port);
334
peers[key] = peer;
335
}
336
}
337
338
List<String> remove;
339
Error err = ERR_BUSY;
340
// TODO this needs to be fair!
341
342
for (KeyValue<String, Ref<PacketPeerDTLS>> &E : peers) {
343
Ref<PacketPeerDTLS> peer = E.value;
344
peer->poll();
345
346
if (peer->get_status() == PacketPeerDTLS::STATUS_HANDSHAKING) {
347
continue;
348
} else if (peer->get_status() != PacketPeerDTLS::STATUS_CONNECTED) {
349
// Peer disconnected, removing it.
350
remove.push_back(E.key);
351
continue;
352
}
353
354
if (peer->get_available_packet_count() > 0) {
355
const uint8_t *buffer;
356
err = peer->get_packet(&buffer, r_read);
357
if (err != OK || p_len < r_read) {
358
// Something wrong with this peer, removing it.
359
remove.push_back(E.key);
360
err = ERR_BUSY;
361
r_read = 0;
362
continue;
363
}
364
365
Vector<String> s = E.key.rsplit(":", false, 1);
366
ERR_CONTINUE(s.size() != 2); // BUG!
367
368
memcpy(p_buffer, buffer, r_read);
369
r_ip = s[0];
370
r_port = s[1].to_int();
371
break; // err = OK
372
}
373
}
374
375
// Remove disconnected peers from map.
376
for (String &E : remove) {
377
peers.erase(E);
378
}
379
380
return err; // OK, ERR_BUSY, or possibly an error.
381
}
382
383
int set_option(ENetSocketOption p_option, int p_value) {
384
return -1;
385
}
386
387
void close() {
388
for (KeyValue<String, Ref<PacketPeerDTLS>> &E : peers) {
389
E.value->disconnect_from_peer();
390
}
391
peers.clear();
392
udp_server->stop();
393
server->stop();
394
local_address.clear();
395
}
396
};
397
398
static enet_uint32 timeBase = 0;
399
400
int enet_initialize(void) {
401
return 0;
402
}
403
404
void enet_deinitialize(void) {
405
}
406
407
enet_uint32 enet_host_random_seed(void) {
408
return (enet_uint32)OS::get_singleton()->get_unix_time();
409
}
410
411
enet_uint32 enet_time_get(void) {
412
return OS::get_singleton()->get_ticks_msec() - timeBase;
413
}
414
415
void enet_time_set(enet_uint32 newTimeBase) {
416
timeBase = OS::get_singleton()->get_ticks_msec() - newTimeBase;
417
}
418
419
int enet_address_set_host(ENetAddress *address, const char *name) {
420
IPAddress ip = IP::get_singleton()->resolve_hostname(name);
421
ERR_FAIL_COND_V(!ip.is_valid(), -1);
422
423
enet_address_set_ip(address, ip.get_ipv6(), 16);
424
return 0;
425
}
426
427
void enet_address_set_ip(ENetAddress *address, const uint8_t *ip, size_t size) {
428
int len = size > 16 ? 16 : size;
429
memset(address->host, 0, 16);
430
memcpy(address->host, ip, len);
431
}
432
433
int enet_address_get_host_ip(const ENetAddress *address, char *name, size_t nameLength) {
434
return -1;
435
}
436
437
int enet_address_get_host(const ENetAddress *address, char *name, size_t nameLength) {
438
return -1;
439
}
440
441
ENetSocket enet_socket_create(ENetSocketType type) {
442
ENetUDP *socket = memnew(ENetUDP);
443
444
return socket;
445
}
446
447
int enet_host_dtls_server_setup(ENetHost *host, void *p_options) {
448
ERR_FAIL_COND_V_MSG(!DTLSServer::is_available(), -1, "DTLS server is not available in this build.");
449
ENetGodotSocket *sock = (ENetGodotSocket *)host->socket;
450
if (!sock->can_upgrade()) {
451
return -1;
452
}
453
host->socket = memnew(ENetDTLSServer(static_cast<ENetUDP *>(sock), Ref<TLSOptions>(static_cast<TLSOptions *>(p_options))));
454
memdelete(sock);
455
return 0;
456
}
457
458
int enet_host_dtls_client_setup(ENetHost *host, const char *p_for_hostname, void *p_options) {
459
ERR_FAIL_COND_V_MSG(!PacketPeerDTLS::is_available(), -1, "DTLS is not available in this build.");
460
ENetGodotSocket *sock = (ENetGodotSocket *)host->socket;
461
if (!sock->can_upgrade()) {
462
return -1;
463
}
464
host->socket = memnew(ENetDTLSClient(static_cast<ENetUDP *>(sock), String::utf8(p_for_hostname), Ref<TLSOptions>(static_cast<TLSOptions *>(p_options))));
465
memdelete(sock);
466
return 0;
467
}
468
469
void enet_host_refuse_new_connections(ENetHost *host, int p_refuse) {
470
ERR_FAIL_NULL(host->socket);
471
((ENetGodotSocket *)host->socket)->set_refuse_new_connections(p_refuse);
472
}
473
474
int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
475
IPAddress ip;
476
if (address->wildcard) {
477
ip = IPAddress("*");
478
} else {
479
ip.set_ipv6(address->host);
480
}
481
482
ENetGodotSocket *sock = (ENetGodotSocket *)socket;
483
if (sock->bind(ip, address->port) != OK) {
484
return -1;
485
}
486
return 0;
487
}
488
489
void enet_socket_destroy(ENetSocket socket) {
490
ENetGodotSocket *sock = (ENetGodotSocket *)socket;
491
sock->close();
492
memdelete(sock);
493
}
494
495
int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBuffer *buffers, size_t bufferCount) {
496
ERR_FAIL_NULL_V(address, -1);
497
498
ENetGodotSocket *sock = (ENetGodotSocket *)socket;
499
IPAddress dest;
500
Error err;
501
size_t i = 0;
502
503
dest.set_ipv6(address->host);
504
505
// Create a single packet.
506
Vector<uint8_t> out;
507
uint8_t *w;
508
int size = 0;
509
int pos = 0;
510
for (i = 0; i < bufferCount; i++) {
511
size += buffers[i].dataLength;
512
}
513
514
out.resize(size);
515
w = out.ptrw();
516
for (i = 0; i < bufferCount; i++) {
517
memcpy(&w[pos], buffers[i].data, buffers[i].dataLength);
518
pos += buffers[i].dataLength;
519
}
520
521
int sent = 0;
522
err = sock->sendto((const uint8_t *)&w[0], size, sent, dest, address->port);
523
if (err != OK) {
524
if (err == ERR_BUSY) { // Blocking call
525
return 0;
526
}
527
528
WARN_PRINT("Sending failed!");
529
return -1;
530
}
531
532
return sent;
533
}
534
535
int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) {
536
ERR_FAIL_COND_V(bufferCount != 1, -1);
537
538
ENetGodotSocket *sock = (ENetGodotSocket *)socket;
539
540
int read;
541
IPAddress ip;
542
543
Error err = sock->recvfrom((uint8_t *)buffers[0].data, buffers[0].dataLength, read, ip, address->port);
544
if (err == ERR_BUSY) {
545
return 0;
546
}
547
if (err == ERR_OUT_OF_MEMORY) {
548
// A packet above the ENET_PROTOCOL_MAXIMUM_MTU was received.
549
return -2;
550
}
551
552
if (err != OK) {
553
return -1;
554
}
555
556
enet_address_set_ip(address, ip.get_ipv6(), 16);
557
558
return read;
559
}
560
561
int enet_socket_get_address(ENetSocket socket, ENetAddress *address) {
562
IPAddress ip;
563
uint16_t port;
564
ENetGodotSocket *sock = (ENetGodotSocket *)socket;
565
566
if (sock->get_socket_address(&ip, &port) != OK) {
567
return -1;
568
}
569
570
enet_address_set_ip(address, ip.get_ipv6(), 16);
571
address->port = port;
572
573
return 0;
574
}
575
576
// Not implemented
577
int enet_socket_wait(ENetSocket socket, enet_uint32 *condition, enet_uint32 timeout) {
578
return 0; // do we need this function?
579
}
580
581
int enet_socketset_select(ENetSocket maxSocket, ENetSocketSet *readSet, ENetSocketSet *writeSet, enet_uint32 timeout) {
582
return -1;
583
}
584
585
int enet_socket_listen(ENetSocket socket, int backlog) {
586
return -1;
587
}
588
589
int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) {
590
ENetGodotSocket *sock = (ENetGodotSocket *)socket;
591
return sock->set_option(option, value);
592
}
593
594
int enet_socket_get_option(ENetSocket socket, ENetSocketOption option, int *value) {
595
return -1;
596
}
597
598
int enet_socket_connect(ENetSocket socket, const ENetAddress *address) {
599
return -1;
600
}
601
602
ENetSocket enet_socket_accept(ENetSocket socket, ENetAddress *address) {
603
return nullptr;
604
}
605
606
int enet_socket_shutdown(ENetSocket socket, ENetSocketShutdown how) {
607
return -1;
608
}
609
610