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 }