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 Allocate and initialize a new osrfRouter.
77 @param domain Domain name of Jabber server
78 @param name Router's username for the Jabber logon.
79 @param resource Router's resource name for the Jabber logon.
80 @param password Router's password for the Jabber logon.
81 @param port Jabber's port number.
82 @param trustedClients The array of client domains that we allow to send requests through us.
83 @param trustedServers The array of server domains that we allow to register, etc. with us.
84 @return Pointer to the newly allocated osrfRouter.
86 Don't connect to Jabber yet. We'll do that later, upon a call to osrfRouterConnect().
88 The calling code is responsible for freeing the osrfRouter by calling osrfRouterFree().
90 osrfRouter* osrfNewRouter(
91 const char* domain, const char* name,
92 const char* resource, const char* password, int port,
93 osrfStringArray* trustedClients, osrfStringArray* trustedServers ) {
95 if(!( domain && name && resource && password && port && trustedClients && trustedServers ))
98 osrfRouter* router = safe_malloc(sizeof(osrfRouter));
99 router->domain = strdup(domain);
100 router->name = strdup(name);
101 router->password = strdup(password);
102 router->resource = strdup(resource);
105 router->trustedClients = trustedClients;
106 router->trustedServers = trustedServers;
109 router->classes = osrfNewHash();
110 osrfHashSetCallback(router->classes, &osrfRouterClassFree);
112 // Prepare to connect to Jabber, as a non-component, over TCP (not UNIX domain).
113 router->connection = client_init( domain, port, NULL, 0 );
119 @brief Connect to Jabber.
120 @param router Pointer to the osrfRouter to connect to Jabber
121 @return 0 if successful, or -1 on error.
123 Allow up to 10 seconds for the logon to succeed.
125 We connect over TCP (not over a UNIX domain), as a non-component.
127 int osrfRouterConnect( osrfRouter* router ) {
128 if(!router) return -1;
129 int ret = client_connect( router->connection, router->name,
130 router->password, router->resource, 10, AUTH_DIGEST );
131 if( ret == 0 ) return -1;
135 void osrfRouterRun( osrfRouter* router ) {
136 if(!(router && router->classes)) return;
138 int routerfd = router->ROUTER_SOCKFD;
144 int maxfd = _osrfRouterFillFDSet( router, &set );
147 if( (selectret = select(maxfd + 1, &set, NULL, NULL, NULL)) < 0 ) {
148 osrfLogWarning( OSRF_LOG_MARK, "Top level select call failed with errno %d", errno);
152 /* see if there is a top level router message */
154 if( FD_ISSET(routerfd, &set) ) {
155 osrfLogDebug( OSRF_LOG_MARK, "Top router socket is active: %d", routerfd );
157 osrfRouterHandleIncoming( router );
161 /* now check each of the connected classes and see if they have data to route */
162 while( numhandled < selectret ) {
164 osrfRouterClass* class;
165 osrfHashIterator* itr = osrfNewHashIterator(router->classes);
167 while( (class = osrfHashIteratorNext(itr)) ) {
169 const char* classname = osrfHashIteratorKey(itr);
171 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
173 osrfLogDebug( OSRF_LOG_MARK, "Checking %s for activity...", classname );
175 int sockfd = class->ROUTER_SOCKFD;
176 if(FD_ISSET( sockfd, &set )) {
177 osrfLogDebug( OSRF_LOG_MARK, "Socket is active: %d", sockfd );
179 osrfRouterClassHandleIncoming( router, classname, class );
184 osrfHashIteratorFree(itr);
191 @brief Handle incoming requests to the router and make sure the sender is allowed.
192 @param router Pointer to the osrfRouter.
194 static void osrfRouterHandleIncoming( osrfRouter* router ) {
197 transport_message* msg = NULL;
199 while( (msg = client_recv( router->connection, 0 )) ) {
203 osrfLogDebug(OSRF_LOG_MARK,
204 "osrfRouterHandleIncoming(): investigating message from %s", msg->sender);
206 /* if the sender is not a trusted server, drop the message */
207 int len = strlen(msg->sender) + 1;
209 memset(domain, 0, sizeof(domain));
210 jid_get_domain( msg->sender, domain, len - 1 );
212 if(osrfStringArrayContains( router->trustedServers, domain))
213 osrfRouterHandleMessage( router, msg );
215 osrfLogWarning( OSRF_LOG_MARK,
216 "Received message from un-trusted server domain %s", msg->sender);
224 @brief Handle incoming requests to a router class.
225 @param router Pointer to the osrfRouter.
226 @param classname Class name.
227 @param class Pointer to an osrfRouterClass.
229 Make sure sender is a trusted client.
231 static int osrfRouterClassHandleIncoming( osrfRouter* router, const char* classname,
232 osrfRouterClass* class ) {
233 if(!(router && class)) return -1;
235 transport_message* msg;
236 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleIncoming()");
238 while( (msg = client_recv( class->connection, 0 )) ) {
240 osrfLogSetXid(msg->osrf_xid);
244 osrfLogDebug(OSRF_LOG_MARK,
245 "osrfRouterClassHandleIncoming(): investigating message from %s", msg->sender);
247 /* if the client is not from a trusted domain, drop the message */
248 int len = strlen(msg->sender) + 1;
250 memset(domain, 0, sizeof(domain));
251 jid_get_domain( msg->sender, domain, len - 1 );
253 if(osrfStringArrayContains( router->trustedClients, domain)) {
255 transport_message* bouncedMessage = NULL;
256 if( msg->is_error ) {
258 /* handle bounced message */
259 if( !(bouncedMessage = osrfRouterClassHandleBounce( router, classname,
261 return -1; /* we have no one to send the requested message to */
264 msg = bouncedMessage;
266 osrfRouterClassHandleMessage( router, class, msg );
269 osrfLogWarning( OSRF_LOG_MARK,
270 "Received client message from untrusted client domain %s", domain );
282 @brief Handle a top level router message.
283 @param router Pointer to the osrfRouter.
284 @param msg Pointer to the transport_message to be handled.
285 @return 0 on success.
287 static int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg ) {
288 if(!(router && msg)) return -1;
290 if( !msg->router_command || !strcmp(msg->router_command,""))
291 /* assume it's an app session level request */
292 return osrfRouterHandleAppRequest( router, msg );
294 if(!msg->router_class) return -1;
296 osrfRouterClass* class = NULL;
297 if(!strcmp(msg->router_command, ROUTER_REGISTER)) {
298 class = osrfRouterFindClass( router, msg->router_class );
300 osrfLogInfo( OSRF_LOG_MARK, "Registering class %s", msg->router_class );
302 if(!class) class = osrfRouterAddClass( router, msg->router_class );
306 if( osrfRouterClassFindNode( class, msg->sender ) )
309 osrfRouterClassAddNode( class, msg->sender );
313 } else if( !strcmp( msg->router_command, ROUTER_UNREGISTER ) ) {
315 if( msg->router_class && strcmp( msg->router_class, "") ) {
316 osrfLogInfo( OSRF_LOG_MARK, "Unregistering router class %s", msg->router_class );
317 osrfRouterClassRemoveNode( router, msg->router_class, msg->sender );
327 @brief Adds a new router class handler to the router's list of handlers.
328 @param router The current router instance.
329 @param classname The name of the class this node handles.
330 @return 0 on success, -1 on connection error.
332 Also connects the class handler to the network at "routername@domain/classname".
334 static osrfRouterClass* osrfRouterAddClass( osrfRouter* router, const char* classname ) {
335 if(!(router && router->classes && classname)) return NULL;
337 osrfRouterClass* class = safe_malloc(sizeof(osrfRouterClass));
338 class->nodes = osrfNewHash();
339 class->itr = osrfNewHashIterator(class->nodes);
340 osrfHashSetCallback(class->nodes, &osrfRouterNodeFree);
341 class->router = router;
343 class->connection = client_init( router->domain, router->port, NULL, 0 );
345 if(!client_connect( class->connection, router->name,
346 router->password, classname, 10, AUTH_DIGEST ) ) {
347 // We cast away the constness of classname. Though ugly, this
348 // cast is benign because osrfRouterClassFree doesn't actually
349 // write through the pointer. We can't readily change its
350 // signature because it is used for a function pointer, and
351 // we would have to change other signatures the same way.
352 osrfRouterClassFree( (char *) classname, class );
356 osrfHashSet( router->classes, class, classname );
362 @brief Add a new server node to the given class.
363 @param rclass The Router class to add the node to.
364 @param remoteId The remote login of this node.
365 @return 0 on success, -1 on generic error.
367 static int osrfRouterClassAddNode( osrfRouterClass* rclass, const char* remoteId ) {
368 if(!(rclass && rclass->nodes && remoteId)) return -1;
370 osrfLogInfo( OSRF_LOG_MARK, "Adding router node for remote id %s", remoteId );
372 osrfRouterNode* node = safe_malloc(sizeof(osrfRouterNode));
374 node->lastMessage = NULL;
375 node->remoteId = strdup(remoteId);
377 osrfHashSet( rclass->nodes, node, remoteId );
381 /* copy off the lastMessage, remove the offending node, send error if it's tht last node
382 ? return NULL if it's the last node ?
385 /* handles case where router node is not longer reachable. copies over the
386 data from the last sent message and returns a newly crafted suitable for treating
387 as a newly inconing message. Removes the dead node and If there are no more
388 nodes to send the new message to, returns NULL.
390 static transport_message* osrfRouterClassHandleBounce( osrfRouter* router,
391 const char* classname, osrfRouterClass* rclass, transport_message* msg ) {
393 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleBounce()");
395 osrfLogInfo( OSRF_LOG_MARK, "Received network layer error message from %s", msg->sender );
396 osrfRouterNode* node = osrfRouterClassFindNode( rclass, msg->sender );
397 transport_message* lastSent = NULL;
399 if( node && osrfHashGetCount(rclass->nodes) == 1 ) { /* the last node is dead */
401 if( node->lastMessage ) {
402 osrfLogWarning( OSRF_LOG_MARK,
403 "We lost the last node in the class, responding with error and removing...");
405 transport_message* error = message_init(
406 node->lastMessage->body, node->lastMessage->subject,
407 node->lastMessage->thread, node->lastMessage->router_from,
408 node->lastMessage->recipient );
409 message_set_osrf_xid(error, node->lastMessage->osrf_xid);
410 set_msg_error( error, "cancel", 501 );
412 /* send the error message back to the original sender */
413 client_send_message( rclass->connection, error );
414 message_free( error );
422 if( node->lastMessage ) {
423 osrfLogDebug( OSRF_LOG_MARK, "Cloning lastMessage so next node can send it");
424 lastSent = message_init( node->lastMessage->body,
425 node->lastMessage->subject, node->lastMessage->thread, "", node->lastMessage->router_from );
426 message_set_router_info( lastSent, node->lastMessage->router_from, NULL, NULL, NULL, 0 );
427 message_set_osrf_xid( lastSent, node->lastMessage->osrf_xid );
431 osrfLogInfo(OSRF_LOG_MARK, "network error occurred after we removed the class.. ignoring");
436 /* remove the dead node */
437 osrfRouterClassRemoveNode( router, classname, msg->sender);
443 Handles class level requests
444 If we get a regular message, we send it to the next node in the list of nodes
445 if we get an error, it's a bounce back from a previous attempt. We take the
446 body and thread from the last sent on the node that had the bounced message
447 and propogate them on to the new message being sent
450 static int osrfRouterClassHandleMessage(
451 osrfRouter* router, osrfRouterClass* rclass, transport_message* msg ) {
452 if(!(router && rclass && msg)) return -1;
454 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleMessage()");
456 osrfRouterNode* node = osrfHashIteratorNext( rclass->itr );
458 osrfHashIteratorReset(rclass->itr);
459 node = osrfHashIteratorNext( rclass->itr );
464 transport_message* new_msg= message_init( msg->body,
465 msg->subject, msg->thread, node->remoteId, msg->sender );
466 message_set_router_info( new_msg, msg->sender, NULL, NULL, NULL, 0 );
467 message_set_osrf_xid( new_msg, msg->osrf_xid );
469 osrfLogInfo( OSRF_LOG_MARK, "Routing message:\nfrom: [%s]\nto: [%s]",
470 new_msg->router_from, new_msg->recipient );
472 message_free( node->lastMessage );
473 node->lastMessage = new_msg;
475 if ( client_send_message( rclass->connection, new_msg ) == 0 )
479 message_prepare_xml(new_msg);
480 osrfLogWarning( OSRF_LOG_MARK, "Error sending message from %s to %s\n%s",
481 new_msg->sender, new_msg->recipient, new_msg->msg_xml );
491 @brief Remove a given class from the router, freeing as it goes
492 @param router Pointer to the osrfRouter.
493 @param classname The name of the class to be removed.
494 @return 0 if successful, or -1 upon error.
496 The only error conditions are when one of the parameters is NULL, or when the
497 class name is an empty string.
499 static int osrfRouterRemoveClass( osrfRouter* router, const char* classname ) {
500 if(!(router && router->classes && classname)) return -1;
501 osrfLogInfo( OSRF_LOG_MARK, "Removing router class %s", classname );
502 osrfHashRemove( router->classes, classname );
508 Removes the given node from the class. Also, if this is that last node in the set,
509 removes the class from the router
510 @return 0 on successful removal with no class removal
511 @return 1 on successful remove with class removal
512 @return -1 error on removal
514 static int osrfRouterClassRemoveNode(
515 osrfRouter* router, const char* classname, const char* remoteId ) {
517 if(!(router && router->classes && classname && remoteId)) return 0;
519 osrfLogInfo( OSRF_LOG_MARK, "Removing router node %s", remoteId );
521 osrfRouterClass* class = osrfRouterFindClass( router, classname );
525 osrfHashRemove( class->nodes, remoteId );
526 if( osrfHashGetCount(class->nodes) == 0 ) {
527 osrfRouterRemoveClass( router, classname );
539 @brief Free a router class object.
540 @param classname Class name.
541 @param c Pointer to the osrfRouterClass, cast to a void pointer.
543 This function is designated to the osrfHash as a callback.
545 static void osrfRouterClassFree( char* classname, void* c ) {
546 if(!(classname && c)) return;
547 osrfRouterClass* rclass = (osrfRouterClass*) c;
548 client_disconnect( rclass->connection );
549 client_free( rclass->connection );
551 osrfHashIteratorReset( rclass->itr );
552 osrfRouterNode* node;
554 while( (node = osrfHashIteratorNext(rclass->itr)) )
555 osrfRouterClassRemoveNode( rclass->router, classname, node->remoteId );
557 osrfHashIteratorFree(rclass->itr);
558 osrfHashFree(rclass->nodes);
564 @brief Free an osrfRouterNode.
565 @param remoteId Name of router (not used).
566 @param n Pointer to the osrfRouterNode to be freed, cast to a void pointer.
568 This is a callback installed in an osrfHash (the nodes member of an osrfRouterClass).
570 static void osrfRouterNodeFree( char* remoteId, void* n ) {
572 osrfRouterNode* node = (osrfRouterNode*) n;
573 free(node->remoteId);
574 message_free(node->lastMessage);
579 void osrfRouterFree( osrfRouter* router ) {
582 osrfHashFree(router->classes);
583 free(router->domain);
585 free(router->resource);
586 free(router->password);
588 osrfStringArrayFree( router->trustedClients );
589 osrfStringArrayFree( router->trustedServers );
591 client_free( router->connection );
598 Finds the class associated with the given class name in the list of classes
600 static osrfRouterClass* osrfRouterFindClass( osrfRouter* router, const char* classname ) {
601 if(!( router && router->classes && classname )) return NULL;
602 return (osrfRouterClass*) osrfHashGet( router->classes, classname );
607 Finds the router node within this class with the given remote id
609 static osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass,
610 const char* remoteId ) {
611 if(!(rclass && remoteId)) return NULL;
612 return (osrfRouterNode*) osrfHashGet( rclass->nodes, remoteId );
617 Clears and populates the provided fd_set* with file descriptors
618 from the router's top level connection as well as each of the
619 router class connections
620 @return The largest file descriptor found in the filling process
623 @brief Fill an fd_set with all the sockets owned by the osrfRouter.
624 @param router Pointer to the osrfRouter whose sockets are to be used.
625 @param set Pointer to the fd_set that is to be filled.
626 @return The largest file descriptor loaded into the fd_set; or -1 upon error.
628 There's one socket for the osrfRouter as a whole, and one for each osrfRouterClass
629 that belongs to it. We load them all.
631 static int _osrfRouterFillFDSet( osrfRouter* router, fd_set* set ) {
632 if(!(router && router->classes && set)) return -1;
635 int maxfd = router->ROUTER_SOCKFD;
640 osrfRouterClass* class = NULL;
641 osrfHashIterator* itr = osrfNewHashIterator(router->classes);
643 while( (class = osrfHashIteratorNext(itr)) ) {
644 const char* classname = osrfHashIteratorKey(itr);
646 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
647 sockid = class->ROUTER_SOCKFD;
649 if( osrfUtilsCheckFileDescriptor( sockid ) ) {
651 osrfLogWarning(OSRF_LOG_MARK,
652 "Removing router class '%s' because of a bad top-level file descriptor [%d]",
654 osrfRouterRemoveClass( router, classname );
657 if( sockid > maxfd ) maxfd = sockid;
663 osrfHashIteratorFree(itr);
668 handles messages that don't have a 'router_command' set. They are assumed to
669 be app request messages
671 static int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg ) {
675 memset(arr, 0, sizeof(arr));
677 int num_msgs = osrf_message_deserialize( msg->body, arr, T );
678 osrfMessage* omsg = NULL;
681 for( i = 0; i != num_msgs; i++ ) {
683 if( !(omsg = arr[i]) ) continue;
685 switch( omsg->m_type ) {
688 osrfRouterRespondConnect( router, msg, omsg );
692 osrfRouterProcessAppRequest( router, msg, omsg );
698 osrfMessageFree( omsg );
704 static int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg,
705 osrfMessage* omsg ) {
706 if(!(router && msg && omsg)) return -1;
708 osrfMessage* success = osrf_message_init( STATUS, omsg->thread_trace, omsg->protocol );
710 osrfLogDebug( OSRF_LOG_MARK, "router received a CONNECT message from %s", msg->sender );
712 osrf_message_set_status_info(
713 success, "osrfConnectStatus", "Connection Successful", OSRF_STATUS_OK );
715 char* data = osrf_message_serialize(success);
717 transport_message* return_m = message_init(
718 data, "", msg->thread, msg->sender, "" );
720 client_send_message(router->connection, return_m);
723 osrfMessageFree(success);
724 message_free(return_m);
731 static int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg,
732 osrfMessage* omsg ) {
734 if(!(router && msg && omsg && omsg->method_name)) return -1;
736 osrfLogInfo( OSRF_LOG_MARK, "Router received app request: %s", omsg->method_name );
738 jsonObject* jresponse = NULL;
739 if(!strcmp( omsg->method_name, ROUTER_REQUEST_CLASS_LIST )) {
742 jresponse = jsonNewObjectType(JSON_ARRAY);
744 osrfStringArray* keys = osrfHashKeys( router->classes );
745 for( i = 0; i != keys->size; i++ )
746 jsonObjectPush( jresponse, jsonNewObject(osrfStringArrayGetString( keys, i )) );
747 osrfStringArrayFree(keys);
750 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_SUMMARY )) {
752 osrfRouterClass* class;
753 osrfRouterNode* node;
756 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
761 class = osrfHashGet(router->classes, classname);
764 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
765 while( (node = osrfHashIteratorNext(node_itr)) ) {
766 count += node->count;
767 //jsonObjectSetKey( class_res, node->remoteId, jsonNewNumberObject( (double) node->count ) );
769 osrfHashIteratorFree(node_itr);
771 jresponse = jsonNewNumberObject( (double) count );
773 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS )) {
775 osrfRouterClass* class;
776 osrfRouterNode* node;
778 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
783 jresponse = jsonNewObjectType(JSON_HASH);
784 class = osrfHashGet(router->classes, classname);
787 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
788 while( (node = osrfHashIteratorNext(node_itr)) ) {
789 jsonObjectSetKey( jresponse, node->remoteId,
790 jsonNewNumberObject( (double) node->count ) );
792 osrfHashIteratorFree(node_itr);
794 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_FULL )) {
796 osrfRouterClass* class;
797 osrfRouterNode* node;
798 jresponse = jsonNewObjectType(JSON_HASH);
800 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
801 while( (class = osrfHashIteratorNext(class_itr)) ) {
803 jsonObject* class_res = jsonNewObjectType(JSON_HASH);
804 const char* classname = osrfHashIteratorKey(class_itr);
806 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
807 while( (node = osrfHashIteratorNext(node_itr)) ) {
808 jsonObjectSetKey( class_res, node->remoteId,
809 jsonNewNumberObject( (double) node->count ) );
811 osrfHashIteratorFree(node_itr);
813 jsonObjectSetKey( jresponse, classname, class_res );
816 osrfHashIteratorFree(class_itr);
818 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_NODE_FULL )) {
820 osrfRouterClass* class;
821 osrfRouterNode* node;
823 jresponse = jsonNewObjectType(JSON_HASH);
825 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
826 while( (class = osrfHashIteratorNext(class_itr)) ) {
829 const char* classname = osrfHashIteratorKey(class_itr);
831 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
832 while( (node = osrfHashIteratorNext(node_itr)) ) {
833 count += node->count;
835 osrfHashIteratorFree(node_itr);
837 jsonObjectSetKey( jresponse, classname, jsonNewNumberObject( (double) count ) );
840 osrfHashIteratorFree(class_itr);
844 return osrfRouterHandleMethodNFound( router, msg, omsg );
848 osrfRouterHandleAppResponse( router, msg, omsg, jresponse );
849 jsonObjectFree(jresponse);
856 static int osrfRouterHandleMethodNFound(
857 osrfRouter* router, transport_message* msg, osrfMessage* omsg ) {
859 osrfMessage* err = osrf_message_init( STATUS, omsg->thread_trace, 1);
860 osrf_message_set_status_info( err,
861 "osrfMethodException", "Router method not found", OSRF_STATUS_NOTFOUND );
863 char* data = osrf_message_serialize(err);
865 transport_message* tresponse = message_init(
866 data, "", msg->thread, msg->sender, msg->recipient );
868 client_send_message(router->connection, tresponse );
871 osrfMessageFree( err );
872 message_free(tresponse);
877 static int osrfRouterHandleAppResponse( osrfRouter* router,
878 transport_message* msg, osrfMessage* omsg, const jsonObject* response ) {
880 if( response ) { /* send the response message */
882 osrfMessage* oresponse = osrf_message_init(
883 RESULT, omsg->thread_trace, omsg->protocol );
885 char* json = jsonObjectToJSON(response);
886 osrf_message_set_result_content( oresponse, json);
888 char* data = osrf_message_serialize(oresponse);
889 osrfLogDebug( OSRF_LOG_MARK, "Responding to client app request with data: \n%s\n", data );
891 transport_message* tresponse = message_init(
892 data, "", msg->thread, msg->sender, msg->recipient );
894 client_send_message(router->connection, tresponse );
896 osrfMessageFree(oresponse);
897 message_free(tresponse);
902 /* now send the 'request complete' message */
903 osrfMessage* status = osrf_message_init( STATUS, omsg->thread_trace, 1);
904 osrf_message_set_status_info( status, "osrfConnectStatus", "Request Complete",
905 OSRF_STATUS_COMPLETE );
907 char* statusdata = osrf_message_serialize(status);
909 transport_message* sresponse = message_init(
910 statusdata, "", msg->thread, msg->sender, msg->recipient );
911 client_send_message(router->connection, sresponse );
914 osrfMessageFree(status);
915 message_free(sresponse);