1 #include "osrf_router.h"
5 @brief Implementation of osrfRouter.
8 /* a router maintains a list of server classes */
9 struct osrfRouterStruct {
11 osrfHash* classes; /**< our list of server classes */
12 char* domain; /**< Domain name of Jabber server. */
13 char* name; /**< Router's username for the Jabber logon. */
14 char* resource; /**< Router's resource name for the Jabber logon. */
15 char* password; /**< Router's password for the Jabber logon. */
16 int port; /**< Jabber's port number. */
17 sig_atomic_t stop; /**< To be set by signal handler to interrupt main loop */
19 /** Array of client domains that we allow to send requests through us. */
20 osrfStringArray* trustedClients;
21 /** Array of server domains that we allow to register, etc. with us. */
22 osrfStringArray* trustedServers;
24 transport_client* connection;
28 @brief Maintains a set of server nodes belonging to the same class.
30 struct _osrfRouterClassStruct {
31 osrfRouter* router; /**< The osrfRouter that owns this osrfRouterClass. */
32 osrfHashIterator* itr; /**< Iterator for set of osrfRouterNodes. */
34 @brief Hash store of server nodes.
36 The key of each entry is a node name, and the associated data is an osrfRouterNode.
37 We install a callback for freeing the entries.
40 transport_client* connection;
42 typedef struct _osrfRouterClassStruct osrfRouterClass;
45 @brief Represents a link to a single server's inbound connection.
47 struct _osrfRouterNodeStruct {
48 char* remoteId; /**< Send message to me via this login. */
49 int count; /**< How many message have been sent to this node. */
50 transport_message* lastMessage;
52 typedef struct _osrfRouterNodeStruct osrfRouterNode;
54 static osrfRouterClass* osrfRouterAddClass( osrfRouter* router, const char* classname );
55 static int osrfRouterClassAddNode( osrfRouterClass* rclass, const char* remoteId );
56 static int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg );
57 static int osrfRouterClassHandleMessage( osrfRouter* router,
58 osrfRouterClass* rclass, transport_message* msg );
59 static int osrfRouterRemoveClass( osrfRouter* router, const char* classname );
60 static int osrfRouterClassRemoveNode( osrfRouter* router, const char* classname,
61 const char* remoteId );
62 static void osrfRouterClassFree( char* classname, void* rclass );
63 static void osrfRouterNodeFree( char* remoteId, void* node );
64 static osrfRouterClass* osrfRouterFindClass( osrfRouter* router, const char* classname );
65 static osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass,
66 const char* remoteId );
67 static int _osrfRouterFillFDSet( osrfRouter* router, fd_set* set );
68 static void osrfRouterHandleIncoming( osrfRouter* router );
69 static int osrfRouterClassHandleIncoming( osrfRouter* router,
70 const char* classname, osrfRouterClass* class );
71 static transport_message* osrfRouterClassHandleBounce( osrfRouter* router,
72 const char* classname, osrfRouterClass* rclass, transport_message* msg );
73 static int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg );
74 static int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg,
76 static int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg,
78 static int osrfRouterHandleAppResponse( osrfRouter* router,
79 transport_message* msg, osrfMessage* omsg, const jsonObject* response );
80 static int osrfRouterHandleMethodNFound( osrfRouter* router, transport_message* msg,
83 #define ROUTER_REGISTER "register"
84 #define ROUTER_UNREGISTER "unregister"
86 #define ROUTER_REQUEST_CLASS_LIST "opensrf.router.info.class.list"
87 #define ROUTER_REQUEST_STATS_NODE_FULL "opensrf.router.info.stats.class.node.all"
88 #define ROUTER_REQUEST_STATS_CLASS_FULL "opensrf.router.info.stats.class.all"
89 #define ROUTER_REQUEST_STATS_CLASS "opensrf.router.info.stats.class"
90 #define ROUTER_REQUEST_STATS_CLASS_SUMMARY "opensrf.router.info.stats.class.summary"
93 @brief Stop the otherwise infinite main loop of the router.
94 @param router Pointer to the osrfRouter to be stopped.
96 To be called by a signal handler.
98 void router_stop( osrfRouter* router )
105 @brief Allocate and initialize a new osrfRouter.
106 @param domain Domain name of Jabber server
107 @param name Router's username for the Jabber logon.
108 @param resource Router's resource name for the Jabber logon.
109 @param password Router's password for the Jabber logon.
110 @param port Jabber's port number.
111 @param trustedClients Array of client domains that we allow to send requests through us.
112 @param trustedServers Array of server domains that we allow to register, etc. with us.
113 @return Pointer to the newly allocated osrfRouter.
115 Don't connect to Jabber yet. We'll do that later, upon a call to osrfRouterConnect().
117 The calling code is responsible for freeing the osrfRouter by calling osrfRouterFree().
119 osrfRouter* osrfNewRouter(
120 const char* domain, const char* name,
121 const char* resource, const char* password, int port,
122 osrfStringArray* trustedClients, osrfStringArray* trustedServers ) {
124 if(!( domain && name && resource && password && port && trustedClients && trustedServers ))
127 osrfRouter* router = safe_malloc(sizeof(osrfRouter));
128 router->domain = strdup(domain);
129 router->name = strdup(name);
130 router->password = strdup(password);
131 router->resource = strdup(resource);
135 router->trustedClients = trustedClients;
136 router->trustedServers = trustedServers;
139 router->classes = osrfNewHash();
140 osrfHashSetCallback(router->classes, &osrfRouterClassFree);
142 // Prepare to connect to Jabber, as a non-component, over TCP (not UNIX domain).
143 router->connection = client_init( domain, port, NULL, 0 );
149 @brief Connect to Jabber.
150 @param router Pointer to the osrfRouter to connect to Jabber
151 @return 0 if successful, or -1 on error.
153 Allow up to 10 seconds for the logon to succeed.
155 We connect over TCP (not over a UNIX domain), as a non-component.
157 int osrfRouterConnect( osrfRouter* router ) {
158 if(!router) return -1;
159 int ret = client_connect( router->connection, router->name,
160 router->password, router->resource, 10, AUTH_DIGEST );
161 if( ret == 0 ) return -1;
166 @brief Enter endless loop to receive and respond to input.
167 @param router Pointer to the osrfRouter that's looping.
170 On each iteration: wait for incoming messages to arrive on any of our sockets -- i.e.
171 either the top level socket belong to the router or any of the lower level sockets
172 belonging to the classes. React to the incoming activity as needed.
174 We don't exit the loop until we receive a signal to stop.
176 void osrfRouterRun( osrfRouter* router ) {
177 if(!(router && router->classes)) return;
179 int routerfd = client_sock_fd( router->connection );
182 // Loop until a signal handler sets router->stop
183 while( ! router->stop ) {
186 int maxfd = _osrfRouterFillFDSet( router, &set );
189 if( (selectret = select(maxfd + 1, &set, NULL, NULL, NULL)) < 0 ) {
190 if( EINTR == errno ) {
192 osrfLogWarning( OSRF_LOG_MARK, "Top level select call interrupted by signal" );
196 continue; // Irrelevant signal; ignore it
198 osrfLogWarning( OSRF_LOG_MARK, "Top level select call failed with errno %d: %s",
199 errno, strerror( errno ) );
204 /* see if there is a top level router message */
206 if( FD_ISSET(routerfd, &set) ) {
207 osrfLogDebug( OSRF_LOG_MARK, "Top router socket is active: %d", routerfd );
209 osrfRouterHandleIncoming( router );
212 /* now check each of the connected classes and see if they have data to route */
213 while( numhandled < selectret ) {
215 osrfRouterClass* class;
216 osrfHashIterator* itr = osrfNewHashIterator(router->classes);
218 while( (class = osrfHashIteratorNext(itr)) ) {
220 const char* classname = osrfHashIteratorKey(itr);
222 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
224 osrfLogDebug( OSRF_LOG_MARK, "Checking %s for activity...", classname );
226 int sockfd = client_sock_fd( class->connection );
227 if(FD_ISSET( sockfd, &set )) {
228 osrfLogDebug( OSRF_LOG_MARK, "Socket is active: %d", sockfd );
230 osrfRouterClassHandleIncoming( router, classname, class );
235 osrfHashIteratorFree(itr);
242 @brief Handle incoming requests to the router and make sure the sender is allowed.
243 @param router Pointer to the osrfRouter.
245 static void osrfRouterHandleIncoming( osrfRouter* router ) {
248 transport_message* msg = NULL;
250 while( (msg = client_recv( router->connection, 0 )) ) {
254 osrfLogDebug(OSRF_LOG_MARK,
255 "osrfRouterHandleIncoming(): investigating message from %s", msg->sender);
257 /* if the sender is not a trusted server, drop the message */
258 int len = strlen(msg->sender) + 1;
260 memset(domain, 0, sizeof(domain));
261 jid_get_domain( msg->sender, domain, len - 1 );
263 if(osrfStringArrayContains( router->trustedServers, domain))
264 osrfRouterHandleMessage( router, msg );
266 osrfLogWarning( OSRF_LOG_MARK,
267 "Received message from un-trusted server domain %s", msg->sender);
275 @brief Handle incoming requests to a router class.
276 @param router Pointer to the osrfRouter.
277 @param classname Class name.
278 @param class Pointer to an osrfRouterClass.
280 Make sure sender is a trusted client.
282 static int osrfRouterClassHandleIncoming( osrfRouter* router, const char* classname,
283 osrfRouterClass* class ) {
284 if(!(router && class)) return -1;
286 transport_message* msg;
287 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleIncoming()");
289 while( (msg = client_recv( class->connection, 0 )) ) {
291 osrfLogSetXid(msg->osrf_xid);
295 osrfLogDebug(OSRF_LOG_MARK,
296 "osrfRouterClassHandleIncoming(): investigating message from %s", msg->sender);
298 /* if the client is not from a trusted domain, drop the message */
299 int len = strlen(msg->sender) + 1;
301 memset(domain, 0, sizeof(domain));
302 jid_get_domain( msg->sender, domain, len - 1 );
304 if(osrfStringArrayContains( router->trustedClients, domain)) {
306 transport_message* bouncedMessage = NULL;
307 if( msg->is_error ) {
309 /* handle bounced message */
310 if( !(bouncedMessage = osrfRouterClassHandleBounce( router, classname,
312 return -1; /* we have no one to send the requested message to */
315 msg = bouncedMessage;
317 osrfRouterClassHandleMessage( router, class, msg );
320 osrfLogWarning( OSRF_LOG_MARK,
321 "Received client message from untrusted client domain %s", domain );
333 @brief Handle a top level router message.
334 @param router Pointer to the osrfRouter.
335 @param msg Pointer to the transport_message to be handled.
336 @return 0 on success.
338 static int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg ) {
339 if(!(router && msg)) return -1;
341 if( !msg->router_command || !strcmp(msg->router_command,""))
342 /* assume it's an app session level request */
343 return osrfRouterHandleAppRequest( router, msg );
345 if(!msg->router_class) return -1;
347 osrfRouterClass* class = NULL;
348 if(!strcmp(msg->router_command, ROUTER_REGISTER)) {
349 class = osrfRouterFindClass( router, msg->router_class );
351 osrfLogInfo( OSRF_LOG_MARK, "Registering class %s", msg->router_class );
353 if(!class) class = osrfRouterAddClass( router, msg->router_class );
357 if( osrfRouterClassFindNode( class, msg->sender ) )
360 osrfRouterClassAddNode( class, msg->sender );
364 } else if( !strcmp( msg->router_command, ROUTER_UNREGISTER ) ) {
366 if( msg->router_class && strcmp( msg->router_class, "") ) {
367 osrfLogInfo( OSRF_LOG_MARK, "Unregistering router class %s", msg->router_class );
368 osrfRouterClassRemoveNode( router, msg->router_class, msg->sender );
378 @brief Adds a new router class handler to the router's list of handlers.
379 @param router The current router instance.
380 @param classname The name of the class this node handles.
381 @return 0 on success, -1 on connection error.
383 Also connects the class handler to the network at "routername@domain/classname".
385 static osrfRouterClass* osrfRouterAddClass( osrfRouter* router, const char* classname ) {
386 if(!(router && router->classes && classname)) return NULL;
388 osrfRouterClass* class = safe_malloc(sizeof(osrfRouterClass));
389 class->nodes = osrfNewHash();
390 class->itr = osrfNewHashIterator(class->nodes);
391 osrfHashSetCallback(class->nodes, &osrfRouterNodeFree);
392 class->router = router;
394 class->connection = client_init( router->domain, router->port, NULL, 0 );
396 if(!client_connect( class->connection, router->name,
397 router->password, classname, 10, AUTH_DIGEST ) ) {
398 // We cast away the constness of classname. Though ugly, this
399 // cast is benign because osrfRouterClassFree doesn't actually
400 // write through the pointer. We can't readily change its
401 // signature because it is used for a function pointer, and
402 // we would have to change other signatures the same way.
403 osrfRouterClassFree( (char *) classname, class );
407 osrfHashSet( router->classes, class, classname );
413 @brief Add a new server node to the given class.
414 @param rclass The Router class to add the node to.
415 @param remoteId The remote login of this node.
416 @return 0 on success, -1 on generic error.
418 static int osrfRouterClassAddNode( osrfRouterClass* rclass, const char* remoteId ) {
419 if(!(rclass && rclass->nodes && remoteId)) return -1;
421 osrfLogInfo( OSRF_LOG_MARK, "Adding router node for remote id %s", remoteId );
423 osrfRouterNode* node = safe_malloc(sizeof(osrfRouterNode));
425 node->lastMessage = NULL;
426 node->remoteId = strdup(remoteId);
428 osrfHashSet( rclass->nodes, node, remoteId );
432 /* copy off the lastMessage, remove the offending node, send error if it's tht last node
433 ? return NULL if it's the last node ?
436 /* handles case where router node is not longer reachable. copies over the
437 data from the last sent message and returns a newly crafted suitable for treating
438 as a newly inconing message. Removes the dead node and If there are no more
439 nodes to send the new message to, returns NULL.
441 static transport_message* osrfRouterClassHandleBounce( osrfRouter* router,
442 const char* classname, osrfRouterClass* rclass, transport_message* msg ) {
444 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleBounce()");
446 osrfLogInfo( OSRF_LOG_MARK, "Received network layer error message from %s", msg->sender );
447 osrfRouterNode* node = osrfRouterClassFindNode( rclass, msg->sender );
448 transport_message* lastSent = NULL;
450 if( node && osrfHashGetCount(rclass->nodes) == 1 ) { /* the last node is dead */
452 if( node->lastMessage ) {
453 osrfLogWarning( OSRF_LOG_MARK,
454 "We lost the last node in the class, responding with error and removing...");
456 transport_message* error = message_init(
457 node->lastMessage->body, node->lastMessage->subject,
458 node->lastMessage->thread, node->lastMessage->router_from,
459 node->lastMessage->recipient );
460 message_set_osrf_xid(error, node->lastMessage->osrf_xid);
461 set_msg_error( error, "cancel", 501 );
463 /* send the error message back to the original sender */
464 client_send_message( rclass->connection, error );
465 message_free( error );
473 if( node->lastMessage ) {
474 osrfLogDebug( OSRF_LOG_MARK, "Cloning lastMessage so next node can send it");
475 lastSent = message_init( node->lastMessage->body,
476 node->lastMessage->subject, node->lastMessage->thread, "", node->lastMessage->router_from );
477 message_set_router_info( lastSent, node->lastMessage->router_from, NULL, NULL, NULL, 0 );
478 message_set_osrf_xid( lastSent, node->lastMessage->osrf_xid );
482 osrfLogInfo(OSRF_LOG_MARK, "network error occurred after we removed the class.. ignoring");
487 /* remove the dead node */
488 osrfRouterClassRemoveNode( router, classname, msg->sender);
494 Handles class level requests
495 If we get a regular message, we send it to the next node in the list of nodes
496 if we get an error, it's a bounce back from a previous attempt. We take the
497 body and thread from the last sent on the node that had the bounced message
498 and propogate them on to the new message being sent
501 static int osrfRouterClassHandleMessage(
502 osrfRouter* router, osrfRouterClass* rclass, transport_message* msg ) {
503 if(!(router && rclass && msg)) return -1;
505 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleMessage()");
507 osrfRouterNode* node = osrfHashIteratorNext( rclass->itr );
509 osrfHashIteratorReset(rclass->itr);
510 node = osrfHashIteratorNext( rclass->itr );
515 transport_message* new_msg= message_init( msg->body,
516 msg->subject, msg->thread, node->remoteId, msg->sender );
517 message_set_router_info( new_msg, msg->sender, NULL, NULL, NULL, 0 );
518 message_set_osrf_xid( new_msg, msg->osrf_xid );
520 osrfLogInfo( OSRF_LOG_MARK, "Routing message:\nfrom: [%s]\nto: [%s]",
521 new_msg->router_from, new_msg->recipient );
523 message_free( node->lastMessage );
524 node->lastMessage = new_msg;
526 if ( client_send_message( rclass->connection, new_msg ) == 0 )
530 message_prepare_xml(new_msg);
531 osrfLogWarning( OSRF_LOG_MARK, "Error sending message from %s to %s\n%s",
532 new_msg->sender, new_msg->recipient, new_msg->msg_xml );
542 @brief Remove a given class from the router, freeing as it goes
543 @param router Pointer to the osrfRouter.
544 @param classname The name of the class to be removed.
545 @return 0 if successful, or -1 upon error.
547 The only error conditions are when one of the parameters is NULL, or when the
548 class name is an empty string.
550 static int osrfRouterRemoveClass( osrfRouter* router, const char* classname ) {
551 if(!(router && router->classes && classname)) return -1;
552 osrfLogInfo( OSRF_LOG_MARK, "Removing router class %s", classname );
553 osrfHashRemove( router->classes, classname );
559 Removes the given node from the class. Also, if this is that last node in the set,
560 removes the class from the router
561 @return 0 on successful removal with no class removal
562 @return 1 on successful remove with class removal
563 @return -1 error on removal
565 static int osrfRouterClassRemoveNode(
566 osrfRouter* router, const char* classname, const char* remoteId ) {
568 if(!(router && router->classes && classname && remoteId)) return 0;
570 osrfLogInfo( OSRF_LOG_MARK, "Removing router node %s", remoteId );
572 osrfRouterClass* class = osrfRouterFindClass( router, classname );
576 osrfHashRemove( class->nodes, remoteId );
577 if( osrfHashGetCount(class->nodes) == 0 ) {
578 osrfRouterRemoveClass( router, classname );
590 @brief Free a router class object.
591 @param classname Class name.
592 @param c Pointer to the osrfRouterClass, cast to a void pointer.
594 This function is designated to the osrfHash as a callback.
596 static void osrfRouterClassFree( char* classname, void* c ) {
597 if(!(classname && c)) return;
598 osrfRouterClass* rclass = (osrfRouterClass*) c;
599 client_disconnect( rclass->connection );
600 client_free( rclass->connection );
602 osrfHashIteratorReset( rclass->itr );
603 osrfRouterNode* node;
605 while( (node = osrfHashIteratorNext(rclass->itr)) )
606 osrfHashRemove( rclass->nodes, node->remoteId );
608 osrfHashIteratorFree(rclass->itr);
609 osrfHashFree(rclass->nodes);
615 @brief Free an osrfRouterNode.
616 @param remoteId Name of router (not used).
617 @param n Pointer to the osrfRouterNode to be freed, cast to a void pointer.
619 This is a callback installed in an osrfHash (the nodes member of an osrfRouterClass).
621 static void osrfRouterNodeFree( char* remoteId, void* n ) {
623 osrfRouterNode* node = (osrfRouterNode*) n;
624 free(node->remoteId);
625 message_free(node->lastMessage);
630 void osrfRouterFree( osrfRouter* router ) {
633 osrfHashFree(router->classes);
634 free(router->domain);
636 free(router->resource);
637 free(router->password);
639 osrfStringArrayFree( router->trustedClients );
640 osrfStringArrayFree( router->trustedServers );
642 client_free( router->connection );
649 Finds the class associated with the given class name in the list of classes
651 static osrfRouterClass* osrfRouterFindClass( osrfRouter* router, const char* classname ) {
652 if(!( router && router->classes && classname )) return NULL;
653 return (osrfRouterClass*) osrfHashGet( router->classes, classname );
658 Finds the router node within this class with the given remote id
660 static osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass,
661 const char* remoteId ) {
662 if(!(rclass && remoteId)) return NULL;
663 return (osrfRouterNode*) osrfHashGet( rclass->nodes, remoteId );
668 Clears and populates the provided fd_set* with file descriptors
669 from the router's top level connection as well as each of the
670 router class connections
671 @return The largest file descriptor found in the filling process
674 @brief Fill an fd_set with all the sockets owned by the osrfRouter.
675 @param router Pointer to the osrfRouter whose sockets are to be used.
676 @param set Pointer to the fd_set that is to be filled.
677 @return The largest file descriptor loaded into the fd_set; or -1 upon error.
679 There's one socket for the osrfRouter as a whole, and one for each osrfRouterClass
680 that belongs to it. We load them all.
682 static int _osrfRouterFillFDSet( osrfRouter* router, fd_set* set ) {
683 if(!(router && router->classes && set)) return -1;
686 int maxfd = client_sock_fd( router->connection );
691 osrfRouterClass* class = NULL;
692 osrfHashIterator* itr = osrfNewHashIterator(router->classes);
694 while( (class = osrfHashIteratorNext(itr)) ) {
695 const char* classname = osrfHashIteratorKey(itr);
697 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
698 sockid = client_sock_fd( class->connection );
700 if( osrfUtilsCheckFileDescriptor( sockid ) ) {
702 osrfLogWarning(OSRF_LOG_MARK,
703 "Removing router class '%s' because of a bad top-level file descriptor [%d]",
705 osrfRouterRemoveClass( router, classname );
708 if( sockid > maxfd ) maxfd = sockid;
714 osrfHashIteratorFree(itr);
719 handles messages that don't have a 'router_command' set. They are assumed to
720 be app request messages
722 static int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg ) {
726 memset(arr, 0, sizeof(arr));
728 int num_msgs = osrf_message_deserialize( msg->body, arr, T );
729 osrfMessage* omsg = NULL;
732 for( i = 0; i != num_msgs; i++ ) {
734 if( !(omsg = arr[i]) ) continue;
736 switch( omsg->m_type ) {
739 osrfRouterRespondConnect( router, msg, omsg );
743 osrfRouterProcessAppRequest( router, msg, omsg );
749 osrfMessageFree( omsg );
755 static int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg,
756 osrfMessage* omsg ) {
757 if(!(router && msg && omsg)) return -1;
759 osrfMessage* success = osrf_message_init( STATUS, omsg->thread_trace, omsg->protocol );
761 osrfLogDebug( OSRF_LOG_MARK, "router received a CONNECT message from %s", msg->sender );
763 osrf_message_set_status_info(
764 success, "osrfConnectStatus", "Connection Successful", OSRF_STATUS_OK );
766 char* data = osrf_message_serialize(success);
768 transport_message* return_m = message_init(
769 data, "", msg->thread, msg->sender, "" );
771 client_send_message(router->connection, return_m);
774 osrfMessageFree(success);
775 message_free(return_m);
782 static int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg,
783 osrfMessage* omsg ) {
785 if(!(router && msg && omsg && omsg->method_name)) return -1;
787 osrfLogInfo( OSRF_LOG_MARK, "Router received app request: %s", omsg->method_name );
789 jsonObject* jresponse = NULL;
790 if(!strcmp( omsg->method_name, ROUTER_REQUEST_CLASS_LIST )) {
793 jresponse = jsonNewObjectType(JSON_ARRAY);
795 osrfStringArray* keys = osrfHashKeys( router->classes );
796 for( i = 0; i != keys->size; i++ )
797 jsonObjectPush( jresponse, jsonNewObject(osrfStringArrayGetString( keys, i )) );
798 osrfStringArrayFree(keys);
801 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_SUMMARY )) {
803 osrfRouterClass* class;
804 osrfRouterNode* node;
807 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
812 class = osrfHashGet(router->classes, classname);
815 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
816 while( (node = osrfHashIteratorNext(node_itr)) ) {
817 count += node->count;
818 //jsonObjectSetKey( class_res, node->remoteId, jsonNewNumberObject( (double) node->count ) );
820 osrfHashIteratorFree(node_itr);
822 jresponse = jsonNewNumberObject( (double) count );
824 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS )) {
826 osrfRouterClass* class;
827 osrfRouterNode* node;
829 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
834 jresponse = jsonNewObjectType(JSON_HASH);
835 class = osrfHashGet(router->classes, classname);
838 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
839 while( (node = osrfHashIteratorNext(node_itr)) ) {
840 jsonObjectSetKey( jresponse, node->remoteId,
841 jsonNewNumberObject( (double) node->count ) );
843 osrfHashIteratorFree(node_itr);
845 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_FULL )) {
847 osrfRouterClass* class;
848 osrfRouterNode* node;
849 jresponse = jsonNewObjectType(JSON_HASH);
851 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
852 while( (class = osrfHashIteratorNext(class_itr)) ) {
854 jsonObject* class_res = jsonNewObjectType(JSON_HASH);
855 const char* classname = osrfHashIteratorKey(class_itr);
857 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
858 while( (node = osrfHashIteratorNext(node_itr)) ) {
859 jsonObjectSetKey( class_res, node->remoteId,
860 jsonNewNumberObject( (double) node->count ) );
862 osrfHashIteratorFree(node_itr);
864 jsonObjectSetKey( jresponse, classname, class_res );
867 osrfHashIteratorFree(class_itr);
869 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_NODE_FULL )) {
871 osrfRouterClass* class;
872 osrfRouterNode* node;
874 jresponse = jsonNewObjectType(JSON_HASH);
876 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
877 while( (class = osrfHashIteratorNext(class_itr)) ) {
880 const char* classname = osrfHashIteratorKey(class_itr);
882 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
883 while( (node = osrfHashIteratorNext(node_itr)) ) {
884 count += node->count;
886 osrfHashIteratorFree(node_itr);
888 jsonObjectSetKey( jresponse, classname, jsonNewNumberObject( (double) count ) );
891 osrfHashIteratorFree(class_itr);
895 return osrfRouterHandleMethodNFound( router, msg, omsg );
899 osrfRouterHandleAppResponse( router, msg, omsg, jresponse );
900 jsonObjectFree(jresponse);
907 static int osrfRouterHandleMethodNFound(
908 osrfRouter* router, transport_message* msg, osrfMessage* omsg ) {
910 osrfMessage* err = osrf_message_init( STATUS, omsg->thread_trace, 1);
911 osrf_message_set_status_info( err,
912 "osrfMethodException", "Router method not found", OSRF_STATUS_NOTFOUND );
914 char* data = osrf_message_serialize(err);
916 transport_message* tresponse = message_init(
917 data, "", msg->thread, msg->sender, msg->recipient );
919 client_send_message(router->connection, tresponse );
922 osrfMessageFree( err );
923 message_free(tresponse);
928 static int osrfRouterHandleAppResponse( osrfRouter* router,
929 transport_message* msg, osrfMessage* omsg, const jsonObject* response ) {
931 if( response ) { /* send the response message */
933 osrfMessage* oresponse = osrf_message_init(
934 RESULT, omsg->thread_trace, omsg->protocol );
936 char* json = jsonObjectToJSON(response);
937 osrf_message_set_result_content( oresponse, json);
939 char* data = osrf_message_serialize(oresponse);
940 osrfLogDebug( OSRF_LOG_MARK, "Responding to client app request with data: \n%s\n", data );
942 transport_message* tresponse = message_init(
943 data, "", msg->thread, msg->sender, msg->recipient );
945 client_send_message(router->connection, tresponse );
947 osrfMessageFree(oresponse);
948 message_free(tresponse);
953 /* now send the 'request complete' message */
954 osrfMessage* status = osrf_message_init( STATUS, omsg->thread_trace, 1);
955 osrf_message_set_status_info( status, "osrfConnectStatus", "Request Complete",
956 OSRF_STATUS_COMPLETE );
958 char* statusdata = osrf_message_serialize(status);
960 transport_message* sresponse = message_init(
961 statusdata, "", msg->thread, msg->sender, msg->recipient );
962 client_send_message(router->connection, sresponse );
965 osrfMessageFree(status);
966 message_free(sresponse);