]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/libopensrf/osrf_app_session.c
2662822b9d6d846154f1943a4b4e48babc6d29a0
[OpenSRF.git] / src / libopensrf / osrf_app_session.c
1 #include <opensrf/osrf_app_session.h>
2 #include <time.h>
3
4 /** Send the given message */
5 static int _osrf_app_session_send( osrfAppSession*, osrf_message* msg );
6
7 static int osrfAppSessionMakeLocaleRequest(
8                 osrfAppSession* session, const jsonObject* params, const char* method_name,
9                 int protocol, string_array* param_strings, char* locale );
10
11 /* the global app_session cache */
12 osrfHash* osrfAppSessionCache = NULL;
13
14 // --------------------------------------------------------------------------
15 // --------------------------------------------------------------------------
16 // Request API
17 // --------------------------------------------------------------------------
18
19 /** Allocates and initializes a new app_request object */
20 static osrfAppRequest* _osrf_app_request_init(
21                 osrfAppSession* session, osrf_message* msg ) {
22
23         osrfAppRequest* req =
24                 (osrfAppRequest*) safe_malloc(sizeof(osrfAppRequest));
25
26         req->session            = session;
27         req->request_id = msg->thread_trace;
28         req->complete           = 0;
29         req->payload            = msg;
30         req->result                     = NULL;
31         req->reset_timeout  = 0;
32
33         return req;
34
35 }
36
37
38 void osrfAppSessionCleanup() {
39         osrfHashFree(osrfAppSessionCache);      
40 }
41
42 /** Frees memory used by an app_request object */
43 static void _osrf_app_request_free( void * req ){
44         if( req == NULL ) return;
45         osrfAppRequest* r = (osrfAppRequest*) req;
46         if( r->payload ) osrf_message_free( r->payload );
47         free( r );
48 }
49
50 /** Pushes the given message onto the list of 'responses' to this request */
51 static void _osrf_app_request_push_queue( osrfAppRequest* req, osrf_message* result ){
52         if(req == NULL || result == NULL) return;
53         osrfLogDebug( OSRF_LOG_MARK,  "App Session pushing request [%d] onto request queue", result->thread_trace );
54         if(req->result == NULL) {
55                 req->result = result;
56
57         } else {
58                 
59                 osrf_message* ptr = req->result;
60                 osrf_message* ptr2 = req->result->next;
61                 while( ptr2 ) {
62                         ptr = ptr2;
63                         ptr2 = ptr2->next;
64                 }
65                 ptr->next = result;
66         }
67 }
68
69 /** Removes this app_request from our session request set */
70 void osrf_app_session_request_finish( 
71                 osrfAppSession* session, int req_id ){
72
73         if(session == NULL) return;
74         osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, req_id );
75         if(req == NULL) return;
76         osrfListRemove( req->session->request_queue, req->request_id );
77 }
78
79
80 void osrf_app_session_request_reset_timeout( osrfAppSession* session, int req_id ) {
81         if(session == NULL) return;
82         osrfLogDebug( OSRF_LOG_MARK, "Resetting request timeout %d", req_id );
83         osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, req_id );
84         if(req == NULL) return;
85         req->reset_timeout = 1;
86 }
87
88 /** Checks the receive queue for messages.  If any are found, the first
89   * is popped off and returned.  Otherwise, this method will wait at most timeout 
90   * seconds for a message to appear in the receive queue.  Once it arrives it is returned.
91   * If no messages arrive in the timeout provided, null is returned.
92   */
93 static osrf_message* _osrf_app_request_recv( osrfAppRequest* req, int timeout ) {
94
95         if(req == NULL) return NULL;
96
97         if( req->result != NULL ) {
98                 /* pop off the first message in the list */
99                 osrf_message* tmp_msg = req->result;
100                 req->result = req->result->next;
101                 return tmp_msg;
102         }
103
104         time_t start = time(NULL);      
105         time_t remaining = (time_t) timeout;
106
107         while( remaining >= 0 ) {
108                 /* tell the session to wait for stuff */
109                 osrfLogDebug( OSRF_LOG_MARK,  "In app_request receive with remaining time [%d]", (int) remaining );
110
111                 osrf_app_session_queue_wait( req->session, 0, NULL );
112
113                 if( req->result != NULL ) { /* if we received anything */
114                         /* pop off the first message in the list */
115                         osrfLogDebug( OSRF_LOG_MARK,  "app_request_recv received a message, returning it");
116                         osrf_message* ret_msg = req->result;
117                         osrf_message* tmp_msg = ret_msg->next;
118                         req->result = tmp_msg;
119                         if (ret_msg->sender_locale) {
120                                 if (req->session->session_locale)
121                                         free(req->session->session_locale);
122                                 req->session->session_locale = strdup(ret_msg->sender_locale);
123                         }
124                         return ret_msg;
125                 }
126
127                 if( req->complete )
128                         return NULL;
129
130                 osrf_app_session_queue_wait( req->session, (int) remaining, NULL );
131
132                 if( req->result != NULL ) { /* if we received anything */
133                         /* pop off the first message in the list */
134                         osrfLogDebug( OSRF_LOG_MARK,  "app_request_recv received a message, returning it");
135                         osrf_message* ret_msg = req->result;
136                         osrf_message* tmp_msg = ret_msg->next;
137                         req->result = tmp_msg;
138                         if (ret_msg->sender_locale) {
139                                 if (req->session->session_locale)
140                                         free(req->session->session_locale);
141                                 req->session->session_locale = strdup(ret_msg->sender_locale);
142                         }
143                         return ret_msg;
144                 }
145                 if( req->complete )
146                         return NULL;
147
148                 if(req->reset_timeout) {
149                         remaining = (time_t) timeout;
150                         req->reset_timeout = 0;
151                         osrfLogDebug( OSRF_LOG_MARK, "Received a timeout reset");
152                 } else {
153                         remaining -= (int) (time(NULL) - start);
154                 }
155         }
156
157         osrfLogInfo( OSRF_LOG_MARK, "Returning NULL from app_request_recv after timeout");
158         return NULL;
159 }
160
161 /** Resend this requests original request message */
162 static int _osrf_app_request_resend( osrfAppRequest* req ) {
163         if(req == NULL) return 0;
164         if(!req->complete) {
165                 osrfLogDebug( OSRF_LOG_MARK,  "Resending request [%d]", req->request_id );
166                 return _osrf_app_session_send( req->session, req->payload );
167         }
168         return 1;
169 }
170
171
172
173 // --------------------------------------------------------------------------
174 // --------------------------------------------------------------------------
175 // Session API
176 // --------------------------------------------------------------------------
177
178 /** returns a session from the global session hash */
179 char* osrf_app_session_set_locale( osrfAppSession* session, const char* locale ) {
180         if (!session || !locale)
181                 return NULL;
182
183         if(session->session_locale)
184                 free(session->session_locale);
185
186         session->session_locale = strdup( locale );
187         return session->session_locale;
188 }
189
190 /** returns a session from the global session hash */
191 osrfAppSession* osrf_app_session_find_session( const char* session_id ) {
192         if(session_id) return osrfHashGet(osrfAppSessionCache, session_id);
193         return NULL;
194 }
195
196
197 /** adds a session to the global session cache */
198 static void _osrf_app_session_push_session( osrfAppSession* session ) {
199         if(!session) return;
200         if( osrfAppSessionCache == NULL ) osrfAppSessionCache = osrfNewHash();
201         if( osrfHashGet( osrfAppSessionCache, session->session_id ) ) return;
202         osrfHashSet( osrfAppSessionCache, session, session->session_id );
203 }
204
205 /** Allocates and initializes a new app_session */
206
207 osrfAppSession* osrfAppSessionClientInit( const char* remote_service ) {
208         return osrf_app_client_session_init( remote_service );
209 }
210
211 osrfAppSession* osrf_app_client_session_init( const char* remote_service ) {
212
213         if (!remote_service) {
214                 osrfLogWarning( OSRF_LOG_MARK, "No remote service specified in osrf_app_client_session_init");
215                 return NULL;
216         }
217
218         osrfAppSession* session = safe_malloc(sizeof(osrfAppSession));
219
220         session->transport_handle = osrfSystemGetTransportClient();
221         if( session->transport_handle == NULL ) {
222                 osrfLogWarning( OSRF_LOG_MARK, "No transport client for service 'client'");
223                 free( session );
224                 return NULL;
225         }
226
227         osrfStringArray* arr = osrfNewStringArray(8);
228         osrfConfigGetValueList(NULL, arr, "/domains/domain");
229         char* domain = osrfStringArrayGetString(arr, 0);
230
231         if (!domain) {
232                 osrfLogWarning( OSRF_LOG_MARK, "No domains specified in the OpenSRF config file");
233                 free( session );
234                 osrfStringArrayFree(arr);
235                 return NULL;
236         }
237
238         char* router_name = osrfConfigGetValue(NULL, "/router_name");
239         if (!router_name) {
240                 osrfLogWarning( OSRF_LOG_MARK, "No router name specified in the OpenSRF config file");
241                 free( session );
242                 osrfStringArrayFree(arr);
243                 return NULL;
244         }
245
246         char target_buf[512];
247         target_buf[ 0 ] = '\0';
248
249         int len = snprintf( target_buf, sizeof(target_buf), "%s@%s/%s",
250                         router_name ? router_name : "(null)",
251                         domain ? domain : "(null)",
252                         remote_service ? remote_service : "(null)" );
253         osrfStringArrayFree(arr);
254         //free(domain);
255         free(router_name);
256
257         if( len >= sizeof( target_buf ) ) {
258                 osrfLogWarning( OSRF_LOG_MARK, "Buffer overflow for remote_id");
259                 free( session );
260                 return NULL;
261         }
262
263         session->request_queue = osrfNewList();
264         session->request_queue->freeItem = &_osrf_app_request_free;
265         session->remote_id = strdup(target_buf);
266         session->orig_remote_id = strdup(session->remote_id);
267         session->remote_service = strdup(remote_service);
268         session->session_locale = NULL;
269
270         #ifdef ASSUME_STATELESS
271         session->stateless = 1;
272         osrfLogDebug( OSRF_LOG_MARK, "%s session is stateless", remote_service );
273         #else
274         session->stateless = 0;
275         osrfLogDebug( OSRF_LOG_MARK, "%s session is NOT stateless", remote_service );
276         #endif
277
278         /* build a chunky, random session id */
279         char id[256];
280
281         snprintf(id, sizeof(id), "%f.%d%ld", get_timestamp_millis(), (int)time(NULL), (long) getpid());
282         session->session_id = strdup(id);
283         osrfLogDebug( OSRF_LOG_MARK,  "Building a new client session with id [%s] [%s]", 
284                         session->remote_service, session->session_id );
285
286         session->thread_trace = 0;
287         session->state = OSRF_SESSION_DISCONNECTED;
288         session->type = OSRF_SESSION_CLIENT;
289         //session->next = NULL;
290
291         session->userData = NULL;
292         session->userDataFree = NULL;
293         
294         _osrf_app_session_push_session( session );
295         return session;
296 }
297
298 osrfAppSession* osrf_app_server_session_init(
299                 const char* session_id, const char* our_app, const char* remote_id ) {
300
301         osrfLogDebug( OSRF_LOG_MARK, "Initing server session with session id %s, service %s,"
302                         " and remote_id %s", session_id, our_app, remote_id );
303
304         osrfAppSession* session = osrf_app_session_find_session( session_id );
305         if(session) return session;
306
307         session = safe_malloc(sizeof(osrfAppSession));
308
309         session->transport_handle = osrfSystemGetTransportClient();
310         if( session->transport_handle == NULL ) {
311                 osrfLogWarning( OSRF_LOG_MARK, "No transport client for service '%s'", our_app );
312                 return NULL;
313         }
314
315         int stateless = 0;
316         char* statel = osrf_settings_host_value("/apps/%s/stateless", our_app );
317         if(statel) stateless = atoi(statel);
318         free(statel);
319
320
321         session->request_queue = osrfNewList();
322         session->request_queue->freeItem = &_osrf_app_request_free;
323         session->remote_id = strdup(remote_id);
324         session->orig_remote_id = strdup(remote_id);
325         session->session_id = strdup(session_id);
326         session->remote_service = strdup(our_app);
327         session->stateless = stateless;
328
329         #ifdef ASSUME_STATELESS
330         session->stateless = 1;
331         #else
332         session->stateless = 0;
333         #endif
334
335         session->thread_trace = 0;
336         session->state = OSRF_SESSION_DISCONNECTED;
337         session->type = OSRF_SESSION_SERVER;
338         session->session_locale = NULL;
339
340         session->userData = NULL;
341         session->userDataFree = NULL;
342         
343         _osrf_app_session_push_session( session );
344         return session;
345
346 }
347
348
349
350 /** frees memory held by a session */
351 static void _osrf_app_session_free( osrfAppSession* session ){
352         if(session==NULL)
353                 return;
354
355         if( session->userDataFree && session->userData ) 
356                 session->userDataFree(session->userData);
357         
358         if(session->session_locale)
359                 free(session->session_locale);
360
361         free(session->remote_id);
362         free(session->orig_remote_id);
363         free(session->session_id);
364         free(session->remote_service);
365         osrfListFree(session->request_queue);
366         free(session);
367 }
368
369 int osrfAppSessionMakeRequest(
370                 osrfAppSession* session, const jsonObject* params,
371                 const char* method_name, int protocol, string_array* param_strings ) {
372
373         return osrfAppSessionMakeLocaleRequest( session, params,
374                         method_name, protocol, param_strings, NULL );
375 }
376
377 int osrf_app_session_make_req(
378                 osrfAppSession* session, const jsonObject* params,
379                 const char* method_name, int protocol, string_array* param_strings) {
380
381         return osrfAppSessionMakeLocaleRequest(session, params,
382                         method_name, protocol, param_strings, NULL);
383 }
384
385 static int osrfAppSessionMakeLocaleRequest(
386                 osrfAppSession* session, const jsonObject* params, const char* method_name,
387                 int protocol, string_array* param_strings, char* locale ) {
388
389         if(session == NULL) return -1;
390
391         osrfLogMkXid();
392
393         osrf_message* req_msg = osrf_message_init( REQUEST, ++(session->thread_trace), protocol );
394         osrf_message_set_method(req_msg, method_name);
395
396         if (locale) {
397                 osrf_message_set_locale(req_msg, locale);
398         } else if (session->session_locale) {
399                 osrf_message_set_locale(req_msg, session->session_locale);
400         }
401
402         if(params) {
403                 osrf_message_set_params(req_msg, params);
404
405         } else {
406
407                 if(param_strings) {
408                         int i;
409                         for(i = 0; i!= param_strings->size ; i++ ) {
410                                 osrf_message_add_param(req_msg,
411                                         string_array_get_string(param_strings,i));
412                         }
413                 }
414         }
415
416         osrfAppRequest* req = _osrf_app_request_init( session, req_msg );
417         if(_osrf_app_session_send( session, req_msg ) ) {
418                 osrfLogWarning( OSRF_LOG_MARK,  "Error sending request message [%d]", session->thread_trace );
419                 return -1;
420         }
421
422         osrfLogDebug( OSRF_LOG_MARK,  "Pushing [%d] onto request queue for session [%s] [%s]",
423                         req->request_id, session->remote_service, session->session_id );
424         osrfListSet( session->request_queue, req, req->request_id ); 
425         return req->request_id;
426 }
427
428 void osrf_app_session_set_complete( osrfAppSession* session, int request_id ) {
429         if(session == NULL)
430                 return;
431
432         osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, request_id );
433         if(req) req->complete = 1;
434 }
435
436 int osrf_app_session_request_complete( const osrfAppSession* session, int request_id ) {
437         if(session == NULL)
438                 return 0;
439         osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, request_id );
440         if(req)
441                 return req->complete;
442         return 0;
443 }
444
445
446 /** Resets the remote connection id to that of the original*/
447 void osrf_app_session_reset_remote( osrfAppSession* session ){
448         if( session==NULL )
449                 return;
450
451         free(session->remote_id);
452         osrfLogDebug( OSRF_LOG_MARK,  "App Session [%s] [%s] resetting remote id to %s",
453                         session->remote_service, session->session_id, session->orig_remote_id );
454
455         session->remote_id = strdup(session->orig_remote_id);
456 }
457
458 void osrf_app_session_set_remote( osrfAppSession* session, const char* remote_id ) {
459         if(session == NULL)
460                 return;
461         if( session->remote_id )
462                 free(session->remote_id );
463         session->remote_id = strdup( remote_id );
464 }
465
466 /** pushes the given message into the result list of the app_request
467   with the given request_id */
468 int osrf_app_session_push_queue( 
469                 osrfAppSession* session, osrf_message* msg ){
470         if(session == NULL || msg == NULL) return 0;
471
472         osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, msg->thread_trace );
473         if(req == NULL) return 0;
474         _osrf_app_request_push_queue( req, msg );
475
476         return 0;
477 }
478
479 int osrfAppSessionConnect( osrfAppSession* session ) { 
480         return osrf_app_session_connect(session);
481 }
482
483
484 /** Attempts to connect to the remote service */
485 int osrf_app_session_connect(osrfAppSession* session){
486         
487         if(session == NULL)
488                 return 0;
489
490         if(session->state == OSRF_SESSION_CONNECTED) {
491                 return 1;
492         }
493
494         int timeout = 5; /* XXX CONFIG VALUE */
495
496         osrfLogDebug( OSRF_LOG_MARK,  "AppSession connecting to %s", session->remote_id );
497
498         /* defaulting to protocol 1 for now */
499         osrf_message* con_msg = osrf_message_init( CONNECT, session->thread_trace, 1 );
500         osrf_app_session_reset_remote( session );
501         session->state = OSRF_SESSION_CONNECTING;
502         int ret = _osrf_app_session_send( session, con_msg );
503         osrf_message_free(con_msg);
504         if(ret) return 0;
505
506         time_t start = time(NULL);      
507         time_t remaining = (time_t) timeout;
508
509         while( session->state != OSRF_SESSION_CONNECTED && remaining >= 0 ) {
510                 osrf_app_session_queue_wait( session, remaining, NULL );
511                 remaining -= (int) (time(NULL) - start);
512         }
513
514         if(session->state == OSRF_SESSION_CONNECTED)
515                 osrfLogDebug( OSRF_LOG_MARK, " * Connected Successfully to %s", session->remote_service );
516
517         if(session->state != OSRF_SESSION_CONNECTED)
518                 return 0;
519
520         return 1;
521 }
522
523
524
525 /** Disconnects from the remote service */
526 int osrf_app_session_disconnect( osrfAppSession* session){
527         if(session == NULL)
528                 return 1;
529
530         if(session->state == OSRF_SESSION_DISCONNECTED)
531                 return 1;
532
533         if(session->stateless && session->state != OSRF_SESSION_CONNECTED) {
534                 osrfLogDebug( OSRF_LOG_MARK,  
535                                 "Exiting disconnect on stateless session %s", 
536                                 session->session_id);
537                 return 1;
538         }
539
540         osrfLogDebug(OSRF_LOG_MARK,  "AppSession disconnecting from %s", session->remote_id );
541
542         osrf_message* dis_msg = osrf_message_init( DISCONNECT, session->thread_trace, 1 );
543         _osrf_app_session_send( session, dis_msg );
544         session->state = OSRF_SESSION_DISCONNECTED;
545
546         osrf_message_free( dis_msg );
547         osrf_app_session_reset_remote( session );
548         return 1;
549 }
550
551 int osrf_app_session_request_resend( osrfAppSession* session, int req_id ) {
552         osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, req_id );
553         return _osrf_app_request_resend( req );
554 }
555
556
557 static int osrfAppSessionSendBatch( osrfAppSession* session, osrf_message* msgs[], int size ) {
558
559         if( !(session && msgs && size > 0) ) return 0;
560         int retval = 0;
561
562         osrfMessage* msg = msgs[0];
563
564         if(msg) {
565
566                 osrf_app_session_queue_wait( session, 0, NULL );
567
568                 if(session->state != OSRF_SESSION_CONNECTED)  {
569
570                         if(session->stateless) { /* stateless session always send to the root listener */
571                                 osrf_app_session_reset_remote(session);
572
573                         } else { 
574
575                                 /* do an auto-connect if necessary */
576                                 if( ! session->stateless &&
577                                         (msg->m_type != CONNECT) && 
578                                         (msg->m_type != DISCONNECT) &&
579                                         (session->state != OSRF_SESSION_CONNECTED) ) {
580
581                                         if(!osrf_app_session_connect( session )) 
582                                                 return 0;
583                                 }
584                         }
585                 }
586         }
587
588         char* string = osrfMessageSerializeBatch(msgs, size);
589
590         if( string ) {
591
592                 transport_message* t_msg = message_init( 
593                                 string, "", session->session_id, session->remote_id, NULL );
594       message_set_osrf_xid( t_msg, osrfLogGetXid() );
595
596                 retval = client_send_message( session->transport_handle, t_msg );
597
598                 if( retval ) osrfLogError(OSRF_LOG_MARK, "client_send_message failed");
599
600                 osrfLogInfo(OSRF_LOG_MARK, "[%s] sent %d bytes of data to %s",
601                         session->remote_service, strlen(string), t_msg->recipient );
602
603                 osrfLogDebug(OSRF_LOG_MARK, "Sent: %s", string );
604
605                 free(string);
606                 message_free( t_msg );
607         }
608
609         return retval; 
610 }
611
612
613
614 static int _osrf_app_session_send( osrfAppSession* session, osrf_message* msg ){
615         if( !(session && msg) ) return 0;
616         osrfMessage* a[1];
617         a[0] = msg;
618         return osrfAppSessionSendBatch( session, a, 1 );
619 }
620
621
622
623
624 /**  Waits up to 'timeout' seconds for some data to arrive.
625   * Any data that arrives will be processed according to its
626   * payload and message type.  This method will return after
627   * any data has arrived.
628   */
629 int osrf_app_session_queue_wait( osrfAppSession* session, int timeout, int* recvd ){
630         if(session == NULL) return 0;
631         osrfLogDebug(OSRF_LOG_MARK,  "AppSession in queue_wait with timeout %d", timeout );
632         return osrf_stack_entry_point(session->transport_handle, timeout, recvd);
633 }
634
635 /** Disconnects (if client) and removes the given session from the global session cache 
636   * ! This free's all attached app_requests ! 
637   */
638 void osrfAppSessionFree( osrfAppSession* ses ) {
639         osrf_app_session_destroy( ses );
640 }
641
642
643 void osrf_app_session_destroy( osrfAppSession* session ){
644         if(session == NULL) return;
645
646         osrfLogDebug(OSRF_LOG_MARK,  "AppSession [%s] [%s] destroying self and deleting requests", 
647                         session->remote_service, session->session_id );
648         if(session->type == OSRF_SESSION_CLIENT 
649                         && session->state != OSRF_SESSION_DISCONNECTED ) { /* disconnect if we're a client */
650                 osrf_message* dis_msg = osrf_message_init( DISCONNECT, session->thread_trace, 1 );
651                 _osrf_app_session_send( session, dis_msg ); 
652                 osrf_message_free(dis_msg);
653         }
654
655         osrfHashRemove( osrfAppSessionCache, session->session_id );
656         _osrf_app_session_free( session );
657 }
658
659 osrf_message* osrfAppSessionRequestRecv(
660                 osrfAppSession* session, int req_id, int timeout ) {
661         return osrf_app_session_request_recv( session, req_id, timeout );
662 }
663 osrf_message* osrf_app_session_request_recv( 
664                 osrfAppSession* session, int req_id, int timeout ) {
665         if(req_id < 0 || session == NULL)
666                 return NULL;
667         osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, req_id );
668         return _osrf_app_request_recv( req, timeout );
669 }
670
671
672
673 int osrfAppRequestRespond( osrfAppSession* ses, int requestId, const jsonObject* data ) {
674         if(!ses || ! data ) return -1;
675
676         osrf_message* msg = osrf_message_init( RESULT, requestId, 1 );
677         osrf_message_set_status_info( msg, NULL, "OK", OSRF_STATUS_OK );
678         char* json = jsonObjectToJSON( data );
679
680         osrf_message_set_result_content( msg, json );
681         _osrf_app_session_send( ses, msg ); 
682
683         free(json);
684         osrf_message_free( msg );
685
686         return 0;
687 }
688
689
690 int osrfAppRequestRespondComplete( 
691                 osrfAppSession* ses, int requestId, const jsonObject* data ) {
692
693         osrf_message* payload = osrf_message_init( RESULT, requestId, 1 );
694         osrf_message_set_status_info( payload, NULL, "OK", OSRF_STATUS_OK );
695
696         osrf_message* status = osrf_message_init( STATUS, requestId, 1);
697         osrf_message_set_status_info( status, "osrfConnectStatus", "Request Complete", OSRF_STATUS_COMPLETE );
698         
699         if (data) {
700                 char* json = jsonObjectToJSON( data );
701                 osrf_message_set_result_content( payload, json );
702                 free(json);
703
704                 osrfMessage* ms[2];
705                 ms[0] = payload;
706                 ms[1] = status;
707
708                 osrfAppSessionSendBatch( ses, ms, 2 );
709
710                 osrf_message_free( payload );
711         } else {
712                 osrfAppSessionSendBatch( ses, &status, 1 );
713         }
714
715         osrf_message_free( status );
716
717         return 0;
718 }
719
720 int osrfAppSessionStatus( osrfAppSession* ses, int type,
721                 const char* name, int reqId, const char* message ) {
722
723         if(ses) {
724                 osrf_message* msg = osrf_message_init( STATUS, reqId, 1);
725                 osrf_message_set_status_info( msg, name, message, type );
726                 _osrf_app_session_send( ses, msg ); 
727                 osrf_message_free( msg );
728                 return 0;
729         }
730         return -1;
731 }
732
733
734
735
736
737