1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gio.SocketListener;
26 
27 private import gio.AsyncResultIF;
28 private import gio.Cancellable;
29 private import gio.Socket;
30 private import gio.SocketAddress;
31 private import gio.SocketConnection;
32 private import glib.ConstructionException;
33 private import glib.ErrorG;
34 private import glib.GException;
35 private import gobject.ObjectG;
36 private import gobject.Signals;
37 public  import gtkc.gdktypes;
38 private import gtkc.gio;
39 public  import gtkc.giotypes;
40 private import std.algorithm;
41 
42 
43 /**
44  * A #GSocketListener is an object that keeps track of a set
45  * of server sockets and helps you accept sockets from any of the
46  * socket, either sync or async.
47  * 
48  * If you want to implement a network server, also look at #GSocketService
49  * and #GThreadedSocketService which are subclass of #GSocketListener
50  * that makes this even easier.
51  *
52  * Since: 2.22
53  */
54 public class SocketListener : ObjectG
55 {
56 	/** the main Gtk struct */
57 	protected GSocketListener* gSocketListener;
58 
59 	/** Get the main Gtk struct */
60 	public GSocketListener* getSocketListenerStruct()
61 	{
62 		return gSocketListener;
63 	}
64 
65 	/** the main Gtk struct as a void* */
66 	protected override void* getStruct()
67 	{
68 		return cast(void*)gSocketListener;
69 	}
70 
71 	protected override void setStruct(GObject* obj)
72 	{
73 		gSocketListener = cast(GSocketListener*)obj;
74 		super.setStruct(obj);
75 	}
76 
77 	/**
78 	 * Sets our main struct and passes it to the parent class.
79 	 */
80 	public this (GSocketListener* gSocketListener, bool ownedRef = false)
81 	{
82 		this.gSocketListener = gSocketListener;
83 		super(cast(GObject*)gSocketListener, ownedRef);
84 	}
85 
86 
87 	/** */
88 	public static GType getType()
89 	{
90 		return g_socket_listener_get_type();
91 	}
92 
93 	/**
94 	 * Creates a new #GSocketListener with no sockets to listen for.
95 	 * New listeners can be added with e.g. g_socket_listener_add_address()
96 	 * or g_socket_listener_add_inet_port().
97 	 *
98 	 * Return: a new #GSocketListener.
99 	 *
100 	 * Since: 2.22
101 	 *
102 	 * Throws: ConstructionException GTK+ fails to create the object.
103 	 */
104 	public this()
105 	{
106 		auto p = g_socket_listener_new();
107 		
108 		if(p is null)
109 		{
110 			throw new ConstructionException("null returned by new");
111 		}
112 		
113 		this(cast(GSocketListener*) p, true);
114 	}
115 
116 	/**
117 	 * Blocks waiting for a client to connect to any of the sockets added
118 	 * to the listener. Returns a #GSocketConnection for the socket that was
119 	 * accepted.
120 	 *
121 	 * If @source_object is not %NULL it will be filled out with the source
122 	 * object specified when the corresponding socket or address was added
123 	 * to the listener.
124 	 *
125 	 * If @cancellable is not %NULL, then the operation can be cancelled by
126 	 * triggering the cancellable object from another thread. If the operation
127 	 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
128 	 *
129 	 * Params:
130 	 *     sourceObject = location where #GObject pointer will be stored, or %NULL
131 	 *     cancellable = optional #GCancellable object, %NULL to ignore.
132 	 *
133 	 * Return: a #GSocketConnection on success, %NULL on error.
134 	 *
135 	 * Since: 2.22
136 	 *
137 	 * Throws: GException on failure.
138 	 */
139 	public SocketConnection accept(out ObjectG sourceObject, Cancellable cancellable)
140 	{
141 		GObject* outsourceObject = null;
142 		GError* err = null;
143 		
144 		auto p = g_socket_listener_accept(gSocketListener, &outsourceObject, (cancellable is null) ? null : cancellable.getCancellableStruct(), &err);
145 		
146 		if (err !is null)
147 		{
148 			throw new GException( new ErrorG(err) );
149 		}
150 		
151 		sourceObject = ObjectG.getDObject!(ObjectG)(outsourceObject);
152 		
153 		if(p is null)
154 		{
155 			return null;
156 		}
157 		
158 		return ObjectG.getDObject!(SocketConnection)(cast(GSocketConnection*) p, true);
159 	}
160 
161 	/**
162 	 * This is the asynchronous version of g_socket_listener_accept().
163 	 *
164 	 * When the operation is finished @callback will be
165 	 * called. You can then call g_socket_listener_accept_socket()
166 	 * to get the result of the operation.
167 	 *
168 	 * Params:
169 	 *     cancellable = a #GCancellable, or %NULL
170 	 *     callback = a #GAsyncReadyCallback
171 	 *     userData = user data for the callback
172 	 *
173 	 * Since: 2.22
174 	 */
175 	public void acceptAsync(Cancellable cancellable, GAsyncReadyCallback callback, void* userData)
176 	{
177 		g_socket_listener_accept_async(gSocketListener, (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData);
178 	}
179 
180 	/**
181 	 * Finishes an async accept operation. See g_socket_listener_accept_async()
182 	 *
183 	 * Params:
184 	 *     result = a #GAsyncResult.
185 	 *     sourceObject = Optional #GObject identifying this source
186 	 *
187 	 * Return: a #GSocketConnection on success, %NULL on error.
188 	 *
189 	 * Since: 2.22
190 	 *
191 	 * Throws: GException on failure.
192 	 */
193 	public SocketConnection acceptFinish(AsyncResultIF result, out ObjectG sourceObject)
194 	{
195 		GObject* outsourceObject = null;
196 		GError* err = null;
197 		
198 		auto p = g_socket_listener_accept_finish(gSocketListener, (result is null) ? null : result.getAsyncResultStruct(), &outsourceObject, &err);
199 		
200 		if (err !is null)
201 		{
202 			throw new GException( new ErrorG(err) );
203 		}
204 		
205 		sourceObject = ObjectG.getDObject!(ObjectG)(outsourceObject);
206 		
207 		if(p is null)
208 		{
209 			return null;
210 		}
211 		
212 		return ObjectG.getDObject!(SocketConnection)(cast(GSocketConnection*) p, true);
213 	}
214 
215 	/**
216 	 * Blocks waiting for a client to connect to any of the sockets added
217 	 * to the listener. Returns the #GSocket that was accepted.
218 	 *
219 	 * If you want to accept the high-level #GSocketConnection, not a #GSocket,
220 	 * which is often the case, then you should use g_socket_listener_accept()
221 	 * instead.
222 	 *
223 	 * If @source_object is not %NULL it will be filled out with the source
224 	 * object specified when the corresponding socket or address was added
225 	 * to the listener.
226 	 *
227 	 * If @cancellable is not %NULL, then the operation can be cancelled by
228 	 * triggering the cancellable object from another thread. If the operation
229 	 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
230 	 *
231 	 * Params:
232 	 *     sourceObject = location where #GObject pointer will be stored, or %NULL.
233 	 *     cancellable = optional #GCancellable object, %NULL to ignore.
234 	 *
235 	 * Return: a #GSocket on success, %NULL on error.
236 	 *
237 	 * Since: 2.22
238 	 *
239 	 * Throws: GException on failure.
240 	 */
241 	public Socket acceptSocket(out ObjectG sourceObject, Cancellable cancellable)
242 	{
243 		GObject* outsourceObject = null;
244 		GError* err = null;
245 		
246 		auto p = g_socket_listener_accept_socket(gSocketListener, &outsourceObject, (cancellable is null) ? null : cancellable.getCancellableStruct(), &err);
247 		
248 		if (err !is null)
249 		{
250 			throw new GException( new ErrorG(err) );
251 		}
252 		
253 		sourceObject = ObjectG.getDObject!(ObjectG)(outsourceObject);
254 		
255 		if(p is null)
256 		{
257 			return null;
258 		}
259 		
260 		return ObjectG.getDObject!(Socket)(cast(GSocket*) p, true);
261 	}
262 
263 	/**
264 	 * This is the asynchronous version of g_socket_listener_accept_socket().
265 	 *
266 	 * When the operation is finished @callback will be
267 	 * called. You can then call g_socket_listener_accept_socket_finish()
268 	 * to get the result of the operation.
269 	 *
270 	 * Params:
271 	 *     cancellable = a #GCancellable, or %NULL
272 	 *     callback = a #GAsyncReadyCallback
273 	 *     userData = user data for the callback
274 	 *
275 	 * Since: 2.22
276 	 */
277 	public void acceptSocketAsync(Cancellable cancellable, GAsyncReadyCallback callback, void* userData)
278 	{
279 		g_socket_listener_accept_socket_async(gSocketListener, (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData);
280 	}
281 
282 	/**
283 	 * Finishes an async accept operation. See g_socket_listener_accept_socket_async()
284 	 *
285 	 * Params:
286 	 *     result = a #GAsyncResult.
287 	 *     sourceObject = Optional #GObject identifying this source
288 	 *
289 	 * Return: a #GSocket on success, %NULL on error.
290 	 *
291 	 * Since: 2.22
292 	 *
293 	 * Throws: GException on failure.
294 	 */
295 	public Socket acceptSocketFinish(AsyncResultIF result, out ObjectG sourceObject)
296 	{
297 		GObject* outsourceObject = null;
298 		GError* err = null;
299 		
300 		auto p = g_socket_listener_accept_socket_finish(gSocketListener, (result is null) ? null : result.getAsyncResultStruct(), &outsourceObject, &err);
301 		
302 		if (err !is null)
303 		{
304 			throw new GException( new ErrorG(err) );
305 		}
306 		
307 		sourceObject = ObjectG.getDObject!(ObjectG)(outsourceObject);
308 		
309 		if(p is null)
310 		{
311 			return null;
312 		}
313 		
314 		return ObjectG.getDObject!(Socket)(cast(GSocket*) p, true);
315 	}
316 
317 	/**
318 	 * Creates a socket of type @type and protocol @protocol, binds
319 	 * it to @address and adds it to the set of sockets we're accepting
320 	 * sockets from.
321 	 *
322 	 * Note that adding an IPv6 address, depending on the platform,
323 	 * may or may not result in a listener that also accepts IPv4
324 	 * connections.  For more deterministic behavior, see
325 	 * g_socket_listener_add_inet_port().
326 	 *
327 	 * @source_object will be passed out in the various calls
328 	 * to accept to identify this particular source, which is
329 	 * useful if you're listening on multiple addresses and do
330 	 * different things depending on what address is connected to.
331 	 *
332 	 * If successful and @effective_address is non-%NULL then it will
333 	 * be set to the address that the binding actually occurred at.  This
334 	 * is helpful for determining the port number that was used for when
335 	 * requesting a binding to port 0 (ie: "any port").  This address, if
336 	 * requested, belongs to the caller and must be freed.
337 	 *
338 	 * Params:
339 	 *     address = a #GSocketAddress
340 	 *     type = a #GSocketType
341 	 *     protocol = a #GSocketProtocol
342 	 *     sourceObject = Optional #GObject identifying this source
343 	 *     effectiveAddress = location to store the address that was bound to, or %NULL.
344 	 *
345 	 * Return: %TRUE on success, %FALSE on error.
346 	 *
347 	 * Since: 2.22
348 	 *
349 	 * Throws: GException on failure.
350 	 */
351 	public bool addAddress(SocketAddress address, GSocketType type, GSocketProtocol protocol, ObjectG sourceObject, out SocketAddress effectiveAddress)
352 	{
353 		GSocketAddress* outeffectiveAddress = null;
354 		GError* err = null;
355 		
356 		auto p = g_socket_listener_add_address(gSocketListener, (address is null) ? null : address.getSocketAddressStruct(), type, protocol, (sourceObject is null) ? null : sourceObject.getObjectGStruct(), &outeffectiveAddress, &err) != 0;
357 		
358 		if (err !is null)
359 		{
360 			throw new GException( new ErrorG(err) );
361 		}
362 		
363 		effectiveAddress = ObjectG.getDObject!(SocketAddress)(outeffectiveAddress);
364 		
365 		return p;
366 	}
367 
368 	/**
369 	 * Listens for TCP connections on any available port number for both
370 	 * IPv6 and IPv4 (if each is available).
371 	 *
372 	 * This is useful if you need to have a socket for incoming connections
373 	 * but don't care about the specific port number.
374 	 *
375 	 * @source_object will be passed out in the various calls
376 	 * to accept to identify this particular source, which is
377 	 * useful if you're listening on multiple addresses and do
378 	 * different things depending on what address is connected to.
379 	 *
380 	 * Params:
381 	 *     sourceObject = Optional #GObject identifying this source
382 	 *
383 	 * Return: the port number, or 0 in case of failure.
384 	 *
385 	 * Since: 2.24
386 	 *
387 	 * Throws: GException on failure.
388 	 */
389 	public ushort addAnyInetPort(ObjectG sourceObject)
390 	{
391 		GError* err = null;
392 		
393 		auto p = g_socket_listener_add_any_inet_port(gSocketListener, (sourceObject is null) ? null : sourceObject.getObjectGStruct(), &err);
394 		
395 		if (err !is null)
396 		{
397 			throw new GException( new ErrorG(err) );
398 		}
399 		
400 		return p;
401 	}
402 
403 	/**
404 	 * Helper function for g_socket_listener_add_address() that
405 	 * creates a TCP/IP socket listening on IPv4 and IPv6 (if
406 	 * supported) on the specified port on all interfaces.
407 	 *
408 	 * @source_object will be passed out in the various calls
409 	 * to accept to identify this particular source, which is
410 	 * useful if you're listening on multiple addresses and do
411 	 * different things depending on what address is connected to.
412 	 *
413 	 * Params:
414 	 *     port = an IP port number (non-zero)
415 	 *     sourceObject = Optional #GObject identifying this source
416 	 *
417 	 * Return: %TRUE on success, %FALSE on error.
418 	 *
419 	 * Since: 2.22
420 	 *
421 	 * Throws: GException on failure.
422 	 */
423 	public bool addInetPort(ushort port, ObjectG sourceObject)
424 	{
425 		GError* err = null;
426 		
427 		auto p = g_socket_listener_add_inet_port(gSocketListener, port, (sourceObject is null) ? null : sourceObject.getObjectGStruct(), &err) != 0;
428 		
429 		if (err !is null)
430 		{
431 			throw new GException( new ErrorG(err) );
432 		}
433 		
434 		return p;
435 	}
436 
437 	/**
438 	 * Adds @socket to the set of sockets that we try to accept
439 	 * new clients from. The socket must be bound to a local
440 	 * address and listened to.
441 	 *
442 	 * @source_object will be passed out in the various calls
443 	 * to accept to identify this particular source, which is
444 	 * useful if you're listening on multiple addresses and do
445 	 * different things depending on what address is connected to.
446 	 *
447 	 * The @socket will not be automatically closed when the @listener is finalized
448 	 * unless the listener held the final reference to the socket. Before GLib 2.42,
449 	 * the @socket was automatically closed on finalization of the @listener, even
450 	 * if references to it were held elsewhere.
451 	 *
452 	 * Params:
453 	 *     socket = a listening #GSocket
454 	 *     sourceObject = Optional #GObject identifying this source
455 	 *
456 	 * Return: %TRUE on success, %FALSE on error.
457 	 *
458 	 * Since: 2.22
459 	 *
460 	 * Throws: GException on failure.
461 	 */
462 	public bool addSocket(Socket socket, ObjectG sourceObject)
463 	{
464 		GError* err = null;
465 		
466 		auto p = g_socket_listener_add_socket(gSocketListener, (socket is null) ? null : socket.getSocketStruct(), (sourceObject is null) ? null : sourceObject.getObjectGStruct(), &err) != 0;
467 		
468 		if (err !is null)
469 		{
470 			throw new GException( new ErrorG(err) );
471 		}
472 		
473 		return p;
474 	}
475 
476 	/**
477 	 * Closes all the sockets in the listener.
478 	 *
479 	 * Since: 2.22
480 	 */
481 	public void close()
482 	{
483 		g_socket_listener_close(gSocketListener);
484 	}
485 
486 	/**
487 	 * Sets the listen backlog on the sockets in the listener.
488 	 *
489 	 * See g_socket_set_listen_backlog() for details
490 	 *
491 	 * Params:
492 	 *     listenBacklog = an integer
493 	 *
494 	 * Since: 2.22
495 	 */
496 	public void setBacklog(int listenBacklog)
497 	{
498 		g_socket_listener_set_backlog(gSocketListener, listenBacklog);
499 	}
500 
501 	protected class OnDelegateWrapper
502 	{
503 		void delegate(GSocketListenerEvent, Socket, SocketListener) dlg;
504 		gulong handlerId;
505 		ConnectFlags flags;
506 		this(void delegate(GSocketListenerEvent, Socket, SocketListener) dlg, gulong handlerId, ConnectFlags flags)
507 		{
508 			this.dlg = dlg;
509 			this.handlerId = handlerId;
510 			this.flags = flags;
511 		}
512 	}
513 	protected OnDelegateWrapper[] onListeners;
514 
515 	/**
516 	 * Emitted when @listener's activity on @socket changes state.
517 	 * Note that when @listener is used to listen on both IPv4 and
518 	 * IPv6, a separate set of signals will be emitted for each, and
519 	 * the order they happen in is undefined.
520 	 *
521 	 * Params:
522 	 *     event = the event that is occurring
523 	 *     socket = the #GSocket the event is occurring on
524 	 *
525 	 * Since: 2.46
526 	 */
527 	gulong addOn(void delegate(GSocketListenerEvent, Socket, SocketListener) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
528 	{
529 		onListeners ~= new OnDelegateWrapper(dlg, 0, connectFlags);
530 		onListeners[onListeners.length - 1].handlerId = Signals.connectData(
531 			this,
532 			"event",
533 			cast(GCallback)&callBack,
534 			cast(void*)onListeners[onListeners.length - 1],
535 			cast(GClosureNotify)&callBackDestroy,
536 			connectFlags);
537 		return onListeners[onListeners.length - 1].handlerId;
538 	}
539 	
540 	extern(C) static void callBack(GSocketListener* socketlistenerStruct, GSocketListenerEvent event, GSocket* socket,OnDelegateWrapper wrapper)
541 	{
542 		wrapper.dlg(event, ObjectG.getDObject!(Socket)(socket), wrapper.outer);
543 	}
544 	
545 	extern(C) static void callBackDestroy(OnDelegateWrapper wrapper, GClosure* closure)
546 	{
547 		wrapper.outer.internalRemoveOn(wrapper);
548 	}
549 
550 	protected void internalRemoveOn(OnDelegateWrapper source)
551 	{
552 		foreach(index, wrapper; onListeners)
553 		{
554 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
555 			{
556 				onListeners[index] = null;
557 				onListeners = std.algorithm.remove(onListeners, index);
558 				break;
559 			}
560 		}
561 	}
562 	
563 }