1/**************************************************************************/
2/* enet_connection.h */
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#ifndef ENET_CONNECTION_H
32#define ENET_CONNECTION_H
33
34#include "enet_packet_peer.h"
35
36#include "core/crypto/crypto.h"
37#include "core/object/ref_counted.h"
38
39#include <enet/enet.h>
40
41template <typename T>
42class TypedArray;
43
44class ENetConnection : public RefCounted {
45 GDCLASS(ENetConnection, RefCounted);
46
47public:
48 enum CompressionMode {
49 COMPRESS_NONE = 0,
50 COMPRESS_RANGE_CODER,
51 COMPRESS_FASTLZ,
52 COMPRESS_ZLIB,
53 COMPRESS_ZSTD,
54 };
55
56 enum HostStatistic {
57 HOST_TOTAL_SENT_DATA,
58 HOST_TOTAL_SENT_PACKETS,
59 HOST_TOTAL_RECEIVED_DATA,
60 HOST_TOTAL_RECEIVED_PACKETS,
61 };
62
63 enum EventType {
64 EVENT_ERROR = -1,
65 EVENT_NONE = 0,
66 EVENT_CONNECT,
67 EVENT_DISCONNECT,
68 EVENT_RECEIVE,
69 };
70
71 struct Event {
72 Ref<ENetPacketPeer> peer;
73 enet_uint8 channel_id = 0;
74 enet_uint32 data = 0;
75 ENetPacket *packet = nullptr;
76 };
77
78protected:
79 static void _bind_methods();
80
81private:
82 ENetHost *host = nullptr;
83 List<Ref<ENetPacketPeer>> peers;
84
85 EventType _parse_event(const ENetEvent &p_event, Event &r_event);
86 Error _create(ENetAddress *p_address, int p_max_peers, int p_max_channels, int p_in_bandwidth, int p_out_bandwidth);
87 Array _service(int p_timeout = 0);
88 void _broadcast(int p_channel, PackedByteArray p_packet, int p_flags);
89 TypedArray<ENetPacketPeer> _get_peers();
90
91 class Compressor {
92 private:
93 CompressionMode mode = COMPRESS_NONE;
94 Vector<uint8_t> src_mem;
95 Vector<uint8_t> dst_mem;
96 ENetCompressor enet_compressor;
97
98 Compressor(CompressionMode mode);
99
100 static size_t enet_compress(void *context, const ENetBuffer *inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 *outData, size_t outLimit);
101 static size_t enet_decompress(void *context, const enet_uint8 *inData, size_t inLimit, enet_uint8 *outData, size_t outLimit);
102 static void enet_compressor_destroy(void *context) {
103 memdelete((Compressor *)context);
104 }
105
106 public:
107 static void setup(ENetHost *p_host, CompressionMode p_mode);
108 };
109
110public:
111 void broadcast(enet_uint8 p_channel, ENetPacket *p_packet);
112 void socket_send(const String &p_address, int p_port, const PackedByteArray &p_packet);
113 Error create_host_bound(const IPAddress &p_bind_address = IPAddress("*"), int p_port = 0, int p_max_peers = 32, int p_max_channels = 0, int p_in_bandwidth = 0, int p_out_bandwidth = 0);
114 Error create_host(int p_max_peers = 32, int p_max_channels = 0, int p_in_bandwidth = 0, int p_out_bandwidth = 0);
115 void destroy();
116 Ref<ENetPacketPeer> connect_to_host(const String &p_address, int p_port, int p_channels, int p_data = 0);
117 EventType service(int p_timeout, Event &r_event);
118 int check_events(EventType &r_type, Event &r_event);
119 void flush();
120 void bandwidth_limit(int p_in_bandwidth = 0, int p_out_bandwidth = 0);
121 void channel_limit(int p_max_channels);
122 void bandwidth_throttle();
123 void compress(CompressionMode p_mode);
124 double pop_statistic(HostStatistic p_stat);
125 int get_max_channels() const;
126
127 // Extras
128 void get_peers(List<Ref<ENetPacketPeer>> &r_peers);
129 int get_local_port() const;
130
131 // Godot additions
132 Error dtls_server_setup(const Ref<TLSOptions> &p_options);
133 Error dtls_client_setup(const String &p_hostname, const Ref<TLSOptions> &p_options);
134 void refuse_new_connections(bool p_refuse);
135
136 ENetConnection() {}
137 ~ENetConnection();
138};
139
140VARIANT_ENUM_CAST(ENetConnection::CompressionMode);
141VARIANT_ENUM_CAST(ENetConnection::EventType);
142VARIANT_ENUM_CAST(ENetConnection::HostStatistic);
143
144#endif // ENET_CONNECTION_H
145