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