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