1 #include "osrf_router.h"
3 /* a class maintains a set of server nodes */
4 struct _osrfRouterClassStruct {
5 osrfRouter* router; /* our router handle */
8 transport_client* connection;
10 typedef struct _osrfRouterClassStruct osrfRouterClass;
12 /* represents a link to a single server's inbound connection */
13 struct _osrfRouterNodeStruct {
14 char* remoteId; /* send message to me via this login */
15 int count; /* how many message have been sent to this node */
16 transport_message* lastMessage;
18 typedef struct _osrfRouterNodeStruct osrfRouterNode;
20 static osrfRouterClass* osrfRouterAddClass( osrfRouter* router, const char* classname );
21 static int osrfRouterClassAddNode( osrfRouterClass* rclass, const char* remoteId );
22 static int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg );
23 static int osrfRouterClassHandleMessage( osrfRouter* router,
24 osrfRouterClass* rclass, transport_message* msg );
25 static int osrfRouterRemoveClass( osrfRouter* router, const char* classname );
26 static int osrfRouterClassRemoveNode( osrfRouter* router, const char* classname,
27 const char* remoteId );
28 static void osrfRouterClassFree( char* classname, void* rclass );
29 static void osrfRouterNodeFree( char* remoteId, void* node );
30 static osrfRouterClass* osrfRouterFindClass( osrfRouter* router, const char* classname );
31 static osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass,
32 const char* remoteId );
33 static int _osrfRouterFillFDSet( osrfRouter* router, fd_set* set );
34 static void osrfRouterHandleIncoming( osrfRouter* router );
35 static int osrfRouterClassHandleIncoming( osrfRouter* router,
36 const char* classname, osrfRouterClass* class );
37 static transport_message* osrfRouterClassHandleBounce( osrfRouter* router,
38 const char* classname, osrfRouterClass* rclass, transport_message* msg );
39 static int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg );
40 static int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg,
42 static int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg,
44 static int osrfRouterHandleAppResponse( osrfRouter* router,
45 transport_message* msg, osrfMessage* omsg, const jsonObject* response );
46 static int osrfRouterHandleMethodNFound( osrfRouter* router, transport_message* msg,
49 #define ROUTER_SOCKFD connection->session->sock_id
50 #define ROUTER_REGISTER "register"
51 #define ROUTER_UNREGISTER "unregister"
54 #define ROUTER_REQUEST_CLASS_LIST "opensrf.router.info.class.list"
55 #define ROUTER_REQUEST_STATS_NODE_FULL "opensrf.router.info.stats.class.node.all"
56 #define ROUTER_REQUEST_STATS_CLASS_FULL "opensrf.router.info.stats.class.all"
57 #define ROUTER_REQUEST_STATS_CLASS "opensrf.router.info.stats.class"
58 #define ROUTER_REQUEST_STATS_CLASS_SUMMARY "opensrf.router.info.stats.class.summary"
60 osrfRouter* osrfNewRouter(
61 const char* domain, const char* name,
62 const char* resource, const char* password, int port,
63 osrfStringArray* trustedClients, osrfStringArray* trustedServers ) {
65 if(!( domain && name && resource && password && port && trustedClients && trustedServers )) return NULL;
67 osrfRouter* router = safe_malloc(sizeof(osrfRouter));
68 router->domain = strdup(domain);
69 router->name = strdup(name);
70 router->password = strdup(password);
71 router->resource = strdup(resource);
74 router->trustedClients = trustedClients;
75 router->trustedServers = trustedServers;
78 router->classes = osrfNewHash();
79 osrfHashSetCallback(router->classes, &osrfRouterClassFree);
81 router->connection = client_init( domain, port, NULL, 0 );
88 int osrfRouterConnect( osrfRouter* router ) {
89 if(!router) return -1;
90 int ret = client_connect( router->connection, router->name,
91 router->password, router->resource, 10, AUTH_DIGEST );
92 if( ret == 0 ) return -1;
97 void osrfRouterRun( osrfRouter* router ) {
98 if(!(router && router->classes)) return;
100 int routerfd = router->ROUTER_SOCKFD;
106 int maxfd = _osrfRouterFillFDSet( router, &set );
109 if( (selectret = select(maxfd + 1, &set, NULL, NULL, NULL)) < 0 ) {
110 osrfLogWarning( OSRF_LOG_MARK, "Top level select call failed with errno %d", errno);
114 /* see if there is a top level router message */
116 if( FD_ISSET(routerfd, &set) ) {
117 osrfLogDebug( OSRF_LOG_MARK, "Top router socket is active: %d", routerfd );
119 osrfRouterHandleIncoming( router );
123 /* now check each of the connected classes and see if they have data to route */
124 while( numhandled < selectret ) {
126 osrfRouterClass* class;
127 osrfHashIterator* itr = osrfNewHashIterator(router->classes);
129 while( (class = osrfHashIteratorNext(itr)) ) {
131 const char* classname = osrfHashIteratorKey(itr);
133 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
135 osrfLogDebug( OSRF_LOG_MARK, "Checking %s for activity...", classname );
137 int sockfd = class->ROUTER_SOCKFD;
138 if(FD_ISSET( sockfd, &set )) {
139 osrfLogDebug( OSRF_LOG_MARK, "Socket is active: %d", sockfd );
141 osrfRouterClassHandleIncoming( router, classname, class );
146 osrfHashIteratorFree(itr);
153 Utility method for handling incoming requests to the router
154 and making sure the sender is allowed.
156 static void osrfRouterHandleIncoming( osrfRouter* router ) {
159 transport_message* msg = NULL;
161 //if( (msg = client_recv( router->connection, 0 )) ) {
162 while( (msg = client_recv( router->connection, 0 )) ) {
166 osrfLogDebug(OSRF_LOG_MARK,
167 "osrfRouterHandleIncoming(): investigating message from %s", msg->sender);
169 /* if the sender is not a trusted server, drop the message */
170 int len = strlen(msg->sender) + 1;
172 memset(domain, 0, sizeof(domain));
173 jid_get_domain( msg->sender, domain, len - 1 );
175 if(osrfStringArrayContains( router->trustedServers, domain))
176 osrfRouterHandleMessage( router, msg );
178 osrfLogWarning( OSRF_LOG_MARK, "Received message from un-trusted server domain %s", msg->sender);
186 Utility method for handling incoming requests to a router class,
187 makes sure sender is a trusted client
189 static int osrfRouterClassHandleIncoming( osrfRouter* router, const char* classname,
190 osrfRouterClass* class ) {
191 if(!(router && class)) return -1;
193 transport_message* msg;
194 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleIncoming()");
196 while( (msg = client_recv( class->connection, 0 )) ) {
198 osrfLogSetXid(msg->osrf_xid);
202 osrfLogDebug(OSRF_LOG_MARK,
203 "osrfRouterClassHandleIncoming(): investigating message from %s", msg->sender);
205 /* if the client is not from a trusted domain, drop the message */
206 int len = strlen(msg->sender) + 1;
208 memset(domain, 0, sizeof(domain));
209 jid_get_domain( msg->sender, domain, len - 1 );
211 if(osrfStringArrayContains( router->trustedClients, domain)) {
213 transport_message* bouncedMessage = NULL;
214 if( msg->is_error ) {
216 /* handle bounced message */
217 if( !(bouncedMessage = osrfRouterClassHandleBounce( router, classname, class, msg )) )
218 return -1; /* we have no one to send the requested message to */
221 msg = bouncedMessage;
223 osrfRouterClassHandleMessage( router, class, msg );
226 osrfLogWarning( OSRF_LOG_MARK, "Received client message from untrusted client domain %s", domain );
241 Handles top level router messages
244 static int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg ) {
245 if(!(router && msg)) return -1;
247 if( !msg->router_command || !strcmp(msg->router_command,""))
248 return osrfRouterHandleAppRequest( router, msg ); /* assume it's an app session level request */
250 if(!msg->router_class) return -1;
252 osrfRouterClass* class = NULL;
253 if(!strcmp(msg->router_command, ROUTER_REGISTER)) {
254 class = osrfRouterFindClass( router, msg->router_class );
256 osrfLogInfo( OSRF_LOG_MARK, "Registering class %s", msg->router_class );
258 if(!class) class = osrfRouterAddClass( router, msg->router_class );
262 if( osrfRouterClassFindNode( class, msg->sender ) )
265 osrfRouterClassAddNode( class, msg->sender );
269 } else if( !strcmp( msg->router_command, ROUTER_UNREGISTER ) ) {
271 if( msg->router_class && strcmp( msg->router_class, "") ) {
272 osrfLogInfo( OSRF_LOG_MARK, "Unregistering router class %s", msg->router_class );
273 osrfRouterClassRemoveNode( router, msg->router_class, msg->sender );
283 Allocates and adds a new router class handler to the router's list of handlers.
284 Also connects the class handler to the network at <routername>@domain/<classname>
285 @param router The current router instance
286 @param classname The name of the class this node handles.
287 @return 0 on success, -1 on connection error.
289 static osrfRouterClass* osrfRouterAddClass( osrfRouter* router, const char* classname ) {
290 if(!(router && router->classes && classname)) return NULL;
292 osrfRouterClass* class = safe_malloc(sizeof(osrfRouterClass));
293 class->nodes = osrfNewHash();
294 class->itr = osrfNewHashIterator(class->nodes);
295 osrfHashSetCallback(class->nodes, &osrfRouterNodeFree);
296 class->router = router;
298 class->connection = client_init( router->domain, router->port, NULL, 0 );
300 if(!client_connect( class->connection, router->name,
301 router->password, classname, 10, AUTH_DIGEST ) ) {
302 // We cast away the constness of classname. Though ugly, this
303 // cast is benign because osrfRouterClassFree doesn't actually
304 // write through the pointer. We can't readily change its
305 // signature because it is used for a function pointer, and
306 // we would have to change other signatures the same way.
307 osrfRouterClassFree( (char *) classname, class );
311 osrfHashSet( router->classes, class, classname );
317 Adds a new server node to the given class.
318 @param rclass The Router class to add the node to
319 @param remoteId The remote login of this node
320 @return 0 on success, -1 on generic error
322 static int osrfRouterClassAddNode( osrfRouterClass* rclass, const char* remoteId ) {
323 if(!(rclass && rclass->nodes && remoteId)) return -1;
325 osrfLogInfo( OSRF_LOG_MARK, "Adding router node for remote id %s", remoteId );
327 osrfRouterNode* node = safe_malloc(sizeof(osrfRouterNode));
329 node->lastMessage = NULL;
330 node->remoteId = strdup(remoteId);
332 osrfHashSet( rclass->nodes, node, remoteId );
336 /* copy off the lastMessage, remove the offending node, send error if it's tht last node
337 ? return NULL if it's the last node ?
340 /* handles case where router node is not longer reachable. copies over the
341 data from the last sent message and returns a newly crafted suitable for treating
342 as a newly inconing message. Removes the dead node and If there are no more
343 nodes to send the new message to, returns NULL.
345 static transport_message* osrfRouterClassHandleBounce( osrfRouter* router,
346 const char* classname, osrfRouterClass* rclass, transport_message* msg ) {
348 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleBounce()");
350 osrfLogInfo( OSRF_LOG_MARK, "Received network layer error message from %s", msg->sender );
351 osrfRouterNode* node = osrfRouterClassFindNode( rclass, msg->sender );
352 transport_message* lastSent = NULL;
354 if( node && osrfHashGetCount(rclass->nodes) == 1 ) { /* the last node is dead */
356 if( node->lastMessage ) {
357 osrfLogWarning( OSRF_LOG_MARK, "We lost the last node in the class, responding with error and removing...");
359 transport_message* error = message_init(
360 node->lastMessage->body, node->lastMessage->subject,
361 node->lastMessage->thread, node->lastMessage->router_from, node->lastMessage->recipient );
362 message_set_osrf_xid(error, node->lastMessage->osrf_xid);
363 set_msg_error( error, "cancel", 501 );
365 /* send the error message back to the original sender */
366 client_send_message( rclass->connection, error );
367 message_free( error );
375 if( node->lastMessage ) {
376 osrfLogDebug( OSRF_LOG_MARK, "Cloning lastMessage so next node can send it");
377 lastSent = message_init( node->lastMessage->body,
378 node->lastMessage->subject, node->lastMessage->thread, "", node->lastMessage->router_from );
379 message_set_router_info( lastSent, node->lastMessage->router_from, NULL, NULL, NULL, 0 );
380 message_set_osrf_xid( lastSent, node->lastMessage->osrf_xid );
384 osrfLogInfo(OSRF_LOG_MARK, "network error occurred after we removed the class.. ignoring");
389 /* remove the dead node */
390 osrfRouterClassRemoveNode( router, classname, msg->sender);
396 Handles class level requests
397 If we get a regular message, we send it to the next node in the list of nodes
398 if we get an error, it's a bounce back from a previous attempt. We take the
399 body and thread from the last sent on the node that had the bounced message
400 and propogate them on to the new message being sent
403 static int osrfRouterClassHandleMessage(
404 osrfRouter* router, osrfRouterClass* rclass, transport_message* msg ) {
405 if(!(router && rclass && msg)) return -1;
407 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleMessage()");
409 osrfRouterNode* node = osrfHashIteratorNext( rclass->itr );
411 osrfHashIteratorReset(rclass->itr);
412 node = osrfHashIteratorNext( rclass->itr );
417 transport_message* new_msg= message_init( msg->body,
418 msg->subject, msg->thread, node->remoteId, msg->sender );
419 message_set_router_info( new_msg, msg->sender, NULL, NULL, NULL, 0 );
420 message_set_osrf_xid( new_msg, msg->osrf_xid );
422 osrfLogInfo( OSRF_LOG_MARK, "Routing message:\nfrom: [%s]\nto: [%s]",
423 new_msg->router_from, new_msg->recipient );
425 message_free( node->lastMessage );
426 node->lastMessage = new_msg;
428 if ( client_send_message( rclass->connection, new_msg ) == 0 )
432 message_prepare_xml(new_msg);
433 osrfLogWarning( OSRF_LOG_MARK, "Error sending message from %s to %s\n%s",
434 new_msg->sender, new_msg->recipient, new_msg->msg_xml );
444 Removes a given class from the router, freeing as it goes
446 static int osrfRouterRemoveClass( osrfRouter* router, const char* classname ) {
447 if(!(router && router->classes && classname)) return -1;
448 osrfLogInfo( OSRF_LOG_MARK, "Removing router class %s", classname );
449 osrfHashRemove( router->classes, classname );
455 Removes the given node from the class. Also, if this is that last node in the set,
456 removes the class from the router
457 @return 0 on successful removal with no class removal
458 @return 1 on successful remove with class removal
459 @return -1 error on removal
461 static int osrfRouterClassRemoveNode(
462 osrfRouter* router, const char* classname, const char* remoteId ) {
464 if(!(router && router->classes && classname && remoteId)) return 0;
466 osrfLogInfo( OSRF_LOG_MARK, "Removing router node %s", remoteId );
468 osrfRouterClass* class = osrfRouterFindClass( router, classname );
472 osrfHashRemove( class->nodes, remoteId );
473 if( osrfHashGetCount(class->nodes) == 0 ) {
474 osrfRouterRemoveClass( router, classname );
486 Frees a router class object
487 Takes a void* since it is freed by the hash code
489 static void osrfRouterClassFree( char* classname, void* c ) {
490 if(!(classname && c)) return;
491 osrfRouterClass* rclass = (osrfRouterClass*) c;
492 client_disconnect( rclass->connection );
493 client_free( rclass->connection );
495 osrfHashIteratorReset( rclass->itr );
496 osrfRouterNode* node;
498 while( (node = osrfHashIteratorNext(rclass->itr)) )
499 osrfRouterClassRemoveNode( rclass->router, classname, node->remoteId );
501 osrfHashIteratorFree(rclass->itr);
502 osrfHashFree(rclass->nodes);
509 Frees a router node object
510 Takes a void* since it is freed by the list code
512 static void osrfRouterNodeFree( char* remoteId, void* n ) {
514 osrfRouterNode* node = (osrfRouterNode*) n;
515 free(node->remoteId);
516 message_free(node->lastMessage);
521 void osrfRouterFree( osrfRouter* router ) {
524 osrfHashFree(router->classes);
525 free(router->domain);
527 free(router->resource);
528 free(router->password);
530 osrfStringArrayFree( router->trustedClients );
531 osrfStringArrayFree( router->trustedServers );
533 client_free( router->connection );
540 Finds the class associated with the given class name in the list of classes
542 static osrfRouterClass* osrfRouterFindClass( osrfRouter* router, const char* classname ) {
543 if(!( router && router->classes && classname )) return NULL;
544 return (osrfRouterClass*) osrfHashGet( router->classes, classname );
549 Finds the router node within this class with the given remote id
551 static osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass,
552 const char* remoteId ) {
553 if(!(rclass && remoteId)) return NULL;
554 return (osrfRouterNode*) osrfHashGet( rclass->nodes, remoteId );
559 Clears and populates the provided fd_set* with file descriptors
560 from the router's top level connection as well as each of the
561 router class connections
562 @return The largest file descriptor found in the filling process
564 static int _osrfRouterFillFDSet( osrfRouter* router, fd_set* set ) {
565 if(!(router && router->classes && set)) return -1;
568 int maxfd = router->ROUTER_SOCKFD;
573 osrfRouterClass* class = NULL;
574 osrfHashIterator* itr = osrfNewHashIterator(router->classes);
576 while( (class = osrfHashIteratorNext(itr)) ) {
577 const char* classname = osrfHashIteratorKey(itr);
579 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
580 sockid = class->ROUTER_SOCKFD;
582 if( osrfUtilsCheckFileDescriptor( sockid ) ) {
584 osrfLogWarning(OSRF_LOG_MARK,
585 "Removing router class '%s' because of a bad top-level file descriptor [%d]", classname, sockid);
586 osrfRouterRemoveClass( router, classname );
589 if( sockid > maxfd ) maxfd = sockid;
595 osrfHashIteratorFree(itr);
600 handles messages that don't have a 'router_command' set. They are assumed to
601 be app request messages
603 static int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg ) {
607 memset(arr, 0, sizeof(arr));
609 int num_msgs = osrf_message_deserialize( msg->body, arr, T );
610 osrfMessage* omsg = NULL;
613 for( i = 0; i != num_msgs; i++ ) {
615 if( !(omsg = arr[i]) ) continue;
617 switch( omsg->m_type ) {
620 osrfRouterRespondConnect( router, msg, omsg );
624 osrfRouterProcessAppRequest( router, msg, omsg );
630 osrfMessageFree( omsg );
636 static int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg,
637 osrfMessage* omsg ) {
638 if(!(router && msg && omsg)) return -1;
640 osrfMessage* success = osrf_message_init( STATUS, omsg->thread_trace, omsg->protocol );
642 osrfLogDebug( OSRF_LOG_MARK, "router received a CONNECT message from %s", msg->sender );
644 osrf_message_set_status_info(
645 success, "osrfConnectStatus", "Connection Successful", OSRF_STATUS_OK );
647 char* data = osrf_message_serialize(success);
649 transport_message* return_m = message_init(
650 data, "", msg->thread, msg->sender, "" );
652 client_send_message(router->connection, return_m);
655 osrfMessageFree(success);
656 message_free(return_m);
663 static int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg,
664 osrfMessage* omsg ) {
666 if(!(router && msg && omsg && omsg->method_name)) return -1;
668 osrfLogInfo( OSRF_LOG_MARK, "Router received app request: %s", omsg->method_name );
670 jsonObject* jresponse = NULL;
671 if(!strcmp( omsg->method_name, ROUTER_REQUEST_CLASS_LIST )) {
674 jresponse = jsonNewObjectType(JSON_ARRAY);
676 osrfStringArray* keys = osrfHashKeys( router->classes );
677 for( i = 0; i != keys->size; i++ )
678 jsonObjectPush( jresponse, jsonNewObject(osrfStringArrayGetString( keys, i )) );
679 osrfStringArrayFree(keys);
682 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_SUMMARY )) {
684 osrfRouterClass* class;
685 osrfRouterNode* node;
688 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
693 class = osrfHashGet(router->classes, classname);
696 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
697 while( (node = osrfHashIteratorNext(node_itr)) ) {
698 count += node->count;
699 //jsonObjectSetKey( class_res, node->remoteId, jsonNewNumberObject( (double) node->count ) );
701 osrfHashIteratorFree(node_itr);
703 jresponse = jsonNewNumberObject( (double) count );
705 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS )) {
707 osrfRouterClass* class;
708 osrfRouterNode* node;
710 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
715 jresponse = jsonNewObjectType(JSON_HASH);
716 class = osrfHashGet(router->classes, classname);
719 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
720 while( (node = osrfHashIteratorNext(node_itr)) ) {
721 jsonObjectSetKey( jresponse, node->remoteId, jsonNewNumberObject( (double) node->count ) );
723 osrfHashIteratorFree(node_itr);
725 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_FULL )) {
727 osrfRouterClass* class;
728 osrfRouterNode* node;
729 jresponse = jsonNewObjectType(JSON_HASH);
731 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
732 while( (class = osrfHashIteratorNext(class_itr)) ) {
734 jsonObject* class_res = jsonNewObjectType(JSON_HASH);
735 const char* classname = osrfHashIteratorKey(class_itr);
737 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
738 while( (node = osrfHashIteratorNext(node_itr)) ) {
739 jsonObjectSetKey( class_res, node->remoteId, jsonNewNumberObject( (double) node->count ) );
741 osrfHashIteratorFree(node_itr);
743 jsonObjectSetKey( jresponse, classname, class_res );
746 osrfHashIteratorFree(class_itr);
748 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_NODE_FULL )) {
750 osrfRouterClass* class;
751 osrfRouterNode* node;
753 jresponse = jsonNewObjectType(JSON_HASH);
755 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
756 while( (class = osrfHashIteratorNext(class_itr)) ) {
759 const char* classname = osrfHashIteratorKey(class_itr);
761 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
762 while( (node = osrfHashIteratorNext(node_itr)) ) {
763 count += node->count;
765 osrfHashIteratorFree(node_itr);
767 jsonObjectSetKey( jresponse, classname, jsonNewNumberObject( (double) count ) );
770 osrfHashIteratorFree(class_itr);
774 return osrfRouterHandleMethodNFound( router, msg, omsg );
778 osrfRouterHandleAppResponse( router, msg, omsg, jresponse );
779 jsonObjectFree(jresponse);
787 static int osrfRouterHandleMethodNFound(
788 osrfRouter* router, transport_message* msg, osrfMessage* omsg ) {
790 osrfMessage* err = osrf_message_init( STATUS, omsg->thread_trace, 1);
791 osrf_message_set_status_info( err,
792 "osrfMethodException", "Router method not found", OSRF_STATUS_NOTFOUND );
794 char* data = osrf_message_serialize(err);
796 transport_message* tresponse = message_init(
797 data, "", msg->thread, msg->sender, msg->recipient );
799 client_send_message(router->connection, tresponse );
802 osrfMessageFree( err );
803 message_free(tresponse);
809 static int osrfRouterHandleAppResponse( osrfRouter* router,
810 transport_message* msg, osrfMessage* omsg, const jsonObject* response ) {
812 if( response ) { /* send the response message */
814 osrfMessage* oresponse = osrf_message_init(
815 RESULT, omsg->thread_trace, omsg->protocol );
817 char* json = jsonObjectToJSON(response);
818 osrf_message_set_result_content( oresponse, json);
820 char* data = osrf_message_serialize(oresponse);
821 osrfLogDebug( OSRF_LOG_MARK, "Responding to client app request with data: \n%s\n", data );
823 transport_message* tresponse = message_init(
824 data, "", msg->thread, msg->sender, msg->recipient );
826 client_send_message(router->connection, tresponse );
828 osrfMessageFree(oresponse);
829 message_free(tresponse);
835 /* now send the 'request complete' message */
836 osrfMessage* status = osrf_message_init( STATUS, omsg->thread_trace, 1);
837 osrf_message_set_status_info( status, "osrfConnectStatus", "Request Complete", OSRF_STATUS_COMPLETE );
839 char* statusdata = osrf_message_serialize(status);
841 transport_message* sresponse = message_init(
842 statusdata, "", msg->thread, msg->sender, msg->recipient );
843 client_send_message(router->connection, sresponse );
847 osrfMessageFree(status);
848 message_free(sresponse);