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.SocketService; 26 27 private import gio.SocketConnection; 28 private import gio.SocketListener; 29 private import glib.ConstructionException; 30 private import gobject.ObjectG; 31 private import gobject.Signals; 32 public import gtkc.gdktypes; 33 private import gtkc.gio; 34 public import gtkc.giotypes; 35 private import std.algorithm; 36 37 38 /** 39 * A #GSocketService is an object that represents a service that 40 * is provided to the network or over local sockets. When a new 41 * connection is made to the service the #GSocketService::incoming 42 * signal is emitted. 43 * 44 * A #GSocketService is a subclass of #GSocketListener and you need 45 * to add the addresses you want to accept connections on with the 46 * #GSocketListener APIs. 47 * 48 * There are two options for implementing a network service based on 49 * #GSocketService. The first is to create the service using 50 * g_socket_service_new() and to connect to the #GSocketService::incoming 51 * signal. The second is to subclass #GSocketService and override the 52 * default signal handler implementation. 53 * 54 * In either case, the handler must immediately return, or else it 55 * will block additional incoming connections from being serviced. 56 * If you are interested in writing connection handlers that contain 57 * blocking code then see #GThreadedSocketService. 58 * 59 * The socket service runs on the main loop of the 60 * [thread-default context][g-main-context-push-thread-default-context] 61 * of the thread it is created in, and is not 62 * threadsafe in general. However, the calls to start and stop the 63 * service are thread-safe so these can be used from threads that 64 * handle incoming clients. 65 * 66 * Since: 2.22 67 */ 68 public class SocketService : SocketListener 69 { 70 /** the main Gtk struct */ 71 protected GSocketService* gSocketService; 72 73 /** Get the main Gtk struct */ 74 public GSocketService* getSocketServiceStruct() 75 { 76 return gSocketService; 77 } 78 79 /** the main Gtk struct as a void* */ 80 protected override void* getStruct() 81 { 82 return cast(void*)gSocketService; 83 } 84 85 protected override void setStruct(GObject* obj) 86 { 87 gSocketService = cast(GSocketService*)obj; 88 super.setStruct(obj); 89 } 90 91 /** 92 * Sets our main struct and passes it to the parent class. 93 */ 94 public this (GSocketService* gSocketService, bool ownedRef = false) 95 { 96 this.gSocketService = gSocketService; 97 super(cast(GSocketListener*)gSocketService, ownedRef); 98 } 99 100 101 /** */ 102 public static GType getType() 103 { 104 return g_socket_service_get_type(); 105 } 106 107 /** 108 * Creates a new #GSocketService with no sockets to listen for. 109 * New listeners can be added with e.g. g_socket_listener_add_address() 110 * or g_socket_listener_add_inet_port(). 111 * 112 * New services are created active, there is no need to call 113 * g_socket_service_start(), unless g_socket_service_stop() has been 114 * called before. 115 * 116 * Return: a new #GSocketService. 117 * 118 * Since: 2.22 119 * 120 * Throws: ConstructionException GTK+ fails to create the object. 121 */ 122 public this() 123 { 124 auto p = g_socket_service_new(); 125 126 if(p is null) 127 { 128 throw new ConstructionException("null returned by new"); 129 } 130 131 this(cast(GSocketService*) p, true); 132 } 133 134 /** 135 * Check whether the service is active or not. An active 136 * service will accept new clients that connect, while 137 * a non-active service will let connecting clients queue 138 * up until the service is started. 139 * 140 * Return: %TRUE if the service is active, %FALSE otherwise 141 * 142 * Since: 2.22 143 */ 144 public bool isActive() 145 { 146 return g_socket_service_is_active(gSocketService) != 0; 147 } 148 149 /** 150 * Restarts the service, i.e. start accepting connections 151 * from the added sockets when the mainloop runs. This only needs 152 * to be called after the service has been stopped from 153 * g_socket_service_stop(). 154 * 155 * This call is thread-safe, so it may be called from a thread 156 * handling an incoming client request. 157 * 158 * Since: 2.22 159 */ 160 public void start() 161 { 162 g_socket_service_start(gSocketService); 163 } 164 165 /** 166 * Stops the service, i.e. stops accepting connections 167 * from the added sockets when the mainloop runs. 168 * 169 * This call is thread-safe, so it may be called from a thread 170 * handling an incoming client request. 171 * 172 * Note that this only stops accepting new connections; it does not 173 * close the listening sockets, and you can call 174 * g_socket_service_start() again later to begin listening again. To 175 * close the listening sockets, call g_socket_listener_close(). (This 176 * will happen automatically when the #GSocketService is finalized.) 177 * 178 * This must be called before calling g_socket_listener_close() as 179 * the socket service will start accepting connections immediately 180 * when a new socket is added. 181 * 182 * Since: 2.22 183 */ 184 public void stop() 185 { 186 g_socket_service_stop(gSocketService); 187 } 188 189 protected class OnIncomingDelegateWrapper 190 { 191 bool delegate(SocketConnection, ObjectG, SocketService) dlg; 192 gulong handlerId; 193 ConnectFlags flags; 194 this(bool delegate(SocketConnection, ObjectG, SocketService) dlg, gulong handlerId, ConnectFlags flags) 195 { 196 this.dlg = dlg; 197 this.handlerId = handlerId; 198 this.flags = flags; 199 } 200 } 201 protected OnIncomingDelegateWrapper[] onIncomingListeners; 202 203 /** 204 * The ::incoming signal is emitted when a new incoming connection 205 * to @service needs to be handled. The handler must initiate the 206 * handling of @connection, but may not block; in essence, 207 * asynchronous operations must be used. 208 * 209 * @connection will be unreffed once the signal handler returns, 210 * so you need to ref it yourself if you are planning to use it. 211 * 212 * Params: 213 * connection = a new #GSocketConnection object 214 * sourceObject = the source_object passed to 215 * g_socket_listener_add_address() 216 * 217 * Return: %TRUE to stop other handlers from being called 218 * 219 * Since: 2.22 220 */ 221 gulong addOnIncoming(bool delegate(SocketConnection, ObjectG, SocketService) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 222 { 223 onIncomingListeners ~= new OnIncomingDelegateWrapper(dlg, 0, connectFlags); 224 onIncomingListeners[onIncomingListeners.length - 1].handlerId = Signals.connectData( 225 this, 226 "incoming", 227 cast(GCallback)&callBackIncoming, 228 cast(void*)onIncomingListeners[onIncomingListeners.length - 1], 229 cast(GClosureNotify)&callBackIncomingDestroy, 230 connectFlags); 231 return onIncomingListeners[onIncomingListeners.length - 1].handlerId; 232 } 233 234 extern(C) static int callBackIncoming(GSocketService* socketserviceStruct, GSocketConnection* connection, GObject* sourceObject,OnIncomingDelegateWrapper wrapper) 235 { 236 return wrapper.dlg(ObjectG.getDObject!(SocketConnection)(connection), ObjectG.getDObject!(ObjectG)(sourceObject), wrapper.outer); 237 } 238 239 extern(C) static void callBackIncomingDestroy(OnIncomingDelegateWrapper wrapper, GClosure* closure) 240 { 241 wrapper.outer.internalRemoveOnIncoming(wrapper); 242 } 243 244 protected void internalRemoveOnIncoming(OnIncomingDelegateWrapper source) 245 { 246 foreach(index, wrapper; onIncomingListeners) 247 { 248 if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId) 249 { 250 onIncomingListeners[index] = null; 251 onIncomingListeners = std.algorithm.remove(onIncomingListeners, index); 252 break; 253 } 254 } 255 } 256 257 }