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 OnEventDelegateWrapper 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 onEventListeners ~= this; 512 } 513 514 void remove(OnEventDelegateWrapper source) 515 { 516 foreach(index, wrapper; onEventListeners) 517 { 518 if (wrapper.handlerId == source.handlerId) 519 { 520 onEventListeners[index] = null; 521 onEventListeners = std.algorithm.remove(onEventListeners, index); 522 break; 523 } 524 } 525 } 526 } 527 OnEventDelegateWrapper[] onEventListeners; 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 addOnEvent(void delegate(GSocketListenerEvent, Socket, SocketListener) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 542 { 543 auto wrapper = new OnEventDelegateWrapper(dlg); 544 wrapper.handlerId = Signals.connectData( 545 this, 546 "event", 547 cast(GCallback)&callBackEvent, 548 cast(void*)wrapper, 549 cast(GClosureNotify)&callBackEventDestroy, 550 connectFlags); 551 return wrapper.handlerId; 552 } 553 554 extern(C) static void callBackEvent(GSocketListener* socketlistenerStruct, GSocketListenerEvent event, GSocket* socket, OnEventDelegateWrapper wrapper) 555 { 556 wrapper.dlg(event, ObjectG.getDObject!(Socket)(socket), wrapper.outer); 557 } 558 559 extern(C) static void callBackEventDestroy(OnEventDelegateWrapper wrapper, GClosure* closure) 560 { 561 wrapper.remove(wrapper); 562 } 563 }