static int osrfHttpTranslatorCheckStatus(osrfHttpTranslator* trans, transport_message* msg) { osrfMessage* omsgList[MAX_MSGS_PER_PACKET]; int numMsgs = osrf_message_deserialize(msg->body, omsgList, MAX_MSGS_PER_PACKET); osrfLogDebug(OSRF_LOG_MARK, "parsed %d response messages", numMsgs); if(numMsgs == 0) return 0; osrfMessage* last = omsgList[numMsgs-1]; if(last->m_type == STATUS) { if(last->status_code == OSRF_STATUS_TIMEOUT) { osrfLogDebug(OSRF_LOG_MARK, "removing cached session on request timeout"); osrfCacheRemove(trans->thread); return 0; } // XXX hm, check for explicit status=COMPLETE message instead?? if(last->status_code != OSRF_STATUS_CONTINUE) trans->complete = 1; } return 1; }
/** @brief Unpack a transport_message into one or more osrfMessages, and process each one. @param msg Pointer to the transport_message to be unpacked and processed. @param my_service Application name (optional). @return Pointer to an osrfAppSession -- either a pre-existing one or a new one. Look for an existing osrfAppSession with which the message is associated. Such a session may already exist if, for example, you're a client waiting for a response from some other application, or if you're a server that has opened a stateful session with a client. If you can't find an existing session for the current message, and the @a my_service parameter has provided an application name, then you're presumably a server receiving something from a new client. Create an application server session to own the new message. Barring various errors and malformations, extract one or more osrfMessages from the transport_message. Pass each one to the appropriate routine for processing, depending on whether you're acting as a client or as a server. */ struct osrf_app_session_struct* osrf_stack_transport_handler( transport_message* msg, const char* my_service ) { if(!msg) return NULL; osrfLogSetXid(msg->osrf_xid); osrfLogDebug( OSRF_LOG_MARK, "Transport handler received new message \nfrom %s " "to %s with body \n\n%s\n", msg->sender, msg->recipient, msg->body ); if( msg->is_error && ! msg->thread ) { osrfLogWarning( OSRF_LOG_MARK, "!! Received jabber layer error for %s ... exiting\n", msg->sender ); message_free( msg ); return NULL; } if(! msg->thread && ! msg->is_error ) { osrfLogWarning( OSRF_LOG_MARK, "Received a non-error message with no thread trace... dropping"); message_free( msg ); return NULL; } osrfAppSession* session = osrf_app_session_find_session( msg->thread ); if( !session && my_service ) session = osrf_app_server_session_init( msg->thread, my_service, msg->sender); if( !session ) { message_free( msg ); return NULL; } if(!msg->is_error) osrfLogDebug( OSRF_LOG_MARK, "Session [%s] found or built", session->session_id ); osrf_app_session_set_remote( session, msg->sender ); osrfMessage* arr[OSRF_MAX_MSGS_PER_PACKET]; /* Convert the message body into one or more osrfMessages */ int num_msgs = osrf_message_deserialize(msg->body, arr, OSRF_MAX_MSGS_PER_PACKET); osrfLogDebug( OSRF_LOG_MARK, "We received %d messages from %s", num_msgs, msg->sender ); double starttime = get_timestamp_millis(); int i; for( i = 0; i < num_msgs; i++ ) { /* if we've received a jabber layer error message (probably talking to someone who no longer exists) and we're not talking to the original remote id for this server, consider it a redirect and pass it up */ if(msg->is_error) { osrfLogWarning( OSRF_LOG_MARK, " !!! Received Jabber layer error message" ); if( strcmp( session->remote_id, session->orig_remote_id ) ) { osrfLogWarning( OSRF_LOG_MARK, "Treating jabber error as redirect for tt [%d] " "and session [%s]", arr[i]->thread_trace, session->session_id ); arr[i]->m_type = STATUS; arr[i]->status_code = OSRF_STATUS_REDIRECTED; } else { osrfLogWarning( OSRF_LOG_MARK, " * Jabber Error is for top level remote " " id [%s], no one to send my message to! Cutting request short...", session->remote_id ); session->transport_error = 1; break; } } // grab the ingress value from the first message. // they will all be the same if (i == 0) osrfAppSessionSetIngress(arr[i]->sender_ingress); if( session->type == OSRF_SESSION_CLIENT ) _do_client( session, arr[i] ); else _do_server( session, arr[i] ); } double duration = get_timestamp_millis() - starttime; osrfLogInfo(OSRF_LOG_MARK, "Message processing duration %f", duration); message_free( msg ); osrfLogDebug( OSRF_LOG_MARK, "after msg delete"); return session; }
/** * Parses the request body, logs any REQUEST messages to the activity log, * stamps the translator ingress on each message, and returns the updated * messages as a JSON string. */ static char* osrfHttpTranslatorParseRequest(osrfHttpTranslator* trans) { osrfMessage* msg; osrfMessage* msgList[MAX_MSGS_PER_PACKET]; int numMsgs = osrf_message_deserialize(trans->body, msgList, MAX_MSGS_PER_PACKET); osrfLogDebug(OSRF_LOG_MARK, "parsed %d opensrf messages in this packet", numMsgs); if(numMsgs == 0) return NULL; // log request messages to the activity log int i; for(i = 0; i < numMsgs; i++) { msg = msgList[i]; osrfMessageSetIngress(msg, TRANSLATOR_INGRESS); switch(msg->m_type) { case REQUEST: { const jsonObject* params = msg->_params; growing_buffer* act = buffer_init(128); char* method = msg->method_name; buffer_fadd(act, "[%s] [%s] %s %s", trans->remoteHost, "", trans->service, method); const jsonObject* obj = NULL; int i = 0; const char* str; int redactParams = 0; while( (str = osrfStringArrayGetString(log_protect_arr, i++)) ) { //osrfLogInternal(OSRF_LOG_MARK, "Checking for log protection [%s]", str); if(!strncmp(method, str, strlen(str))) { redactParams = 1; break; } } if(redactParams) { OSRF_BUFFER_ADD(act, " **PARAMS REDACTED**"); } else { i = 0; while((obj = jsonObjectGetIndex(params, i++))) { str = jsonObjectToJSON(obj); if( i == 1 ) OSRF_BUFFER_ADD(act, " "); else OSRF_BUFFER_ADD(act, ", "); OSRF_BUFFER_ADD(act, str); free(str); } } osrfLogActivity(OSRF_LOG_MARK, "%s", act->buf); buffer_free(act); break; } case CONNECT: trans->connecting = 1; if (numMsgs == 1) trans->connectOnly = 1; break; case DISCONNECT: trans->disconnecting = 1; if (numMsgs == 1) trans->disconnectOnly = 1; break; case RESULT: osrfLogWarning( OSRF_LOG_MARK, "Unexpected RESULT message received" ); break; case STATUS: osrfLogWarning( OSRF_LOG_MARK, "Unexpected STATUS message received" ); break; default: osrfLogWarning( OSRF_LOG_MARK, "Invalid message type %d received", msg->m_type ); break; } } char* jsonString = osrfMessageSerializeBatch(msgList, numMsgs); for(i = 0; i < numMsgs; i++) { osrfMessageFree(msgList[i]); } return jsonString; }
static char* extract_inbound_messages( const request_rec *r, const char* service, const char* thread, const char* recipient, const jsonObject *osrf_msg) { int i; int num_msgs = osrf_msg->size; osrfMessage* msg; osrfMessage* msg_list[num_msgs]; // here we do an extra json round-trip to get the data // in a form osrf_message_deserialize can understand // TODO: consider a version of osrf_message_init which can // accept a jsonObject* instead of a JSON string. char *osrf_msg_json = jsonObjectToJSON(osrf_msg); osrf_message_deserialize(osrf_msg_json, msg_list, num_msgs); free(osrf_msg_json); // should we require the caller to always pass the service? if (service == NULL) service = ""; for(i = 0; i < num_msgs; i++) { msg = msg_list[i]; osrfMessageSetIngress(msg, WEBSOCKET_TRANSLATOR_INGRESS); switch(msg->m_type) { case REQUEST: { const jsonObject* params = msg->_params; growing_buffer* act = buffer_init(128); char* method = msg->method_name; buffer_fadd(act, "[%s] [%s] %s %s", get_client_ip(r), "", service, method); const jsonObject* obj = NULL; int i = 0; const char* str; int redactParams = 0; while( (str = osrfStringArrayGetString(log_protect_arr, i++)) ) { if(!strncmp(method, str, strlen(str))) { redactParams = 1; break; } } if(redactParams) { OSRF_BUFFER_ADD(act, " **PARAMS REDACTED**"); } else { i = 0; while((obj = jsonObjectGetIndex(params, i++))) { char* str = jsonObjectToJSON(obj); if( i == 1 ) OSRF_BUFFER_ADD(act, " "); else OSRF_BUFFER_ADD(act, ", "); OSRF_BUFFER_ADD(act, str); free(str); } } osrfLogActivity(OSRF_LOG_MARK, "%s", act->buf); buffer_free(act); requests_in_flight++; break; } case DISCONNECT: clear_cached_recipient(thread); break; } } char* finalMsg = osrfMessageSerializeBatch(msg_list, num_msgs); // clean up our messages for(i = 0; i < num_msgs; i++) osrfMessageFree(msg_list[i]); return finalMsg; }