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