1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2019 Joël Krähemann
3 *
4 * This file is part of GSequencer.
5 *
6 * GSequencer is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * GSequencer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with GSequencer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <ags/audio/osc/xmlrpc/ags_osc_xmlrpc_controller.h>
21
22 #include <ags/audio/osc/ags_osc_xmlrpc_server.h>
23 #include <ags/audio/osc/ags_osc_xmlrpc_message.h>
24 #include <ags/audio/osc/ags_osc_message.h>
25 #include <ags/audio/osc/ags_osc_response.h>
26 #include <ags/audio/osc/ags_osc_util.h>
27 #include <ags/audio/osc/ags_osc_buffer_util.h>
28
29 #include <ags/audio/osc/controller/ags_osc_action_controller.h>
30 #include <ags/audio/osc/controller/ags_osc_config_controller.h>
31 #include <ags/audio/osc/controller/ags_osc_controller.h>
32 #include <ags/audio/osc/controller/ags_osc_info_controller.h>
33 #include <ags/audio/osc/controller/ags_osc_meter_controller.h>
34 #include <ags/audio/osc/controller/ags_osc_node_controller.h>
35 #include <ags/audio/osc/controller/ags_osc_plugin_controller.h>
36 #include <ags/audio/osc/controller/ags_osc_renew_controller.h>
37 #include <ags/audio/osc/controller/ags_osc_status_controller.h>
38
39 #include <string.h>
40
41 #ifdef __APPLE__
42 #include <mach/clock.h>
43 #include <mach/mach.h>
44 #endif
45
46 #include <ags/i18n.h>
47
48 void ags_osc_xmlrpc_controller_class_init(AgsOscXmlrpcControllerClass *osc_xmlrpc_controller);
49 void ags_osc_xmlrpc_controller_plugin_controller_interface_init(AgsPluginControllerInterface *plugin_controller);
50 void ags_osc_xmlrpc_controller_init(AgsOscXmlrpcController *osc_xmlrpc_controller);
51 void ags_osc_xmlrpc_controller_set_property(GObject *gobject,
52 guint prop_id,
53 const GValue *value,
54 GParamSpec *param_spec);
55 void ags_osc_xmlrpc_controller_get_property(GObject *gobject,
56 guint prop_id,
57 GValue *value,
58 GParamSpec *param_spec);
59 void ags_osc_xmlrpc_controller_dispose(GObject *gobject);
60 void ags_osc_xmlrpc_controller_finalize(GObject *gobject);
61
62 gboolean ags_osc_xmlrpc_controller_delegate_timeout(AgsOscXmlrpcController *osc_xmlrpc_controller);
63
64 void ags_osc_xmlrpc_controller_real_start_delegate(AgsOscXmlrpcController *osc_xmlrpc_controller);
65 void ags_osc_xmlrpc_controller_real_stop_delegate(AgsOscXmlrpcController *osc_xmlrpc_controller);
66
67 gsize ags_osc_xmlrpc_controller_read_bundle(AgsOscXmlrpcController *osc_xmlrpc_controller,
68 AgsOscWebsocketConnection *osc_websocket_connection,
69 SoupMessage *msg,
70 GHashTable *query,
71 guchar *packet, gsize packet_size,
72 gsize offset);
73 gsize ags_osc_xmlrpc_controller_read_message(AgsOscXmlrpcController *osc_xmlrpc_controller,
74 AgsOscWebsocketConnection *osc_websocket_connection,
75 SoupMessage *msg,
76 GHashTable *query,
77 guchar *packet, gsize packet_size,
78 gsize offset,
79 gint32 tv_sec, gint32 tv_fraction, gboolean immediately);
80
81 gpointer ags_osc_xmlrpc_controller_do_request(AgsPluginController *plugin_controller,
82 SoupMessage *msg,
83 GHashTable *query,
84 SoupClientContext *client,
85 GObject *security_context,
86 gchar *context_path,
87 gchar *login,
88 gchar *security_token);
89
90 enum{
91 PROP_0,
92 PROP_OSC_XMLRPC_SERVER,
93 };
94
95 enum{
96 START_DELEGATE,
97 STOP_DELEGATE,
98 LAST_SIGNAL,
99 };
100
101 /**
102 * SECTION:ags_osc_xmlrpc_controller
103 * @short_description: handle OSC XMLRPC requests
104 * @title: AgsOscXmlrpcController
105 * @section_id:
106 * @include: ags/audio/osc/controller/ags_osc_xmlrpc_controller.h
107 *
108 * The #AgsOscXmlrpcController is an object to handle XMLRPC requests.
109 */
110
111 static gpointer ags_osc_xmlrpc_controller_parent_class = NULL;
112 static guint osc_xmlrpc_controller_signals[LAST_SIGNAL];
113
114 GType
ags_osc_xmlrpc_controller_get_type()115 ags_osc_xmlrpc_controller_get_type()
116 {
117 static volatile gsize g_define_type_id__volatile = 0;
118
119 if(g_once_init_enter (&g_define_type_id__volatile)){
120 GType ags_type_osc_xmlrpc_controller = 0;
121
122 static const GTypeInfo ags_osc_xmlrpc_controller_info = {
123 sizeof (AgsOscXmlrpcControllerClass),
124 NULL, /* base_init */
125 NULL, /* base_finalize */
126 (GClassInitFunc) ags_osc_xmlrpc_controller_class_init,
127 NULL, /* class_finalize */
128 NULL, /* class_data */
129 sizeof (AgsOscXmlrpcController),
130 0, /* n_preallocs */
131 (GInstanceInitFunc) ags_osc_xmlrpc_controller_init,
132 };
133
134 static const GInterfaceInfo ags_plugin_controller_interface_info = {
135 (GInterfaceInitFunc) ags_osc_xmlrpc_controller_plugin_controller_interface_init,
136 NULL, /* interface_finalize */
137 NULL, /* interface_data */
138 };
139
140 ags_type_osc_xmlrpc_controller = g_type_register_static(AGS_TYPE_CONTROLLER,
141 "AgsOscXmlrpcController",
142 &ags_osc_xmlrpc_controller_info,
143 0);
144
145 g_type_add_interface_static(ags_type_osc_xmlrpc_controller,
146 AGS_TYPE_PLUGIN_CONTROLLER,
147 &ags_plugin_controller_interface_info);
148
149 g_once_init_leave(&g_define_type_id__volatile, ags_type_osc_xmlrpc_controller);
150 }
151
152 return g_define_type_id__volatile;
153 }
154
155 void
ags_osc_xmlrpc_controller_class_init(AgsOscXmlrpcControllerClass * osc_xmlrpc_controller)156 ags_osc_xmlrpc_controller_class_init(AgsOscXmlrpcControllerClass *osc_xmlrpc_controller)
157 {
158 GObjectClass *gobject;
159
160 GParamSpec *param_spec;
161
162 ags_osc_xmlrpc_controller_parent_class = g_type_class_peek_parent(osc_xmlrpc_controller);
163
164 /* GObjectClass */
165 gobject = (GObjectClass *) osc_xmlrpc_controller;
166
167 gobject->set_property = ags_osc_xmlrpc_controller_set_property;
168 gobject->get_property = ags_osc_xmlrpc_controller_get_property;
169
170 gobject->dispose = ags_osc_xmlrpc_controller_dispose;
171 gobject->finalize = ags_osc_xmlrpc_controller_finalize;
172
173 /* properties */
174 /**
175 * AgsOscXmlrpcController:osc-xmlrpc-server:
176 *
177 * The assigned #AgsOscXmlrpcServer
178 *
179 * Since: 3.0.0
180 */
181 param_spec = g_param_spec_object("osc-xmlrpc-server",
182 i18n("assigned OSC XMLRPC server"),
183 i18n("The assigned OSC XMLRPC server"),
184 AGS_TYPE_OSC_XMLRPC_SERVER,
185 G_PARAM_READABLE | G_PARAM_WRITABLE);
186 g_object_class_install_property(gobject,
187 PROP_OSC_XMLRPC_SERVER,
188 param_spec);
189
190 /* AgsOscXmlrpcController */
191 osc_xmlrpc_controller->start_delegate = ags_osc_xmlrpc_controller_real_start_delegate;
192 osc_xmlrpc_controller->stop_delegate = ags_osc_xmlrpc_controller_real_stop_delegate;
193
194 /* signals */
195 /**
196 * AgsOscXmlrpcController::start-delegate:
197 * @osc_xmlrpc_controller: the #AgsOscXmlrpcController
198 *
199 * The ::start-delegate signal is emited during start of delegating messages.
200 *
201 * Since: 3.0.0
202 */
203 osc_xmlrpc_controller_signals[START_DELEGATE] =
204 g_signal_new("start-delegate",
205 G_TYPE_FROM_CLASS(osc_xmlrpc_controller),
206 G_SIGNAL_RUN_LAST,
207 G_STRUCT_OFFSET(AgsOscXmlrpcControllerClass, start_delegate),
208 NULL, NULL,
209 g_cclosure_marshal_VOID__VOID,
210 G_TYPE_NONE, 0);
211
212 /**
213 * AgsOscXmlrpcController::stop-delegate:
214 * @osc_xmlrpc_controller: the #AgsOscXmlrpcController
215 *
216 * The ::stop-delegate signal is emited during stop of delegating messages.
217 *
218 * Since: 3.0.0
219 */
220 osc_xmlrpc_controller_signals[STOP_DELEGATE] =
221 g_signal_new("stop-delegate",
222 G_TYPE_FROM_CLASS(osc_xmlrpc_controller),
223 G_SIGNAL_RUN_LAST,
224 G_STRUCT_OFFSET(AgsOscXmlrpcControllerClass, stop_delegate),
225 NULL, NULL,
226 g_cclosure_marshal_VOID__VOID,
227 G_TYPE_NONE, 0);
228 }
229
230 void
ags_osc_xmlrpc_controller_plugin_controller_interface_init(AgsPluginControllerInterface * plugin_controller)231 ags_osc_xmlrpc_controller_plugin_controller_interface_init(AgsPluginControllerInterface *plugin_controller)
232 {
233 plugin_controller->do_request = ags_osc_xmlrpc_controller_do_request;
234 }
235
236 void
ags_osc_xmlrpc_controller_init(AgsOscXmlrpcController * osc_xmlrpc_controller)237 ags_osc_xmlrpc_controller_init(AgsOscXmlrpcController *osc_xmlrpc_controller)
238 {
239 gchar *context_path;
240
241 context_path = g_strdup_printf("%s/ags-osc-over-xmlrpc",
242 AGS_CONTROLLER_BASE_PATH);
243
244 g_object_set(osc_xmlrpc_controller,
245 "context-path", context_path,
246 NULL);
247
248 g_free(context_path);
249
250 /* OSC XMLRPC server */
251 osc_xmlrpc_controller->flags = 0;
252
253 osc_xmlrpc_controller->osc_xmlrpc_server = NULL;
254
255 g_atomic_int_set(&(osc_xmlrpc_controller->do_reset),
256 FALSE);
257
258 g_mutex_init(&(osc_xmlrpc_controller->delegate_mutex));
259
260 g_cond_init(&(osc_xmlrpc_controller->delegate_cond));
261
262 osc_xmlrpc_controller->message = NULL;
263
264 osc_xmlrpc_controller->queued_response = NULL;
265 }
266
267 void
ags_osc_xmlrpc_controller_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)268 ags_osc_xmlrpc_controller_set_property(GObject *gobject,
269 guint prop_id,
270 const GValue *value,
271 GParamSpec *param_spec)
272 {
273 AgsOscXmlrpcController *osc_xmlrpc_controller;
274
275 GRecMutex *controller_mutex;
276
277 osc_xmlrpc_controller = AGS_OSC_XMLRPC_CONTROLLER(gobject);
278
279 /* get osc controller mutex */
280 controller_mutex = AGS_CONTROLLER_GET_OBJ_MUTEX(osc_xmlrpc_controller);
281
282 switch(prop_id){
283 case PROP_OSC_XMLRPC_SERVER:
284 {
285 AgsOscXmlrpcServer *osc_xmlrpc_server;
286
287 osc_xmlrpc_server = (AgsOscServer *) g_value_get_object(value);
288
289 g_rec_mutex_lock(controller_mutex);
290
291 if(osc_xmlrpc_controller->osc_xmlrpc_server == (GObject *) osc_xmlrpc_server){
292 g_rec_mutex_unlock(controller_mutex);
293
294 return;
295 }
296
297 if(osc_xmlrpc_controller->osc_xmlrpc_server != NULL){
298 g_object_unref(G_OBJECT(osc_xmlrpc_controller->osc_xmlrpc_server));
299 }
300
301 if(osc_xmlrpc_server != NULL){
302 g_object_ref(G_OBJECT(osc_xmlrpc_server));
303 }
304
305 osc_xmlrpc_controller->osc_xmlrpc_server = (GObject *) osc_xmlrpc_server;
306
307 g_rec_mutex_unlock(controller_mutex);
308 }
309 break;
310 default:
311 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
312 break;
313 }
314 }
315
316 void
ags_osc_xmlrpc_controller_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)317 ags_osc_xmlrpc_controller_get_property(GObject *gobject,
318 guint prop_id,
319 GValue *value,
320 GParamSpec *param_spec)
321 {
322 AgsOscXmlrpcController *osc_xmlrpc_controller;
323
324 GRecMutex *controller_mutex;
325
326 osc_xmlrpc_controller = AGS_OSC_XMLRPC_CONTROLLER(gobject);
327
328 /* get osc controller mutex */
329 controller_mutex = AGS_CONTROLLER_GET_OBJ_MUTEX(osc_xmlrpc_controller);
330
331 switch(prop_id){
332 case PROP_OSC_XMLRPC_SERVER:
333 {
334 g_rec_mutex_lock(controller_mutex);
335
336 g_value_set_object(value, osc_xmlrpc_controller->osc_xmlrpc_server);
337
338 g_rec_mutex_unlock(controller_mutex);
339 }
340 break;
341 default:
342 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
343 break;
344 }
345 }
346
347 void
ags_osc_xmlrpc_controller_dispose(GObject * gobject)348 ags_osc_xmlrpc_controller_dispose(GObject *gobject)
349 {
350 AgsOscXmlrpcController *osc_xmlrpc_controller;
351
352 osc_xmlrpc_controller = AGS_OSC_XMLRPC_CONTROLLER(gobject);
353
354 if(osc_xmlrpc_controller->osc_xmlrpc_server != NULL){
355 g_object_unref(osc_xmlrpc_controller->osc_xmlrpc_server);
356
357 osc_xmlrpc_controller->osc_xmlrpc_server = NULL;
358 }
359
360 if(osc_xmlrpc_controller->message != NULL){
361 g_list_free_full(osc_xmlrpc_controller->message,
362 (GDestroyNotify) g_object_unref);
363
364 osc_xmlrpc_controller->message = NULL;
365 }
366
367 /* call parent */
368 G_OBJECT_CLASS(ags_osc_xmlrpc_controller_parent_class)->dispose(gobject);
369 }
370
371 void
ags_osc_xmlrpc_controller_finalize(GObject * gobject)372 ags_osc_xmlrpc_controller_finalize(GObject *gobject)
373 {
374 AgsOscXmlrpcController *osc_xmlrpc_controller;
375
376 osc_xmlrpc_controller = AGS_OSC_XMLRPC_CONTROLLER(gobject);
377
378 if(osc_xmlrpc_controller->osc_xmlrpc_server != NULL){
379 g_object_unref(osc_xmlrpc_controller->osc_xmlrpc_server);
380 }
381
382 if(osc_xmlrpc_controller->message != NULL){
383 g_list_free_full(osc_xmlrpc_controller->message,
384 (GDestroyNotify) g_object_unref);
385 }
386
387 /* call parent */
388 G_OBJECT_CLASS(ags_osc_xmlrpc_controller_parent_class)->finalize(gobject);
389 }
390
391 gboolean
ags_osc_xmlrpc_controller_delegate_timeout(AgsOscXmlrpcController * osc_xmlrpc_controller)392 ags_osc_xmlrpc_controller_delegate_timeout(AgsOscXmlrpcController *osc_xmlrpc_controller)
393 {
394 AgsOscXmlrpcServer *osc_xmlrpc_server;
395
396 AgsOscMessage *current;
397
398 GList *start_osc_response, *osc_response;
399 GList *start_message, *message;
400 GList *start_list, *list;
401 GList *start_controller, *controller;
402
403 gint64 time_now, time_next;
404 gint64 current_time;
405
406 GRecMutex *controller_mutex;
407
408 g_object_get(osc_xmlrpc_controller,
409 "osc-xmlrpc-server", &osc_xmlrpc_server,
410 NULL);
411
412 g_object_get(osc_xmlrpc_server,
413 "controller", &start_controller,
414 NULL);
415
416 /* get OSC xmlrpc controller mutex */
417 controller_mutex = AGS_CONTROLLER_GET_OBJ_MUTEX(osc_xmlrpc_controller);
418
419 time_next = 0;
420
421 /* */
422 g_mutex_lock(&(osc_xmlrpc_controller->delegate_mutex));
423
424 time_now = g_get_monotonic_time();
425
426 g_atomic_int_set(&(osc_xmlrpc_controller->do_reset),
427 FALSE);
428
429 g_mutex_unlock(&(osc_xmlrpc_controller->delegate_mutex));
430
431
432 /* check queued response */
433 g_rec_mutex_lock(controller_mutex);
434
435 start_osc_response = g_list_copy_deep(osc_xmlrpc_controller->queued_response,
436 (GCopyFunc) g_object_ref,
437 NULL);
438
439 g_rec_mutex_unlock(controller_mutex);
440
441 osc_response = start_osc_response;
442
443 while(osc_response != NULL){
444 gint64 num_written;
445
446 gboolean has_expired;
447
448 GRecMutex *response_mutex;
449
450 static const struct timespec timeout_delay = {
451 30,
452 0,
453 };
454
455 g_object_get(osc_response->data,
456 "osc-message", ¤t,
457 NULL);
458
459 num_written = ags_osc_connection_write_response(current->osc_connection,
460 osc_response->data);
461
462 g_object_unref(current);
463
464 response_mutex = AGS_OSC_RESPONSE_GET_OBJ_MUTEX(osc_response->data);
465
466 g_rec_mutex_lock(response_mutex);
467
468 has_expired = ags_time_timeout_expired(AGS_OSC_RESPONSE(osc_response->data)->creation_time, &timeout_delay);
469
470 g_rec_mutex_unlock(response_mutex);
471
472 if(num_written != -1 ||
473 has_expired){
474 g_rec_mutex_lock(controller_mutex);
475
476 osc_xmlrpc_controller->queued_response = g_list_remove(osc_xmlrpc_controller->queued_response,
477 osc_response->data);
478 g_object_unref(osc_response->data);
479
480 g_rec_mutex_unlock(controller_mutex);
481 }
482
483 osc_response = osc_response->next;
484 }
485
486 g_list_free_full(start_osc_response,
487 g_object_unref);
488
489 /* check delegate */
490 g_rec_mutex_lock(controller_mutex);
491
492 start_message = NULL;
493 list =
494 start_list = g_list_copy_deep(osc_xmlrpc_controller->message,
495 (GCopyFunc) g_object_ref,
496 NULL);
497
498 g_rec_mutex_unlock(controller_mutex);
499
500 while(list != NULL){
501 gboolean immediately;
502
503 GRecMutex *message_mutex;
504
505 message_mutex = AGS_OSC_MESSAGE_GET_OBJ_MUTEX(list->data);
506
507 g_object_get(list->data,
508 "immediately", &immediately,
509 NULL);
510
511 if(immediately){
512 start_message = g_list_prepend(start_message,
513 list->data);
514 g_object_ref(list->data);
515
516 ags_osc_xmlrpc_controller_remove_message(osc_xmlrpc_controller,
517 list->data);
518 }else{
519 g_rec_mutex_lock(message_mutex);
520
521 current_time = AGS_OSC_MESSAGE(list->data)->tv_sec + AGS_OSC_MESSAGE(list->data)->tv_fraction / 4.294967296 * 1000.0;
522
523 g_rec_mutex_unlock(message_mutex);
524
525 if(current_time < time_now){
526 start_message = g_list_prepend(start_message,
527 list->data);
528 g_object_ref(list->data);
529
530 ags_osc_xmlrpc_controller_remove_message(osc_xmlrpc_controller,
531 list->data);
532 }else{
533 break;
534 }
535 }
536
537 list = list->next;
538 }
539
540 g_list_free_full(start_list,
541 (GDestroyNotify) g_object_unref);
542
543 message =
544 start_message = g_list_reverse(start_message);
545
546 while(message != NULL){
547 gchar *path;
548
549 ags_osc_buffer_util_get_string(AGS_OSC_MESSAGE(message->data)->message,
550 &path, NULL);
551
552 controller = start_controller;
553 start_osc_response = NULL;
554
555 while(controller != NULL){
556 gboolean success;
557
558 GRecMutex *mutex;
559
560 /* get OSC controller mutex */
561 mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(controller->data);
562
563 /* match path */
564 g_rec_mutex_lock(mutex);
565
566 success = !g_strcmp0(AGS_OSC_CONTROLLER(controller->data)->context_path,
567 path);
568
569 g_rec_mutex_unlock(mutex);
570
571 if(success){
572 current = AGS_OSC_MESSAGE(message->data);
573
574 /* delegate */
575 if(AGS_IS_OSC_ACTION_CONTROLLER(controller->data)){
576 start_osc_response = ags_osc_action_controller_run_action(controller->data,
577 current->osc_connection,
578 current->message, current->message_size);
579 }else if(AGS_IS_OSC_CONFIG_CONTROLLER(controller->data)){
580 start_osc_response = ags_osc_config_controller_apply_config(controller->data,
581 current->osc_connection,
582 current->message, current->message_size);
583 }else if(AGS_IS_OSC_INFO_CONTROLLER(controller->data)){
584 start_osc_response = ags_osc_info_controller_get_info(controller->data,
585 current->osc_connection,
586 current->message, current->message_size);
587 }else if(AGS_IS_OSC_METER_CONTROLLER(controller->data)){
588 start_osc_response = ags_osc_meter_controller_monitor_meter(controller->data,
589 current->osc_connection,
590 current->message, current->message_size);
591 }else if(AGS_IS_OSC_NODE_CONTROLLER(controller->data)){
592 start_osc_response = ags_osc_node_controller_get_data(controller->data,
593 current->osc_connection,
594 current->message, current->message_size);
595 }else if(AGS_IS_OSC_RENEW_CONTROLLER(controller->data)){
596 start_osc_response = ags_osc_renew_controller_set_data(controller->data,
597 current->osc_connection,
598 current->message, current->message_size);
599 }else if(AGS_IS_OSC_STATUS_CONTROLLER(controller->data)){
600 start_osc_response = ags_osc_status_controller_get_status(controller->data,
601 current->osc_connection,
602 current->message, current->message_size);
603 }else if(AGS_IS_OSC_PLUGIN_CONTROLLER(controller->data)){
604 start_osc_response = ags_osc_plugin_controller_do_request(AGS_OSC_PLUGIN_CONTROLLER(controller->data),
605 current->osc_connection,
606 current->message, current->message_size);
607 }
608
609 /* write response */
610 osc_response = start_osc_response;
611
612 while(osc_response != NULL){
613 gint64 num_written;
614
615 #ifdef __APPLE__
616 clock_serv_t cclock;
617 mach_timespec_t mts;
618 #endif
619
620 GRecMutex *response_mutex;
621
622 num_written = ags_osc_connection_write_response(current->osc_connection,
623 osc_response->data);
624
625 if(num_written == -1){
626 response_mutex = AGS_OSC_RESPONSE_GET_OBJ_MUTEX(osc_response->data);
627
628 g_rec_mutex_lock(response_mutex);
629
630 AGS_OSC_RESPONSE(osc_response->data)->creation_time = (struct timespec *) malloc(sizeof(struct timespec));
631
632 #ifdef __APPLE__
633 host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
634
635 clock_get_time(cclock, &mts);
636 mach_port_deallocate(mach_task_self(), cclock);
637
638 AGS_OSC_RESPONSE(osc_response->data)->creation_time->tv_sec = mts.tv_sec;
639 AGS_OSC_RESPONSE(osc_response->data)->creation_time->tv_nsec = mts.tv_nsec;
640 #else
641 clock_gettime(CLOCK_MONOTONIC, AGS_OSC_RESPONSE(osc_response->data)->creation_time);
642 #endif
643
644 g_rec_mutex_unlock(response_mutex);
645
646 g_object_set(osc_response->data,
647 "osc-message", current,
648 NULL);
649
650 g_rec_mutex_lock(controller_mutex);
651
652 osc_xmlrpc_controller->queued_response = g_list_prepend(osc_xmlrpc_controller->queued_response,
653 osc_response->data);
654 g_object_ref(osc_response->data);
655
656 g_rec_mutex_unlock(controller_mutex);
657 }
658
659 osc_response = osc_response->next;
660 }
661
662 g_list_free_full(start_osc_response,
663 g_object_unref);
664
665 break;
666 }
667
668 controller = controller->next;
669 }
670
671 message = message->next;
672 }
673
674 /* free messages */
675 g_list_free_full(start_message,
676 (GDestroyNotify) g_object_unref);
677
678 /* next */
679 g_mutex_lock(&(osc_xmlrpc_controller->delegate_mutex));
680
681 if(osc_xmlrpc_controller->message != NULL){
682 time_next = AGS_OSC_MESSAGE(osc_xmlrpc_controller->message)->tv_sec + AGS_OSC_MESSAGE(osc_xmlrpc_controller->message)->tv_fraction / 4.294967296 * 1000.0;
683 }else{
684 time_now = g_get_monotonic_time();
685
686 time_next = time_now + G_TIME_SPAN_SECOND / 30;
687 }
688
689 g_mutex_unlock(&(osc_xmlrpc_controller->delegate_mutex));
690
691 g_object_unref(osc_xmlrpc_server);
692
693 g_list_free_full(start_controller,
694 g_object_unref);
695
696 if(!ags_osc_xmlrpc_controller_test_flags(osc_xmlrpc_controller, AGS_OSC_XMLRPC_CONTROLLER_DELEGATE_RUNNING)){
697 return(G_SOURCE_REMOVE);
698 }
699
700 return(G_SOURCE_CONTINUE);
701 }
702
703 /**
704 * ags_osc_xmlrpc_controller_test_flags:
705 * @osc_xmlrpc_controller: the #AgsOscXmlrpcController
706 * @flags: the flags
707 *
708 * Test @flags to be set on @osc_xmlrpc_controller.
709 *
710 * Returns: %TRUE if flags are set, else %FALSE
711 *
712 * Since: 3.0.0
713 */
714 gboolean
ags_osc_xmlrpc_controller_test_flags(AgsOscXmlrpcController * osc_xmlrpc_controller,guint flags)715 ags_osc_xmlrpc_controller_test_flags(AgsOscXmlrpcController *osc_xmlrpc_controller, guint flags)
716 {
717 gboolean retval;
718
719 GRecMutex *controller_mutex;
720
721 if(!AGS_IS_OSC_XMLRPC_CONTROLLER(osc_xmlrpc_controller)){
722 return(FALSE);
723 }
724
725 /* get OSC xmlrpc controller mutex */
726 controller_mutex = AGS_CONTROLLER_GET_OBJ_MUTEX(osc_xmlrpc_controller);
727
728 /* test */
729 g_rec_mutex_lock(controller_mutex);
730
731 retval = (flags & (osc_xmlrpc_controller->flags)) ? TRUE: FALSE;
732
733 g_rec_mutex_unlock(controller_mutex);
734
735 return(retval);
736 }
737
738 /**
739 * ags_osc_xmlrpc_controller_set_flags:
740 * @osc_xmlrpc_controller: the #AgsOscXmlrpcController
741 * @flags: the flags
742 *
743 * Set flags.
744 *
745 * Since: 3.0.0
746 */
747 void
ags_osc_xmlrpc_controller_set_flags(AgsOscXmlrpcController * osc_xmlrpc_controller,guint flags)748 ags_osc_xmlrpc_controller_set_flags(AgsOscXmlrpcController *osc_xmlrpc_controller, guint flags)
749 {
750 GRecMutex *controller_mutex;
751
752 if(!AGS_IS_OSC_XMLRPC_CONTROLLER(osc_xmlrpc_controller)){
753 return;
754 }
755
756 /* get OSC xmlrpc controller mutex */
757 controller_mutex = AGS_CONTROLLER_GET_OBJ_MUTEX(osc_xmlrpc_controller);
758
759 /* set flags */
760 g_rec_mutex_lock(controller_mutex);
761
762 osc_xmlrpc_controller->flags |= flags;
763
764 g_rec_mutex_unlock(controller_mutex);
765 }
766
767 /**
768 * ags_osc_xmlrpc_controller_unset_flags:
769 * @osc_xmlrpc_controller: the #AgsOscXmlrpcController
770 * @flags: the flags
771 *
772 * Unset flags.
773 *
774 * Since: 3.0.0
775 */
776 void
ags_osc_xmlrpc_controller_unset_flags(AgsOscXmlrpcController * osc_xmlrpc_controller,guint flags)777 ags_osc_xmlrpc_controller_unset_flags(AgsOscXmlrpcController *osc_xmlrpc_controller, guint flags)
778 {
779 GRecMutex *controller_mutex;
780
781 if(!AGS_IS_OSC_XMLRPC_CONTROLLER(osc_xmlrpc_controller)){
782 return;
783 }
784
785 /* get OSC xmlrpc controller mutex */
786 controller_mutex = AGS_CONTROLLER_GET_OBJ_MUTEX(osc_xmlrpc_controller);
787
788 /* set flags */
789 g_rec_mutex_lock(controller_mutex);
790
791 osc_xmlrpc_controller->flags &= (~flags);
792
793 g_rec_mutex_unlock(controller_mutex);
794 }
795
796 /**
797 * ags_osc_xmlrpc_controller_add_message:
798 * @osc_xmlrpc_controller: the #AgsOscXmlrpcController
799 * @message: the #AgsOscMessage
800 *
801 * Add @message to @osc_xmlrpc_controller.
802 *
803 * Since: 3.0.0
804 */
805 void
ags_osc_xmlrpc_controller_add_message(AgsOscXmlrpcController * osc_xmlrpc_controller,GObject * message)806 ags_osc_xmlrpc_controller_add_message(AgsOscXmlrpcController *osc_xmlrpc_controller,
807 GObject *message)
808 {
809 GRecMutex *controller_mutex;
810
811 if(!AGS_IS_OSC_XMLRPC_CONTROLLER(osc_xmlrpc_controller) ||
812 !AGS_IS_OSC_MESSAGE(message)){
813 return;
814 }
815
816 /* get OSC xmlrpc controller mutex */
817 controller_mutex = AGS_CONTROLLER_GET_OBJ_MUTEX(osc_xmlrpc_controller);
818
819 /* add */
820 g_rec_mutex_lock(controller_mutex);
821
822 if(g_list_find(osc_xmlrpc_controller->message, message) == NULL){
823 osc_xmlrpc_controller->message = g_list_insert_sorted(osc_xmlrpc_controller->message,
824 message,
825 ags_osc_message_sort_func);
826 g_object_ref(message);
827 }
828
829 g_rec_mutex_unlock(controller_mutex);
830 }
831
832 /**
833 * ags_osc_xmlrpc_controller_remove_message:
834 * @osc_xmlrpc_controller: the #AgsOscXmlrpcController
835 * @message: the #AgsOscMessage
836 *
837 * Remove @message from @osc_xmlrpc_controller.
838 *
839 * Since: 3.0.0
840 */
841 void
ags_osc_xmlrpc_controller_remove_message(AgsOscXmlrpcController * osc_xmlrpc_controller,GObject * message)842 ags_osc_xmlrpc_controller_remove_message(AgsOscXmlrpcController *osc_xmlrpc_controller,
843 GObject *message)
844 {
845 GRecMutex *controller_mutex;
846
847 if(!AGS_IS_OSC_XMLRPC_CONTROLLER(osc_xmlrpc_controller) ||
848 !AGS_IS_OSC_MESSAGE(message)){
849 return;
850 }
851
852 /* get OSC xmlrpc controller mutex */
853 controller_mutex = AGS_CONTROLLER_GET_OBJ_MUTEX(osc_xmlrpc_controller);
854
855 /* remove */
856 g_rec_mutex_lock(controller_mutex);
857
858 if(g_list_find(osc_xmlrpc_controller->message, message) != NULL){
859 osc_xmlrpc_controller->message = g_list_remove(osc_xmlrpc_controller->message,
860 message);
861 g_object_unref(message);
862 }
863
864 g_rec_mutex_unlock(controller_mutex);
865 }
866
867 void
ags_osc_xmlrpc_controller_real_start_delegate(AgsOscXmlrpcController * osc_xmlrpc_controller)868 ags_osc_xmlrpc_controller_real_start_delegate(AgsOscXmlrpcController *osc_xmlrpc_controller)
869 {
870 AgsConfig *config;
871
872 GMainContext *main_context;
873 GSource *timeout_source;
874
875 gchar *str;
876
877 gdouble delegate_timeout;
878
879 GRecMutex *controller_mutex;
880
881 /* get OSC xmlrpc controller mutex */
882 controller_mutex = AGS_CONTROLLER_GET_OBJ_MUTEX(osc_xmlrpc_controller);
883
884 /* test if already started */
885 g_rec_mutex_lock(controller_mutex);
886
887 if(ags_osc_xmlrpc_controller_test_flags(osc_xmlrpc_controller, AGS_OSC_XMLRPC_CONTROLLER_DELEGATE_STARTED)){
888 g_rec_mutex_unlock(controller_mutex);
889
890 return;
891 }
892
893 ags_osc_xmlrpc_controller_set_flags(osc_xmlrpc_controller, AGS_OSC_XMLRPC_CONTROLLER_DELEGATE_STARTED);
894
895 g_rec_mutex_unlock(controller_mutex);
896
897 config = ags_config_get_instance();
898
899 /* delegate timeout */
900 ags_osc_xmlrpc_controller_set_flags(osc_xmlrpc_controller,
901 AGS_OSC_XMLRPC_CONTROLLER_DELEGATE_RUNNING);
902
903 delegate_timeout = AGS_OSC_XMLRPC_CONTROLLER_DEFAULT_DELEGATE_TIMEOUT;
904
905 str = ags_config_get_value(config,
906 AGS_CONFIG_OSC_SERVER,
907 "delegate-timeout");
908
909 if(str == NULL){
910 str = ags_config_get_value(config,
911 AGS_CONFIG_OSC_SERVER_0,
912 "delegate-timeout");
913 }
914
915 if(str != NULL){
916 delegate_timeout = g_ascii_strtod(str,
917 NULL);
918
919 free(str);
920 }
921
922 /* create delegate timeout */
923 main_context = g_main_context_get_thread_default();
924
925 timeout_source = g_timeout_source_new(delegate_timeout * G_TIME_SPAN_MILLISECOND);
926 g_source_set_callback(timeout_source,
927 ags_osc_xmlrpc_controller_delegate_timeout,
928 osc_xmlrpc_controller,
929 NULL);
930 g_source_attach(timeout_source,
931 main_context);
932 }
933
934 /**
935 * ags_osc_xmlrpc_controller_start_delegate:
936 * @osc_xmlrpc_controller: the #AgsOscXmlrpcController
937 *
938 * Start delegating.
939 *
940 * Since: 3.0.0
941 */
942 void
ags_osc_xmlrpc_controller_start_delegate(AgsOscXmlrpcController * osc_xmlrpc_controller)943 ags_osc_xmlrpc_controller_start_delegate(AgsOscXmlrpcController *osc_xmlrpc_controller)
944 {
945 g_return_if_fail(AGS_IS_OSC_XMLRPC_CONTROLLER(osc_xmlrpc_controller));
946
947 g_object_ref((GObject *) osc_xmlrpc_controller);
948 g_signal_emit(G_OBJECT(osc_xmlrpc_controller),
949 osc_xmlrpc_controller_signals[START_DELEGATE], 0);
950 g_object_unref((GObject *) osc_xmlrpc_controller);
951 }
952
953 void
ags_osc_xmlrpc_controller_real_stop_delegate(AgsOscXmlrpcController * osc_xmlrpc_controller)954 ags_osc_xmlrpc_controller_real_stop_delegate(AgsOscXmlrpcController *osc_xmlrpc_controller)
955 {
956 if(!ags_osc_xmlrpc_controller_test_flags(osc_xmlrpc_controller, AGS_OSC_XMLRPC_CONTROLLER_DELEGATE_RUNNING)){
957 return;
958 }
959
960 ags_osc_xmlrpc_controller_set_flags(osc_xmlrpc_controller, AGS_OSC_XMLRPC_CONTROLLER_DELEGATE_TERMINATING);
961 ags_osc_xmlrpc_controller_unset_flags(osc_xmlrpc_controller, AGS_OSC_XMLRPC_CONTROLLER_DELEGATE_RUNNING);
962
963 /* join thread */
964 ags_osc_xmlrpc_controller_unset_flags(osc_xmlrpc_controller, (AGS_OSC_XMLRPC_CONTROLLER_DELEGATE_TERMINATING |
965 AGS_OSC_XMLRPC_CONTROLLER_DELEGATE_STARTED));
966 }
967
968 /**
969 * ags_osc_xmlrpc_controller_stop_delegate:
970 * @osc_xmlrpc_controller: the #AgsOscXmlrpcController
971 *
972 * Stop delegating.
973 *
974 * Since: 3.0.0
975 */
976 void
ags_osc_xmlrpc_controller_stop_delegate(AgsOscXmlrpcController * osc_xmlrpc_controller)977 ags_osc_xmlrpc_controller_stop_delegate(AgsOscXmlrpcController *osc_xmlrpc_controller)
978 {
979 g_return_if_fail(AGS_IS_OSC_XMLRPC_CONTROLLER(osc_xmlrpc_controller));
980
981 g_object_ref((GObject *) osc_xmlrpc_controller);
982 g_signal_emit(G_OBJECT(osc_xmlrpc_controller),
983 osc_xmlrpc_controller_signals[STOP_DELEGATE], 0);
984 g_object_unref((GObject *) osc_xmlrpc_controller);
985 }
986
987 gsize
ags_osc_xmlrpc_controller_read_bundle(AgsOscXmlrpcController * osc_xmlrpc_controller,AgsOscWebsocketConnection * osc_websocket_connection,SoupMessage * msg,GHashTable * query,guchar * packet,gsize packet_size,gsize offset)988 ags_osc_xmlrpc_controller_read_bundle(AgsOscXmlrpcController *osc_xmlrpc_controller,
989 AgsOscWebsocketConnection *osc_websocket_connection,
990 SoupMessage *msg,
991 GHashTable *query,
992 guchar *packet, gsize packet_size,
993 gsize offset)
994 {
995 gint32 tv_sec;
996 gint32 tv_fraction;
997 gboolean immediately;
998 gsize read_count;
999 gint32 length;
1000
1001 read_count = 8;
1002
1003 ags_osc_buffer_util_get_timetag(packet + offset + read_count,
1004 &(tv_sec), &(tv_fraction), &(immediately));
1005 read_count += 8;
1006
1007 for(; offset < packet_size;){
1008 ags_osc_buffer_util_get_int32(packet + offset + read_count,
1009 &length);
1010 read_count += 4;
1011
1012 if(!g_strcmp0(packet + offset + read_count, "#bundle")){
1013 ags_osc_xmlrpc_controller_read_bundle(osc_xmlrpc_controller,
1014 osc_websocket_connection,
1015 msg,
1016 query,
1017 packet, packet_size,
1018 offset + read_count);
1019
1020 read_count += ((gsize) 4 * ceil((double) length / 4.0));
1021 }else if(packet[offset + read_count] == '/'){
1022 ags_osc_xmlrpc_controller_read_message(osc_xmlrpc_controller,
1023 osc_websocket_connection,
1024 msg,
1025 query,
1026 packet, packet_size,
1027 offset + read_count,
1028 tv_sec, tv_fraction, immediately);
1029
1030 read_count += ((gsize) 4 * ceil((double) length / 4.0));
1031 }else{
1032 read_count += 1;
1033
1034 g_warning("malformed data");
1035 }
1036 }
1037
1038 return(read_count);
1039 }
1040
1041 gsize
ags_osc_xmlrpc_controller_read_message(AgsOscXmlrpcController * osc_xmlrpc_controller,AgsOscWebsocketConnection * osc_websocket_connection,SoupMessage * msg,GHashTable * query,guchar * packet,gsize packet_size,gsize offset,gint32 tv_sec,gint32 tv_fraction,gboolean immediately)1042 ags_osc_xmlrpc_controller_read_message(AgsOscXmlrpcController *osc_xmlrpc_controller,
1043 AgsOscWebsocketConnection *osc_websocket_connection,
1044 SoupMessage *msg,
1045 GHashTable *query,
1046 guchar *packet, gsize packet_size,
1047 gsize offset,
1048 gint32 tv_sec, gint32 tv_fraction, gboolean immediately)
1049 {
1050 AgsOscMessage *osc_message;
1051
1052 guchar *message;
1053 gchar *address_pattern;
1054 gchar *type_tag;
1055
1056 gsize address_pattern_length;
1057 gsize type_tag_length;
1058 gsize data_length;
1059 gsize read_count;
1060 guint i;
1061
1062 read_count = 0;
1063
1064 ags_osc_buffer_util_get_string(packet + offset,
1065 &address_pattern, &address_pattern_length);
1066
1067 if(address_pattern == NULL){
1068 return(0);
1069 }
1070
1071 read_count += (4 * (gsize) ceil((double) (address_pattern_length + 1) / 4.0));
1072 free(address_pattern);
1073
1074 type_tag = NULL;
1075
1076 if(packet_size > offset + read_count){
1077 if(packet[offset + read_count] == ','){
1078 ags_osc_buffer_util_get_string(packet + offset + read_count,
1079 &type_tag, &type_tag_length);
1080
1081 read_count += (4 * (gsize) ceil((double) (type_tag_length + 1) / 4.0));
1082 }
1083 }
1084
1085 data_length = 0;
1086
1087 if(type_tag != NULL){
1088 for(i = 1; i < type_tag_length; i++){
1089 switch(type_tag[i]){
1090 case AGS_OSC_UTIL_TYPE_TAG_STRING_TRUE:
1091 case AGS_OSC_UTIL_TYPE_TAG_STRING_FALSE:
1092 case AGS_OSC_UTIL_TYPE_TAG_STRING_NIL:
1093 case AGS_OSC_UTIL_TYPE_TAG_STRING_INFINITE:
1094 case AGS_OSC_UTIL_TYPE_TAG_STRING_ARRAY_START:
1095 case AGS_OSC_UTIL_TYPE_TAG_STRING_ARRAY_END:
1096 {
1097 //empty
1098 }
1099 break;
1100 case AGS_OSC_UTIL_TYPE_TAG_STRING_CHAR:
1101 case AGS_OSC_UTIL_TYPE_TAG_STRING_INT32:
1102 case AGS_OSC_UTIL_TYPE_TAG_STRING_FLOAT:
1103 case AGS_OSC_UTIL_TYPE_TAG_STRING_RGBA:
1104 case AGS_OSC_UTIL_TYPE_TAG_STRING_MIDI:
1105 {
1106 data_length += 4;
1107 }
1108 break;
1109 case AGS_OSC_UTIL_TYPE_TAG_STRING_INT64:
1110 case AGS_OSC_UTIL_TYPE_TAG_STRING_DOUBLE:
1111 case AGS_OSC_UTIL_TYPE_TAG_STRING_TIMETAG:
1112 {
1113 data_length += 8;
1114 }
1115 break;
1116 case AGS_OSC_UTIL_TYPE_TAG_STRING_SYMBOL:
1117 case AGS_OSC_UTIL_TYPE_TAG_STRING_STRING:
1118 {
1119 gsize length;
1120
1121 length = strlen(packet + offset + read_count + data_length);
1122
1123 data_length += (4 * (gsize) ceil((double) (length + 1) / 4.0));
1124 }
1125 break;
1126 case AGS_OSC_UTIL_TYPE_TAG_STRING_BLOB:
1127 {
1128 gint32 data_size;
1129
1130 ags_osc_buffer_util_get_int32(packet + offset + read_count + data_length,
1131 &data_size);
1132
1133 data_length += data_size;
1134 }
1135 break;
1136 }
1137 }
1138
1139 free(type_tag);
1140 }
1141
1142 read_count += (4 * (gsize) ceil((double) data_length / 4.0));
1143
1144 osc_message = ags_osc_xmlrpc_message_new();
1145
1146 message = (guchar *) malloc(read_count * sizeof(guchar));
1147 memcpy(message,
1148 packet + offset,
1149 read_count * sizeof(guchar));
1150
1151 g_object_set(osc_message,
1152 "osc-connection", osc_websocket_connection,
1153 "tv-sec", tv_sec,
1154 "tv-fraction", tv_fraction,
1155 "immediately", immediately,
1156 "message-size", read_count,
1157 "message", message,
1158 "msg", msg,
1159 "query", query,
1160 NULL);
1161
1162 ags_osc_xmlrpc_controller_add_message(osc_xmlrpc_controller,
1163 osc_message);
1164
1165 return(read_count);
1166 }
1167
1168 gpointer
ags_osc_xmlrpc_controller_do_request(AgsPluginController * plugin_controller,SoupMessage * msg,GHashTable * query,SoupClientContext * client,GObject * security_context,gchar * path,gchar * login,gchar * security_token)1169 ags_osc_xmlrpc_controller_do_request(AgsPluginController *plugin_controller,
1170 SoupMessage *msg,
1171 GHashTable *query,
1172 SoupClientContext *client,
1173 GObject *security_context,
1174 gchar *path,
1175 gchar *login,
1176 gchar *security_token)
1177 {
1178 AgsOscXmlrpcServer *osc_xmlrpc_server;
1179 AgsOscXmlrpcController *osc_xmlrpc_controller;
1180 AgsOscWebsocketConnection *osc_websocket_connection;
1181
1182 xmlDoc *doc;
1183 xmlDoc *response_doc;
1184 xmlNode *root_node;
1185 xmlNode *osc_packet_node_list;
1186 xmlNode *osc_packet_node;
1187 xmlNode *response_root_node;
1188 xmlNode *response_redirect_node;
1189
1190 #if HAVE_GLIB_2_52
1191 #else
1192 AgsUUID *resource_uuid;
1193 #endif
1194
1195 GBytes *request_body_data;
1196
1197 xmlChar *buffer;
1198 gchar *data;
1199 guchar *packet;
1200 xmlChar *response_buffer;
1201 gchar *response_resource_id;
1202
1203 gsize data_size;
1204 gsize packet_size;
1205 gint32 tv_sec;
1206 gint32 tv_fraction;
1207 gboolean immediately;
1208 gsize offset;
1209 int response_buffer_length;
1210
1211 if(!AGS_IS_SECURITY_CONTEXT(security_context) ||
1212 path == NULL ||
1213 login == NULL ||
1214 security_token == NULL){
1215 return(NULL);
1216 }
1217
1218 g_object_get(msg,
1219 "request-body-data", &request_body_data,
1220 NULL);
1221
1222 data = g_bytes_get_data(request_body_data,
1223 &data_size);
1224
1225 /* parse XML doc */
1226 buffer = xmlCharStrndup(data,
1227 data_size);
1228
1229 doc = xmlParseDoc(buffer);
1230
1231 xmlFree(buffer);
1232
1233 if(doc == NULL){
1234 return(NULL);
1235 }
1236
1237 root_node = xmlDocGetRootElement(doc);
1238
1239 if(root_node == NULL){
1240 return(NULL);
1241 }
1242
1243 /* */
1244 osc_xmlrpc_controller = AGS_OSC_XMLRPC_CONTROLLER(plugin_controller);
1245
1246 g_object_get(osc_xmlrpc_controller,
1247 "osc-xmlrpc-server", &osc_xmlrpc_server,
1248 NULL);
1249
1250 #if HAVE_GLIB_2_52
1251 response_resource_id = g_uuid_string_random();
1252 #else
1253 resource_uuid = ags_uuid_alloc();
1254 ags_uuid_generate(resource_uuid);
1255
1256 response_resource_id = ags_uuid_to_string(resource_uuid);
1257
1258 ags_uuid_free(resource_uuid);
1259 #endif
1260
1261 osc_websocket_connection = ags_osc_websocket_connection_new(osc_xmlrpc_server);
1262 g_object_set(osc_websocket_connection,
1263 "security-context", security_context,
1264 "login", login,
1265 "security-token", security_token,
1266 "resource-id", response_resource_id,
1267 NULL);
1268
1269 ags_osc_server_add_connection(osc_xmlrpc_server,
1270 osc_websocket_connection);
1271
1272 osc_packet_node_list = root_node->children;
1273
1274 while(osc_packet_node_list != NULL){
1275 if(osc_packet_node_list->type == XML_ELEMENT_NODE){
1276 if(!xmlStrncmp(osc_packet_node_list->name,
1277 "ags-osc-packet-list",
1278 20)){
1279 osc_packet_node = osc_packet_node_list->children;
1280
1281 while(osc_packet_node != NULL){
1282 if(osc_packet_node->type == XML_ELEMENT_NODE){
1283 if(!xmlStrncmp(osc_packet_node->name,
1284 "ags-osc-packet",
1285 15)){
1286 xmlChar *tmp_packet;
1287
1288 tmp_packet = xmlNodeGetContent(osc_packet_node);
1289
1290 packet = g_base64_decode(tmp_packet,
1291 &packet_size);
1292
1293 tv_sec = 0;
1294 tv_fraction = 0;
1295 immediately = TRUE;
1296
1297 for(offset = 4; offset < packet_size;){
1298 gsize read_count;
1299
1300 #ifdef AGS_DEBUG
1301 g_message("%d %d", offset, packet_size);
1302 g_message("%x[%c]", packet[offset], packet[offset]);
1303 #endif
1304
1305 if(!g_strcmp0(packet + offset, "#bundle")){
1306 read_count = ags_osc_xmlrpc_controller_read_bundle(osc_xmlrpc_controller,
1307 osc_websocket_connection,
1308 msg,
1309 query,
1310 packet, packet_size,
1311 offset);
1312 }else if(packet[offset] == '/'){
1313 read_count = ags_osc_xmlrpc_controller_read_message(osc_xmlrpc_controller,
1314 osc_websocket_connection,
1315 msg,
1316 query,
1317 packet, packet_size,
1318 offset,
1319 0, 0, TRUE);
1320 }else{
1321 read_count = 1;
1322
1323 g_warning("malformed data");
1324 }
1325
1326 if(read_count > 0){
1327 offset += ((gsize) 4 * ceil((double) read_count / 4.0));
1328 }else{
1329 offset += 1;
1330
1331 g_warning("malformed data");
1332 }
1333 }
1334
1335 g_free(packet);
1336 }
1337 }
1338
1339 osc_packet_node = osc_packet_node->next;
1340 }
1341 }
1342 }
1343
1344 osc_packet_node_list = osc_packet_node_list->next;
1345 }
1346
1347 xmlFreeDoc(doc);
1348
1349 /* response */
1350 g_message("PATH=%s", path);
1351 response_doc = xmlNewDoc("1.0");
1352
1353 response_root_node = xmlNewNode(NULL, "ags-osc-over-xmlrpc");
1354 xmlDocSetRootElement(response_doc, response_root_node);
1355
1356 response_redirect_node = xmlNewNode(NULL,
1357 "ags-srv-redirect");
1358
1359 xmlNewProp(response_redirect_node,
1360 "resource-id",
1361 response_resource_id);
1362
1363 xmlAddChild(response_root_node,
1364 response_redirect_node);
1365
1366 /* set body */
1367 xmlDocDumpFormatMemoryEnc(response_doc, &response_buffer, &response_buffer_length, "UTF-8", TRUE);
1368
1369 soup_message_set_response(msg,
1370 "text/xml; charset=UTF-8",
1371 SOUP_MEMORY_COPY,
1372 response_buffer,
1373 response_buffer_length);
1374
1375 soup_message_set_status(msg,
1376 200);
1377
1378 xmlFree(response_buffer);
1379 xmlFreeDoc(response_doc);
1380
1381 g_free(response_resource_id);
1382
1383 return(NULL);
1384 }
1385
1386 /**
1387 * ags_osc_xmlrpc_controller_new:
1388 *
1389 * Instantiate new #AgsOscXmlrpcController
1390 *
1391 * Returns: the #AgsOscXmlrpcController
1392 *
1393 * Since: 3.0.0
1394 */
1395 AgsOscXmlrpcController*
ags_osc_xmlrpc_controller_new()1396 ags_osc_xmlrpc_controller_new()
1397 {
1398 AgsOscXmlrpcController *osc_xmlrpc_controller;
1399
1400 osc_xmlrpc_controller = (AgsOscXmlrpcController *) g_object_new(AGS_TYPE_OSC_XMLRPC_CONTROLLER,
1401 NULL);
1402
1403 return(osc_xmlrpc_controller);
1404 }
1405