make numbers garbage-collected objects
[swfdec.git] / swfdec / swfdec_xml_socket.c
blob64f7a2eed0342f27cc048f5f54e44c1716bc1022
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 GQuark xml_socket_quark = 0;
37 static void
38 swfdec_xml_socket_ensure_closed (SwfdecXmlSocket *xml)
40 if (xml->socket == NULL)
41 return;
43 swfdec_stream_set_target (SWFDEC_STREAM (xml->socket), NULL);
44 g_object_unref (xml->socket);
45 xml->socket = NULL;
47 swfdec_player_unroot (SWFDEC_PLAYER (swfdec_gc_object_get_context (xml)), xml);
48 if (xml->target_owner) {
49 g_object_steal_qdata (G_OBJECT (xml->target), xml_socket_quark);
50 xml->target_owner = FALSE;
52 xml->target = NULL;
55 /*** SWFDEC_STREAM_TARGET ***/
57 static SwfdecPlayer *
58 swfdec_xml_socket_stream_target_get_player (SwfdecStreamTarget *target)
60 return SWFDEC_PLAYER (swfdec_gc_object_get_context (target));
63 static void
64 swfdec_xml_socket_stream_target_open (SwfdecStreamTarget *target,
65 SwfdecStream *stream)
67 SwfdecXmlSocket *xml = SWFDEC_XML_SOCKET (target);
68 SwfdecAsValue value;
70 xml->open = TRUE;
71 SWFDEC_AS_VALUE_SET_BOOLEAN (&value, TRUE);
72 swfdec_sandbox_use (xml->sandbox);
73 swfdec_as_object_call (xml->target, SWFDEC_AS_STR_onConnect, 1, &value, NULL);
74 swfdec_sandbox_unuse (xml->sandbox);
77 static void
78 swfdec_xml_socket_stream_target_error (SwfdecStreamTarget *target,
79 SwfdecStream *stream)
81 SwfdecXmlSocket *xml = SWFDEC_XML_SOCKET (target);
83 swfdec_sandbox_use (xml->sandbox);
84 if (xml->open) {
85 SWFDEC_FIXME ("is onClose emitted on error?");
86 swfdec_as_object_call (xml->target, SWFDEC_AS_STR_onClose, 0, NULL, NULL);
87 } else {
88 SwfdecAsValue value;
90 SWFDEC_AS_VALUE_SET_BOOLEAN (&value, FALSE);
91 swfdec_as_object_call (xml->target, SWFDEC_AS_STR_onConnect, 1, &value, NULL);
93 swfdec_sandbox_unuse (xml->sandbox);
95 swfdec_xml_socket_ensure_closed (xml);
98 static gboolean
99 swfdec_xml_socket_stream_target_parse (SwfdecStreamTarget *target,
100 SwfdecStream *stream)
102 SwfdecXmlSocket *xml = SWFDEC_XML_SOCKET (target);
103 SwfdecBufferQueue *queue;
104 SwfdecBuffer *buffer;
105 gsize len;
107 /* parse until next 0 byte or take everything */
108 queue = swfdec_stream_get_queue (stream);
109 while ((buffer = swfdec_buffer_queue_peek_buffer (queue))) {
110 guchar *nul = memchr (buffer->data, 0, buffer->length);
112 len = nul ? (gsize) (nul - buffer->data + 1) : buffer->length;
113 g_assert (len > 0);
114 swfdec_buffer_unref (buffer);
115 buffer = swfdec_buffer_queue_pull (queue, len);
116 swfdec_buffer_queue_push (xml->queue, buffer);
117 if (nul) {
118 len = swfdec_buffer_queue_get_depth (xml->queue);
119 g_assert (len > 0);
120 buffer = swfdec_buffer_queue_pull (xml->queue, len);
121 if (!g_utf8_validate ((char *) buffer->data, len, NULL)) {
122 SWFDEC_FIXME ("invalid utf8 sent through socket, what now?");
123 } else {
124 SwfdecAsValue val;
126 SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_get_string (
127 swfdec_gc_object_get_context (xml), (char *) buffer->data));
128 swfdec_sandbox_use (xml->sandbox);
129 swfdec_as_object_call (xml->target, SWFDEC_AS_STR_onData, 1, &val, NULL);
130 swfdec_sandbox_unuse (xml->sandbox);
134 return FALSE;
137 static void
138 swfdec_xml_socket_stream_target_close (SwfdecStreamTarget *target,
139 SwfdecStream *stream)
141 SwfdecXmlSocket *xml = SWFDEC_XML_SOCKET (target);
143 if (swfdec_buffer_queue_get_depth (xml->queue)) {
144 SWFDEC_FIXME ("data left in socket, what now?");
147 swfdec_sandbox_use (xml->sandbox);
148 swfdec_as_object_call (xml->target, SWFDEC_AS_STR_onClose, 0, NULL, NULL);
149 swfdec_sandbox_unuse (xml->sandbox);
151 swfdec_xml_socket_ensure_closed (xml);
154 static void
155 swfdec_xml_socket_stream_target_init (SwfdecStreamTargetInterface *iface)
157 iface->get_player = swfdec_xml_socket_stream_target_get_player;
158 iface->open = swfdec_xml_socket_stream_target_open;
159 iface->parse = swfdec_xml_socket_stream_target_parse;
160 iface->close = swfdec_xml_socket_stream_target_close;
161 iface->error = swfdec_xml_socket_stream_target_error;
164 /*** SWFDEC_XML_SOCKET ***/
166 G_DEFINE_TYPE_WITH_CODE (SwfdecXmlSocket, swfdec_xml_socket, SWFDEC_TYPE_AS_OBJECT,
167 G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_STREAM_TARGET, swfdec_xml_socket_stream_target_init))
169 static void
170 swfdec_xml_socket_mark (SwfdecGcObject *object)
172 SwfdecXmlSocket *sock = SWFDEC_XML_SOCKET (object);
174 swfdec_gc_object_mark (sock->target);
175 swfdec_gc_object_mark (sock->sandbox);
177 SWFDEC_GC_OBJECT_CLASS (swfdec_xml_socket_parent_class)->mark (object);
180 static void
181 swfdec_xml_socket_dispose (GObject *object)
183 SwfdecXmlSocket *xml = SWFDEC_XML_SOCKET (object);
185 swfdec_xml_socket_ensure_closed (xml);
186 if (xml->queue) {
187 swfdec_buffer_queue_unref (xml->queue);
188 xml->queue = NULL;
191 G_OBJECT_CLASS (swfdec_xml_socket_parent_class)->dispose (object);
194 static void
195 swfdec_xml_socket_class_init (SwfdecXmlSocketClass *klass)
197 GObjectClass *object_class = G_OBJECT_CLASS (klass);
198 SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
200 object_class->dispose = swfdec_xml_socket_dispose;
202 gc_class->mark = swfdec_xml_socket_mark;
205 static void
206 swfdec_xml_socket_init (SwfdecXmlSocket *xml)
208 xml->queue = swfdec_buffer_queue_new ();
211 static void
212 swfdec_xml_socket_target_gone (gpointer xmlp)
214 SwfdecXmlSocket *xml = xmlp;
216 xml->target_owner = FALSE;
219 static SwfdecXmlSocket *
220 swfdec_xml_socket_create (SwfdecAsObject *target, SwfdecSandbox *sandbox, const char *hostname, guint port)
222 SwfdecAsContext *cx = swfdec_gc_object_get_context (target);
223 SwfdecXmlSocket *xml;
224 SwfdecSocket *sock;
226 SWFDEC_FIXME ("implement security checks please");
227 sock = swfdec_player_create_socket (SWFDEC_PLAYER (cx), hostname, port);
228 if (sock == NULL)
229 return NULL;
231 xml = g_object_new (SWFDEC_TYPE_XML_SOCKET, "context", cx, NULL);
232 swfdec_player_root (SWFDEC_PLAYER (cx), xml, (GFunc) swfdec_gc_object_mark);
234 if (xml_socket_quark == 0)
235 xml_socket_quark = g_quark_from_static_string ("swfdec-xml-socket");
236 g_object_set_qdata_full (G_OBJECT (target), xml_socket_quark, xml, swfdec_xml_socket_target_gone);
237 xml->target = target;
238 xml->target_owner = TRUE;
239 xml->socket = sock;
240 xml->sandbox = sandbox;
241 swfdec_stream_set_target (SWFDEC_STREAM (sock), SWFDEC_STREAM_TARGET (xml));
243 return xml;
246 /*** AS CODE ***/
248 static SwfdecXmlSocket *
249 swfdec_xml_socket_get (SwfdecAsObject *object)
251 SwfdecXmlSocket *xml;
253 if (object == NULL) {
254 SWFDEC_WARNING ("no object to get xml socket from");
255 return NULL;
257 if (xml_socket_quark == 0) {
258 SWFDEC_WARNING ("no sockets have been created yet");
259 return NULL;
262 xml = g_object_get_qdata (G_OBJECT (object), xml_socket_quark);
263 if (xml == NULL) {
264 SWFDEC_WARNING ("no xml socket on object");
265 return NULL;
267 if (xml->socket == NULL) {
268 SWFDEC_WARNING ("xml socket not open");
269 return NULL;
272 return xml;
276 SWFDEC_AS_NATIVE (400, 0, swfdec_xml_socket_connect)
277 void
278 swfdec_xml_socket_connect (SwfdecAsContext *cx, SwfdecAsObject *object,
279 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
281 const char *host;
282 int port;
284 SWFDEC_AS_CHECK (0, NULL, "si", &host, &port);
286 if (SWFDEC_IS_MOVIE (object) || object == NULL)
287 return;
289 swfdec_xml_socket_create (object, SWFDEC_SANDBOX (cx->global), host, port);
292 SWFDEC_AS_NATIVE (400, 1, swfdec_xml_socket_send)
293 void
294 swfdec_xml_socket_send (SwfdecAsContext *cx, SwfdecAsObject *object,
295 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
297 SwfdecXmlSocket *xml;
298 SwfdecBuffer *buf;
299 const char *send;
300 gsize len;
302 if (argc < 1)
303 return;
305 xml = swfdec_xml_socket_get (object);
306 if (xml == NULL)
307 return;
308 if (!swfdec_stream_is_open (SWFDEC_STREAM (xml->socket))) {
309 SWFDEC_WARNING ("sending data down a closed stream");
310 return;
313 send = swfdec_as_value_to_string (cx, &argv[0]);
314 len = strlen (send) + 1;
315 buf = swfdec_buffer_new (len);
316 memcpy (buf->data, send, len);
318 swfdec_socket_send (xml->socket, buf);
321 SWFDEC_AS_NATIVE (400, 2, swfdec_xml_socket_close)
322 void
323 swfdec_xml_socket_close (SwfdecAsContext *cx, SwfdecAsObject *object,
324 guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
326 SwfdecXmlSocket *xml;
328 xml = swfdec_xml_socket_get (object);
329 if (xml == NULL)
330 return;
331 swfdec_stream_ensure_closed (SWFDEC_STREAM (xml->socket));