2 @file osrf_app_session.c
3 @brief Implementation of osrfAppSession.
7 #include "opensrf/osrf_app_session.h"
8 #include "opensrf/osrf_stack.h"
10 struct osrf_app_request_struct {
11 /** The controlling session. */
12 struct osrf_app_session_struct* session;
14 /** Request id. It is the same as the thread_trace of the REQUEST message
15 for which it was created.
18 /** True if we have received a 'request complete' message from our request. */
20 /** The original REQUEST message payload. */
22 /** Linked list of responses to the request. */
25 /** Boolean; if true, then a call that is waiting on a response will reset the
26 timeout and set this variable back to false. */
29 typedef struct osrf_app_request_struct osrfAppRequest;
31 /* Send the given message */
32 static int _osrf_app_session_send( osrfAppSession*, osrfMessage* msg );
34 static int osrfAppSessionMakeLocaleRequest(
35 osrfAppSession* session, const jsonObject* params, const char* method_name,
36 int protocol, osrfStringArray* param_strings, char* locale );
38 /** @brief The global session cache.
40 Key: session_id. Data: osrfAppSession.
42 static osrfHash* osrfAppSessionCache = NULL;
44 // --------------------------------------------------------------------------
46 // --------------------------------------------------------------------------
49 @brief Create a new osrfAppRequest.
50 @param session Pointer to the osrfAppSession that will own the new osrfAppRequest.
51 @param msg Pointer to the osrfMessage representing the request.
52 @return Pointer to the new osrfAppRequest.
54 The calling code is responsible for freeing the osrfAppRequest by calling
55 _osrf_app_request_free(). In practice this normally happens via a callback installed
58 static osrfAppRequest* _osrf_app_request_init(
59 osrfAppSession* session, osrfMessage* msg ) {
62 (osrfAppRequest*) safe_malloc(sizeof(osrfAppRequest));
64 req->session = session;
65 req->request_id = msg->thread_trace;
69 req->reset_timeout = 0;
76 @brief Free an osrfAppRequest and everything it owns.
77 @param req Pointer to an osrfAppRequest, cast to a void pointer.
79 This function is installed as a callback in the osrfList request_queue, a member
82 static void _osrf_app_request_free( void * req ){
84 osrfAppRequest* r = (osrfAppRequest*) req;
86 osrfMessageFree( r->payload );
88 /* Free the messages in the result queue */
89 osrfMessage* next_msg;
91 next_msg = r->result->next;
92 osrfMessageFree( r->result );
101 @brief Append a new message to the list of responses to a request.
102 @param req Pointer to the osrfAppRequest for the original REQUEST message.
103 @param result Pointer to an osrfMessage received in response to the request.
105 We maintain a linked list of response messages, and traverse it to find the end.
107 static void _osrf_app_request_push_queue( osrfAppRequest* req, osrfMessage* result ){
108 if(req == NULL || result == NULL)
111 osrfLogDebug( OSRF_LOG_MARK, "App Session pushing request [%d] onto request queue",
112 result->thread_trace );
113 if(req->result == NULL) {
114 req->result = result; // Add the first node
118 // Find the last node in the list, and append the new node to it
119 osrfMessage* ptr = req->result;
120 osrfMessage* ptr2 = req->result->next;
130 @brief Remove an osrfAppRequest (identified by request_id) from an osrfAppSession.
131 @param session Pointer to the osrfAppSession that owns the osrfAppRequest.
132 @param req_id request_id of the osrfAppRequest to be removed.
134 The osrfAppRequest itself is freed by a callback installed in the osrfList where it resides.
136 void osrf_app_session_request_finish(
137 osrfAppSession* session, int req_id ){
140 osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, req_id );
142 osrfListRemove( req->session->request_queue, req->request_id );
148 @brief Set the timeout for a request to one second.
149 @param session Pointer to the relevant osrfAppSession.
150 @param req_id Request ID of the request whose timeout is to be reset.
152 The request to be reset is identified by the combination of session and request id.
154 void osrf_app_session_request_reset_timeout( osrfAppSession* session, int req_id ) {
157 osrfLogDebug( OSRF_LOG_MARK, "Resetting request timeout %d", req_id );
158 osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, req_id );
160 req->reset_timeout = 1;
164 Checks the receive queue for messages. If any are found, the first
165 is popped off and returned. Otherwise, this method will wait at most timeout
166 seconds for a message to appear in the receive queue. Once it arrives it is returned.
167 If no messages arrive in the timeout provided, null is returned.
170 @brief Return the next response message for a given request, subject to a timeout.
171 @param req Pointer to the osrfAppRequest representing the request.
172 @param timeout Maxmimum time to wait, in seconds.
176 If the input queue for this request is not empty, dequeue the next message and return it.
178 static osrfMessage* _osrf_app_request_recv( osrfAppRequest* req, int timeout ) {
180 if(req == NULL) return NULL;
182 if( req->result != NULL ) {
183 /* Dequeue the next message in the list */
184 osrfMessage* tmp_msg = req->result;
185 req->result = req->result->next;
189 time_t start = time(NULL);
190 time_t remaining = (time_t) timeout;
192 while( remaining >= 0 ) {
193 /* tell the session to wait for stuff */
194 osrfLogDebug( OSRF_LOG_MARK, "In app_request receive with remaining time [%d]",
197 osrf_app_session_queue_wait( req->session, 0, NULL );
198 if(req->session->transport_error) {
199 osrfLogError(OSRF_LOG_MARK, "Transport error in recv()");
203 if( req->result != NULL ) { /* if we received anything */
204 /* pop off the first message in the list */
205 osrfLogDebug( OSRF_LOG_MARK, "app_request_recv received a message, returning it" );
206 osrfMessage* ret_msg = req->result;
207 req->result = ret_msg->next;
208 if (ret_msg->sender_locale)
209 osrf_app_session_set_locale(req->session, ret_msg->sender_locale);
217 osrf_app_session_queue_wait( req->session, (int) remaining, NULL );
219 if(req->session->transport_error) {
220 osrfLogError(OSRF_LOG_MARK, "Transport error in recv()");
224 if( req->result != NULL ) { /* if we received anything */
225 /* pop off the first message in the list */
226 osrfLogDebug( OSRF_LOG_MARK, "app_request_recv received a message, returning it");
227 osrfMessage* ret_msg = req->result;
228 req->result = ret_msg->next;
229 if (ret_msg->sender_locale)
230 osrf_app_session_set_locale(req->session, ret_msg->sender_locale);
237 if(req->reset_timeout) {
238 remaining = (time_t) timeout;
239 req->reset_timeout = 0;
240 osrfLogDebug( OSRF_LOG_MARK, "Received a timeout reset");
242 remaining -= (int) (time(NULL) - start);
246 char* paramString = jsonObjectToJSON(req->payload->_params);
247 osrfLogInfo( OSRF_LOG_MARK, "Returning NULL from app_request_recv after timeout: %s %s",
248 req->payload->method_name, paramString);
254 /** Resend this requests original request message */
255 static int _osrf_app_request_resend( osrfAppRequest* req ) {
256 if(req == NULL) return 0;
258 osrfLogDebug( OSRF_LOG_MARK, "Resending request [%d]", req->request_id );
259 return _osrf_app_session_send( req->session, req->payload );
265 // --------------------------------------------------------------------------
267 // --------------------------------------------------------------------------
269 /** Install a locale for the session */
270 char* osrf_app_session_set_locale( osrfAppSession* session, const char* locale ) {
271 if (!session || !locale)
274 if(session->session_locale) {
275 if( strlen(session->session_locale) >= strlen(locale) ) {
276 /* There's room available; just copy */
277 strcpy(session->session_locale, locale);
279 free(session->session_locale);
280 session->session_locale = strdup( locale );
283 session->session_locale = strdup( locale );
286 return session->session_locale;
290 @brief Find the osrfAppSession for a given session id.
291 @param session_id The session id to look for.
292 @return Pointer to the corresponding osrfAppSession if found, or NULL if not.
294 Search the global session cache for the specified session id.
296 osrfAppSession* osrf_app_session_find_session( const char* session_id ) {
298 return osrfHashGet( osrfAppSessionCache, session_id );
304 @brief Add a session to the global session cache, keyed by session id.
305 @param session Pointer to the osrfAppSession to be added.
307 If a cache doesn't exist yet, create one. It's an osrfHash using session ids for the
308 key and osrfAppSessions for the data.
310 static void _osrf_app_session_push_session( osrfAppSession* session ) {
312 if( osrfAppSessionCache == NULL )
313 osrfAppSessionCache = osrfNewHash();
314 if( osrfHashGet( osrfAppSessionCache, session->session_id ) )
315 return; // A session with this id is already in the cache. Shouldn't happen.
316 osrfHashSet( osrfAppSessionCache, session, session->session_id );
320 /** Allocates and initializes a new app_session */
322 osrfAppSession* osrfAppSessionClientInit( const char* remote_service ) {
324 if (!remote_service) {
325 osrfLogWarning( OSRF_LOG_MARK, "No remote service specified in osrfAppSessionClientInit");
329 osrfAppSession* session = safe_malloc(sizeof(osrfAppSession));
331 session->transport_handle = osrfSystemGetTransportClient();
332 if( session->transport_handle == NULL ) {
333 osrfLogWarning( OSRF_LOG_MARK, "No transport client for service 'client'");
338 osrfStringArray* arr = osrfNewStringArray(8);
339 osrfConfigGetValueList(NULL, arr, "/domain");
340 const char* domain = osrfStringArrayGetString(arr, 0);
343 osrfLogWarning( OSRF_LOG_MARK, "No domains specified in the OpenSRF config file");
345 osrfStringArrayFree(arr);
349 char* router_name = osrfConfigGetValue(NULL, "/router_name");
351 osrfLogWarning( OSRF_LOG_MARK, "No router name specified in the OpenSRF config file");
353 osrfStringArrayFree(arr);
357 char target_buf[512];
358 target_buf[ 0 ] = '\0';
360 int len = snprintf( target_buf, sizeof(target_buf), "%s@%s/%s",
361 router_name ? router_name : "(null)",
362 domain ? domain : "(null)",
363 remote_service ? remote_service : "(null)" );
364 osrfStringArrayFree(arr);
368 if( len >= sizeof( target_buf ) ) {
369 osrfLogWarning( OSRF_LOG_MARK, "Buffer overflow for remote_id");
374 session->request_queue = osrfNewList();
375 session->request_queue->freeItem = &_osrf_app_request_free;
376 session->remote_id = strdup(target_buf);
377 session->orig_remote_id = strdup(session->remote_id);
378 session->remote_service = strdup(remote_service);
379 session->session_locale = NULL;
380 session->transport_error = 0;
382 #ifdef ASSUME_STATELESS
383 session->stateless = 1;
384 osrfLogDebug( OSRF_LOG_MARK, "%s session is stateless", remote_service );
386 session->stateless = 0;
387 osrfLogDebug( OSRF_LOG_MARK, "%s session is NOT stateless", remote_service );
390 /* build a chunky, random session id */
393 snprintf(id, sizeof(id), "%f.%d%ld", get_timestamp_millis(), (int)time(NULL), (long) getpid());
394 session->session_id = strdup(id);
395 osrfLogDebug( OSRF_LOG_MARK, "Building a new client session with id [%s] [%s]",
396 session->remote_service, session->session_id );
398 session->thread_trace = 0;
399 session->state = OSRF_SESSION_DISCONNECTED;
400 session->type = OSRF_SESSION_CLIENT;
402 session->userData = NULL;
403 session->userDataFree = NULL;
405 _osrf_app_session_push_session( session );
409 osrfAppSession* osrf_app_server_session_init(
410 const char* session_id, const char* our_app, const char* remote_id ) {
412 osrfLogDebug( OSRF_LOG_MARK, "Initing server session with session id %s, service %s,"
413 " and remote_id %s", session_id, our_app, remote_id );
415 osrfAppSession* session = osrf_app_session_find_session( session_id );
416 if(session) return session;
418 session = safe_malloc(sizeof(osrfAppSession));
420 session->transport_handle = osrfSystemGetTransportClient();
421 if( session->transport_handle == NULL ) {
422 osrfLogWarning( OSRF_LOG_MARK, "No transport client for service '%s'", our_app );
428 char* statel = osrf_settings_host_value("/apps/%s/stateless", our_app );
429 if(statel) stateless = atoi(statel);
433 session->request_queue = osrfNewList();
434 session->request_queue->freeItem = &_osrf_app_request_free;
435 session->remote_id = strdup(remote_id);
436 session->orig_remote_id = strdup(remote_id);
437 session->session_id = strdup(session_id);
438 session->remote_service = strdup(our_app);
439 session->stateless = stateless;
441 #ifdef ASSUME_STATELESS
442 session->stateless = 1;
444 session->stateless = 0;
447 session->thread_trace = 0;
448 session->state = OSRF_SESSION_DISCONNECTED;
449 session->type = OSRF_SESSION_SERVER;
450 session->session_locale = NULL;
452 session->userData = NULL;
453 session->userDataFree = NULL;
455 _osrf_app_session_push_session( session );
461 @brief Create a REQUEST message, send it, and save it for future reference.
462 @param session Pointer to the current session, which has the addressing information.
463 @param params One way of specifying the parameters for the method.
464 @param method_name The name of the method to be called.
465 @param protocol Protocol.
466 @param param_strings Another way of specifying the parameters for the method.
467 @return The request ID of the resulting REQUEST message, or -1 upon error.
469 DEPRECATED. Use osrfAppSessionSendRequest() instead. It is identical except that it
470 doesn't use the param_strings argument, which is redundant, confusing, and unused.
472 If @a params is non-NULL, use it to specify the parameters to the method. Otherwise
473 use @a param_strings.
475 If @a params points to a JSON_ARRAY, then pass each element of the array as a separate
476 parameter. If @a params points to any other kind of jsonObject, pass it as a single
479 If @a params is NULL, and @a param_strings is not NULL, then each pointer in the
480 osrfStringArray must point to a JSON string encoding a parameter. Pass them.
482 At this writing, all calls to this function use @a params to pass parameters, rather than
485 This function is a thin wrapper for osrfAppSessionMakeLocaleRequest().
487 int osrfAppSessionMakeRequest(
488 osrfAppSession* session, const jsonObject* params,
489 const char* method_name, int protocol, osrfStringArray* param_strings ) {
491 return osrfAppSessionMakeLocaleRequest( session, params,
492 method_name, protocol, param_strings, NULL );
496 @brief Create a REQUEST message, send it, and save it for future reference.
497 @param session Pointer to the current session, which has the addressing information.
498 @param params One way of specifying the parameters for the method.
499 @param method_name The name of the method to be called.
500 @param protocol Protocol.
501 @return The request ID of the resulting REQUEST message, or -1 upon error.
503 If @a params points to a JSON_ARRAY, then pass each element of the array as a separate
504 parameter. If @a params points to any other kind of jsonObject, pass it as a single
507 This function is a thin wrapper for osrfAppSessionMakeLocaleRequest().
509 int osrfAppSessionSendRequest( osrfAppSession* session, const jsonObject* params,
510 const char* method_name, int protocol ) {
512 return osrfAppSessionMakeLocaleRequest( session, params,
513 method_name, protocol, NULL, NULL );
517 @brief Create a REQUEST message, send it, and save it for future reference.
518 @param session Pointer to the current session, which has the addressing information.
519 @param params One way of specifying the parameters for the method.
520 @param method_name The name of the method to be called.
521 @param protocol Protocol.
522 @param param_strings Another way of specifying the parameters for the method.
523 @param locale Pointer to a locale string.
524 @return The request ID of the resulting REQUEST message, or -1 upon error.
526 See the discussion of osrfAppSessionSendRequest(), which at this writing is the only
527 place that calls this function, except for the similar but deprecated function
528 osrfAppSessionMakeRequest().
530 At this writing, the @a param_strings and @a locale parameters are always NULL.
532 static int osrfAppSessionMakeLocaleRequest(
533 osrfAppSession* session, const jsonObject* params, const char* method_name,
534 int protocol, osrfStringArray* param_strings, char* locale ) {
536 if(session == NULL) return -1;
540 osrfMessage* req_msg = osrf_message_init( REQUEST, ++(session->thread_trace), protocol );
541 osrf_message_set_method(req_msg, method_name);
544 osrf_message_set_locale(req_msg, locale);
545 } else if (session->session_locale) {
546 osrf_message_set_locale(req_msg, session->session_locale);
550 osrf_message_set_params(req_msg, params);
556 for(i = 0; i!= param_strings->size ; i++ ) {
557 osrf_message_add_param(req_msg,
558 osrfStringArrayGetString(param_strings,i));
563 osrfAppRequest* req = _osrf_app_request_init( session, req_msg );
564 if(_osrf_app_session_send( session, req_msg ) ) {
565 osrfLogWarning( OSRF_LOG_MARK, "Error sending request message [%d]",
566 session->thread_trace );
567 _osrf_app_request_free(req);
571 osrfLogDebug( OSRF_LOG_MARK, "Pushing [%d] onto request queue for session [%s] [%s]",
572 req->request_id, session->remote_service, session->session_id );
573 osrfListSet( session->request_queue, req, req->request_id );
574 return req->request_id;
577 void osrf_app_session_set_complete( osrfAppSession* session, int request_id ) {
581 osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, request_id );
582 if(req) req->complete = 1;
585 int osrf_app_session_request_complete( const osrfAppSession* session, int request_id ) {
588 osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, request_id );
590 return req->complete;
595 /** Resets the remote connection id to that of the original*/
596 void osrf_app_session_reset_remote( osrfAppSession* session ){
600 osrfLogDebug( OSRF_LOG_MARK, "App Session [%s] [%s] resetting remote id to %s",
601 session->remote_service, session->session_id, session->orig_remote_id );
603 osrf_app_session_set_remote( session, session->orig_remote_id );
606 void osrf_app_session_set_remote( osrfAppSession* session, const char* remote_id ) {
610 if( session->remote_id ) {
611 if( strlen(session->remote_id) >= strlen(remote_id) ) {
612 // There's enough room; just copy it
613 strcpy(session->remote_id, remote_id);
615 free(session->remote_id );
616 session->remote_id = strdup( remote_id );
619 session->remote_id = strdup( remote_id );
623 pushes the given message into the result list of the app_request
624 with the given request_id
626 int osrf_app_session_push_queue(
627 osrfAppSession* session, osrfMessage* msg ){
628 if(session == NULL || msg == NULL) return 0;
630 osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, msg->thread_trace );
631 if(req == NULL) return 0;
632 _osrf_app_request_push_queue( req, msg );
637 /** Attempts to connect to the remote service */
638 int osrfAppSessionConnect( osrfAppSession* session ) {
643 if(session->state == OSRF_SESSION_CONNECTED) {
647 int timeout = 5; /* XXX CONFIG VALUE */
649 osrfLogDebug( OSRF_LOG_MARK, "AppSession connecting to %s", session->remote_id );
651 /* defaulting to protocol 1 for now */
652 osrfMessage* con_msg = osrf_message_init( CONNECT, session->thread_trace, 1 );
653 osrf_app_session_reset_remote( session );
654 session->state = OSRF_SESSION_CONNECTING;
655 int ret = _osrf_app_session_send( session, con_msg );
656 osrfMessageFree(con_msg);
660 time_t start = time(NULL);
661 time_t remaining = (time_t) timeout;
663 while( session->state != OSRF_SESSION_CONNECTED && remaining >= 0 ) {
664 osrf_app_session_queue_wait( session, remaining, NULL );
665 if(session->transport_error) {
666 osrfLogError(OSRF_LOG_MARK, "cannot communicate with %s", session->remote_service);
669 remaining -= (int) (time(NULL) - start);
672 if(session->state == OSRF_SESSION_CONNECTED)
673 osrfLogDebug( OSRF_LOG_MARK, " * Connected Successfully to %s", session->remote_service );
675 if(session->state != OSRF_SESSION_CONNECTED)
683 /** Disconnects from the remote service */
684 int osrf_app_session_disconnect( osrfAppSession* session){
688 if(session->state == OSRF_SESSION_DISCONNECTED)
691 if(session->stateless && session->state != OSRF_SESSION_CONNECTED) {
692 osrfLogDebug( OSRF_LOG_MARK,
693 "Exiting disconnect on stateless session %s",
694 session->session_id);
698 osrfLogDebug(OSRF_LOG_MARK, "AppSession disconnecting from %s", session->remote_id );
700 osrfMessage* dis_msg = osrf_message_init( DISCONNECT, session->thread_trace, 1 );
701 _osrf_app_session_send( session, dis_msg );
702 session->state = OSRF_SESSION_DISCONNECTED;
704 osrfMessageFree( dis_msg );
705 osrf_app_session_reset_remote( session );
709 int osrf_app_session_request_resend( osrfAppSession* session, int req_id ) {
710 osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, req_id );
711 return _osrf_app_request_resend( req );
715 static int osrfAppSessionSendBatch( osrfAppSession* session, osrfMessage* msgs[], int size ) {
717 if( !(session && msgs && size > 0) ) return 0;
720 osrfMessage* msg = msgs[0];
724 osrf_app_session_queue_wait( session, 0, NULL );
726 if(session->state != OSRF_SESSION_CONNECTED) {
728 if(session->stateless) { /* stateless session always send to the root listener */
729 osrf_app_session_reset_remote(session);
733 /* do an auto-connect if necessary */
734 if( ! session->stateless &&
735 (msg->m_type != CONNECT) &&
736 (msg->m_type != DISCONNECT) &&
737 (session->state != OSRF_SESSION_CONNECTED) ) {
739 if(!osrfAppSessionConnect( session ))
746 char* string = osrfMessageSerializeBatch(msgs, size);
750 transport_message* t_msg = message_init(
751 string, "", session->session_id, session->remote_id, NULL );
752 message_set_osrf_xid( t_msg, osrfLogGetXid() );
754 retval = client_send_message( session->transport_handle, t_msg );
756 if( retval ) osrfLogError(OSRF_LOG_MARK, "client_send_message failed");
758 osrfLogInfo(OSRF_LOG_MARK, "[%s] sent %d bytes of data to %s",
759 session->remote_service, strlen(string), t_msg->recipient );
761 osrfLogDebug(OSRF_LOG_MARK, "Sent: %s", string );
764 message_free( t_msg );
772 static int _osrf_app_session_send( osrfAppSession* session, osrfMessage* msg ){
773 if( !(session && msg) ) return 0;
776 return osrfAppSessionSendBatch( session, a, 1 );
781 Waits up to 'timeout' seconds for some data to arrive.
782 Any data that arrives will be processed according to its
783 payload and message type. This method will return after
784 any data has arrived.
786 int osrf_app_session_queue_wait( osrfAppSession* session, int timeout, int* recvd ){
787 if(session == NULL) return 0;
788 osrfLogDebug(OSRF_LOG_MARK, "AppSession in queue_wait with timeout %d", timeout );
789 return osrf_stack_process(session->transport_handle, timeout, recvd);
792 /** Disconnects (if client) and removes the given session from the global session cache
793 ! This frees all attached app_requests !
795 void osrfAppSessionFree( osrfAppSession* session ){
796 if(session == NULL) return;
800 osrfLogDebug(OSRF_LOG_MARK, "AppSession [%s] [%s] destroying self and deleting requests",
801 session->remote_service, session->session_id );
802 if(session->type == OSRF_SESSION_CLIENT
803 && session->state != OSRF_SESSION_DISCONNECTED ) { /* disconnect if we're a client */
804 osrfMessage* dis_msg = osrf_message_init( DISCONNECT, session->thread_trace, 1 );
805 _osrf_app_session_send( session, dis_msg );
806 osrfMessageFree(dis_msg);
809 /* Remove self from the global session cache */
811 osrfHashRemove( osrfAppSessionCache, session->session_id );
813 /* Free the memory */
815 if( session->userDataFree && session->userData )
816 session->userDataFree(session->userData);
818 if(session->session_locale)
819 free(session->session_locale);
821 free(session->remote_id);
822 free(session->orig_remote_id);
823 free(session->session_id);
824 free(session->remote_service);
825 osrfListFree(session->request_queue);
829 osrfMessage* osrfAppSessionRequestRecv(
830 osrfAppSession* session, int req_id, int timeout ) {
831 if(req_id < 0 || session == NULL)
833 osrfAppRequest* req = OSRF_LIST_GET_INDEX( session->request_queue, req_id );
834 return _osrf_app_request_recv( req, timeout );
839 int osrfAppRequestRespond( osrfAppSession* ses, int requestId, const jsonObject* data ) {
840 if(!ses || ! data ) return -1;
842 osrfMessage* msg = osrf_message_init( RESULT, requestId, 1 );
843 osrf_message_set_status_info( msg, NULL, "OK", OSRF_STATUS_OK );
844 char* json = jsonObjectToJSON( data );
846 osrf_message_set_result_content( msg, json );
847 _osrf_app_session_send( ses, msg );
850 osrfMessageFree( msg );
856 int osrfAppRequestRespondComplete(
857 osrfAppSession* ses, int requestId, const jsonObject* data ) {
859 osrfMessage* status = osrf_message_init( STATUS, requestId, 1);
860 osrf_message_set_status_info( status, "osrfConnectStatus", "Request Complete",
861 OSRF_STATUS_COMPLETE );
864 osrfMessage* payload = osrf_message_init( RESULT, requestId, 1 );
865 osrf_message_set_status_info( payload, NULL, "OK", OSRF_STATUS_OK );
867 char* json = jsonObjectToJSON( data );
868 osrf_message_set_result_content( payload, json );
875 osrfAppSessionSendBatch( ses, ms, 2 );
877 osrfMessageFree( payload );
879 osrfAppSessionSendBatch( ses, &status, 1 );
882 osrfMessageFree( status );
887 int osrfAppSessionStatus( osrfAppSession* ses, int type,
888 const char* name, int reqId, const char* message ) {
891 osrfMessage* msg = osrf_message_init( STATUS, reqId, 1);
892 osrf_message_set_status_info( msg, name, message, type );
893 _osrf_app_session_send( ses, msg );
894 osrfMessageFree( msg );
901 @brief Free the global session cache.
903 Note that the osrfHash that implements the global session cache does @em not have a
904 callback function installed for freeing its cargo. As a result, any outstanding
905 osrfAppSessions are leaked, along with all the osrfAppRequests and osrfMessages they
908 void osrfAppSessionCleanup( void ) {
909 osrfHashFree(osrfAppSessionCache);
910 osrfAppSessionCache = NULL;