+/**
+ @file osrf_app_session.h
+ @brief Header for osrfAppSession.
+*/
+
#ifndef OSRF_APP_SESSION_H
#define OSRF_APP_SESSION_H
-#include <opensrf/transport_client.h>
-#include <opensrf/osrf_message.h>
-#include <opensrf/osrf_system.h>
-#include <opensrf/string_array.h>
-#include <opensrf/osrfConfig.h>
-#include <opensrf/osrf_hash.h>
-#include <opensrf/osrf_list.h>
-
-#include <opensrf/osrf_json.h>
+#include "opensrf/transport_client.h"
+#include "opensrf/osrf_message.h"
+#include "opensrf/osrf_system.h"
+#include "opensrf/string_array.h"
+#include "opensrf/osrfConfig.h"
+#include "opensrf/osrf_hash.h"
+#include "opensrf/osrf_list.h"
+#include "opensrf/osrf_json.h"
#ifdef __cplusplus
extern "C" {
#endif
-#define DEF_RECV_TIMEOUT 6 /* receive timeout */
-#define DEF_QUEUE_SIZE
+#define DEF_RECV_TIMEOUT 6 /* receive timeout */
+#define DEF_QUEUE_SIZE
-enum OSRF_SESSION_STATE { OSRF_SESSION_CONNECTING, OSRF_SESSION_CONNECTED, OSRF_SESSION_DISCONNECTED };
-enum OSRF_SESSION_TYPE { OSRF_SESSION_SERVER, OSRF_SESSION_CLIENT };
+enum OSRF_SESSION_STATE {
+ OSRF_SESSION_CONNECTING,
+ OSRF_SESSION_CONNECTED,
+ OSRF_SESSION_DISCONNECTED
+};
+
+enum OSRF_SESSION_TYPE {
+ OSRF_SESSION_SERVER,
+ OSRF_SESSION_CLIENT
+};
-/* entry point for data into the stack. gets set in osrf_stack.c */
+/* entry point for data into the stack. Gets set in osrf_stack.c */
int (*osrf_stack_entry_point) (transport_client* client, int timeout, int* recvd );
struct osrf_app_session_struct {
/** The current remote id of the remote service we're talking to */
char* remote_id;
- /** Who we're talking to if we're a client.
- what app we're serving if we're a server */
+ /** Whom we're talking to if we're a client; what app we're serving if we're a server */
char* remote_service;
/** The current request thread_trace */
/** Our ID */
char* session_id;
- /* true if this session does not require connect messages */
+ /** Boolean; true if this session does not require connect messages */
int stateless;
/** The connect state */
void (*userDataFree) (void*);
- int transport_error;
+ int transport_error;
};
typedef struct osrf_app_session_struct osrfAppSession;
-// --------------------------------------------------------------------------
+// --------------------------------------------------------------------------
// PUBLIC API ***
-// --------------------------------------------------------------------------
+// --------------------------------------------------------------------------
/** Allocates a initializes a new app_session */
osrfAppSession* osrfAppSessionClientInit( const char* remote_service );
/** Allocates and initializes a new server session. The global session cache
- * is checked to see if this session already exists, if so, it's returned
- */
+ is checked to see if this session already exists, if so, it's returned
+*/
osrfAppSession* osrf_app_server_session_init(
const char* session_id, const char* our_app, const char* remote_id );
osrfAppSession* osrf_app_session_find_session( const char* session_id );
/** Builds a new app_request object with the given payload andn returns
- * the id of the request. This id is then used to perform work on the
- * requeset.
- */
+ the id of the request. This id is then used to perform work on the requeset.
+*/
int osrfAppSessionMakeRequest(
osrfAppSession* session, const jsonObject* params,
const char* method_name, int protocol, osrfStringArray* param_strings);
void osrf_app_session_set_remote( osrfAppSession* session, const char* remote_id );
/** pushes the given message into the result list of the app_request
- * whose request_id matches the messages thread_trace
- */
+ whose request_id matches the messages thread_trace
+*/
int osrf_app_session_push_queue( osrfAppSession*, osrfMessage* msg );
-/** Attempts to connect to the remote service. Returns 1 on successful
- * connection, 0 otherwise.
- */
+/** Attempts to connect to the remote service. Returns 1 on successful
+ connection, 0 otherwise.
+*/
int osrfAppSessionConnect( osrfAppSession* );
/** Sends a disconnect message to the remote service. No response is expected */
int osrf_app_session_disconnect( osrfAppSession* );
/** Waits up to 'timeout' seconds for some data to arrive.
- * Any data that arrives will be processed according to its
- * payload and message type. This method will return after
- * any data has arrived.
- */
+ Any data that arrives will be processed according to its
+ payload and message type. This method will return after
+ any data has arrived.
+*/
int osrf_app_session_queue_wait( osrfAppSession*, int timeout, int* recvd );
-/** Disconnects (if client), frees any attached app_reuqests, removes the session from the
- * global session cache and frees the session. Needless to say, only call this when the
- * session is completely done.
- */
+/** Disconnects (if client), frees any attached app_reuqests, removes the session from the
+ global session cache and frees the session. Needless to say, only call this when the
+ session is completely done.
+*/
void osrfAppSessionFree( osrfAppSession* );
-/* tells the request to reset it's wait timeout */
+/** Tells the request to reset its wait timeout */
void osrf_app_session_request_reset_timeout( osrfAppSession* session, int req_id );
int osrfAppRequestRespond( osrfAppSession* ses, int requestId, const jsonObject* data );
int osrfAppRequestRespondComplete(
- osrfAppSession* ses, int requestId, const jsonObject* data );
+ osrfAppSession* ses, int requestId, const jsonObject* data );
int osrfAppSessionStatus( osrfAppSession* ses, int type,
const char* name, int reqId, const char* message );
-#include <opensrf/osrf_app_session.h>
+/**
+ @file osrf_app_session.c
+ @brief Implementation of osrfAppSession.
+*/
+
#include <time.h>
+#include "opensrf/osrf_app_session.h"
struct osrf_app_request_struct {
- /** Our controlling session */
+ /** Our controlling session. */
struct osrf_app_session_struct* session;
- /** our "id" */
+ /** Our "id". */
int request_id;
- /** True if we have received a 'request complete' message from our request */
+ /** True if we have received a 'request complete' message from our request. */
int complete;
- /** Our original request payload */
+ /** Our original request payload. */
osrfMessage* payload;
- /** List of responses to our request */
+ /** List of responses to our request. */
osrfMessage* result;
- /* if set to true, then a call that is waiting on a response, will reset the
- timeout and set this variable back to false */
+ /** Boolean; if true, then a call that is waiting on a response, will reset the
+ timeout and set this variable back to false. */
int reset_timeout;
};
typedef struct osrf_app_request_struct osrfAppRequest;
osrfAppRequest* req =
(osrfAppRequest*) safe_malloc(sizeof(osrfAppRequest));
- req->session = session;
- req->request_id = msg->thread_trace;
- req->complete = 0;
- req->payload = msg;
- req->result = NULL;
+ req->session = session;
+ req->request_id = msg->thread_trace;
+ req->complete = 0;
+ req->payload = msg;
+ req->result = NULL;
req->reset_timeout = 0;
return req;
void osrfAppSessionCleanup() {
osrfHashFree(osrfAppSessionCache);
- osrfAppSessionCache = NULL;
+ osrfAppSessionCache = NULL;
}
/** Frees memory used by an app_request object */
osrfMessageFree( r->result );
r->result = next_msg;
}
-
+
free( r );
}
req->result = result;
} else {
-
+
osrfMessage* ptr = req->result;
osrfMessage* ptr2 = req->result->next;
while( ptr2 ) {
}
/** Removes this app_request from our session request set */
-void osrf_app_session_request_finish(
+void osrf_app_session_request_finish(
osrfAppSession* session, int req_id ){
if(session == NULL) return;
req->reset_timeout = 1;
}
-/** Checks the receive queue for messages. If any are found, the first
- * is popped off and returned. Otherwise, this method will wait at most timeout
- * seconds for a message to appear in the receive queue. Once it arrives it is returned.
- * If no messages arrive in the timeout provided, null is returned.
- */
+/**
+ Checks the receive queue for messages. If any are found, the first
+ is popped off and returned. Otherwise, this method will wait at most timeout
+ seconds for a message to appear in the receive queue. Once it arrives it is returned.
+ If no messages arrive in the timeout provided, null is returned.
+*/
static osrfMessage* _osrf_app_request_recv( osrfAppRequest* req, int timeout ) {
if(req == NULL) return NULL;
return tmp_msg;
}
- time_t start = time(NULL);
+ time_t start = time(NULL);
time_t remaining = (time_t) timeout;
while( remaining >= 0 ) {
osrfLogDebug( OSRF_LOG_MARK, "In app_request receive with remaining time [%d]", (int) remaining );
osrf_app_session_queue_wait( req->session, 0, NULL );
- if(req->session->transport_error) {
- osrfLogError(OSRF_LOG_MARK, "Transport error in recv()");
- return NULL;
- }
+ if(req->session->transport_error) {
+ osrfLogError(OSRF_LOG_MARK, "Transport error in recv()");
+ return NULL;
+ }
if( req->result != NULL ) { /* if we received anything */
/* pop off the first message in the list */
osrf_app_session_queue_wait( req->session, (int) remaining, NULL );
- if(req->session->transport_error) {
- osrfLogError(OSRF_LOG_MARK, "Transport error in recv()");
- return NULL;
- }
+ if(req->session->transport_error) {
+ osrfLogError(OSRF_LOG_MARK, "Transport error in recv()");
+ return NULL;
+ }
if( req->result != NULL ) { /* if we received anything */
/* pop off the first message in the list */
}
}
- char* paramString = jsonObjectToJSON(req->payload->_params);
+ char* paramString = jsonObjectToJSON(req->payload->_params);
osrfLogInfo( OSRF_LOG_MARK, "Returning NULL from app_request_recv after timeout: %s %s",
- req->payload->method_name, paramString);
- free(paramString);
+ req->payload->method_name, paramString);
+ free(paramString);
return NULL;
}
session->orig_remote_id = strdup(session->remote_id);
session->remote_service = strdup(remote_service);
session->session_locale = NULL;
- session->transport_error = 0;
+ session->transport_error = 0;
#ifdef ASSUME_STATELESS
session->stateless = 1;
snprintf(id, sizeof(id), "%f.%d%ld", get_timestamp_millis(), (int)time(NULL), (long) getpid());
session->session_id = strdup(id);
- osrfLogDebug( OSRF_LOG_MARK, "Building a new client session with id [%s] [%s]",
+ osrfLogDebug( OSRF_LOG_MARK, "Building a new client session with id [%s] [%s]",
session->remote_service, session->session_id );
session->thread_trace = 0;
session->userData = NULL;
session->userDataFree = NULL;
-
+
_osrf_app_session_push_session( session );
return session;
}
session->userData = NULL;
session->userDataFree = NULL;
-
+
_osrf_app_session_push_session( session );
return session;
osrfLogDebug( OSRF_LOG_MARK, "Pushing [%d] onto request queue for session [%s] [%s]",
req->request_id, session->remote_service, session->session_id );
- osrfListSet( session->request_queue, req, req->request_id );
+ osrfListSet( session->request_queue, req, req->request_id );
return req->request_id;
}
session->remote_id = strdup( remote_id );
}
-/** pushes the given message into the result list of the app_request
- with the given request_id */
-int osrf_app_session_push_queue(
+/**
+ pushes the given message into the result list of the app_request
+ with the given request_id
+*/
+int osrf_app_session_push_queue(
osrfAppSession* session, osrfMessage* msg ){
if(session == NULL || msg == NULL) return 0;
/** Attempts to connect to the remote service */
int osrfAppSessionConnect( osrfAppSession* session ) {
-
+
if(session == NULL)
return 0;
session->state = OSRF_SESSION_CONNECTING;
int ret = _osrf_app_session_send( session, con_msg );
osrfMessageFree(con_msg);
- if(ret) return 0;
+ if(ret)
+ return 0;
- time_t start = time(NULL);
+ time_t start = time(NULL);
time_t remaining = (time_t) timeout;
while( session->state != OSRF_SESSION_CONNECTED && remaining >= 0 ) {
osrf_app_session_queue_wait( session, remaining, NULL );
- if(session->transport_error) {
- osrfLogError(OSRF_LOG_MARK, "cannot communicate with %s", session->remote_service);
- return 0;
- }
+ if(session->transport_error) {
+ osrfLogError(OSRF_LOG_MARK, "cannot communicate with %s", session->remote_service);
+ return 0;
+ }
remaining -= (int) (time(NULL) - start);
}
return 1;
if(session->stateless && session->state != OSRF_SESSION_CONNECTED) {
- osrfLogDebug( OSRF_LOG_MARK,
- "Exiting disconnect on stateless session %s",
+ osrfLogDebug( OSRF_LOG_MARK,
+ "Exiting disconnect on stateless session %s",
session->session_id);
return 1;
}
if(session->stateless) { /* stateless session always send to the root listener */
osrf_app_session_reset_remote(session);
- } else {
+ } else {
/* do an auto-connect if necessary */
if( ! session->stateless &&
- (msg->m_type != CONNECT) &&
+ (msg->m_type != CONNECT) &&
(msg->m_type != DISCONNECT) &&
(session->state != OSRF_SESSION_CONNECTED) ) {
- if(!osrfAppSessionConnect( session ))
+ if(!osrfAppSessionConnect( session ))
return 0;
}
}
if( string ) {
- transport_message* t_msg = message_init(
+ transport_message* t_msg = message_init(
string, "", session->session_id, session->remote_id, NULL );
- message_set_osrf_xid( t_msg, osrfLogGetXid() );
+ message_set_osrf_xid( t_msg, osrfLogGetXid() );
retval = client_send_message( session->transport_handle, t_msg );
message_free( t_msg );
}
- return retval;
+ return retval;
}
}
-
-
-/** Waits up to 'timeout' seconds for some data to arrive.
- * Any data that arrives will be processed according to its
- * payload and message type. This method will return after
- * any data has arrived.
- */
+/**
+ Waits up to 'timeout' seconds for some data to arrive.
+ Any data that arrives will be processed according to its
+ payload and message type. This method will return after
+ any data has arrived.
+*/
int osrf_app_session_queue_wait( osrfAppSession* session, int timeout, int* recvd ){
if(session == NULL) return 0;
osrfLogDebug(OSRF_LOG_MARK, "AppSession in queue_wait with timeout %d", timeout );
return osrf_stack_entry_point(session->transport_handle, timeout, recvd);
}
-/** Disconnects (if client) and removes the given session from the global session cache
- * ! This frees all attached app_requests !
- */
+/** Disconnects (if client) and removes the given session from the global session cache
+ ! This frees all attached app_requests !
+*/
void osrfAppSessionFree( osrfAppSession* session ){
if(session == NULL) return;
/* Disconnect */
-
- osrfLogDebug(OSRF_LOG_MARK, "AppSession [%s] [%s] destroying self and deleting requests",
+
+ osrfLogDebug(OSRF_LOG_MARK, "AppSession [%s] [%s] destroying self and deleting requests",
session->remote_service, session->session_id );
- if(session->type == OSRF_SESSION_CLIENT
+ if(session->type == OSRF_SESSION_CLIENT
&& session->state != OSRF_SESSION_DISCONNECTED ) { /* disconnect if we're a client */
osrfMessage* dis_msg = osrf_message_init( DISCONNECT, session->thread_trace, 1 );
- _osrf_app_session_send( session, dis_msg );
+ _osrf_app_session_send( session, dis_msg );
osrfMessageFree(dis_msg);
}
/* Remove self from the global session cache */
-
+
osrfHashRemove( osrfAppSessionCache, session->session_id );
-
+
/* Free the memory */
-
+
if( session->userDataFree && session->userData )
session->userDataFree(session->userData);
-
+
if(session->session_locale)
free(session->session_locale);
char* json = jsonObjectToJSON( data );
osrf_message_set_result_content( msg, json );
- _osrf_app_session_send( ses, msg );
+ _osrf_app_session_send( ses, msg );
free(json);
osrfMessageFree( msg );
}
-int osrfAppRequestRespondComplete(
+int osrfAppRequestRespondComplete(
osrfAppSession* ses, int requestId, const jsonObject* data ) {
osrfMessage* status = osrf_message_init( STATUS, requestId, 1);
osrf_message_set_status_info( status, "osrfConnectStatus", "Request Complete", OSRF_STATUS_COMPLETE );
-
+
if (data) {
osrfMessage* payload = osrf_message_init( RESULT, requestId, 1 );
osrf_message_set_status_info( payload, NULL, "OK", OSRF_STATUS_OK );
if(ses) {
osrfMessage* msg = osrf_message_init( STATUS, reqId, 1);
osrf_message_set_status_info( msg, name, message, type );
- _osrf_app_session_send( ses, msg );
+ _osrf_app_session_send( ses, msg );
osrfMessageFree( msg );
return 0;
}