/** @brief React to the closing of an XML tag. @param session Pointer to a transport_session, cast to a void pointer. @param name Pointer to the name of the tag that is closing. See what kind of tag is closing, and respond accordingly. */ static void endElementHandler( void *session, const xmlChar *name) { transport_session* ses = (transport_session*) session; if( ! ses ) { return; } // Bypass a level of indirection, since we'll examine the machine repeatedly: jabber_machine* machine = ses->state_machine; if( machine->in_message && strcmp( (char*) name, "message" ) == 0 ) { /* pass off the message info the callback */ if( ses->message_callback ) { transport_message* msg = message_init( OSRF_BUFFER_C_STR( ses->body_buffer ), OSRF_BUFFER_C_STR( ses->subject_buffer ), OSRF_BUFFER_C_STR( ses->thread_buffer ), OSRF_BUFFER_C_STR( ses->recipient_buffer ), OSRF_BUFFER_C_STR( ses->from_buffer ) ); message_set_router_info( msg, ses->router_from_buffer->buf, ses->router_to_buffer->buf, ses->router_class_buffer->buf, ses->router_command_buffer->buf, ses->router_broadcast ); message_set_osrf_xid( msg, ses->osrf_xid_buffer->buf ); if( ses->message_error_type->n_used > 0 ) { set_msg_error( msg, ses->message_error_type->buf, ses->message_error_code ); } if( msg == NULL ) { return; } ses->message_callback( ses->user_data, msg ); } machine->in_message = 0; reset_session_buffers( session ); return; } if( machine->in_message_body && strcmp( (const char*) name, "body" ) == 0 ) { machine->in_message_body = 0; return; } if( machine->in_subject && strcmp( (const char*) name, "subject" ) == 0 ) { machine->in_subject = 0; return; } if( machine->in_thread && strcmp( (const char*) name, "thread" ) == 0 ) { machine->in_thread = 0; return; } if( machine->in_iq && strcmp( (const char*) name, "iq" ) == 0 ) { machine->in_iq = 0; if( ses->message_error_code > 0 ) { if( 401 == ses->message_error_code ) osrfLogWarning( OSRF_LOG_MARK, "Error 401 in IQ packet: not authorized" ); else osrfLogWarning( OSRF_LOG_MARK, "Error in IQ packet: code %d", ses->message_error_code ); } reset_session_buffers( session ); return; } if( machine->in_presence && strcmp( (const char*) name, "presence" ) == 0 ) { machine->in_presence = 0; /* if( ses->presence_callback ) { // call the callback with the status, etc. } */ reset_session_buffers( session ); return; } if( machine->in_status && strcmp( (const char*) name, "status" ) == 0 ) { machine->in_status = 0; return; } if( machine->in_message_error && strcmp( (const char*) name, "error" ) == 0 ) { machine->in_message_error = 0; return; } if( machine->in_error && strcmp( (const char*) name, "stream:error" ) == 0 ) { machine->in_error = 0; return; } }
static int osrfHttpTranslatorProcess(osrfHttpTranslator* trans) { if(trans->body == NULL) return HTTP_BAD_REQUEST; if(!osrfHttpTranslatorSetTo(trans)) return HTTP_BAD_REQUEST; char* jsonBody = osrfHttpTranslatorParseRequest(trans); if (NULL == jsonBody) return HTTP_BAD_REQUEST; while(client_recv(trans->handle, 0)) continue; // discard any old status messages in the recv queue // send the message to the recipient transport_message* tmsg = message_init( jsonBody, NULL, trans->thread, trans->recipient, NULL); message_set_osrf_xid(tmsg, osrfLogGetXid()); client_send_message(trans->handle, tmsg); message_free(tmsg); free(jsonBody); if(trans->disconnectOnly) { osrfLogDebug(OSRF_LOG_MARK, "exiting early on disconnect"); osrfCacheRemove(trans->thread); return OK; } // process the response from the opensrf service int firstWrite = 1; while(!trans->complete) { transport_message* msg = client_recv(trans->handle, trans->timeout); if(trans->handle->error) { osrfLogError(OSRF_LOG_MARK, "Transport error"); osrfCacheRemove(trans->thread); return HTTP_INTERNAL_SERVER_ERROR; } if(msg == NULL) return HTTP_GATEWAY_TIME_OUT; if(msg->is_error) { osrfLogError(OSRF_LOG_MARK, "XMPP message resulted in error code %d", msg->error_code); osrfCacheRemove(trans->thread); return HTTP_NOT_FOUND; } if(!osrfHttpTranslatorCheckStatus(trans, msg)) continue; if(firstWrite) { osrfHttpTranslatorInitHeaders(trans, msg); if(trans->connecting) osrfHttpTranslatorCacheSession(trans, msg->sender); firstWrite = 0; } if(trans->multipart) { osrfHttpTranslatorWriteChunk(trans, msg); if(trans->connectOnly) break; } else { if(!trans->messages) trans->messages = osrfNewList(); osrfListPush(trans->messages, msg->body); if(trans->complete || trans->connectOnly) { growing_buffer* buf = buffer_init(128); unsigned int i; OSRF_BUFFER_ADD(buf, osrfListGetIndex(trans->messages, 0)); for(i = 1; i < trans->messages->size; i++) { buffer_chomp(buf); // chomp off the closing array bracket char* body = osrfListGetIndex(trans->messages, i); char newbuf[strlen(body)]; sprintf(newbuf, "%s", body+1); // chomp off the opening array bracket OSRF_BUFFER_ADD_CHAR(buf, ','); OSRF_BUFFER_ADD(buf, newbuf); } ap_rputs(buf->buf, trans->apreq); buffer_free(buf); } } } if(trans->disconnecting) // DISCONNECT within a multi-message batch osrfCacheRemove(trans->thread); return OK; }
/** * Parse opensrf request and relay the request to the opensrf network. */ static size_t on_message_handler_body(void *data, const WebSocketServer *server, const int type, unsigned char *buffer, const size_t buffer_size) { request_rec *r = server->request(server); jsonObject *msg_wrapper = NULL; // free me const jsonObject *tmp_obj = NULL; const jsonObject *osrf_msg = NULL; const char *service = NULL; const char *thread = NULL; const char *log_xid = NULL; char *msg_body = NULL; char *recipient = NULL; int i; if (buffer_size <= 0) return OK; // generate a new log trace for this request. it // may be replaced by a client-provided trace below. osrfLogMkXid(); osrfLogDebug(OSRF_LOG_MARK, "WS received message size=%d", buffer_size); // buffer may not be \0-terminated, which jsonParse requires char buf[buffer_size + 1]; memcpy(buf, buffer, buffer_size); buf[buffer_size] = '\0'; osrfLogInternal(OSRF_LOG_MARK, "WS received inbound message: %s", buf); msg_wrapper = jsonParse(buf); if (msg_wrapper == NULL) { osrfLogWarning(OSRF_LOG_MARK, "WS Invalid JSON: %s", buf); return HTTP_BAD_REQUEST; } osrf_msg = jsonObjectGetKeyConst(msg_wrapper, "osrf_msg"); if (tmp_obj = jsonObjectGetKeyConst(msg_wrapper, "service")) service = jsonObjectGetString(tmp_obj); if (tmp_obj = jsonObjectGetKeyConst(msg_wrapper, "thread")) thread = jsonObjectGetString(tmp_obj); if (tmp_obj = jsonObjectGetKeyConst(msg_wrapper, "log_xid")) log_xid = jsonObjectGetString(tmp_obj); if (log_xid) { // use the caller-provide log trace id if (strlen(log_xid) > MAX_THREAD_SIZE) { osrfLogWarning(OSRF_LOG_MARK, "WS log_xid exceeds max length"); return HTTP_BAD_REQUEST; } osrfLogForceXid(log_xid); } if (thread) { if (strlen(thread) > MAX_THREAD_SIZE) { osrfLogWarning(OSRF_LOG_MARK, "WS thread exceeds max length"); return HTTP_BAD_REQUEST; } // since clients can provide their own threads at session start time, // the presence of a thread does not guarantee a cached recipient recipient = (char*) apr_hash_get( trans->stateful_session_cache, thread, APR_HASH_KEY_STRING); if (recipient) { osrfLogDebug(OSRF_LOG_MARK, "WS found cached recipient %s", recipient); } } if (!recipient) { if (service) { int size = snprintf(recipient_buf, RECIP_BUF_SIZE - 1, "%s@%s/%s", trans->osrf_router, trans->osrf_domain, service); recipient_buf[size] = '\0'; recipient = recipient_buf; } else { osrfLogWarning(OSRF_LOG_MARK, "WS Unable to determine recipient"); return HTTP_BAD_REQUEST; } } osrfLogDebug(OSRF_LOG_MARK, "WS relaying message to opensrf thread=%s, recipient=%s", thread, recipient); msg_body = extract_inbound_messages( r, service, thread, recipient, osrf_msg); osrfLogInternal(OSRF_LOG_MARK, "WS relaying inbound message: %s", msg_body); transport_message *tmsg = message_init( msg_body, NULL, thread, recipient, NULL); message_set_osrf_xid(tmsg, osrfLogGetXid()); client_send_message(osrf_handle, tmsg); osrfLogClearXid(); message_free(tmsg); jsonObjectFree(msg_wrapper); free(msg_body); last_activity_time = time(NULL); return OK; }