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