]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/router/osrf_router.c
3c127456916fa8089d6a1d34c4efd06eab88366f
[OpenSRF.git] / src / router / osrf_router.c
1 #include "osrf_router.h"
2
3 #define ROUTER_SOCKFD connection->session->sock_id
4 #define ROUTER_REGISTER "register"
5 #define ROUTER_UNREGISTER "unregister"
6
7
8 #define ROUTER_REQUEST_CLASS_LIST "opensrf.router.info.class.list"
9 #define ROUTER_REQUEST_STATS_NODE_FULL "opensrf.router.info.stats.class.node.all"
10 #define ROUTER_REQUEST_STATS_CLASS_FULL "opensrf.router.info.stats.class.all"
11 #define ROUTER_REQUEST_STATS_CLASS "opensrf.router.info.stats.class"
12 #define ROUTER_REQUEST_STATS_CLASS_SUMMARY "opensrf.router.info.stats.class.summary"
13
14 osrfRouter* osrfNewRouter( 
15                 char* domain, char* name, 
16                 char* resource, char* password, int port, 
17                 osrfStringArray* trustedClients, osrfStringArray* trustedServers ) {
18
19         if(!( domain && name && resource && password && port && trustedClients && trustedServers )) return NULL;
20
21         osrfRouter* router      = safe_malloc(sizeof(osrfRouter));
22         router->domain                  = strdup(domain);
23         router->name                    = strdup(name);
24         router->password                = strdup(password);
25         router->resource                = strdup(resource);
26         router->port                    = port;
27
28         router->trustedClients = trustedClients;
29         router->trustedServers = trustedServers;
30
31         
32         router->classes = osrfNewHash(); 
33         router->classes->freeItem = &osrfRouterClassFree;
34
35         router->connection = client_init( domain, port, NULL, 0 );
36
37         return router;
38 }
39
40
41
42 int osrfRouterConnect( osrfRouter* router ) {
43         if(!router) return -1;
44         int ret = client_connect( router->connection, router->name, 
45                         router->password, router->resource, 10, AUTH_DIGEST );
46         if( ret == 0 ) return -1;
47         return 0;
48 }
49
50
51 void osrfRouterRun( osrfRouter* router ) {
52         if(!(router && router->classes)) return;
53
54         int routerfd = router->ROUTER_SOCKFD;
55         int selectret = 0;
56
57         while(1) {
58
59                 fd_set set;
60                 int maxfd = __osrfRouterFillFDSet( router, &set );
61                 int numhandled = 0;
62
63                 if( (selectret = select(maxfd + 1, &set, NULL, NULL, NULL)) < 0 ) {
64                         osrfLogWarning( OSRF_LOG_MARK, "Top level select call failed with errno %d", errno);
65                         continue;
66                 }
67
68                 /* see if there is a top level router message */
69
70                 if( FD_ISSET(routerfd, &set) ) {
71                         osrfLogDebug( OSRF_LOG_MARK, "Top router socket is active: %d", routerfd );
72                         numhandled++;
73                         osrfRouterHandleIncoming( router );
74                 }
75
76
77                 /* now check each of the connected classes and see if they have data to route */
78                 while( numhandled < selectret ) {
79
80                         osrfRouterClass* class;
81                         osrfHashIterator* itr = osrfNewHashIterator(router->classes);
82
83                         while( (class = osrfHashIteratorNext(itr)) ) {
84
85                                 char* classname = itr->current;
86
87                                 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
88
89                                         osrfLogDebug( OSRF_LOG_MARK, "Checking %s for activity...", classname );
90
91                                         int sockfd = class->ROUTER_SOCKFD;
92                                         if(FD_ISSET( sockfd, &set )) {
93                                                 osrfLogDebug( OSRF_LOG_MARK, "Socket is active: %d", sockfd );
94                                                 numhandled++;
95                                                 osrfRouterClassHandleIncoming( router, classname, class );
96                                         }
97                                 }
98                         }
99
100                         osrfHashIteratorFree(itr);
101                 }
102         }
103 }
104
105
106 void osrfRouterHandleIncoming( osrfRouter* router ) {
107         if(!router) return;
108
109         transport_message* msg = NULL;
110
111         //if( (msg = client_recv( router->connection, 0 )) ) { 
112         while( (msg = client_recv( router->connection, 0 )) ) { 
113
114                 if( msg->sender ) {
115
116                         osrfLogDebug(OSRF_LOG_MARK, 
117                                 "osrfRouterHandleIncoming(): investigating message from %s", msg->sender);
118
119                         /* if the sender is not a trusted server, drop the message */
120                         int len = strlen(msg->sender) + 1;
121                         char domain[len];
122                         memset(domain, 0, sizeof(domain));
123                         jid_get_domain( msg->sender, domain, len - 1 );
124
125                         if(osrfStringArrayContains( router->trustedServers, domain)) 
126                                 osrfRouterHandleMessage( router, msg );
127                          else 
128                                 osrfLogWarning( OSRF_LOG_MARK, "Received message from un-trusted server domain %s", msg->sender);
129                 }
130
131                 message_free(msg);
132         }
133 }
134
135 int osrfRouterClassHandleIncoming( osrfRouter* router, char* classname, osrfRouterClass* class ) {
136         if(!(router && class)) return -1;
137
138         transport_message* msg;
139         osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleIncoming()");
140
141         while( (msg = client_recv( class->connection, 0 )) ) {
142
143       osrfLogSetXid(msg->osrf_xid);
144
145                 if( msg->sender ) {
146
147                         osrfLogDebug(OSRF_LOG_MARK, 
148                                 "osrfRouterClassHandleIncoming(): investigating message from %s", msg->sender);
149
150                         /* if the client is not from a trusted domain, drop the message */
151                         int len = strlen(msg->sender) + 1;
152                         char domain[len];
153                         memset(domain, 0, sizeof(domain));
154                         jid_get_domain( msg->sender, domain, len - 1 );
155
156                         if(osrfStringArrayContains( router->trustedClients, domain)) {
157
158                                 transport_message* bouncedMessage = NULL;
159                                 if( msg->is_error )  {
160
161                                         /* handle bounced message */
162                                         if( !(bouncedMessage = osrfRouterClassHandleBounce( router, classname, class, msg )) ) 
163                                                 return -1; /* we have no one to send the requested message to */
164
165                                         message_free( msg );
166                                         msg = bouncedMessage;
167                                 }
168                                 osrfRouterClassHandleMessage( router, class, msg );
169
170                         } else {
171                                 osrfLogWarning( OSRF_LOG_MARK, "Received client message from untrusted client domain %s", domain );
172                         }
173                 }
174
175       osrfLogClearXid();
176                 message_free( msg );
177         }
178
179         return 0;
180 }
181
182
183
184
185 int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg ) {
186         if(!(router && msg)) return -1;
187
188         if( !msg->router_command || !strcmp(msg->router_command,"")) 
189                 return osrfRouterHandleAppRequest( router, msg ); /* assume it's an app session level request */
190
191         if(!msg->router_class) return -1;
192
193         osrfRouterClass* class = NULL;
194         if(!strcmp(msg->router_command, ROUTER_REGISTER)) {
195                 class = osrfRouterFindClass( router, msg->router_class );
196
197                 osrfLogInfo( OSRF_LOG_MARK, "Registering class %s", msg->router_class );
198
199                 if(!class) class = osrfRouterAddClass( router, msg->router_class );
200
201                 if(class) { 
202
203                         if( osrfRouterClassFindNode( class, msg->sender ) )
204                                 return 0;
205                         else 
206                                 osrfRouterClassAddNode( class, msg->sender );
207
208                 } 
209
210         } else if( !strcmp( msg->router_command, ROUTER_UNREGISTER ) ) {
211
212                 if( msg->router_class && strcmp( msg->router_class, "") ) {
213                         osrfLogInfo( OSRF_LOG_MARK, "Unregistering router class %s", msg->router_class );
214                         osrfRouterClassRemoveNode( router, msg->router_class, msg->sender );
215                 }
216         }
217
218         return 0;
219 }
220
221
222
223 osrfRouterClass* osrfRouterAddClass( osrfRouter* router, char* classname ) {
224         if(!(router && router->classes && classname)) return NULL;
225
226         osrfRouterClass* class = safe_malloc(sizeof(osrfRouterClass));
227         class->nodes = osrfNewHash();
228         class->itr = osrfNewHashIterator(class->nodes);
229         class->nodes->freeItem = &osrfRouterNodeFree;
230         class->router   = router;
231
232         class->connection = client_init( router->domain, router->port, NULL, 0 );
233
234         if(!client_connect( class->connection, router->name, 
235                         router->password, classname, 10, AUTH_DIGEST ) ) {
236                 osrfRouterClassFree( classname, class );
237                 return NULL;
238         }
239         
240         osrfHashSet( router->classes, class, classname );
241         return class;
242 }
243
244
245 int osrfRouterClassAddNode( osrfRouterClass* rclass, char* remoteId ) {
246         if(!(rclass && rclass->nodes && remoteId)) return -1;
247
248         osrfLogInfo( OSRF_LOG_MARK, "Adding router node for remote id %s", remoteId );
249
250         osrfRouterNode* node = safe_malloc(sizeof(osrfRouterNode));
251         node->count = 0;
252         node->lastMessage = NULL;
253         node->remoteId = strdup(remoteId);
254
255         osrfHashSet( rclass->nodes, node, remoteId );
256         return 0;
257 }
258
259 /* copy off the lastMessage, remove the offending node, send error if it's tht last node 
260         ? return NULL if it's the last node ?
261  */
262
263 transport_message* osrfRouterClassHandleBounce( 
264                 osrfRouter* router, char* classname, osrfRouterClass* rclass, transport_message* msg ) {
265
266         osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleBounce()");
267
268         osrfLogInfo( OSRF_LOG_MARK, "Received network layer error message from %s", msg->sender );
269         osrfRouterNode* node = osrfRouterClassFindNode( rclass, msg->sender );
270         transport_message* lastSent = NULL;
271
272         if( node && osrfHashGetCount(rclass->nodes) == 1 ) { /* the last node is dead */
273
274                 if( node->lastMessage ) {
275                         osrfLogWarning( OSRF_LOG_MARK, "We lost the last node in the class, responding with error and removing...");
276         
277                         transport_message* error = message_init( 
278                                 node->lastMessage->body, node->lastMessage->subject, 
279                                 node->lastMessage->thread, node->lastMessage->router_from, node->lastMessage->recipient );
280          message_set_osrf_xid(error, node->lastMessage->osrf_xid);
281                         set_msg_error( error, "cancel", 501 );
282         
283                         /* send the error message back to the original sender */
284                         client_send_message( rclass->connection, error );
285                         message_free( error );
286                 }
287         
288                 return NULL;
289         
290         } else { 
291
292                 if( node ) {
293                         if( node->lastMessage ) {
294                                 osrfLogDebug( OSRF_LOG_MARK, "Cloning lastMessage so next node can send it");
295                                 lastSent = message_init( node->lastMessage->body,
296                                         node->lastMessage->subject, node->lastMessage->thread, "", node->lastMessage->router_from );
297                                 message_set_router_info( lastSent, node->lastMessage->router_from, NULL, NULL, NULL, 0 );
298             message_set_osrf_xid( lastSent, node->lastMessage->osrf_xid );
299                         }
300                 } else {
301
302                         osrfLogInfo(OSRF_LOG_MARK, "network error occurred after we removed the class.. ignoring");
303                         return NULL;
304                 }
305         }
306
307         /* remove the dead node */
308         osrfRouterClassRemoveNode( router, classname, msg->sender);
309         return lastSent;
310 }
311
312
313 /**
314   If we get a regular message, we send it to the next node in the list of nodes
315   if we get an error, it's a bounce back from a previous attempt.  We take the
316   body and thread from the last sent on the node that had the bounced message
317   and propogate them on to the new message being sent
318   */
319 int osrfRouterClassHandleMessage( 
320                 osrfRouter* router, osrfRouterClass* rclass, transport_message* msg ) {
321         if(!(router && rclass && msg)) return -1;
322
323         osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleMessage()");
324
325         osrfRouterNode* node = osrfHashIteratorNext( rclass->itr );
326         if(!node) {
327                 osrfHashIteratorReset(rclass->itr);
328                 node = osrfHashIteratorNext( rclass->itr );
329         }
330
331         if(node) {
332
333                 transport_message* new_msg= message_init(       msg->body, 
334                                 msg->subject, msg->thread, node->remoteId, msg->sender );
335                 message_set_router_info( new_msg, msg->sender, NULL, NULL, NULL, 0 );
336       message_set_osrf_xid( new_msg, msg->osrf_xid );
337
338                 osrfLogInfo( OSRF_LOG_MARK,  "Routing message:\nfrom: [%s]\nto: [%s]", 
339                                 new_msg->router_from, new_msg->recipient );
340
341                 message_free( node->lastMessage );
342                 node->lastMessage = new_msg;
343
344                 if ( client_send_message( rclass->connection, new_msg ) == 0 ) 
345                         node->count++;
346
347                 else {
348                         message_prepare_xml(new_msg);
349                         osrfLogWarning( OSRF_LOG_MARK, "Error sending message from %s to %s\n%s", 
350                                         new_msg->sender, new_msg->recipient, new_msg->msg_xml );
351                 }
352
353         } 
354
355         return 0;
356 }
357
358
359 int osrfRouterRemoveClass( osrfRouter* router, char* classname ) {
360         if(!(router && router->classes && classname)) return -1;
361         osrfLogInfo( OSRF_LOG_MARK, "Removing router class %s", classname );
362         osrfHashRemove( router->classes, classname );
363         return 0;
364 }
365
366
367 int osrfRouterClassRemoveNode( 
368                 osrfRouter* router, char* classname, char* remoteId ) {
369
370         if(!(router && router->classes && classname && remoteId)) return 0;
371
372         osrfLogInfo( OSRF_LOG_MARK, "Removing router node %s", remoteId );
373
374         osrfRouterClass* class = osrfRouterFindClass( router, classname );
375
376         if( class ) {
377
378                 osrfHashRemove( class->nodes, remoteId );
379                 if( osrfHashGetCount(class->nodes) == 0 ) {
380                         osrfRouterRemoveClass( router, classname );
381                         return 1;
382                 }
383
384                 return 0;
385         }
386
387         return -1;
388 }
389
390
391 void osrfRouterClassFree( char* classname, void* c ) {
392         if(!(classname && c)) return;
393         osrfRouterClass* rclass = (osrfRouterClass*) c;
394         client_disconnect( rclass->connection );        
395         client_free( rclass->connection );      
396
397         osrfHashIteratorReset( rclass->itr );
398         osrfRouterNode* node;
399
400         while( (node = osrfHashIteratorNext(rclass->itr)) ) 
401                 osrfRouterClassRemoveNode( rclass->router, classname, node->remoteId );
402
403    osrfHashIteratorFree(rclass->itr);
404    osrfHashFree(rclass->nodes);
405
406         free(rclass);
407 }
408
409
410 void osrfRouterNodeFree( char* remoteId, void* n ) {
411         if(!n) return;
412         osrfRouterNode* node = (osrfRouterNode*) n;
413         free(node->remoteId);
414         message_free(node->lastMessage);
415         free(node);
416 }
417
418
419 void osrfRouterFree( osrfRouter* router ) {
420         if(!router) return;
421
422         free(router->domain);           
423         free(router->name);
424         free(router->resource);
425         free(router->password);
426
427         osrfStringArrayFree( router->trustedClients );
428         osrfStringArrayFree( router->trustedServers );
429
430         client_free( router->connection );
431         free(router);
432 }
433
434
435
436 osrfRouterClass* osrfRouterFindClass( osrfRouter* router, char* classname ) {
437         if(!( router && router->classes && classname )) return NULL;
438         return (osrfRouterClass*) osrfHashGet( router->classes, classname );
439 }
440
441
442 osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass, char* remoteId ) {
443         if(!(rclass && remoteId))  return NULL;
444         return (osrfRouterNode*) osrfHashGet( rclass->nodes, remoteId );
445 }
446
447
448 int __osrfRouterFillFDSet( osrfRouter* router, fd_set* set ) {
449         if(!(router && router->classes && set)) return -1;
450
451         FD_ZERO(set);
452         int maxfd = router->ROUTER_SOCKFD;
453         FD_SET(maxfd, set);
454
455         int sockid;
456
457         osrfRouterClass* class = NULL;
458         osrfHashIterator* itr = osrfNewHashIterator(router->classes);
459
460         while( (class = osrfHashIteratorNext(itr)) ) {
461                 char* classname = itr->current;
462
463                 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
464                         sockid = class->ROUTER_SOCKFD;
465         
466                         if( osrfUtilsCheckFileDescriptor( sockid ) ) {
467
468                                 osrfLogWarning(OSRF_LOG_MARK, 
469                                         "Removing router class '%s' because of a bad top-level file descriptor [%d]", classname, sockid);
470                                 osrfRouterRemoveClass( router, classname );
471         
472                         } else {
473                                 if( sockid > maxfd ) maxfd = sockid;
474                                 FD_SET(sockid, set);
475                         }
476                 }
477         }
478
479         osrfHashIteratorFree(itr);
480         return maxfd;
481 }
482
483
484
485 int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg ) {
486
487         int T = 32;
488         osrfMessage* arr[T];
489         memset(arr, 0, sizeof(arr));
490
491         int num_msgs = osrf_message_deserialize( msg->body, arr, T );
492         osrfMessage* omsg = NULL;
493
494         int i;
495         for( i = 0; i != num_msgs; i++ ) {
496
497                 if( !(omsg = arr[i]) ) continue;
498
499                 switch( omsg->m_type ) {
500
501                         case CONNECT:
502                                 osrfRouterRespondConnect( router, msg, omsg );
503                                 break;
504
505                         case REQUEST:
506                                 osrfRouterProcessAppRequest( router, msg, omsg );
507                                 break;
508
509                         default: break;
510                 }
511
512                 osrfMessageFree( omsg );
513         }
514
515         return 0;
516 }
517
518 int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg, osrfMessage* omsg ) {
519         if(!(router && msg && omsg)) return -1;
520
521         osrfMessage* success = osrf_message_init( STATUS, omsg->thread_trace, omsg->protocol );
522
523         osrfLogDebug( OSRF_LOG_MARK, "router received a CONNECT message from %s", msg->sender );
524
525         osrf_message_set_status_info( 
526                 success, "osrfConnectStatus", "Connection Successful", OSRF_STATUS_OK );
527
528         char* data      = osrf_message_serialize(success);
529
530         transport_message* return_m = message_init( 
531                 data, "", msg->thread, msg->sender, "" );
532
533         client_send_message(router->connection, return_m);
534
535         free(data);
536         osrf_message_free(success);
537         message_free(return_m);
538
539         return 0;
540 }
541
542
543
544 int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg, osrfMessage* omsg ) {
545
546         if(!(router && msg && omsg && omsg->method_name)) return -1;
547
548         osrfLogInfo( OSRF_LOG_MARK, "Router received app request: %s", omsg->method_name );
549
550         jsonObject* jresponse = NULL;
551         if(!strcmp( omsg->method_name, ROUTER_REQUEST_CLASS_LIST )) {
552
553                 int i;
554                 jresponse = jsonParseString("[]");
555
556                 osrfStringArray* keys = osrfHashKeys( router->classes );
557                 for( i = 0; i != keys->size; i++ )
558                         jsonObjectPush( jresponse, jsonNewObject(osrfStringArrayGetString( keys, i )) );
559                 osrfStringArrayFree(keys);
560
561
562         } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_SUMMARY )) {
563
564                 osrfRouterClass* class;
565                 osrfRouterNode* node;
566                 int count = 0;
567
568                 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
569
570                 if (!classname) {
571                         free(classname);
572                         return -1;
573                 }
574
575                 class = osrfHashGet(router->classes, classname);
576
577                 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
578                 while( (node = osrfHashIteratorNext(node_itr)) ) {
579                         count += node->count;
580                         //jsonObjectSetKey( class_res, node->remoteId, jsonNewNumberObject( (double) node->count ) );
581                 }
582                 osrfHashIteratorFree(node_itr);
583
584                 jresponse = jsonNewNumberObject( (double) count );
585
586         } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS )) {
587
588                 osrfRouterClass* class;
589                 osrfRouterNode* node;
590
591                 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
592
593                 if (!classname) {
594                         free(classname);
595                         return -1;
596                 }
597
598                 jresponse = jsonParseString("{}");
599                 class = osrfHashGet(router->classes, classname);
600
601                 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
602                 while( (node = osrfHashIteratorNext(node_itr)) ) {
603                         jsonObjectSetKey( jresponse, node->remoteId, jsonNewNumberObject( (double) node->count ) );
604                 }
605                 osrfHashIteratorFree(node_itr);
606
607         } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_FULL )) {
608
609                 osrfRouterClass* class;
610                 osrfRouterNode* node;
611                 jresponse = jsonParseString("{}");
612
613                 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
614                 while( (class = osrfHashIteratorNext(class_itr)) ) {
615
616                         jsonObject* class_res = jsonParseString("{}");
617                         char* classname = class_itr->current;
618
619                         osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
620                         while( (node = osrfHashIteratorNext(node_itr)) ) {
621                                 jsonObjectSetKey( class_res, node->remoteId, jsonNewNumberObject( (double) node->count ) );
622                         }
623                         osrfHashIteratorFree(node_itr);
624
625                         jsonObjectSetKey( jresponse, classname, class_res );
626                 }
627
628                 osrfHashIteratorFree(class_itr);
629
630         } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_NODE_FULL )) {
631
632                 osrfRouterClass* class;
633                 osrfRouterNode* node;
634                 int count;
635                 jresponse = jsonParseString("{}");
636
637                 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
638                 while( (class = osrfHashIteratorNext(class_itr)) ) {
639
640                         count = 0;
641                         char* classname = class_itr->current;
642
643                         osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
644                         while( (node = osrfHashIteratorNext(node_itr)) ) {
645                                 count += node->count;
646                         }
647                         osrfHashIteratorFree(node_itr);
648
649                         jsonObjectSetKey( jresponse, classname, jsonNewNumberObject( (double) count ) );
650                 }
651
652                 osrfHashIteratorFree(class_itr);
653
654         } else {
655
656                 return osrfRouterHandleMethodNFound( router, msg, omsg );
657         }
658
659
660         osrfRouterHandleAppResponse( router, msg, omsg, jresponse );
661         jsonObjectFree(jresponse); 
662
663         return 0;
664
665 }
666
667
668
669 int osrfRouterHandleMethodNFound( 
670                 osrfRouter* router, transport_message* msg, osrfMessage* omsg ) {
671
672         osrf_message* err = osrf_message_init( STATUS, omsg->thread_trace, 1);
673                 osrf_message_set_status_info( err, 
674                                 "osrfMethodException", "Router method not found", OSRF_STATUS_NOTFOUND );
675
676                 char* data =  osrf_message_serialize(err);
677
678                 transport_message* tresponse = message_init(
679                                 data, "", msg->thread, msg->sender, msg->recipient );
680
681                 client_send_message(router->connection, tresponse );
682
683                 free(data);
684                 osrf_message_free( err );
685                 message_free(tresponse);
686                 return 0;
687 }
688
689
690
691 int osrfRouterHandleAppResponse( osrfRouter* router, 
692         transport_message* msg, osrfMessage* omsg, jsonObject* response ) {
693
694         if( response ) { /* send the response message */
695
696                 osrfMessage* oresponse = osrf_message_init(
697                                 RESULT, omsg->thread_trace, omsg->protocol );
698         
699                 char* json = jsonObjectToJSON(response);
700                 osrf_message_set_result_content( oresponse, json);
701         
702                 char* data =  osrf_message_serialize(oresponse);
703                 osrfLogDebug( OSRF_LOG_MARK,  "Responding to client app request with data: \n%s\n", data );
704
705                 transport_message* tresponse = message_init(
706                                 data, "", msg->thread, msg->sender, msg->recipient );
707         
708                 client_send_message(router->connection, tresponse );
709
710                 osrfMessageFree(oresponse); 
711                 message_free(tresponse);
712                 free(json);
713                 free(data);
714         }
715
716
717         /* now send the 'request complete' message */
718         osrf_message* status = osrf_message_init( STATUS, omsg->thread_trace, 1);
719         osrf_message_set_status_info( status, "osrfConnectStatus", "Request Complete", OSRF_STATUS_COMPLETE );
720
721         char* statusdata = osrf_message_serialize(status);
722
723         transport_message* sresponse = message_init(
724                         statusdata, "", msg->thread, msg->sender, msg->recipient );
725         client_send_message(router->connection, sresponse );
726
727
728         free(statusdata);
729         osrfMessageFree(status);
730         message_free(sresponse);
731
732         return 0;
733 }
734
735
736
737