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