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", &current,
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