Patch from Scott McKellar:
[OpenSRF.git] / src / router / osrf_router.c
1 #include "osrf_router.h"
2
3 /* a class maintains a set of server nodes */
4 struct _osrfRouterClassStruct {
5         osrfRouter* router; /* our router handle */
6         osrfHashIterator* itr;
7         osrfHash* nodes;
8         transport_client* connection;
9 };
10 typedef struct _osrfRouterClassStruct osrfRouterClass;
11
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;
17 };
18 typedef struct _osrfRouterNodeStruct osrfRouterNode;
19
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,
41                 osrfMessage* omsg );
42 static int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg,
43                 osrfMessage* omsg );
44 static int osrfRouterHandleAppResponse( osrfRouter* router, 
45                 transport_message* msg, osrfMessage* omsg, const jsonObject* response );
46 static int osrfRouterHandleMethodNFound( osrfRouter* router, transport_message* msg,
47                 osrfMessage* omsg );
48
49 #define ROUTER_SOCKFD connection->session->sock_id
50 #define ROUTER_REGISTER "register"
51 #define ROUTER_UNREGISTER "unregister"
52
53
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"
59
60 osrfRouter* osrfNewRouter( 
61                 const char* domain, const char* name, 
62                 const char* resource, const char* password, int port,
63                 osrfStringArray* trustedClients, osrfStringArray* trustedServers ) {
64
65         if(!( domain && name && resource && password && port && trustedClients && trustedServers )) return NULL;
66
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);
72         router->port                    = port;
73
74         router->trustedClients = trustedClients;
75         router->trustedServers = trustedServers;
76
77         
78         router->classes = osrfNewHash(); 
79         router->classes->freeItem = &osrfRouterClassFree;
80
81         router->connection = client_init( domain, port, NULL, 0 );
82
83         return router;
84 }
85
86
87
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;
93         return 0;
94 }
95
96
97 void osrfRouterRun( osrfRouter* router ) {
98         if(!(router && router->classes)) return;
99
100         int routerfd = router->ROUTER_SOCKFD;
101         int selectret = 0;
102
103         while(1) {
104
105                 fd_set set;
106                 int maxfd = _osrfRouterFillFDSet( router, &set );
107                 int numhandled = 0;
108
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);
111                         continue;
112                 }
113
114                 /* see if there is a top level router message */
115
116                 if( FD_ISSET(routerfd, &set) ) {
117                         osrfLogDebug( OSRF_LOG_MARK, "Top router socket is active: %d", routerfd );
118                         numhandled++;
119                         osrfRouterHandleIncoming( router );
120                 }
121
122
123                 /* now check each of the connected classes and see if they have data to route */
124                 while( numhandled < selectret ) {
125
126                         osrfRouterClass* class;
127                         osrfHashIterator* itr = osrfNewHashIterator(router->classes);
128
129                         while( (class = osrfHashIteratorNext(itr)) ) {
130
131                                 char* classname = itr->current;
132
133                                 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
134
135                                         osrfLogDebug( OSRF_LOG_MARK, "Checking %s for activity...", classname );
136
137                                         int sockfd = class->ROUTER_SOCKFD;
138                                         if(FD_ISSET( sockfd, &set )) {
139                                                 osrfLogDebug( OSRF_LOG_MARK, "Socket is active: %d", sockfd );
140                                                 numhandled++;
141                                                 osrfRouterClassHandleIncoming( router, classname, class );
142                                         }
143                                 }
144                         }
145
146                         osrfHashIteratorFree(itr);
147                 }
148         }
149 }
150
151
152 /**
153   Utility method for handling incoming requests to the router
154   and making sure the sender is allowed.
155  */
156 static void osrfRouterHandleIncoming( osrfRouter* router ) {
157         if(!router) return;
158
159         transport_message* msg = NULL;
160
161         //if( (msg = client_recv( router->connection, 0 )) ) { 
162         while( (msg = client_recv( router->connection, 0 )) ) { 
163
164                 if( msg->sender ) {
165
166                         osrfLogDebug(OSRF_LOG_MARK, 
167                                 "osrfRouterHandleIncoming(): investigating message from %s", msg->sender);
168
169                         /* if the sender is not a trusted server, drop the message */
170                         int len = strlen(msg->sender) + 1;
171                         char domain[len];
172                         memset(domain, 0, sizeof(domain));
173                         jid_get_domain( msg->sender, domain, len - 1 );
174
175                         if(osrfStringArrayContains( router->trustedServers, domain)) 
176                                 osrfRouterHandleMessage( router, msg );
177                          else 
178                                 osrfLogWarning( OSRF_LOG_MARK, "Received message from un-trusted server domain %s", msg->sender);
179                 }
180
181                 message_free(msg);
182         }
183 }
184
185 /**
186         Utility method for handling incoming requests to a router class,
187         makes sure sender is a trusted client
188  */
189 static int osrfRouterClassHandleIncoming( osrfRouter* router, const char* classname,
190                 osrfRouterClass* class ) {
191         if(!(router && class)) return -1;
192
193         transport_message* msg;
194         osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleIncoming()");
195
196         while( (msg = client_recv( class->connection, 0 )) ) {
197
198       osrfLogSetXid(msg->osrf_xid);
199
200                 if( msg->sender ) {
201
202                         osrfLogDebug(OSRF_LOG_MARK, 
203                                 "osrfRouterClassHandleIncoming(): investigating message from %s", msg->sender);
204
205                         /* if the client is not from a trusted domain, drop the message */
206                         int len = strlen(msg->sender) + 1;
207                         char domain[len];
208                         memset(domain, 0, sizeof(domain));
209                         jid_get_domain( msg->sender, domain, len - 1 );
210
211                         if(osrfStringArrayContains( router->trustedClients, domain)) {
212
213                                 transport_message* bouncedMessage = NULL;
214                                 if( msg->is_error )  {
215
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 */
219
220                                         message_free( msg );
221                                         msg = bouncedMessage;
222                                 }
223                                 osrfRouterClassHandleMessage( router, class, msg );
224
225                         } else {
226                                 osrfLogWarning( OSRF_LOG_MARK, "Received client message from untrusted client domain %s", domain );
227                         }
228                 }
229
230       osrfLogClearXid();
231                 message_free( msg );
232         }
233
234         return 0;
235 }
236
237
238
239
240 /**
241   Handles top level router messages
242   @return 0 on success
243  */
244 static int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg ) {
245         if(!(router && msg)) return -1;
246
247         if( !msg->router_command || !strcmp(msg->router_command,"")) 
248                 return osrfRouterHandleAppRequest( router, msg ); /* assume it's an app session level request */
249
250         if(!msg->router_class) return -1;
251
252         osrfRouterClass* class = NULL;
253         if(!strcmp(msg->router_command, ROUTER_REGISTER)) {
254                 class = osrfRouterFindClass( router, msg->router_class );
255
256                 osrfLogInfo( OSRF_LOG_MARK, "Registering class %s", msg->router_class );
257
258                 if(!class) class = osrfRouterAddClass( router, msg->router_class );
259
260                 if(class) { 
261
262                         if( osrfRouterClassFindNode( class, msg->sender ) )
263                                 return 0;
264                         else 
265                                 osrfRouterClassAddNode( class, msg->sender );
266
267                 } 
268
269         } else if( !strcmp( msg->router_command, ROUTER_UNREGISTER ) ) {
270
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 );
274                 }
275         }
276
277         return 0;
278 }
279
280
281
282 /**
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.
288  */
289 static osrfRouterClass* osrfRouterAddClass( osrfRouter* router, const char* classname ) {
290         if(!(router && router->classes && classname)) return NULL;
291
292         osrfRouterClass* class = safe_malloc(sizeof(osrfRouterClass));
293         class->nodes = osrfNewHash();
294         class->itr = osrfNewHashIterator(class->nodes);
295         class->nodes->freeItem = &osrfRouterNodeFree;
296         class->router   = router;
297
298         class->connection = client_init( router->domain, router->port, NULL, 0 );
299
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 );
308                 return NULL;
309         }
310         
311         osrfHashSet( router->classes, class, classname );
312         return class;
313 }
314
315
316 /**
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
321  */
322 static int osrfRouterClassAddNode( osrfRouterClass* rclass, const char* remoteId ) {
323         if(!(rclass && rclass->nodes && remoteId)) return -1;
324
325         osrfLogInfo( OSRF_LOG_MARK, "Adding router node for remote id %s", remoteId );
326
327         osrfRouterNode* node = safe_malloc(sizeof(osrfRouterNode));
328         node->count = 0;
329         node->lastMessage = NULL;
330         node->remoteId = strdup(remoteId);
331
332         osrfHashSet( rclass->nodes, node, remoteId );
333         return 0;
334 }
335
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 ?
338  */
339
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.
344         */
345 static transport_message* osrfRouterClassHandleBounce( osrfRouter* router,
346                 const char* classname, osrfRouterClass* rclass, transport_message* msg ) {
347
348         osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleBounce()");
349
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;
353
354         if( node && osrfHashGetCount(rclass->nodes) == 1 ) { /* the last node is dead */
355
356                 if( node->lastMessage ) {
357                         osrfLogWarning( OSRF_LOG_MARK, "We lost the last node in the class, responding with error and removing...");
358         
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 );
364         
365                         /* send the error message back to the original sender */
366                         client_send_message( rclass->connection, error );
367                         message_free( error );
368                 }
369         
370                 return NULL;
371         
372         } else { 
373
374                 if( node ) {
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 );
381                         }
382                 } else {
383
384                         osrfLogInfo(OSRF_LOG_MARK, "network error occurred after we removed the class.. ignoring");
385                         return NULL;
386                 }
387         }
388
389         /* remove the dead node */
390         osrfRouterClassRemoveNode( router, classname, msg->sender);
391         return lastSent;
392 }
393
394
395 /**
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
401   @return 0 on success
402  */
403 static int osrfRouterClassHandleMessage( 
404                 osrfRouter* router, osrfRouterClass* rclass, transport_message* msg ) {
405         if(!(router && rclass && msg)) return -1;
406
407         osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleMessage()");
408
409         osrfRouterNode* node = osrfHashIteratorNext( rclass->itr );
410         if(!node) {
411                 osrfHashIteratorReset(rclass->itr);
412                 node = osrfHashIteratorNext( rclass->itr );
413         }
414
415         if(node) {
416
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 );
421
422                 osrfLogInfo( OSRF_LOG_MARK,  "Routing message:\nfrom: [%s]\nto: [%s]", 
423                                 new_msg->router_from, new_msg->recipient );
424
425                 message_free( node->lastMessage );
426                 node->lastMessage = new_msg;
427
428                 if ( client_send_message( rclass->connection, new_msg ) == 0 ) 
429                         node->count++;
430
431                 else {
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 );
435                 }
436
437         } 
438
439         return 0;
440 }
441
442
443 /**
444   Removes a given class from the router, freeing as it goes
445  */
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 );
450         return 0;
451 }
452
453
454 /**
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
460  */
461 static int osrfRouterClassRemoveNode( 
462                 osrfRouter* router, const char* classname, const char* remoteId ) {
463
464         if(!(router && router->classes && classname && remoteId)) return 0;
465
466         osrfLogInfo( OSRF_LOG_MARK, "Removing router node %s", remoteId );
467
468         osrfRouterClass* class = osrfRouterFindClass( router, classname );
469
470         if( class ) {
471
472                 osrfHashRemove( class->nodes, remoteId );
473                 if( osrfHashGetCount(class->nodes) == 0 ) {
474                         osrfRouterRemoveClass( router, classname );
475                         return 1;
476                 }
477
478                 return 0;
479         }
480
481         return -1;
482 }
483
484
485 /**
486   Frees a router class object
487   Takes a void* since it is freed by the hash code
488  */
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 );      
494
495         osrfHashIteratorReset( rclass->itr );
496         osrfRouterNode* node;
497
498         while( (node = osrfHashIteratorNext(rclass->itr)) ) 
499                 osrfRouterClassRemoveNode( rclass->router, classname, node->remoteId );
500
501    osrfHashIteratorFree(rclass->itr);
502    osrfHashFree(rclass->nodes);
503
504         free(rclass);
505 }
506
507
508 /**
509   Frees a router node object 
510   Takes a void* since it is freed by the list code
511  */
512 static void osrfRouterNodeFree( char* remoteId, void* n ) {
513         if(!n) return;
514         osrfRouterNode* node = (osrfRouterNode*) n;
515         free(node->remoteId);
516         message_free(node->lastMessage);
517         free(node);
518 }
519
520
521 void osrfRouterFree( osrfRouter* router ) {
522         if(!router) return;
523
524         free(router->domain);           
525         free(router->name);
526         free(router->resource);
527         free(router->password);
528
529         osrfStringArrayFree( router->trustedClients );
530         osrfStringArrayFree( router->trustedServers );
531
532         client_free( router->connection );
533         free(router);
534 }
535
536
537
538 /**
539   Finds the class associated with the given class name in the list of classes
540  */
541 static osrfRouterClass* osrfRouterFindClass( osrfRouter* router, const char* classname ) {
542         if(!( router && router->classes && classname )) return NULL;
543         return (osrfRouterClass*) osrfHashGet( router->classes, classname );
544 }
545
546
547 /**
548   Finds the router node within this class with the given remote id 
549  */
550 static osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass,
551                 const char* remoteId ) {
552         if(!(rclass && remoteId))  return NULL;
553         return (osrfRouterNode*) osrfHashGet( rclass->nodes, remoteId );
554 }
555
556
557 /**
558   Clears and populates the provided fd_set* with file descriptors
559   from the router's top level connection as well as each of the
560   router class connections
561   @return The largest file descriptor found in the filling process
562  */
563 static int _osrfRouterFillFDSet( osrfRouter* router, fd_set* set ) {
564         if(!(router && router->classes && set)) return -1;
565
566         FD_ZERO(set);
567         int maxfd = router->ROUTER_SOCKFD;
568         FD_SET(maxfd, set);
569
570         int sockid;
571
572         osrfRouterClass* class = NULL;
573         osrfHashIterator* itr = osrfNewHashIterator(router->classes);
574
575         while( (class = osrfHashIteratorNext(itr)) ) {
576                 char* classname = itr->current;
577
578                 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
579                         sockid = class->ROUTER_SOCKFD;
580         
581                         if( osrfUtilsCheckFileDescriptor( sockid ) ) {
582
583                                 osrfLogWarning(OSRF_LOG_MARK, 
584                                         "Removing router class '%s' because of a bad top-level file descriptor [%d]", classname, sockid);
585                                 osrfRouterRemoveClass( router, classname );
586         
587                         } else {
588                                 if( sockid > maxfd ) maxfd = sockid;
589                                 FD_SET(sockid, set);
590                         }
591                 }
592         }
593
594         osrfHashIteratorFree(itr);
595         return maxfd;
596 }
597
598 /**
599   handles messages that don't have a 'router_command' set.  They are assumed to
600   be app request messages 
601  */
602 static int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg ) {
603
604         int T = 32;
605         osrfMessage* arr[T];
606         memset(arr, 0, sizeof(arr));
607
608         int num_msgs = osrf_message_deserialize( msg->body, arr, T );
609         osrfMessage* omsg = NULL;
610
611         int i;
612         for( i = 0; i != num_msgs; i++ ) {
613
614                 if( !(omsg = arr[i]) ) continue;
615
616                 switch( omsg->m_type ) {
617
618                         case CONNECT:
619                                 osrfRouterRespondConnect( router, msg, omsg );
620                                 break;
621
622                         case REQUEST:
623                                 osrfRouterProcessAppRequest( router, msg, omsg );
624                                 break;
625
626                         default: break;
627                 }
628
629                 osrfMessageFree( omsg );
630         }
631
632         return 0;
633 }
634
635 static int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg,
636                 osrfMessage* omsg ) {
637         if(!(router && msg && omsg)) return -1;
638
639         osrfMessage* success = osrf_message_init( STATUS, omsg->thread_trace, omsg->protocol );
640
641         osrfLogDebug( OSRF_LOG_MARK, "router received a CONNECT message from %s", msg->sender );
642
643         osrf_message_set_status_info( 
644                 success, "osrfConnectStatus", "Connection Successful", OSRF_STATUS_OK );
645
646         char* data      = osrf_message_serialize(success);
647
648         transport_message* return_m = message_init( 
649                 data, "", msg->thread, msg->sender, "" );
650
651         client_send_message(router->connection, return_m);
652
653         free(data);
654         osrfMessageFree(success);
655         message_free(return_m);
656
657         return 0;
658 }
659
660
661
662 static int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg,
663                 osrfMessage* omsg ) {
664
665         if(!(router && msg && omsg && omsg->method_name)) return -1;
666
667         osrfLogInfo( OSRF_LOG_MARK, "Router received app request: %s", omsg->method_name );
668
669         jsonObject* jresponse = NULL;
670         if(!strcmp( omsg->method_name, ROUTER_REQUEST_CLASS_LIST )) {
671
672                 int i;
673                 jresponse = jsonParseString("[]");
674
675                 osrfStringArray* keys = osrfHashKeys( router->classes );
676                 for( i = 0; i != keys->size; i++ )
677                         jsonObjectPush( jresponse, jsonNewObject(osrfStringArrayGetString( keys, i )) );
678                 osrfStringArrayFree(keys);
679
680
681         } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_SUMMARY )) {
682
683                 osrfRouterClass* class;
684                 osrfRouterNode* node;
685                 int count = 0;
686
687                 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
688
689                 if (!classname)
690                         return -1;
691
692                 class = osrfHashGet(router->classes, classname);
693                 free(classname);
694
695                 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
696                 while( (node = osrfHashIteratorNext(node_itr)) ) {
697                         count += node->count;
698                         //jsonObjectSetKey( class_res, node->remoteId, jsonNewNumberObject( (double) node->count ) );
699                 }
700                 osrfHashIteratorFree(node_itr);
701
702                 jresponse = jsonNewNumberObject( (double) count );
703
704         } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS )) {
705
706                 osrfRouterClass* class;
707                 osrfRouterNode* node;
708
709                 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
710
711                 if (!classname)
712                         return -1;
713
714                 jresponse = jsonParseString("{}");
715                 class = osrfHashGet(router->classes, classname);
716                 free(classname);
717
718                 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
719                 while( (node = osrfHashIteratorNext(node_itr)) ) {
720                         jsonObjectSetKey( jresponse, node->remoteId, jsonNewNumberObject( (double) node->count ) );
721                 }
722                 osrfHashIteratorFree(node_itr);
723
724         } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_FULL )) {
725
726                 osrfRouterClass* class;
727                 osrfRouterNode* node;
728                 jresponse = jsonParseString("{}");
729
730                 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
731                 while( (class = osrfHashIteratorNext(class_itr)) ) {
732
733                         jsonObject* class_res = jsonParseString("{}");
734                         char* classname = class_itr->current;
735
736                         osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
737                         while( (node = osrfHashIteratorNext(node_itr)) ) {
738                                 jsonObjectSetKey( class_res, node->remoteId, jsonNewNumberObject( (double) node->count ) );
739                         }
740                         osrfHashIteratorFree(node_itr);
741
742                         jsonObjectSetKey( jresponse, classname, class_res );
743                 }
744
745                 osrfHashIteratorFree(class_itr);
746
747         } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_NODE_FULL )) {
748
749                 osrfRouterClass* class;
750                 osrfRouterNode* node;
751                 int count;
752                 jresponse = jsonParseString("{}");
753
754                 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
755                 while( (class = osrfHashIteratorNext(class_itr)) ) {
756
757                         count = 0;
758                         char* classname = class_itr->current;
759
760                         osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
761                         while( (node = osrfHashIteratorNext(node_itr)) ) {
762                                 count += node->count;
763                         }
764                         osrfHashIteratorFree(node_itr);
765
766                         jsonObjectSetKey( jresponse, classname, jsonNewNumberObject( (double) count ) );
767                 }
768
769                 osrfHashIteratorFree(class_itr);
770
771         } else {
772
773                 return osrfRouterHandleMethodNFound( router, msg, omsg );
774         }
775
776
777         osrfRouterHandleAppResponse( router, msg, omsg, jresponse );
778         jsonObjectFree(jresponse); 
779
780         return 0;
781
782 }
783
784
785
786 static int osrfRouterHandleMethodNFound( 
787                 osrfRouter* router, transport_message* msg, osrfMessage* omsg ) {
788
789         osrfMessage* err = osrf_message_init( STATUS, omsg->thread_trace, 1);
790                 osrf_message_set_status_info( err, 
791                                 "osrfMethodException", "Router method not found", OSRF_STATUS_NOTFOUND );
792
793                 char* data =  osrf_message_serialize(err);
794
795                 transport_message* tresponse = message_init(
796                                 data, "", msg->thread, msg->sender, msg->recipient );
797
798                 client_send_message(router->connection, tresponse );
799
800                 free(data);
801                 osrfMessageFree( err );
802                 message_free(tresponse);
803                 return 0;
804 }
805
806
807
808 static int osrfRouterHandleAppResponse( osrfRouter* router, 
809         transport_message* msg, osrfMessage* omsg, const jsonObject* response ) {
810
811         if( response ) { /* send the response message */
812
813                 osrfMessage* oresponse = osrf_message_init(
814                                 RESULT, omsg->thread_trace, omsg->protocol );
815         
816                 char* json = jsonObjectToJSON(response);
817                 osrf_message_set_result_content( oresponse, json);
818         
819                 char* data =  osrf_message_serialize(oresponse);
820                 osrfLogDebug( OSRF_LOG_MARK,  "Responding to client app request with data: \n%s\n", data );
821
822                 transport_message* tresponse = message_init(
823                                 data, "", msg->thread, msg->sender, msg->recipient );
824         
825                 client_send_message(router->connection, tresponse );
826
827                 osrfMessageFree(oresponse); 
828                 message_free(tresponse);
829                 free(json);
830                 free(data);
831         }
832
833
834         /* now send the 'request complete' message */
835         osrfMessage* status = osrf_message_init( STATUS, omsg->thread_trace, 1);
836         osrf_message_set_status_info( status, "osrfConnectStatus", "Request Complete", OSRF_STATUS_COMPLETE );
837
838         char* statusdata = osrf_message_serialize(status);
839
840         transport_message* sresponse = message_init(
841                         statusdata, "", msg->thread, msg->sender, msg->recipient );
842         client_send_message(router->connection, sresponse );
843
844
845         free(statusdata);
846         osrfMessageFree(status);
847         message_free(sresponse);
848
849         return 0;
850 }
851
852
853
854