예제 #1
0
/**
	@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;
	}
}
예제 #2
0
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;
}