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