1 module soup.WebsocketConnection;
2 
3 private import gio.IOStream;
4 private import glib.Bytes;
5 private import glib.ConstructionException;
6 private import glib.ErrorG;
7 private import glib.ListG;
8 private import glib.Str;
9 private import gobject.ObjectG;
10 private import gobject.Signals;
11 private import soup.URI;
12 private import soup.WebsocketExtension;
13 private import soup.c.functions;
14 public  import soup.c.types;
15 private import std.algorithm;
16 
17 
18 /**
19  * A class representing a WebSocket connection.
20  *
21  * Since: 2.50
22  */
23 public class WebsocketConnection : ObjectG
24 {
25 	/** the main Gtk struct */
26 	protected SoupWebsocketConnection* soupWebsocketConnection;
27 
28 	/** Get the main Gtk struct */
29 	public SoupWebsocketConnection* getWebsocketConnectionStruct(bool transferOwnership = false)
30 	{
31 		if (transferOwnership)
32 			ownedRef = false;
33 		return soupWebsocketConnection;
34 	}
35 
36 	/** the main Gtk struct as a void* */
37 	protected override void* getStruct()
38 	{
39 		return cast(void*)soupWebsocketConnection;
40 	}
41 
42 	/**
43 	 * Sets our main struct and passes it to the parent class.
44 	 */
45 	public this (SoupWebsocketConnection* soupWebsocketConnection, bool ownedRef = false)
46 	{
47 		this.soupWebsocketConnection = soupWebsocketConnection;
48 		super(cast(GObject*)soupWebsocketConnection, ownedRef);
49 	}
50 
51 
52 	/** */
53 	public static GType getType()
54 	{
55 		return soup_websocket_connection_get_type();
56 	}
57 
58 	/**
59 	 * Creates a #SoupWebsocketConnection on @stream. This should be
60 	 * called after completing the handshake to begin using the WebSocket
61 	 * protocol.
62 	 *
63 	 * Params:
64 	 *     stream = a #GIOStream connected to the WebSocket server
65 	 *     uri = the URI of the connection
66 	 *     type = the type of connection (client/side)
67 	 *     origin = the Origin of the client
68 	 *     protocol = the subprotocol in use
69 	 *
70 	 * Returns: a new #SoupWebsocketConnection
71 	 *
72 	 * Since: 2.50
73 	 *
74 	 * Throws: ConstructionException GTK+ fails to create the object.
75 	 */
76 	public this(IOStream stream, URI uri, SoupWebsocketConnectionType type, string origin, string protocol)
77 	{
78 		auto __p = soup_websocket_connection_new((stream is null) ? null : stream.getIOStreamStruct(), (uri is null) ? null : uri.getURIStruct(), type, Str.toStringz(origin), Str.toStringz(protocol));
79 
80 		if(__p is null)
81 		{
82 			throw new ConstructionException("null returned by new");
83 		}
84 
85 		this(cast(SoupWebsocketConnection*) __p, true);
86 	}
87 
88 	/**
89 	 * Creates a #SoupWebsocketConnection on @stream with the given active @extensions.
90 	 * This should be called after completing the handshake to begin using the WebSocket
91 	 * protocol.
92 	 *
93 	 * Params:
94 	 *     stream = a #GIOStream connected to the WebSocket server
95 	 *     uri = the URI of the connection
96 	 *     type = the type of connection (client/side)
97 	 *     origin = the Origin of the client
98 	 *     protocol = the subprotocol in use
99 	 *     extensions = a #GList of #SoupWebsocketExtension objects
100 	 *
101 	 * Returns: a new #SoupWebsocketConnection
102 	 *
103 	 * Since: 2.68
104 	 *
105 	 * Throws: ConstructionException GTK+ fails to create the object.
106 	 */
107 	public this(IOStream stream, URI uri, SoupWebsocketConnectionType type, string origin, string protocol, ListG extensions)
108 	{
109 		auto __p = soup_websocket_connection_new_with_extensions((stream is null) ? null : stream.getIOStreamStruct(), (uri is null) ? null : uri.getURIStruct(), type, Str.toStringz(origin), Str.toStringz(protocol), (extensions is null) ? null : extensions.getListGStruct());
110 
111 		if(__p is null)
112 		{
113 			throw new ConstructionException("null returned by new_with_extensions");
114 		}
115 
116 		this(cast(SoupWebsocketConnection*) __p, true);
117 	}
118 
119 	/**
120 	 * Close the connection in an orderly fashion.
121 	 *
122 	 * Note that until the #SoupWebsocketConnection::closed signal fires, the connection
123 	 * is not yet completely closed. The close message is not even sent until the
124 	 * main loop runs.
125 	 *
126 	 * The @code and @data are sent to the peer along with the close request.
127 	 * If @code is %SOUP_WEBSOCKET_CLOSE_NO_STATUS a close message with no body
128 	 * (without code and data) is sent.
129 	 * Note that the @data must be UTF-8 valid.
130 	 *
131 	 * Params:
132 	 *     code = close code
133 	 *     data = close data
134 	 *
135 	 * Since: 2.50
136 	 */
137 	public void close(ushort code, string data)
138 	{
139 		soup_websocket_connection_close(soupWebsocketConnection, code, Str.toStringz(data));
140 	}
141 
142 	/**
143 	 * Get the close code received from the WebSocket peer.
144 	 *
145 	 * This only becomes valid once the WebSocket is in the
146 	 * %SOUP_WEBSOCKET_STATE_CLOSED state. The value will often be in the
147 	 * #SoupWebsocketCloseCode enumeration, but may also be an application
148 	 * defined close code.
149 	 *
150 	 * Returns: the close code or zero.
151 	 *
152 	 * Since: 2.50
153 	 */
154 	public ushort getCloseCode()
155 	{
156 		return soup_websocket_connection_get_close_code(soupWebsocketConnection);
157 	}
158 
159 	/**
160 	 * Get the close data received from the WebSocket peer.
161 	 *
162 	 * This only becomes valid once the WebSocket is in the
163 	 * %SOUP_WEBSOCKET_STATE_CLOSED state. The data may be freed once
164 	 * the main loop is run, so copy it if you need to keep it around.
165 	 *
166 	 * Returns: the close data or %NULL
167 	 *
168 	 * Since: 2.50
169 	 */
170 	public string getCloseData()
171 	{
172 		return Str.toString(soup_websocket_connection_get_close_data(soupWebsocketConnection));
173 	}
174 
175 	/**
176 	 * Get the connection type (client/server) of the connection.
177 	 *
178 	 * Returns: the connection type
179 	 *
180 	 * Since: 2.50
181 	 */
182 	public SoupWebsocketConnectionType getConnectionType()
183 	{
184 		return soup_websocket_connection_get_connection_type(soupWebsocketConnection);
185 	}
186 
187 	/**
188 	 * Get the extensions chosen via negotiation with the peer.
189 	 *
190 	 * Returns: a #GList of #SoupWebsocketExtension objects
191 	 *
192 	 * Since: 2.68
193 	 */
194 	public ListG getExtensions()
195 	{
196 		auto __p = soup_websocket_connection_get_extensions(soupWebsocketConnection);
197 
198 		if(__p is null)
199 		{
200 			return null;
201 		}
202 
203 		return new ListG(cast(GList*) __p);
204 	}
205 
206 	/**
207 	 * Get the I/O stream the WebSocket is communicating over.
208 	 *
209 	 * Returns: the WebSocket's I/O stream.
210 	 *
211 	 * Since: 2.50
212 	 */
213 	public IOStream getIoStream()
214 	{
215 		auto __p = soup_websocket_connection_get_io_stream(soupWebsocketConnection);
216 
217 		if(__p is null)
218 		{
219 			return null;
220 		}
221 
222 		return ObjectG.getDObject!(IOStream)(cast(GIOStream*) __p);
223 	}
224 
225 	/**
226 	 * Gets the keepalive interval in seconds or 0 if disabled.
227 	 *
228 	 * Returns: the keepalive interval.
229 	 *
230 	 * Since: 2.58
231 	 */
232 	public uint getKeepaliveInterval()
233 	{
234 		return soup_websocket_connection_get_keepalive_interval(soupWebsocketConnection);
235 	}
236 
237 	/**
238 	 * Gets the maximum payload size allowed for incoming packets.
239 	 *
240 	 * Returns: the maximum payload size.
241 	 *
242 	 * Since: 2.56
243 	 */
244 	public ulong getMaxIncomingPayloadSize()
245 	{
246 		return soup_websocket_connection_get_max_incoming_payload_size(soupWebsocketConnection);
247 	}
248 
249 	/**
250 	 * Get the origin of the WebSocket.
251 	 *
252 	 * Returns: the origin, or %NULL
253 	 *
254 	 * Since: 2.50
255 	 */
256 	public string getOrigin()
257 	{
258 		return Str.toString(soup_websocket_connection_get_origin(soupWebsocketConnection));
259 	}
260 
261 	/**
262 	 * Get the protocol chosen via negotiation with the peer.
263 	 *
264 	 * Returns: the chosen protocol, or %NULL
265 	 *
266 	 * Since: 2.50
267 	 */
268 	public string getProtocol()
269 	{
270 		return Str.toString(soup_websocket_connection_get_protocol(soupWebsocketConnection));
271 	}
272 
273 	/**
274 	 * Get the current state of the WebSocket.
275 	 *
276 	 * Returns: the state
277 	 *
278 	 * Since: 2.50
279 	 */
280 	public SoupWebsocketState getState()
281 	{
282 		return soup_websocket_connection_get_state(soupWebsocketConnection);
283 	}
284 
285 	/**
286 	 * Get the URI of the WebSocket.
287 	 *
288 	 * For servers this represents the address of the WebSocket, and
289 	 * for clients it is the address connected to.
290 	 *
291 	 * Returns: the URI
292 	 *
293 	 * Since: 2.50
294 	 */
295 	public URI getUri()
296 	{
297 		auto __p = soup_websocket_connection_get_uri(soupWebsocketConnection);
298 
299 		if(__p is null)
300 		{
301 			return null;
302 		}
303 
304 		return ObjectG.getDObject!(URI)(cast(SoupURI*) __p);
305 	}
306 
307 	/**
308 	 * Send a binary message to the peer. If @length is 0, @data may be %NULL.
309 	 *
310 	 * The message is queued to be sent and will be sent when the main loop
311 	 * is run.
312 	 *
313 	 * Params:
314 	 *     data = the message contents
315 	 *
316 	 * Since: 2.50
317 	 */
318 	public void sendBinary(ubyte[] data)
319 	{
320 		soup_websocket_connection_send_binary(soupWebsocketConnection, data.ptr, cast(size_t)data.length);
321 	}
322 
323 	/**
324 	 * Send a message of the given @type to the peer. Note that this method,
325 	 * allows to send text messages containing %NULL characters.
326 	 *
327 	 * The message is queued to be sent and will be sent when the main loop
328 	 * is run.
329 	 *
330 	 * Params:
331 	 *     type = the type of message contents
332 	 *     message = the message data as #GBytes
333 	 *
334 	 * Since: 2.68
335 	 */
336 	public void sendMessage(SoupWebsocketDataType type, Bytes message)
337 	{
338 		soup_websocket_connection_send_message(soupWebsocketConnection, type, (message is null) ? null : message.getBytesStruct());
339 	}
340 
341 	/**
342 	 * Send a %NULL-terminated text (UTF-8) message to the peer. If you need
343 	 * to send text messages containing %NULL characters use
344 	 * soup_websocket_connection_send_message() instead.
345 	 *
346 	 * The message is queued to be sent and will be sent when the main loop
347 	 * is run.
348 	 *
349 	 * Params:
350 	 *     text = the message contents
351 	 *
352 	 * Since: 2.50
353 	 */
354 	public void sendText(string text)
355 	{
356 		soup_websocket_connection_send_text(soupWebsocketConnection, Str.toStringz(text));
357 	}
358 
359 	/**
360 	 * Sets the interval in seconds on when to send a ping message which will serve
361 	 * as a keepalive message. If set to 0 the keepalive message is disabled.
362 	 *
363 	 * Params:
364 	 *     interval = the interval to send a ping message or 0 to disable it
365 	 *
366 	 * Since: 2.58
367 	 */
368 	public void setKeepaliveInterval(uint interval)
369 	{
370 		soup_websocket_connection_set_keepalive_interval(soupWebsocketConnection, interval);
371 	}
372 
373 	/**
374 	 * Sets the maximum payload size allowed for incoming packets. It
375 	 * does not limit the outgoing packet size.
376 	 *
377 	 * Params:
378 	 *     maxIncomingPayloadSize = the maximum payload size
379 	 *
380 	 * Since: 2.56
381 	 */
382 	public void setMaxIncomingPayloadSize(ulong maxIncomingPayloadSize)
383 	{
384 		soup_websocket_connection_set_max_incoming_payload_size(soupWebsocketConnection, maxIncomingPayloadSize);
385 	}
386 
387 	/**
388 	 * Emitted when the connection has completely closed, either
389 	 * due to an orderly close from the peer, one initiated via
390 	 * soup_websocket_connection_close() or a fatal error
391 	 * condition that caused a close.
392 	 *
393 	 * This signal will be emitted once.
394 	 *
395 	 * Since: 2.50
396 	 */
397 	gulong addOnClosed(void delegate(WebsocketConnection) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
398 	{
399 		return Signals.connect(this, "closed", dlg, connectFlags ^ ConnectFlags.SWAPPED);
400 	}
401 
402 	/**
403 	 * This signal will be emitted during an orderly close.
404 	 *
405 	 * Since: 2.50
406 	 */
407 	gulong addOnClosing(void delegate(WebsocketConnection) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
408 	{
409 		return Signals.connect(this, "closing", dlg, connectFlags ^ ConnectFlags.SWAPPED);
410 	}
411 
412 	/**
413 	 * Emitted when an error occurred on the WebSocket. This may
414 	 * be fired multiple times. Fatal errors will be followed by
415 	 * the #SoupWebsocketConnection::closed signal being emitted.
416 	 *
417 	 * Params:
418 	 *     error = the error that occured
419 	 *
420 	 * Since: 2.50
421 	 */
422 	gulong addOnError(void delegate(ErrorG, WebsocketConnection) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
423 	{
424 		return Signals.connect(this, "error", dlg, connectFlags ^ ConnectFlags.SWAPPED);
425 	}
426 
427 	/**
428 	 * Emitted when we receive a message from the peer.
429 	 *
430 	 * As a convenience, the @message data will always be
431 	 * NUL-terminated, but the NUL byte will not be included in
432 	 * the length count.
433 	 *
434 	 * Params:
435 	 *     type = the type of message contents
436 	 *     message = the message data
437 	 *
438 	 * Since: 2.50
439 	 */
440 	gulong addOnMessage(void delegate(int, Bytes, WebsocketConnection) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
441 	{
442 		return Signals.connect(this, "message", dlg, connectFlags ^ ConnectFlags.SWAPPED);
443 	}
444 
445 	/**
446 	 * Emitted when we receive a Pong frame (solicited or
447 	 * unsolicited) from the peer.
448 	 *
449 	 * As a convenience, the @message data will always be
450 	 * NUL-terminated, but the NUL byte will not be included in
451 	 * the length count.
452 	 *
453 	 * Params:
454 	 *     message = the application data (if any)
455 	 *
456 	 * Since: 2.60
457 	 */
458 	gulong addOnPong(void delegate(Bytes, WebsocketConnection) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
459 	{
460 		return Signals.connect(this, "pong", dlg, connectFlags ^ ConnectFlags.SWAPPED);
461 	}
462 }