1 /**
2 Helper class to implement a UDP 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.udpserver;
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.packetpeerudp;
26 /**
27 Helper class to implement a UDP server.
28 
29 A simple server that opens a UDP socket and returns connected $(D PacketPeerUDP) upon receiving new packets. See also $(D PacketPeerUDP.connectToHost).
30 After starting the server ($(D listen)), you will need to $(D poll) it at regular intervals (e.g. inside $(D Node._process)) for it to process new packets, delivering them to the appropriate $(D PacketPeerUDP), and taking new connections.
31 Below a small example of how it can be used:
32 
33 
34 # server.gd
35 extends Node
36 
37 var server := UDPServer.new()
38 var peers = []
39 
40 func _ready():
41     server.listen(4242)
42 
43 func _process(delta):
44     server.poll() # Important!
45     if server.is_connection_available():
46         var peer : PacketPeerUDP = server.take_connection()
47         var pkt = peer.get_packet()
48         print("Accepted peer: %s:%s" % $(D peer.get_packet_ip(), peer.get_packet_port()))
49         print("Received data: %s" % $(D pkt.get_string_from_utf8()))
50         # Reply so it knows we received the message.
51         peer.put_packet(pkt)
52         # Keep a reference so we can keep contacting the remote peer.
53         peers.append(peer)
54 
55     for i in range(0, peers.size()):
56         pass # Do something with the connected peers.
57 
58 
59 
60 
61 
62 # client.gd
63 extends Node
64 
65 var udp := PacketPeerUDP.new()
66 var connected = false
67 
68 func _ready():
69     udp.connect_to_host("127.0.0.1", 4242)
70 
71 func _process(delta):
72     if !connected:
73         # Try to contact server
74         udp.put_packet("The answer is... 42!".to_utf8())
75     if udp.get_available_packet_count() > 0:
76         print("Connected: %s" % udp.get_packet().get_string_from_utf8())
77         connected = true
78 
79 
80 */
81 @GodotBaseClass struct UDPServer
82 {
83 	package(godot) enum string _GODOT_internal_name = "UDPServer";
84 public:
85 @nogc nothrow:
86 	union { /** */ godot_object _godot_object; /** */ Reference _GODOT_base; }
87 	alias _GODOT_base this;
88 	alias BaseClasses = AliasSeq!(typeof(_GODOT_base), typeof(_GODOT_base).BaseClasses);
89 	package(godot) __gshared bool _classBindingInitialized = false;
90 	package(godot) static struct GDNativeClassBinding
91 	{
92 		__gshared:
93 		@GodotName("get_max_pending_connections") GodotMethod!(long) getMaxPendingConnections;
94 		@GodotName("is_connection_available") GodotMethod!(bool) isConnectionAvailable;
95 		@GodotName("is_listening") GodotMethod!(bool) isListening;
96 		@GodotName("listen") GodotMethod!(GodotError, long, String) listen;
97 		@GodotName("poll") GodotMethod!(GodotError) poll;
98 		@GodotName("set_max_pending_connections") GodotMethod!(void, long) setMaxPendingConnections;
99 		@GodotName("stop") GodotMethod!(void) stop;
100 		@GodotName("take_connection") GodotMethod!(PacketPeerUDP) takeConnection;
101 	}
102 	/// 
103 	pragma(inline, true) bool opEquals(in UDPServer other) const
104 	{ return _godot_object.ptr is other._godot_object.ptr; }
105 	/// 
106 	pragma(inline, true) typeof(null) opAssign(typeof(null) n)
107 	{ _godot_object.ptr = n; return null; }
108 	/// 
109 	pragma(inline, true) bool opEquals(typeof(null) n) const
110 	{ return _godot_object.ptr is n; }
111 	/// 
112 	size_t toHash() const @trusted { return cast(size_t)_godot_object.ptr; }
113 	mixin baseCasts;
114 	/// Construct a new instance of UDPServer.
115 	/// Note: use `memnew!UDPServer` instead.
116 	static UDPServer _new()
117 	{
118 		static godot_class_constructor constructor;
119 		if(constructor is null) constructor = _godot_api.godot_get_class_constructor("UDPServer");
120 		if(constructor is null) return typeof(this).init;
121 		return cast(UDPServer)(constructor());
122 	}
123 	@disable new(size_t s);
124 	/**
125 	
126 	*/
127 	long getMaxPendingConnections() const
128 	{
129 		checkClassBinding!(typeof(this))();
130 		return ptrcall!(long)(GDNativeClassBinding.getMaxPendingConnections, _godot_object);
131 	}
132 	/**
133 	Returns `true` if a packet with a new address/port combination was received on the socket.
134 	*/
135 	bool isConnectionAvailable() const
136 	{
137 		checkClassBinding!(typeof(this))();
138 		return ptrcall!(bool)(GDNativeClassBinding.isConnectionAvailable, _godot_object);
139 	}
140 	/**
141 	Returns `true` if the socket is open and listening on a port.
142 	*/
143 	bool isListening() const
144 	{
145 		checkClassBinding!(typeof(this))();
146 		return ptrcall!(bool)(GDNativeClassBinding.isListening, _godot_object);
147 	}
148 	/**
149 	Starts the server by opening a UDP socket listening on the given port. You can optionally specify a `bind_address` to only listen for packets sent to that address. See also $(D PacketPeerUDP.listen).
150 	*/
151 	GodotError listen(in long port, in String bind_address = gs!"*")
152 	{
153 		checkClassBinding!(typeof(this))();
154 		return ptrcall!(GodotError)(GDNativeClassBinding.listen, _godot_object, port, bind_address);
155 	}
156 	/**
157 	Call this method at regular intervals (e.g. inside $(D Node._process)) to process new packets. And packet from known address/port pair will be delivered to the appropriate $(D PacketPeerUDP), any packet received from an unknown address/port pair will be added as a pending connection (see $(D isConnectionAvailable), $(D takeConnection)). The maximum number of pending connection is defined via $(D maxPendingConnections).
158 	*/
159 	GodotError poll()
160 	{
161 		checkClassBinding!(typeof(this))();
162 		return ptrcall!(GodotError)(GDNativeClassBinding.poll, _godot_object);
163 	}
164 	/**
165 	
166 	*/
167 	void setMaxPendingConnections(in long max_pending_connections)
168 	{
169 		checkClassBinding!(typeof(this))();
170 		ptrcall!(void)(GDNativeClassBinding.setMaxPendingConnections, _godot_object, max_pending_connections);
171 	}
172 	/**
173 	Stops the server, closing the UDP socket if open. Will close all connected $(D PacketPeerUDP) accepted via $(D takeConnection) (remote peers will not be notified).
174 	*/
175 	void stop()
176 	{
177 		checkClassBinding!(typeof(this))();
178 		ptrcall!(void)(GDNativeClassBinding.stop, _godot_object);
179 	}
180 	/**
181 	Returns the first pending connection (connected to the appropriate address/port). Will return `null` if no new connection is available. See also $(D isConnectionAvailable), $(D PacketPeerUDP.connectToHost).
182 	*/
183 	Ref!PacketPeerUDP takeConnection()
184 	{
185 		checkClassBinding!(typeof(this))();
186 		return ptrcall!(PacketPeerUDP)(GDNativeClassBinding.takeConnection, _godot_object);
187 	}
188 	/**
189 	Define the maximum number of pending connections, during $(D poll), any new pending connection exceeding that value will be automatically dropped. Setting this value to `0` effectively prevents any new pending connection to be accepted (e.g. when all your players have connected).
190 	*/
191 	@property long maxPendingConnections()
192 	{
193 		return getMaxPendingConnections();
194 	}
195 	/// ditto
196 	@property void maxPendingConnections(long v)
197 	{
198 		setMaxPendingConnections(v);
199 	}
200 }