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"
35 static GQuark xml_socket_quark
= 0;
38 swfdec_xml_socket_ensure_closed (SwfdecXmlSocket
*xml
)
40 if (xml
->socket
== NULL
)
43 swfdec_stream_set_target (SWFDEC_STREAM (xml
->socket
), NULL
);
44 g_object_unref (xml
->socket
);
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
;
55 /*** SWFDEC_STREAM_TARGET ***/
58 swfdec_xml_socket_stream_target_get_player (SwfdecStreamTarget
*target
)
60 return SWFDEC_PLAYER (swfdec_gc_object_get_context (target
));
64 swfdec_xml_socket_stream_target_open (SwfdecStreamTarget
*target
,
67 SwfdecXmlSocket
*xml
= SWFDEC_XML_SOCKET (target
);
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
);
78 swfdec_xml_socket_stream_target_error (SwfdecStreamTarget
*target
,
81 SwfdecXmlSocket
*xml
= SWFDEC_XML_SOCKET (target
);
83 swfdec_sandbox_use (xml
->sandbox
);
85 SWFDEC_FIXME ("is onClose emitted on error?");
86 swfdec_as_object_call (xml
->target
, SWFDEC_AS_STR_onClose
, 0, NULL
, NULL
);
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
);
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
;
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
;
114 swfdec_buffer_unref (buffer
);
115 buffer
= swfdec_buffer_queue_pull (queue
, len
);
116 swfdec_buffer_queue_push (xml
->queue
, buffer
);
118 len
= swfdec_buffer_queue_get_depth (xml
->queue
);
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?");
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
);
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
);
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
))
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
);
181 swfdec_xml_socket_dispose (GObject
*object
)
183 SwfdecXmlSocket
*xml
= SWFDEC_XML_SOCKET (object
);
185 swfdec_xml_socket_ensure_closed (xml
);
187 swfdec_buffer_queue_unref (xml
->queue
);
191 G_OBJECT_CLASS (swfdec_xml_socket_parent_class
)->dispose (object
);
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
;
206 swfdec_xml_socket_init (SwfdecXmlSocket
*xml
)
208 xml
->queue
= swfdec_buffer_queue_new ();
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
;
226 SWFDEC_FIXME ("implement security checks please");
227 sock
= swfdec_player_create_socket (SWFDEC_PLAYER (cx
), hostname
, port
);
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
;
240 xml
->sandbox
= sandbox
;
241 swfdec_stream_set_target (SWFDEC_STREAM (sock
), SWFDEC_STREAM_TARGET (xml
));
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");
257 if (xml_socket_quark
== 0) {
258 SWFDEC_WARNING ("no sockets have been created yet");
262 xml
= g_object_get_qdata (G_OBJECT (object
), xml_socket_quark
);
264 SWFDEC_WARNING ("no xml socket on object");
267 if (xml
->socket
== NULL
) {
268 SWFDEC_WARNING ("xml socket not open");
276 SWFDEC_AS_NATIVE (400, 0, swfdec_xml_socket_connect
)
278 swfdec_xml_socket_connect (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
279 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
284 SWFDEC_AS_CHECK (0, NULL
, "si", &host
, &port
);
286 if (SWFDEC_IS_MOVIE (object
) || object
== NULL
)
289 swfdec_xml_socket_create (object
, SWFDEC_SANDBOX (cx
->global
), host
, port
);
292 SWFDEC_AS_NATIVE (400, 1, swfdec_xml_socket_send
)
294 swfdec_xml_socket_send (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
295 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
297 SwfdecXmlSocket
*xml
;
305 xml
= swfdec_xml_socket_get (object
);
308 if (!swfdec_stream_is_open (SWFDEC_STREAM (xml
->socket
))) {
309 SWFDEC_WARNING ("sending data down a closed stream");
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
)
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
);
331 swfdec_stream_ensure_closed (SWFDEC_STREAM (xml
->socket
));