1 #include "osrf_router.h"
5 @brief Implementation of osrfRouter.
9 @brief Maintains a set of server nodes belonging to the same class.
11 struct _osrfRouterClassStruct {
12 osrfRouter* router; /**< The osrfRouter that owns this osrfRouterClass. */
13 osrfHashIterator* itr; /**< Iterator for set of osrfRouterNodes. */
15 @brief Hash store of server nodes.
17 The key of each entry is a node name, and the associated data is an osrfRouterNode.
18 We install a callback for freeing the entries.
21 transport_client* connection;
23 typedef struct _osrfRouterClassStruct osrfRouterClass;
26 @brief Represents a link to a single server's inbound connection.
28 struct _osrfRouterNodeStruct {
29 char* remoteId; /**< Send message to me via this login. */
30 int count; /**< How many message have been sent to this node. */
31 transport_message* lastMessage;
33 typedef struct _osrfRouterNodeStruct osrfRouterNode;
35 static osrfRouterClass* osrfRouterAddClass( osrfRouter* router, const char* classname );
36 static int osrfRouterClassAddNode( osrfRouterClass* rclass, const char* remoteId );
37 static int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg );
38 static int osrfRouterClassHandleMessage( osrfRouter* router,
39 osrfRouterClass* rclass, transport_message* msg );
40 static int osrfRouterRemoveClass( osrfRouter* router, const char* classname );
41 static int osrfRouterClassRemoveNode( osrfRouter* router, const char* classname,
42 const char* remoteId );
43 static void osrfRouterClassFree( char* classname, void* rclass );
44 static void osrfRouterNodeFree( char* remoteId, void* node );
45 static osrfRouterClass* osrfRouterFindClass( osrfRouter* router, const char* classname );
46 static osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass,
47 const char* remoteId );
48 static int _osrfRouterFillFDSet( osrfRouter* router, fd_set* set );
49 static void osrfRouterHandleIncoming( osrfRouter* router );
50 static int osrfRouterClassHandleIncoming( osrfRouter* router,
51 const char* classname, osrfRouterClass* class );
52 static transport_message* osrfRouterClassHandleBounce( osrfRouter* router,
53 const char* classname, osrfRouterClass* rclass, transport_message* msg );
54 static int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg );
55 static int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg,
57 static int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg,
59 static int osrfRouterHandleAppResponse( osrfRouter* router,
60 transport_message* msg, osrfMessage* omsg, const jsonObject* response );
61 static int osrfRouterHandleMethodNFound( osrfRouter* router, transport_message* msg,
64 #define ROUTER_SOCKFD connection->session->sock_id
65 #define ROUTER_REGISTER "register"
66 #define ROUTER_UNREGISTER "unregister"
69 #define ROUTER_REQUEST_CLASS_LIST "opensrf.router.info.class.list"
70 #define ROUTER_REQUEST_STATS_NODE_FULL "opensrf.router.info.stats.class.node.all"
71 #define ROUTER_REQUEST_STATS_CLASS_FULL "opensrf.router.info.stats.class.all"
72 #define ROUTER_REQUEST_STATS_CLASS "opensrf.router.info.stats.class"
73 #define ROUTER_REQUEST_STATS_CLASS_SUMMARY "opensrf.router.info.stats.class.summary"
76 @brief Stop the otherwise infinite main loop of the router.
77 @param router Pointer to the osrfRouter to be stopped.
79 To be called by a signal handler.
81 void router_stop( osrfRouter* router )
88 @brief Allocate and initialize a new osrfRouter.
89 @param domain Domain name of Jabber server
90 @param name Router's username for the Jabber logon.
91 @param resource Router's resource name for the Jabber logon.
92 @param password Router's password for the Jabber logon.
93 @param port Jabber's port number.
94 @param trustedClients The array of client domains that we allow to send requests through us.
95 @param trustedServers The array of server domains that we allow to register, etc. with us.
96 @return Pointer to the newly allocated osrfRouter.
98 Don't connect to Jabber yet. We'll do that later, upon a call to osrfRouterConnect().
100 The calling code is responsible for freeing the osrfRouter by calling osrfRouterFree().
102 osrfRouter* osrfNewRouter(
103 const char* domain, const char* name,
104 const char* resource, const char* password, int port,
105 osrfStringArray* trustedClients, osrfStringArray* trustedServers ) {
107 if(!( domain && name && resource && password && port && trustedClients && trustedServers ))
110 osrfRouter* router = safe_malloc(sizeof(osrfRouter));
111 router->domain = strdup(domain);
112 router->name = strdup(name);
113 router->password = strdup(password);
114 router->resource = strdup(resource);
118 router->trustedClients = trustedClients;
119 router->trustedServers = trustedServers;
122 router->classes = osrfNewHash();
123 osrfHashSetCallback(router->classes, &osrfRouterClassFree);
125 // Prepare to connect to Jabber, as a non-component, over TCP (not UNIX domain).
126 router->connection = client_init( domain, port, NULL, 0 );
132 @brief Connect to Jabber.
133 @param router Pointer to the osrfRouter to connect to Jabber
134 @return 0 if successful, or -1 on error.
136 Allow up to 10 seconds for the logon to succeed.
138 We connect over TCP (not over a UNIX domain), as a non-component.
140 int osrfRouterConnect( osrfRouter* router ) {
141 if(!router) return -1;
142 int ret = client_connect( router->connection, router->name,
143 router->password, router->resource, 10, AUTH_DIGEST );
144 if( ret == 0 ) return -1;
148 void osrfRouterRun( osrfRouter* router ) {
149 if(!(router && router->classes)) return;
151 int routerfd = router->ROUTER_SOCKFD;
154 while( ! router->stop ) {
157 int maxfd = _osrfRouterFillFDSet( router, &set );
160 if( (selectret = select(maxfd + 1, &set, NULL, NULL, NULL)) < 0 ) {
161 if( EINTR == errno ) {
163 osrfLogWarning( OSRF_LOG_MARK, "Top level select call interrupted by signal" );
167 continue; // Irrelevant signal; ignore it
169 osrfLogWarning( OSRF_LOG_MARK,
170 "Top level select call failed with errno %d", errno);
175 /* see if there is a top level router message */
177 if( FD_ISSET(routerfd, &set) ) {
178 osrfLogDebug( OSRF_LOG_MARK, "Top router socket is active: %d", routerfd );
180 osrfRouterHandleIncoming( router );
183 /* now check each of the connected classes and see if they have data to route */
184 while( numhandled < selectret ) {
186 osrfRouterClass* class;
187 osrfHashIterator* itr = osrfNewHashIterator(router->classes);
189 while( (class = osrfHashIteratorNext(itr)) ) {
191 const char* classname = osrfHashIteratorKey(itr);
193 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
195 osrfLogDebug( OSRF_LOG_MARK, "Checking %s for activity...", classname );
197 int sockfd = class->ROUTER_SOCKFD;
198 if(FD_ISSET( sockfd, &set )) {
199 osrfLogDebug( OSRF_LOG_MARK, "Socket is active: %d", sockfd );
201 osrfRouterClassHandleIncoming( router, classname, class );
206 osrfHashIteratorFree(itr);
213 @brief Handle incoming requests to the router and make sure the sender is allowed.
214 @param router Pointer to the osrfRouter.
216 static void osrfRouterHandleIncoming( osrfRouter* router ) {
219 transport_message* msg = NULL;
221 while( (msg = client_recv( router->connection, 0 )) ) {
225 osrfLogDebug(OSRF_LOG_MARK,
226 "osrfRouterHandleIncoming(): investigating message from %s", msg->sender);
228 /* if the sender is not a trusted server, drop the message */
229 int len = strlen(msg->sender) + 1;
231 memset(domain, 0, sizeof(domain));
232 jid_get_domain( msg->sender, domain, len - 1 );
234 if(osrfStringArrayContains( router->trustedServers, domain))
235 osrfRouterHandleMessage( router, msg );
237 osrfLogWarning( OSRF_LOG_MARK,
238 "Received message from un-trusted server domain %s", msg->sender);
246 @brief Handle incoming requests to a router class.
247 @param router Pointer to the osrfRouter.
248 @param classname Class name.
249 @param class Pointer to an osrfRouterClass.
251 Make sure sender is a trusted client.
253 static int osrfRouterClassHandleIncoming( osrfRouter* router, const char* classname,
254 osrfRouterClass* class ) {
255 if(!(router && class)) return -1;
257 transport_message* msg;
258 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleIncoming()");
260 while( (msg = client_recv( class->connection, 0 )) ) {
262 osrfLogSetXid(msg->osrf_xid);
266 osrfLogDebug(OSRF_LOG_MARK,
267 "osrfRouterClassHandleIncoming(): investigating message from %s", msg->sender);
269 /* if the client is not from a trusted domain, drop the message */
270 int len = strlen(msg->sender) + 1;
272 memset(domain, 0, sizeof(domain));
273 jid_get_domain( msg->sender, domain, len - 1 );
275 if(osrfStringArrayContains( router->trustedClients, domain)) {
277 transport_message* bouncedMessage = NULL;
278 if( msg->is_error ) {
280 /* handle bounced message */
281 if( !(bouncedMessage = osrfRouterClassHandleBounce( router, classname,
283 return -1; /* we have no one to send the requested message to */
286 msg = bouncedMessage;
288 osrfRouterClassHandleMessage( router, class, msg );
291 osrfLogWarning( OSRF_LOG_MARK,
292 "Received client message from untrusted client domain %s", domain );
304 @brief Handle a top level router message.
305 @param router Pointer to the osrfRouter.
306 @param msg Pointer to the transport_message to be handled.
307 @return 0 on success.
309 static int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg ) {
310 if(!(router && msg)) return -1;
312 if( !msg->router_command || !strcmp(msg->router_command,""))
313 /* assume it's an app session level request */
314 return osrfRouterHandleAppRequest( router, msg );
316 if(!msg->router_class) return -1;
318 osrfRouterClass* class = NULL;
319 if(!strcmp(msg->router_command, ROUTER_REGISTER)) {
320 class = osrfRouterFindClass( router, msg->router_class );
322 osrfLogInfo( OSRF_LOG_MARK, "Registering class %s", msg->router_class );
324 if(!class) class = osrfRouterAddClass( router, msg->router_class );
328 if( osrfRouterClassFindNode( class, msg->sender ) )
331 osrfRouterClassAddNode( class, msg->sender );
335 } else if( !strcmp( msg->router_command, ROUTER_UNREGISTER ) ) {
337 if( msg->router_class && strcmp( msg->router_class, "") ) {
338 osrfLogInfo( OSRF_LOG_MARK, "Unregistering router class %s", msg->router_class );
339 osrfRouterClassRemoveNode( router, msg->router_class, msg->sender );
349 @brief Adds a new router class handler to the router's list of handlers.
350 @param router The current router instance.
351 @param classname The name of the class this node handles.
352 @return 0 on success, -1 on connection error.
354 Also connects the class handler to the network at "routername@domain/classname".
356 static osrfRouterClass* osrfRouterAddClass( osrfRouter* router, const char* classname ) {
357 if(!(router && router->classes && classname)) return NULL;
359 osrfRouterClass* class = safe_malloc(sizeof(osrfRouterClass));
360 class->nodes = osrfNewHash();
361 class->itr = osrfNewHashIterator(class->nodes);
362 osrfHashSetCallback(class->nodes, &osrfRouterNodeFree);
363 class->router = router;
365 class->connection = client_init( router->domain, router->port, NULL, 0 );
367 if(!client_connect( class->connection, router->name,
368 router->password, classname, 10, AUTH_DIGEST ) ) {
369 // We cast away the constness of classname. Though ugly, this
370 // cast is benign because osrfRouterClassFree doesn't actually
371 // write through the pointer. We can't readily change its
372 // signature because it is used for a function pointer, and
373 // we would have to change other signatures the same way.
374 osrfRouterClassFree( (char *) classname, class );
378 osrfHashSet( router->classes, class, classname );
384 @brief Add a new server node to the given class.
385 @param rclass The Router class to add the node to.
386 @param remoteId The remote login of this node.
387 @return 0 on success, -1 on generic error.
389 static int osrfRouterClassAddNode( osrfRouterClass* rclass, const char* remoteId ) {
390 if(!(rclass && rclass->nodes && remoteId)) return -1;
392 osrfLogInfo( OSRF_LOG_MARK, "Adding router node for remote id %s", remoteId );
394 osrfRouterNode* node = safe_malloc(sizeof(osrfRouterNode));
396 node->lastMessage = NULL;
397 node->remoteId = strdup(remoteId);
399 osrfHashSet( rclass->nodes, node, remoteId );
403 /* copy off the lastMessage, remove the offending node, send error if it's tht last node
404 ? return NULL if it's the last node ?
407 /* handles case where router node is not longer reachable. copies over the
408 data from the last sent message and returns a newly crafted suitable for treating
409 as a newly inconing message. Removes the dead node and If there are no more
410 nodes to send the new message to, returns NULL.
412 static transport_message* osrfRouterClassHandleBounce( osrfRouter* router,
413 const char* classname, osrfRouterClass* rclass, transport_message* msg ) {
415 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleBounce()");
417 osrfLogInfo( OSRF_LOG_MARK, "Received network layer error message from %s", msg->sender );
418 osrfRouterNode* node = osrfRouterClassFindNode( rclass, msg->sender );
419 transport_message* lastSent = NULL;
421 if( node && osrfHashGetCount(rclass->nodes) == 1 ) { /* the last node is dead */
423 if( node->lastMessage ) {
424 osrfLogWarning( OSRF_LOG_MARK,
425 "We lost the last node in the class, responding with error and removing...");
427 transport_message* error = message_init(
428 node->lastMessage->body, node->lastMessage->subject,
429 node->lastMessage->thread, node->lastMessage->router_from,
430 node->lastMessage->recipient );
431 message_set_osrf_xid(error, node->lastMessage->osrf_xid);
432 set_msg_error( error, "cancel", 501 );
434 /* send the error message back to the original sender */
435 client_send_message( rclass->connection, error );
436 message_free( error );
444 if( node->lastMessage ) {
445 osrfLogDebug( OSRF_LOG_MARK, "Cloning lastMessage so next node can send it");
446 lastSent = message_init( node->lastMessage->body,
447 node->lastMessage->subject, node->lastMessage->thread, "", node->lastMessage->router_from );
448 message_set_router_info( lastSent, node->lastMessage->router_from, NULL, NULL, NULL, 0 );
449 message_set_osrf_xid( lastSent, node->lastMessage->osrf_xid );
453 osrfLogInfo(OSRF_LOG_MARK, "network error occurred after we removed the class.. ignoring");
458 /* remove the dead node */
459 osrfRouterClassRemoveNode( router, classname, msg->sender);
465 Handles class level requests
466 If we get a regular message, we send it to the next node in the list of nodes
467 if we get an error, it's a bounce back from a previous attempt. We take the
468 body and thread from the last sent on the node that had the bounced message
469 and propogate them on to the new message being sent
472 static int osrfRouterClassHandleMessage(
473 osrfRouter* router, osrfRouterClass* rclass, transport_message* msg ) {
474 if(!(router && rclass && msg)) return -1;
476 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleMessage()");
478 osrfRouterNode* node = osrfHashIteratorNext( rclass->itr );
480 osrfHashIteratorReset(rclass->itr);
481 node = osrfHashIteratorNext( rclass->itr );
486 transport_message* new_msg= message_init( msg->body,
487 msg->subject, msg->thread, node->remoteId, msg->sender );
488 message_set_router_info( new_msg, msg->sender, NULL, NULL, NULL, 0 );
489 message_set_osrf_xid( new_msg, msg->osrf_xid );
491 osrfLogInfo( OSRF_LOG_MARK, "Routing message:\nfrom: [%s]\nto: [%s]",
492 new_msg->router_from, new_msg->recipient );
494 message_free( node->lastMessage );
495 node->lastMessage = new_msg;
497 if ( client_send_message( rclass->connection, new_msg ) == 0 )
501 message_prepare_xml(new_msg);
502 osrfLogWarning( OSRF_LOG_MARK, "Error sending message from %s to %s\n%s",
503 new_msg->sender, new_msg->recipient, new_msg->msg_xml );
513 @brief Remove a given class from the router, freeing as it goes
514 @param router Pointer to the osrfRouter.
515 @param classname The name of the class to be removed.
516 @return 0 if successful, or -1 upon error.
518 The only error conditions are when one of the parameters is NULL, or when the
519 class name is an empty string.
521 static int osrfRouterRemoveClass( osrfRouter* router, const char* classname ) {
522 if(!(router && router->classes && classname)) return -1;
523 osrfLogInfo( OSRF_LOG_MARK, "Removing router class %s", classname );
524 osrfHashRemove( router->classes, classname );
530 Removes the given node from the class. Also, if this is that last node in the set,
531 removes the class from the router
532 @return 0 on successful removal with no class removal
533 @return 1 on successful remove with class removal
534 @return -1 error on removal
536 static int osrfRouterClassRemoveNode(
537 osrfRouter* router, const char* classname, const char* remoteId ) {
539 if(!(router && router->classes && classname && remoteId)) return 0;
541 osrfLogInfo( OSRF_LOG_MARK, "Removing router node %s", remoteId );
543 osrfRouterClass* class = osrfRouterFindClass( router, classname );
547 osrfHashRemove( class->nodes, remoteId );
548 if( osrfHashGetCount(class->nodes) == 0 ) {
549 osrfRouterRemoveClass( router, classname );
561 @brief Free a router class object.
562 @param classname Class name.
563 @param c Pointer to the osrfRouterClass, cast to a void pointer.
565 This function is designated to the osrfHash as a callback.
567 static void osrfRouterClassFree( char* classname, void* c ) {
568 if(!(classname && c)) return;
569 osrfRouterClass* rclass = (osrfRouterClass*) c;
570 client_disconnect( rclass->connection );
571 client_free( rclass->connection );
573 osrfHashIteratorReset( rclass->itr );
574 osrfRouterNode* node;
576 while( (node = osrfHashIteratorNext(rclass->itr)) )
577 osrfHashRemove( rclass->nodes, node->remoteId );
579 osrfHashIteratorFree(rclass->itr);
580 osrfHashFree(rclass->nodes);
586 @brief Free an osrfRouterNode.
587 @param remoteId Name of router (not used).
588 @param n Pointer to the osrfRouterNode to be freed, cast to a void pointer.
590 This is a callback installed in an osrfHash (the nodes member of an osrfRouterClass).
592 static void osrfRouterNodeFree( char* remoteId, void* n ) {
594 osrfRouterNode* node = (osrfRouterNode*) n;
595 free(node->remoteId);
596 message_free(node->lastMessage);
601 void osrfRouterFree( osrfRouter* router ) {
604 osrfHashFree(router->classes);
605 free(router->domain);
607 free(router->resource);
608 free(router->password);
610 osrfStringArrayFree( router->trustedClients );
611 osrfStringArrayFree( router->trustedServers );
613 client_free( router->connection );
620 Finds the class associated with the given class name in the list of classes
622 static osrfRouterClass* osrfRouterFindClass( osrfRouter* router, const char* classname ) {
623 if(!( router && router->classes && classname )) return NULL;
624 return (osrfRouterClass*) osrfHashGet( router->classes, classname );
629 Finds the router node within this class with the given remote id
631 static osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass,
632 const char* remoteId ) {
633 if(!(rclass && remoteId)) return NULL;
634 return (osrfRouterNode*) osrfHashGet( rclass->nodes, remoteId );
639 Clears and populates the provided fd_set* with file descriptors
640 from the router's top level connection as well as each of the
641 router class connections
642 @return The largest file descriptor found in the filling process
645 @brief Fill an fd_set with all the sockets owned by the osrfRouter.
646 @param router Pointer to the osrfRouter whose sockets are to be used.
647 @param set Pointer to the fd_set that is to be filled.
648 @return The largest file descriptor loaded into the fd_set; or -1 upon error.
650 There's one socket for the osrfRouter as a whole, and one for each osrfRouterClass
651 that belongs to it. We load them all.
653 static int _osrfRouterFillFDSet( osrfRouter* router, fd_set* set ) {
654 if(!(router && router->classes && set)) return -1;
657 int maxfd = router->ROUTER_SOCKFD;
662 osrfRouterClass* class = NULL;
663 osrfHashIterator* itr = osrfNewHashIterator(router->classes);
665 while( (class = osrfHashIteratorNext(itr)) ) {
666 const char* classname = osrfHashIteratorKey(itr);
668 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
669 sockid = class->ROUTER_SOCKFD;
671 if( osrfUtilsCheckFileDescriptor( sockid ) ) {
673 osrfLogWarning(OSRF_LOG_MARK,
674 "Removing router class '%s' because of a bad top-level file descriptor [%d]",
676 osrfRouterRemoveClass( router, classname );
679 if( sockid > maxfd ) maxfd = sockid;
685 osrfHashIteratorFree(itr);
690 handles messages that don't have a 'router_command' set. They are assumed to
691 be app request messages
693 static int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg ) {
697 memset(arr, 0, sizeof(arr));
699 int num_msgs = osrf_message_deserialize( msg->body, arr, T );
700 osrfMessage* omsg = NULL;
703 for( i = 0; i != num_msgs; i++ ) {
705 if( !(omsg = arr[i]) ) continue;
707 switch( omsg->m_type ) {
710 osrfRouterRespondConnect( router, msg, omsg );
714 osrfRouterProcessAppRequest( router, msg, omsg );
720 osrfMessageFree( omsg );
726 static int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg,
727 osrfMessage* omsg ) {
728 if(!(router && msg && omsg)) return -1;
730 osrfMessage* success = osrf_message_init( STATUS, omsg->thread_trace, omsg->protocol );
732 osrfLogDebug( OSRF_LOG_MARK, "router received a CONNECT message from %s", msg->sender );
734 osrf_message_set_status_info(
735 success, "osrfConnectStatus", "Connection Successful", OSRF_STATUS_OK );
737 char* data = osrf_message_serialize(success);
739 transport_message* return_m = message_init(
740 data, "", msg->thread, msg->sender, "" );
742 client_send_message(router->connection, return_m);
745 osrfMessageFree(success);
746 message_free(return_m);
753 static int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg,
754 osrfMessage* omsg ) {
756 if(!(router && msg && omsg && omsg->method_name)) return -1;
758 osrfLogInfo( OSRF_LOG_MARK, "Router received app request: %s", omsg->method_name );
760 jsonObject* jresponse = NULL;
761 if(!strcmp( omsg->method_name, ROUTER_REQUEST_CLASS_LIST )) {
764 jresponse = jsonNewObjectType(JSON_ARRAY);
766 osrfStringArray* keys = osrfHashKeys( router->classes );
767 for( i = 0; i != keys->size; i++ )
768 jsonObjectPush( jresponse, jsonNewObject(osrfStringArrayGetString( keys, i )) );
769 osrfStringArrayFree(keys);
772 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_SUMMARY )) {
774 osrfRouterClass* class;
775 osrfRouterNode* node;
778 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
783 class = osrfHashGet(router->classes, classname);
786 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
787 while( (node = osrfHashIteratorNext(node_itr)) ) {
788 count += node->count;
789 //jsonObjectSetKey( class_res, node->remoteId, jsonNewNumberObject( (double) node->count ) );
791 osrfHashIteratorFree(node_itr);
793 jresponse = jsonNewNumberObject( (double) count );
795 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS )) {
797 osrfRouterClass* class;
798 osrfRouterNode* node;
800 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
805 jresponse = jsonNewObjectType(JSON_HASH);
806 class = osrfHashGet(router->classes, classname);
809 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
810 while( (node = osrfHashIteratorNext(node_itr)) ) {
811 jsonObjectSetKey( jresponse, node->remoteId,
812 jsonNewNumberObject( (double) node->count ) );
814 osrfHashIteratorFree(node_itr);
816 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_FULL )) {
818 osrfRouterClass* class;
819 osrfRouterNode* node;
820 jresponse = jsonNewObjectType(JSON_HASH);
822 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
823 while( (class = osrfHashIteratorNext(class_itr)) ) {
825 jsonObject* class_res = jsonNewObjectType(JSON_HASH);
826 const char* classname = osrfHashIteratorKey(class_itr);
828 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
829 while( (node = osrfHashIteratorNext(node_itr)) ) {
830 jsonObjectSetKey( class_res, node->remoteId,
831 jsonNewNumberObject( (double) node->count ) );
833 osrfHashIteratorFree(node_itr);
835 jsonObjectSetKey( jresponse, classname, class_res );
838 osrfHashIteratorFree(class_itr);
840 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_NODE_FULL )) {
842 osrfRouterClass* class;
843 osrfRouterNode* node;
845 jresponse = jsonNewObjectType(JSON_HASH);
847 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
848 while( (class = osrfHashIteratorNext(class_itr)) ) {
851 const char* classname = osrfHashIteratorKey(class_itr);
853 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
854 while( (node = osrfHashIteratorNext(node_itr)) ) {
855 count += node->count;
857 osrfHashIteratorFree(node_itr);
859 jsonObjectSetKey( jresponse, classname, jsonNewNumberObject( (double) count ) );
862 osrfHashIteratorFree(class_itr);
866 return osrfRouterHandleMethodNFound( router, msg, omsg );
870 osrfRouterHandleAppResponse( router, msg, omsg, jresponse );
871 jsonObjectFree(jresponse);
878 static int osrfRouterHandleMethodNFound(
879 osrfRouter* router, transport_message* msg, osrfMessage* omsg ) {
881 osrfMessage* err = osrf_message_init( STATUS, omsg->thread_trace, 1);
882 osrf_message_set_status_info( err,
883 "osrfMethodException", "Router method not found", OSRF_STATUS_NOTFOUND );
885 char* data = osrf_message_serialize(err);
887 transport_message* tresponse = message_init(
888 data, "", msg->thread, msg->sender, msg->recipient );
890 client_send_message(router->connection, tresponse );
893 osrfMessageFree( err );
894 message_free(tresponse);
899 static int osrfRouterHandleAppResponse( osrfRouter* router,
900 transport_message* msg, osrfMessage* omsg, const jsonObject* response ) {
902 if( response ) { /* send the response message */
904 osrfMessage* oresponse = osrf_message_init(
905 RESULT, omsg->thread_trace, omsg->protocol );
907 char* json = jsonObjectToJSON(response);
908 osrf_message_set_result_content( oresponse, json);
910 char* data = osrf_message_serialize(oresponse);
911 osrfLogDebug( OSRF_LOG_MARK, "Responding to client app request with data: \n%s\n", data );
913 transport_message* tresponse = message_init(
914 data, "", msg->thread, msg->sender, msg->recipient );
916 client_send_message(router->connection, tresponse );
918 osrfMessageFree(oresponse);
919 message_free(tresponse);
924 /* now send the 'request complete' message */
925 osrfMessage* status = osrf_message_init( STATUS, omsg->thread_trace, 1);
926 osrf_message_set_status_info( status, "osrfConnectStatus", "Request Complete",
927 OSRF_STATUS_COMPLETE );
929 char* statusdata = osrf_message_serialize(status);
931 transport_message* sresponse = message_init(
932 statusdata, "", msg->thread, msg->sender, msg->recipient );
933 client_send_message(router->connection, sresponse );
936 osrfMessageFree(status);
937 message_free(sresponse);