1 /**
2 Helper class to implement a DTLS server.
3 
4 Copyright:
5 Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.  
6 Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)  
7 Copyright (c) 2017-2018 Godot-D contributors  
8 
9 License: $(LINK2 https://opensource.org/licenses/MIT, MIT License)
10 
11 
12 */
13 module godot.dtlsserver;
14 import std.meta : AliasSeq, staticIndexOf;
15 import std.traits : Unqual;
16 import godot.d.traits;
17 import godot.core;
18 import godot.c;
19 import godot.d.bind;
20 import godot.d.reference;
21 import godot.globalenums;
22 import godot.object;
23 import godot.classdb;
24 import godot.reference;
25 import godot.cryptokey;
26 import godot.x509certificate;
27 import godot.packetpeerdtls;
28 import godot.packetpeerudp;
29 /**
30 Helper class to implement a DTLS server.
31 
32 This class is used to store the state of a DTLS server. Upon $(D setup) it converts connected $(D PacketPeerUDP) to $(D PacketPeerDTLS) accepting them via $(D takeConnection) as DTLS clients. Under the hood, this class is used to store the DTLS state and cookies of the server. The reason of why the state and cookies are needed is outside of the scope of this documentation.
33 Below a small example of how to use it:
34 
35 
36 # server.gd
37 extends Node
38 
39 var dtls := DTLSServer.new()
40 var server := UDPServer.new()
41 var peers = []
42 
43 func _ready():
44     server.listen(4242)
45     var key = load("key.key") # Your private key.
46     var cert = load("cert.crt") # Your X509 certificate.
47     dtls.setup(key, cert)
48 
49 func _process(delta):
50     while server.is_connection_available():
51         var peer : PacketPeerUDP = server.take_connection()
52         var dtls_peer : PacketPeerDTLS = dtls.take_connection(peer)
53         if dtls_peer.get_status() != PacketPeerDTLS.STATUS_HANDSHAKING:
54             continue # It is normal that 50% of the connections fails due to cookie exchange.
55         print("Peer connected!")
56         peers.append(dtls_peer)
57     for p in peers:
58         p.poll() # Must poll to update the state.
59         if p.get_status() == PacketPeerDTLS.STATUS_CONNECTED:
60             while p.get_available_packet_count() > 0:
61                 print("Received message from client: %s" % p.get_packet().get_string_from_utf8())
62                 p.put_packet("Hello DTLS client".to_utf8())
63 
64 
65 
66 
67 # client.gd
68 extends Node
69 
70 var dtls := PacketPeerDTLS.new()
71 var udp := PacketPeerUDP.new()
72 var connected = false
73 
74 func _ready():
75     udp.connect_to_host("127.0.0.1", 4242)
76     dtls.connect_to_peer(udp, false) # Use true in production for certificate validation!
77 
78 func _process(delta):
79     dtls.poll()
80     if dtls.get_status() == PacketPeerDTLS.STATUS_CONNECTED:
81         if !connected:
82             # Try to contact server
83             dtls.put_packet("The answer is... 42!".to_utf8())
84         while dtls.get_available_packet_count() > 0:
85             print("Connected: %s" % dtls.get_packet().get_string_from_utf8())
86             connected = true
87 
88 
89 */
90 @GodotBaseClass struct DTLSServer
91 {
92 	package(godot) enum string _GODOT_internal_name = "DTLSServer";
93 public:
94 @nogc nothrow:
95 	union { /** */ godot_object _godot_object; /** */ Reference _GODOT_base; }
96 	alias _GODOT_base this;
97 	alias BaseClasses = AliasSeq!(typeof(_GODOT_base), typeof(_GODOT_base).BaseClasses);
98 	package(godot) __gshared bool _classBindingInitialized = false;
99 	package(godot) static struct GDNativeClassBinding
100 	{
101 		__gshared:
102 		@GodotName("setup") GodotMethod!(GodotError, CryptoKey, X509Certificate, X509Certificate) setup;
103 		@GodotName("take_connection") GodotMethod!(PacketPeerDTLS, PacketPeerUDP) takeConnection;
104 	}
105 	/// 
106 	pragma(inline, true) bool opEquals(in DTLSServer other) const
107 	{ return _godot_object.ptr is other._godot_object.ptr; }
108 	/// 
109 	pragma(inline, true) typeof(null) opAssign(typeof(null) n)
110 	{ _godot_object.ptr = n; return null; }
111 	/// 
112 	pragma(inline, true) bool opEquals(typeof(null) n) const
113 	{ return _godot_object.ptr is n; }
114 	/// 
115 	size_t toHash() const @trusted { return cast(size_t)_godot_object.ptr; }
116 	mixin baseCasts;
117 	/// Construct a new instance of DTLSServer.
118 	/// Note: use `memnew!DTLSServer` instead.
119 	static DTLSServer _new()
120 	{
121 		static godot_class_constructor constructor;
122 		if(constructor is null) constructor = _godot_api.godot_get_class_constructor("DTLSServer");
123 		if(constructor is null) return typeof(this).init;
124 		return cast(DTLSServer)(constructor());
125 	}
126 	@disable new(size_t s);
127 	/**
128 	Setup the DTLS server to use the given `private_key` and provide the given `certificate` to clients. You can pass the optional `chain` parameter to provide additional CA chain information along with the certificate.
129 	*/
130 	GodotError setup(CryptoKey key, X509Certificate certificate, X509Certificate chain = X509Certificate.init)
131 	{
132 		checkClassBinding!(typeof(this))();
133 		return ptrcall!(GodotError)(GDNativeClassBinding.setup, _godot_object, key, certificate, chain);
134 	}
135 	/**
136 	Try to initiate the DTLS handshake with the given `udp_peer` which must be already connected (see $(D PacketPeerUDP.connectToHost)).
137 	$(B Note): You must check that the state of the return PacketPeerUDP is $(D constant PacketPeerDTLS.STATUS_HANDSHAKING), as it is normal that 50% of the new connections will be invalid due to cookie exchange.
138 	*/
139 	Ref!PacketPeerDTLS takeConnection(PacketPeerUDP udp_peer)
140 	{
141 		checkClassBinding!(typeof(this))();
142 		return ptrcall!(PacketPeerDTLS)(GDNativeClassBinding.takeConnection, _godot_object, udp_peer);
143 	}
144 }