1 #include "osrf_router.h"
3 /* a class maintains a set of server nodes */
4 struct _osrfRouterClassStruct {
5 osrfRouter* router; /* our router handle */
8 transport_client* connection;
10 typedef struct _osrfRouterClassStruct osrfRouterClass;
12 /* represents a link to a single server's inbound connection */
13 struct _osrfRouterNodeStruct {
14 char* remoteId; /* send message to me via this login */
15 int count; /* how many message have been sent to this node */
16 transport_message* lastMessage;
18 typedef struct _osrfRouterNodeStruct osrfRouterNode;
20 static osrfRouterClass* osrfRouterAddClass( osrfRouter* router, const char* classname );
21 static int osrfRouterClassAddNode( osrfRouterClass* rclass, const char* remoteId );
22 static int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg );
23 static int osrfRouterClassHandleMessage( osrfRouter* router,
24 osrfRouterClass* rclass, transport_message* msg );
25 static int osrfRouterRemoveClass( osrfRouter* router, const char* classname );
26 static int osrfRouterClassRemoveNode( osrfRouter* router, const char* classname,
27 const char* remoteId );
28 static void osrfRouterClassFree( char* classname, void* rclass );
29 static void osrfRouterNodeFree( char* remoteId, void* node );
30 static osrfRouterClass* osrfRouterFindClass( osrfRouter* router, const char* classname );
31 static osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass,
32 const char* remoteId );
33 static int _osrfRouterFillFDSet( osrfRouter* router, fd_set* set );
34 static void osrfRouterHandleIncoming( osrfRouter* router );
35 static int osrfRouterClassHandleIncoming( osrfRouter* router,
36 const char* classname, osrfRouterClass* class );
37 static transport_message* osrfRouterClassHandleBounce( osrfRouter* router,
38 const char* classname, osrfRouterClass* rclass, transport_message* msg );
39 static int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg );
40 static int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg,
42 static int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg,
44 static int osrfRouterHandleAppResponse( osrfRouter* router,
45 transport_message* msg, osrfMessage* omsg, const jsonObject* response );
46 static int osrfRouterHandleMethodNFound( osrfRouter* router, transport_message* msg,
49 #define ROUTER_SOCKFD connection->session->sock_id
50 #define ROUTER_REGISTER "register"
51 #define ROUTER_UNREGISTER "unregister"
54 #define ROUTER_REQUEST_CLASS_LIST "opensrf.router.info.class.list"
55 #define ROUTER_REQUEST_STATS_NODE_FULL "opensrf.router.info.stats.class.node.all"
56 #define ROUTER_REQUEST_STATS_CLASS_FULL "opensrf.router.info.stats.class.all"
57 #define ROUTER_REQUEST_STATS_CLASS "opensrf.router.info.stats.class"
58 #define ROUTER_REQUEST_STATS_CLASS_SUMMARY "opensrf.router.info.stats.class.summary"
60 osrfRouter* osrfNewRouter(
61 const char* domain, const char* name,
62 const char* resource, const char* password, int port,
63 osrfStringArray* trustedClients, osrfStringArray* trustedServers ) {
65 if(!( domain && name && resource && password && port && trustedClients && trustedServers )) return NULL;
67 osrfRouter* router = safe_malloc(sizeof(osrfRouter));
68 router->domain = strdup(domain);
69 router->name = strdup(name);
70 router->password = strdup(password);
71 router->resource = strdup(resource);
74 router->trustedClients = trustedClients;
75 router->trustedServers = trustedServers;
78 router->classes = osrfNewHash();
79 router->classes->freeItem = &osrfRouterClassFree;
81 router->connection = client_init( domain, port, NULL, 0 );
88 int osrfRouterConnect( osrfRouter* router ) {
89 if(!router) return -1;
90 int ret = client_connect( router->connection, router->name,
91 router->password, router->resource, 10, AUTH_DIGEST );
92 if( ret == 0 ) return -1;
97 void osrfRouterRun( osrfRouter* router ) {
98 if(!(router && router->classes)) return;
100 int routerfd = router->ROUTER_SOCKFD;
106 int maxfd = _osrfRouterFillFDSet( router, &set );
109 if( (selectret = select(maxfd + 1, &set, NULL, NULL, NULL)) < 0 ) {
110 osrfLogWarning( OSRF_LOG_MARK, "Top level select call failed with errno %d", errno);
114 /* see if there is a top level router message */
116 if( FD_ISSET(routerfd, &set) ) {
117 osrfLogDebug( OSRF_LOG_MARK, "Top router socket is active: %d", routerfd );
119 osrfRouterHandleIncoming( router );
123 /* now check each of the connected classes and see if they have data to route */
124 while( numhandled < selectret ) {
126 osrfRouterClass* class;
127 osrfHashIterator* itr = osrfNewHashIterator(router->classes);
129 while( (class = osrfHashIteratorNext(itr)) ) {
131 char* classname = itr->current;
133 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
135 osrfLogDebug( OSRF_LOG_MARK, "Checking %s for activity...", classname );
137 int sockfd = class->ROUTER_SOCKFD;
138 if(FD_ISSET( sockfd, &set )) {
139 osrfLogDebug( OSRF_LOG_MARK, "Socket is active: %d", sockfd );
141 osrfRouterClassHandleIncoming( router, classname, class );
146 osrfHashIteratorFree(itr);
153 Utility method for handling incoming requests to the router
154 and making sure the sender is allowed.
156 static void osrfRouterHandleIncoming( osrfRouter* router ) {
159 transport_message* msg = NULL;
161 //if( (msg = client_recv( router->connection, 0 )) ) {
162 while( (msg = client_recv( router->connection, 0 )) ) {
166 osrfLogDebug(OSRF_LOG_MARK,
167 "osrfRouterHandleIncoming(): investigating message from %s", msg->sender);
169 /* if the sender is not a trusted server, drop the message */
170 int len = strlen(msg->sender) + 1;
172 memset(domain, 0, sizeof(domain));
173 jid_get_domain( msg->sender, domain, len - 1 );
175 if(osrfStringArrayContains( router->trustedServers, domain))
176 osrfRouterHandleMessage( router, msg );
178 osrfLogWarning( OSRF_LOG_MARK, "Received message from un-trusted server domain %s", msg->sender);
186 Utility method for handling incoming requests to a router class,
187 makes sure sender is a trusted client
189 static int osrfRouterClassHandleIncoming( osrfRouter* router, const char* classname,
190 osrfRouterClass* class ) {
191 if(!(router && class)) return -1;
193 transport_message* msg;
194 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleIncoming()");
196 while( (msg = client_recv( class->connection, 0 )) ) {
198 osrfLogSetXid(msg->osrf_xid);
202 osrfLogDebug(OSRF_LOG_MARK,
203 "osrfRouterClassHandleIncoming(): investigating message from %s", msg->sender);
205 /* if the client is not from a trusted domain, drop the message */
206 int len = strlen(msg->sender) + 1;
208 memset(domain, 0, sizeof(domain));
209 jid_get_domain( msg->sender, domain, len - 1 );
211 if(osrfStringArrayContains( router->trustedClients, domain)) {
213 transport_message* bouncedMessage = NULL;
214 if( msg->is_error ) {
216 /* handle bounced message */
217 if( !(bouncedMessage = osrfRouterClassHandleBounce( router, classname, class, msg )) )
218 return -1; /* we have no one to send the requested message to */
221 msg = bouncedMessage;
223 osrfRouterClassHandleMessage( router, class, msg );
226 osrfLogWarning( OSRF_LOG_MARK, "Received client message from untrusted client domain %s", domain );
241 Handles top level router messages
244 static int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg ) {
245 if(!(router && msg)) return -1;
247 if( !msg->router_command || !strcmp(msg->router_command,""))
248 return osrfRouterHandleAppRequest( router, msg ); /* assume it's an app session level request */
250 if(!msg->router_class) return -1;
252 osrfRouterClass* class = NULL;
253 if(!strcmp(msg->router_command, ROUTER_REGISTER)) {
254 class = osrfRouterFindClass( router, msg->router_class );
256 osrfLogInfo( OSRF_LOG_MARK, "Registering class %s", msg->router_class );
258 if(!class) class = osrfRouterAddClass( router, msg->router_class );
262 if( osrfRouterClassFindNode( class, msg->sender ) )
265 osrfRouterClassAddNode( class, msg->sender );
269 } else if( !strcmp( msg->router_command, ROUTER_UNREGISTER ) ) {
271 if( msg->router_class && strcmp( msg->router_class, "") ) {
272 osrfLogInfo( OSRF_LOG_MARK, "Unregistering router class %s", msg->router_class );
273 osrfRouterClassRemoveNode( router, msg->router_class, msg->sender );
283 Allocates and adds a new router class handler to the router's list of handlers.
284 Also connects the class handler to the network at <routername>@domain/<classname>
285 @param router The current router instance
286 @param classname The name of the class this node handles.
287 @return 0 on success, -1 on connection error.
289 static osrfRouterClass* osrfRouterAddClass( osrfRouter* router, const char* classname ) {
290 if(!(router && router->classes && classname)) return NULL;
292 osrfRouterClass* class = safe_malloc(sizeof(osrfRouterClass));
293 class->nodes = osrfNewHash();
294 class->itr = osrfNewHashIterator(class->nodes);
295 class->nodes->freeItem = &osrfRouterNodeFree;
296 class->router = router;
298 class->connection = client_init( router->domain, router->port, NULL, 0 );
300 if(!client_connect( class->connection, router->name,
301 router->password, classname, 10, AUTH_DIGEST ) ) {
302 // We cast away the constness of classname. Though ugly, this
303 // cast is benign because osrfRouterClassFree doesn't actually
304 // write through the pointer. We can't readily change its
305 // signature because it is used for a function pointer, and
306 // we would have to change other signatures the same way.
307 osrfRouterClassFree( (char *) classname, class );
311 osrfHashSet( router->classes, class, classname );
317 Adds a new server node to the given class.
318 @param rclass The Router class to add the node to
319 @param remoteId The remote login of this node
320 @return 0 on success, -1 on generic error
322 static int osrfRouterClassAddNode( osrfRouterClass* rclass, const char* remoteId ) {
323 if(!(rclass && rclass->nodes && remoteId)) return -1;
325 osrfLogInfo( OSRF_LOG_MARK, "Adding router node for remote id %s", remoteId );
327 osrfRouterNode* node = safe_malloc(sizeof(osrfRouterNode));
329 node->lastMessage = NULL;
330 node->remoteId = strdup(remoteId);
332 osrfHashSet( rclass->nodes, node, remoteId );
336 /* copy off the lastMessage, remove the offending node, send error if it's tht last node
337 ? return NULL if it's the last node ?
340 /* handles case where router node is not longer reachable. copies over the
341 data from the last sent message and returns a newly crafted suitable for treating
342 as a newly inconing message. Removes the dead node and If there are no more
343 nodes to send the new message to, returns NULL.
345 static transport_message* osrfRouterClassHandleBounce( osrfRouter* router,
346 const char* classname, osrfRouterClass* rclass, transport_message* msg ) {
348 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleBounce()");
350 osrfLogInfo( OSRF_LOG_MARK, "Received network layer error message from %s", msg->sender );
351 osrfRouterNode* node = osrfRouterClassFindNode( rclass, msg->sender );
352 transport_message* lastSent = NULL;
354 if( node && osrfHashGetCount(rclass->nodes) == 1 ) { /* the last node is dead */
356 if( node->lastMessage ) {
357 osrfLogWarning( OSRF_LOG_MARK, "We lost the last node in the class, responding with error and removing...");
359 transport_message* error = message_init(
360 node->lastMessage->body, node->lastMessage->subject,
361 node->lastMessage->thread, node->lastMessage->router_from, node->lastMessage->recipient );
362 message_set_osrf_xid(error, node->lastMessage->osrf_xid);
363 set_msg_error( error, "cancel", 501 );
365 /* send the error message back to the original sender */
366 client_send_message( rclass->connection, error );
367 message_free( error );
375 if( node->lastMessage ) {
376 osrfLogDebug( OSRF_LOG_MARK, "Cloning lastMessage so next node can send it");
377 lastSent = message_init( node->lastMessage->body,
378 node->lastMessage->subject, node->lastMessage->thread, "", node->lastMessage->router_from );
379 message_set_router_info( lastSent, node->lastMessage->router_from, NULL, NULL, NULL, 0 );
380 message_set_osrf_xid( lastSent, node->lastMessage->osrf_xid );
384 osrfLogInfo(OSRF_LOG_MARK, "network error occurred after we removed the class.. ignoring");
389 /* remove the dead node */
390 osrfRouterClassRemoveNode( router, classname, msg->sender);
396 Handles class level requests
397 If we get a regular message, we send it to the next node in the list of nodes
398 if we get an error, it's a bounce back from a previous attempt. We take the
399 body and thread from the last sent on the node that had the bounced message
400 and propogate them on to the new message being sent
403 static int osrfRouterClassHandleMessage(
404 osrfRouter* router, osrfRouterClass* rclass, transport_message* msg ) {
405 if(!(router && rclass && msg)) return -1;
407 osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleMessage()");
409 osrfRouterNode* node = osrfHashIteratorNext( rclass->itr );
411 osrfHashIteratorReset(rclass->itr);
412 node = osrfHashIteratorNext( rclass->itr );
417 transport_message* new_msg= message_init( msg->body,
418 msg->subject, msg->thread, node->remoteId, msg->sender );
419 message_set_router_info( new_msg, msg->sender, NULL, NULL, NULL, 0 );
420 message_set_osrf_xid( new_msg, msg->osrf_xid );
422 osrfLogInfo( OSRF_LOG_MARK, "Routing message:\nfrom: [%s]\nto: [%s]",
423 new_msg->router_from, new_msg->recipient );
425 message_free( node->lastMessage );
426 node->lastMessage = new_msg;
428 if ( client_send_message( rclass->connection, new_msg ) == 0 )
432 message_prepare_xml(new_msg);
433 osrfLogWarning( OSRF_LOG_MARK, "Error sending message from %s to %s\n%s",
434 new_msg->sender, new_msg->recipient, new_msg->msg_xml );
444 Removes a given class from the router, freeing as it goes
446 static int osrfRouterRemoveClass( osrfRouter* router, const char* classname ) {
447 if(!(router && router->classes && classname)) return -1;
448 osrfLogInfo( OSRF_LOG_MARK, "Removing router class %s", classname );
449 osrfHashRemove( router->classes, classname );
455 Removes the given node from the class. Also, if this is that last node in the set,
456 removes the class from the router
457 @return 0 on successful removal with no class removal
458 @return 1 on successful remove with class removal
459 @return -1 error on removal
461 static int osrfRouterClassRemoveNode(
462 osrfRouter* router, const char* classname, const char* remoteId ) {
464 if(!(router && router->classes && classname && remoteId)) return 0;
466 osrfLogInfo( OSRF_LOG_MARK, "Removing router node %s", remoteId );
468 osrfRouterClass* class = osrfRouterFindClass( router, classname );
472 osrfHashRemove( class->nodes, remoteId );
473 if( osrfHashGetCount(class->nodes) == 0 ) {
474 osrfRouterRemoveClass( router, classname );
486 Frees a router class object
487 Takes a void* since it is freed by the hash code
489 static void osrfRouterClassFree( char* classname, void* c ) {
490 if(!(classname && c)) return;
491 osrfRouterClass* rclass = (osrfRouterClass*) c;
492 client_disconnect( rclass->connection );
493 client_free( rclass->connection );
495 osrfHashIteratorReset( rclass->itr );
496 osrfRouterNode* node;
498 while( (node = osrfHashIteratorNext(rclass->itr)) )
499 osrfRouterClassRemoveNode( rclass->router, classname, node->remoteId );
501 osrfHashIteratorFree(rclass->itr);
502 osrfHashFree(rclass->nodes);
509 Frees a router node object
510 Takes a void* since it is freed by the list code
512 static void osrfRouterNodeFree( char* remoteId, void* n ) {
514 osrfRouterNode* node = (osrfRouterNode*) n;
515 free(node->remoteId);
516 message_free(node->lastMessage);
521 void osrfRouterFree( osrfRouter* router ) {
524 free(router->domain);
526 free(router->resource);
527 free(router->password);
529 osrfStringArrayFree( router->trustedClients );
530 osrfStringArrayFree( router->trustedServers );
532 client_free( router->connection );
539 Finds the class associated with the given class name in the list of classes
541 static osrfRouterClass* osrfRouterFindClass( osrfRouter* router, const char* classname ) {
542 if(!( router && router->classes && classname )) return NULL;
543 return (osrfRouterClass*) osrfHashGet( router->classes, classname );
548 Finds the router node within this class with the given remote id
550 static osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass,
551 const char* remoteId ) {
552 if(!(rclass && remoteId)) return NULL;
553 return (osrfRouterNode*) osrfHashGet( rclass->nodes, remoteId );
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
563 static int _osrfRouterFillFDSet( osrfRouter* router, fd_set* set ) {
564 if(!(router && router->classes && set)) return -1;
567 int maxfd = router->ROUTER_SOCKFD;
572 osrfRouterClass* class = NULL;
573 osrfHashIterator* itr = osrfNewHashIterator(router->classes);
575 while( (class = osrfHashIteratorNext(itr)) ) {
576 char* classname = itr->current;
578 if( classname && (class = osrfRouterFindClass( router, classname )) ) {
579 sockid = class->ROUTER_SOCKFD;
581 if( osrfUtilsCheckFileDescriptor( sockid ) ) {
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 );
588 if( sockid > maxfd ) maxfd = sockid;
594 osrfHashIteratorFree(itr);
599 handles messages that don't have a 'router_command' set. They are assumed to
600 be app request messages
602 static int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg ) {
606 memset(arr, 0, sizeof(arr));
608 int num_msgs = osrf_message_deserialize( msg->body, arr, T );
609 osrfMessage* omsg = NULL;
612 for( i = 0; i != num_msgs; i++ ) {
614 if( !(omsg = arr[i]) ) continue;
616 switch( omsg->m_type ) {
619 osrfRouterRespondConnect( router, msg, omsg );
623 osrfRouterProcessAppRequest( router, msg, omsg );
629 osrfMessageFree( omsg );
635 static int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg,
636 osrfMessage* omsg ) {
637 if(!(router && msg && omsg)) return -1;
639 osrfMessage* success = osrf_message_init( STATUS, omsg->thread_trace, omsg->protocol );
641 osrfLogDebug( OSRF_LOG_MARK, "router received a CONNECT message from %s", msg->sender );
643 osrf_message_set_status_info(
644 success, "osrfConnectStatus", "Connection Successful", OSRF_STATUS_OK );
646 char* data = osrf_message_serialize(success);
648 transport_message* return_m = message_init(
649 data, "", msg->thread, msg->sender, "" );
651 client_send_message(router->connection, return_m);
654 osrfMessageFree(success);
655 message_free(return_m);
662 static int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg,
663 osrfMessage* omsg ) {
665 if(!(router && msg && omsg && omsg->method_name)) return -1;
667 osrfLogInfo( OSRF_LOG_MARK, "Router received app request: %s", omsg->method_name );
669 jsonObject* jresponse = NULL;
670 if(!strcmp( omsg->method_name, ROUTER_REQUEST_CLASS_LIST )) {
673 jresponse = jsonParseString("[]");
675 osrfStringArray* keys = osrfHashKeys( router->classes );
676 for( i = 0; i != keys->size; i++ )
677 jsonObjectPush( jresponse, jsonNewObject(osrfStringArrayGetString( keys, i )) );
678 osrfStringArrayFree(keys);
681 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_SUMMARY )) {
683 osrfRouterClass* class;
684 osrfRouterNode* node;
687 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
692 class = osrfHashGet(router->classes, classname);
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 ) );
700 osrfHashIteratorFree(node_itr);
702 jresponse = jsonNewNumberObject( (double) count );
704 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS )) {
706 osrfRouterClass* class;
707 osrfRouterNode* node;
709 char* classname = jsonObjectToSimpleString( jsonObjectGetIndex( omsg->_params, 0 ) );
714 jresponse = jsonParseString("{}");
715 class = osrfHashGet(router->classes, classname);
718 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
719 while( (node = osrfHashIteratorNext(node_itr)) ) {
720 jsonObjectSetKey( jresponse, node->remoteId, jsonNewNumberObject( (double) node->count ) );
722 osrfHashIteratorFree(node_itr);
724 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_CLASS_FULL )) {
726 osrfRouterClass* class;
727 osrfRouterNode* node;
728 jresponse = jsonParseString("{}");
730 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
731 while( (class = osrfHashIteratorNext(class_itr)) ) {
733 jsonObject* class_res = jsonParseString("{}");
734 char* classname = class_itr->current;
736 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
737 while( (node = osrfHashIteratorNext(node_itr)) ) {
738 jsonObjectSetKey( class_res, node->remoteId, jsonNewNumberObject( (double) node->count ) );
740 osrfHashIteratorFree(node_itr);
742 jsonObjectSetKey( jresponse, classname, class_res );
745 osrfHashIteratorFree(class_itr);
747 } else if(!strcmp( omsg->method_name, ROUTER_REQUEST_STATS_NODE_FULL )) {
749 osrfRouterClass* class;
750 osrfRouterNode* node;
752 jresponse = jsonParseString("{}");
754 osrfHashIterator* class_itr = osrfNewHashIterator(router->classes);
755 while( (class = osrfHashIteratorNext(class_itr)) ) {
758 char* classname = class_itr->current;
760 osrfHashIterator* node_itr = osrfNewHashIterator(class->nodes);
761 while( (node = osrfHashIteratorNext(node_itr)) ) {
762 count += node->count;
764 osrfHashIteratorFree(node_itr);
766 jsonObjectSetKey( jresponse, classname, jsonNewNumberObject( (double) count ) );
769 osrfHashIteratorFree(class_itr);
773 return osrfRouterHandleMethodNFound( router, msg, omsg );
777 osrfRouterHandleAppResponse( router, msg, omsg, jresponse );
778 jsonObjectFree(jresponse);
786 static int osrfRouterHandleMethodNFound(
787 osrfRouter* router, transport_message* msg, osrfMessage* omsg ) {
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 );
793 char* data = osrf_message_serialize(err);
795 transport_message* tresponse = message_init(
796 data, "", msg->thread, msg->sender, msg->recipient );
798 client_send_message(router->connection, tresponse );
801 osrfMessageFree( err );
802 message_free(tresponse);
808 static int osrfRouterHandleAppResponse( osrfRouter* router,
809 transport_message* msg, osrfMessage* omsg, const jsonObject* response ) {
811 if( response ) { /* send the response message */
813 osrfMessage* oresponse = osrf_message_init(
814 RESULT, omsg->thread_trace, omsg->protocol );
816 char* json = jsonObjectToJSON(response);
817 osrf_message_set_result_content( oresponse, json);
819 char* data = osrf_message_serialize(oresponse);
820 osrfLogDebug( OSRF_LOG_MARK, "Responding to client app request with data: \n%s\n", data );
822 transport_message* tresponse = message_init(
823 data, "", msg->thread, msg->sender, msg->recipient );
825 client_send_message(router->connection, tresponse );
827 osrfMessageFree(oresponse);
828 message_free(tresponse);
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 );
838 char* statusdata = osrf_message_serialize(status);
840 transport_message* sresponse = message_init(
841 statusdata, "", msg->thread, msg->sender, msg->recipient );
842 client_send_message(router->connection, sresponse );
846 osrfMessageFree(status);
847 message_free(sresponse);