add blend mode tests
[swfdec.git] / swfdec / swfdec_xml_socket.c
blobf637563b64a5971583f0371961aeeaa0aa62da6a
1 /* Swfdec
2 * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <string.h>
26 #include "swfdec_xml_socket.h"
27 #include "swfdec_as_internal.h"
28 #include "swfdec_as_strings.h"
29 #include "swfdec_buffer.h"
30 #include "swfdec_debug.h"
31 #include "swfdec_loader_internal.h"
32 #include "swfdec_movie.h"
33 #include "swfdec_player_internal.h"
35 static void
36 swfdec_xml_socket_ensure_closed (SwfdecXmlSocket *xml)
38 SwfdecPlayer *player = SWFDEC_PLAYER (swfdec_gc_object_get_context (xml));
40 if (xml->socket == NULL)
41 return;
43 swfdec_buffer_queue_clear (xml->send_queue);
44 swfdec_stream_set_target (SWFDEC_STREAM (xml->socket), NULL);
45 g_object_unref (xml->socket);
46 xml->socket = NULL;
47 player->priv->xml_sockets = g_slist_remove (player->priv->xml_sockets, xml);
50 /*** SWFDEC_STREAM_TARGET ***/
52 static SwfdecPlayer *
53 swfdec_xml_socket_stream_target_get_player (SwfdecStreamTarget *target)
55 return SWFDEC_PLAYER (swfdec_gc_object_get_context (target));
58 static void
59 swfdec_xml_socket_stream_target_open (SwfdecStreamTarget *target,
60 SwfdecStream *stream)
62 SwfdecXmlSocket *xml = SWFDEC_XML_SOCKET (target);
63 SwfdecAsValue value;
65 xml->open = TRUE;
66 SWFDEC_AS_VALUE_SET_BOOLEAN (&value, TRUE);
67 swfdec_sandbox_use (xml->sandbox);
68 swfdec_as_object_call (xml->target, SWFDEC_AS_STR_onConnect, 1, &value, NULL);
69 swfdec_sandbox_unuse (xml->sandbox);
72 static void
73 swfdec_xml_socket_stream_target_error (SwfdecStreamTarget *target,
74 SwfdecStream *stream)
76 SwfdecXmlSocket *xml = SWFDEC_XML_SOCKET (target);
78 swfdec_sandbox_use (xml->sandbox);
79 if (xml->open) {
80 SWFDEC_FIXME ("is onClose emitted on error?");
81 swfdec_as_object_call (xml->target, SWFDEC_AS_STR_onClose, 0, NULL, NULL);
82 } else {
83 SwfdecAsValue value;
85 SWFDEC_AS_VALUE_SET_BOOLEAN (&value, FALSE);
86 swfdec_as_object_call (xml->target, SWFDEC_AS_STR_onConnect, 1, &value, NULL);
88 swfdec_sandbox_unuse (xml->sandbox);
90 swfdec_xml_socket_ensure_closed (xml);
93 static gboolean
94 swfdec_xml_socket_stream_target_parse (SwfdecStreamTarget *target,
95 SwfdecStream *stream)
97 SwfdecXmlSocket *xml = SWFDEC_XML_SOCKET (target);
98 SwfdecBufferQueue *queue;
99 SwfdecBuffer *buffer;
100 gsize len;
102 /* parse until next 0 byte or take everything */
103 queue = swfdec_stream_get_queue (stream);
104 while ((buffer = swfdec_buffer_queue_peek_buffer (queue))) {
105 guchar *nul = memchr (buffer->data, 0, buffer->length);
107 len = nul ? (gsize) (nul - buffer->data + 1) : buffer->length;
108 g_assert (len > 0);
109 swfdec_buffer_unref (buffer);
110 buffer = swfdec_buffer_queue_pull (queue, len);
111 swfdec_buffer_queue_push (xml->queue, buffer);
112 if (nul) {
113 len = swfdec_buffer_queue_get_depth (xml->queue);
114 g_assert (len > 0);
115 buffer = swfdec_buffer_queue_pull (xml->queue, len);
116 if (!g_utf8_validate ((char *) buffer->data, len, NULL)) {
117 SWFDEC_FIXME ("invalid utf8 sent through socket, what now?");
118 } else {
119 SwfdecAsValue val;
121 SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_get_string (
122 swfdec_gc_object_get_context (xml), (char *) buffer->data));
123 swfdec_sandbox_use (xml->sandbox);
124 swfdec_as_object_call (xml->target, SWFDEC_AS_STR_onData, 1, &val, NULL);
125 swfdec_sandbox_unuse (xml->sandbox);
129 return FALSE;
132 static void
133 swfdec_xml_socket_stream_target_close (SwfdecStreamTarget *target,
134 SwfdecStream *stream)
136 SwfdecXmlSocket *xml = SWFDEC_XML_SOCKET (target);
138 if (swfdec_buffer_queue_get_depth (xml->queue)) {
139 SWFDEC_FIXME ("data left in socket, what now?");
142 swfdec_sandbox_use (xml->sandbox);
143 swfdec_as_object_call (xml->target, SWFDEC_AS_STR_onClose, 0, NULL, NULL);
144 swfdec_sandbox_unuse (xml->sandbox);
146 swfdec_xml_socket_ensure_closed (xml);
149 static void
150 swfdec_xml_socket_do_write (SwfdecXmlSocket *xml)
152 SwfdecBuffer *buffer;
153 gsize written, length;
155 do {
156 buffer = swfdec_buffer_queue_peek_buffer (xml->send_queue);
157 if (buffer == NULL)
158 break;
159 length = buffer->length;
160 written = swfdec_socket_send (xml->socket, buffer);
161 swfdec_buffer_unref (buffer);
162 swfdec_buffer_queue_flush (xml->send_queue, written);
163 } while (written == length);
166 static void
167 swfdec_xml_socket_stream_target_writable (SwfdecStreamTarget *target,
168 SwfdecStream *stream)
170 swfdec_xml_socket_do_write (SWFDEC_XML_SOCKET (target));
173 static void
174 swfdec_xml_socket_stream_target_init (SwfdecStreamTargetInterface *iface)
176 iface->get_player = swfdec_xml_socket_stream_target_get_player;
177 iface->open = swfdec_xml_socket_stream_target_open;
178 iface->parse = swfdec_xml_socket_stream_target_parse;
179 iface->close = swfdec_xml_socket_stream_target_close;
180 iface->error = swfdec_xml_socket_stream_target_error;
181 iface->writable = swfdec_xml_socket_stream_target_writable;
184 /*** SWFDEC_XML_SOCKET ***/
186 G_DEFINE_TYPE_WITH_CODE (SwfdecXmlSocket, swfdec_xml_socket, SWFDEC_TYPE_GC_OBJECT,
187 G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_STREAM_TARGET, swfdec_xml_socket_stream_target_init))
189 static void
190 swfdec_xml_socket_mark (SwfdecGcObject *object)
192 SwfdecXmlSocket *sock = SWFDEC_XML_SOCKET (object);
194 swfdec_as_object_mark (sock->target);
195 swfdec_gc_object_mark (sock->sandbox);
197 SWFDEC_GC_OBJECT_CLASS (swfdec_xml_socket_parent_class)->mark (object);
200 static void
201 swfdec_xml_socket_dispose (GObject *object)
203 SwfdecXmlSocket *xml = SWFDEC_XML_SOCKET (object);
205 swfdec_xml_socket_ensure_closed (xml);
206 if (xml->queue) {
207 swfdec_buffer_queue_unref (xml->queue);
208 xml->queue = NULL;
210 if (xml->send_queue) {
211 swfdec_buffer_queue_unref (xml->send_queue);
212 xml->send_queue = NULL;
215 G_OBJECT_CLASS (swfdec_xml_socket_parent_class)->dispose (object);
218 static void
219 swfdec_xml_socket_class_init (SwfdecXmlSocketClass *klass)
221 GObjectClass *object_class = G_OBJECT_CLASS (klass);
222 SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
224 object_class->dispose = swfdec_xml_socket_dispose;
226 gc_class->mark = swfdec_xml_socket_mark;
229 static void
230 swfdec_xml_socket_init (SwfdecXmlSocket *xml)
232 xml->queue = swfdec_buffer_queue_new ();
233 xml->send_queue = swfdec_buffer_queue_new ();
236 static SwfdecXmlSocket *
237 swfdec_xml_socket_create (SwfdecAsObject *target, SwfdecSandbox *sandbox, const char *hostname, guint port)
239 SwfdecPlayer *player = SWFDEC_PLAYER (target->context);
240 SwfdecXmlSocket *xml;
241 SwfdecSocket *sock;
243 SWFDEC_FIXME ("implement security checks please");
244 sock = swfdec_player_create_socket (player, hostname, port);
245 if (sock == NULL)
246 return NULL;
248 xml = g_object_new (SWFDEC_TYPE_XML_SOCKET, "context", player, NULL);
249 /* we prepend here, so send etc find the newest socket */
250 player->priv->xml_sockets = g_slist_prepend (player->priv->xml_sockets, xml);
252 xml->target = target;
253 xml->socket = sock;
254 xml->sandbox = sandbox;
255 swfdec_stream_set_target (SWFDEC_STREAM (sock), SWFDEC_STREAM_TARGET (xml));
257 return xml;
260 /*** AS CODE ***/
262 static SwfdecXmlSocket *
263 swfdec_xml_socket_get (SwfdecAsObject *object)
265 SwfdecXmlSocket *xml;
266 SwfdecPlayer *player;
267 GSList *walk;
269 if (object == NULL) {
270 SWFDEC_WARNING ("no object to get xml socket from");
271 return NULL;
274 player = SWFDEC_PLAYER (object->context);
275 for (walk = player->priv->xml_sockets; walk; walk = walk->next) {
276 xml = walk->data;
278 if (xml->target == object) {
279 if (xml->socket == NULL) {
280 SWFDEC_WARNING ("xml socket not open");
281 return NULL;
283 return xml;
287 SWFDEC_WARNING ("no xml socket on object");
288 return NULL;
292 SWFDEC_AS_NATIVE (400, 0, swfdec_xml_socket_connect)
293 void
294 swfdec_xml_socket_connect (SwfdecAsContext *cx, SwfdecAsObject *object,
295 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
297 const char *host;
298 int port;
300 SWFDEC_AS_CHECK (0, NULL, "si", &host, &port);
302 if (object == NULL || object->movie)
303 return;
305 swfdec_xml_socket_create (object, swfdec_sandbox_get (SWFDEC_PLAYER (cx)), host, port);
308 SWFDEC_AS_NATIVE (400, 1, swfdec_xml_socket_send)
309 void
310 swfdec_xml_socket_send (SwfdecAsContext *cx, SwfdecAsObject *object,
311 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
313 SwfdecXmlSocket *xml;
314 SwfdecBuffer *buf;
315 const char *send;
316 gsize len;
318 SWFDEC_AS_CHECK (0, NULL, "s", &send);
319 if (argc < 1)
320 return;
322 xml = swfdec_xml_socket_get (object);
323 if (xml == NULL)
324 return;
325 if (!swfdec_stream_is_open (SWFDEC_STREAM (xml->socket))) {
326 SWFDEC_WARNING ("sending data down a closed stream");
327 return;
330 len = strlen (send) + 1;
331 buf = swfdec_buffer_new_for_data (g_memdup (send, len), len);
333 if (swfdec_buffer_queue_get_depth (xml->send_queue) == 0) {
334 swfdec_buffer_queue_push (xml->send_queue, buf);
335 swfdec_xml_socket_do_write (xml);
336 } else {
337 swfdec_buffer_queue_push (xml->send_queue, buf);
341 SWFDEC_AS_NATIVE (400, 2, swfdec_xml_socket_close)
342 void
343 swfdec_xml_socket_close (SwfdecAsContext *cx, SwfdecAsObject *object,
344 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
346 SwfdecXmlSocket *xml;
348 xml = swfdec_xml_socket_get (object);
349 if (xml == NULL)
350 return;
351 swfdec_stream_ensure_closed (SWFDEC_STREAM (xml->socket));