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.
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
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"
36 swfdec_xml_socket_ensure_closed (SwfdecXmlSocket
*xml
)
38 SwfdecPlayer
*player
= SWFDEC_PLAYER (swfdec_gc_object_get_context (xml
));
40 if (xml
->socket
== NULL
)
43 swfdec_buffer_queue_clear (xml
->send_queue
);
44 swfdec_stream_set_target (SWFDEC_STREAM (xml
->socket
), NULL
);
45 g_object_unref (xml
->socket
);
47 player
->priv
->xml_sockets
= g_slist_remove (player
->priv
->xml_sockets
, xml
);
50 /*** SWFDEC_STREAM_TARGET ***/
53 swfdec_xml_socket_stream_target_get_player (SwfdecStreamTarget
*target
)
55 return SWFDEC_PLAYER (swfdec_gc_object_get_context (target
));
59 swfdec_xml_socket_stream_target_open (SwfdecStreamTarget
*target
,
62 SwfdecXmlSocket
*xml
= SWFDEC_XML_SOCKET (target
);
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
);
73 swfdec_xml_socket_stream_target_error (SwfdecStreamTarget
*target
,
76 SwfdecXmlSocket
*xml
= SWFDEC_XML_SOCKET (target
);
78 swfdec_sandbox_use (xml
->sandbox
);
80 SWFDEC_FIXME ("is onClose emitted on error?");
81 swfdec_as_object_call (xml
->target
, SWFDEC_AS_STR_onClose
, 0, NULL
, NULL
);
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
);
94 swfdec_xml_socket_stream_target_parse (SwfdecStreamTarget
*target
,
97 SwfdecXmlSocket
*xml
= SWFDEC_XML_SOCKET (target
);
98 SwfdecBufferQueue
*queue
;
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
;
109 swfdec_buffer_unref (buffer
);
110 buffer
= swfdec_buffer_queue_pull (queue
, len
);
111 swfdec_buffer_queue_push (xml
->queue
, buffer
);
113 len
= swfdec_buffer_queue_get_depth (xml
->queue
);
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?");
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
);
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
);
150 swfdec_xml_socket_do_write (SwfdecXmlSocket
*xml
)
152 SwfdecBuffer
*buffer
;
153 gsize written
, length
;
156 buffer
= swfdec_buffer_queue_peek_buffer (xml
->send_queue
);
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
);
167 swfdec_xml_socket_stream_target_writable (SwfdecStreamTarget
*target
,
168 SwfdecStream
*stream
)
170 swfdec_xml_socket_do_write (SWFDEC_XML_SOCKET (target
));
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
))
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
);
201 swfdec_xml_socket_dispose (GObject
*object
)
203 SwfdecXmlSocket
*xml
= SWFDEC_XML_SOCKET (object
);
205 swfdec_xml_socket_ensure_closed (xml
);
207 swfdec_buffer_queue_unref (xml
->queue
);
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
);
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
;
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
;
243 SWFDEC_FIXME ("implement security checks please");
244 sock
= swfdec_player_create_socket (player
, hostname
, port
);
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
;
254 xml
->sandbox
= sandbox
;
255 swfdec_stream_set_target (SWFDEC_STREAM (sock
), SWFDEC_STREAM_TARGET (xml
));
262 static SwfdecXmlSocket
*
263 swfdec_xml_socket_get (SwfdecAsObject
*object
)
265 SwfdecXmlSocket
*xml
;
266 SwfdecPlayer
*player
;
269 if (object
== NULL
) {
270 SWFDEC_WARNING ("no object to get xml socket from");
274 player
= SWFDEC_PLAYER (object
->context
);
275 for (walk
= player
->priv
->xml_sockets
; walk
; walk
= walk
->next
) {
278 if (xml
->target
== object
) {
279 if (xml
->socket
== NULL
) {
280 SWFDEC_WARNING ("xml socket not open");
287 SWFDEC_WARNING ("no xml socket on object");
292 SWFDEC_AS_NATIVE (400, 0, swfdec_xml_socket_connect
)
294 swfdec_xml_socket_connect (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
295 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
300 SWFDEC_AS_CHECK (0, NULL
, "si", &host
, &port
);
302 if (object
== NULL
|| object
->movie
)
305 swfdec_xml_socket_create (object
, swfdec_sandbox_get (SWFDEC_PLAYER (cx
)), host
, port
);
308 SWFDEC_AS_NATIVE (400, 1, swfdec_xml_socket_send
)
310 swfdec_xml_socket_send (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
311 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
313 SwfdecXmlSocket
*xml
;
318 SWFDEC_AS_CHECK (0, NULL
, "s", &send
);
322 xml
= swfdec_xml_socket_get (object
);
325 if (!swfdec_stream_is_open (SWFDEC_STREAM (xml
->socket
))) {
326 SWFDEC_WARNING ("sending data down a closed stream");
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
);
337 swfdec_buffer_queue_push (xml
->send_queue
, buf
);
341 SWFDEC_AS_NATIVE (400, 2, swfdec_xml_socket_close
)
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
);
351 swfdec_stream_ensure_closed (SWFDEC_STREAM (xml
->socket
));