Ejemplo n.º 1
0
void queue_foreach(struct queue *queue, queue_foreach_func_t function,
							void *user_data)
{
	struct queue_entry *entry;

	if (!queue || !function)
		return;

	entry = queue->head;
	if (!entry)
		return;

	queue_ref(queue);
	while (entry && queue->ref_count > 1) {
		struct queue_entry *tmp = entry;

		entry = tmp->next;

		function(tmp->data, user_data);

		if (!queue_find_entry(queue, entry))
			break;
	}
	queue_unref(queue);
}
Ejemplo n.º 2
0
/* Release the event handle returned by framework_event_query.
 * In the ASYNC model we must remove the event handle from the FIFO request
 * queue. */
void framework_release_handle(naf_handle handle)
{
    queue_entry* entry;

    if (!handle) {
        return;
    }
    if (queue_empty()) {
        /* Why do the application try to release a handle on an empty queue? */
        NABTO_LOG_FATAL(("SW error: Calling framework_release_handle on an empty queue"));
        return;
    }

    /* Find the entry containing the handle */
    entry = queue_find_entry(handle);
    /* The given handle must belong to the queue */
    UNABTO_ASSERT(entry);

    entry->state = APPREQ_FREE;
    LOG_APPREQ_WHERE("framework_release_handle", entry);

    /* Remove top entry from FIFO queue - and remove all consecutive
     * entries that have expired/finished in the mean time. */
    while (!queue_empty()) {
        if (queue_top()->state != APPREQ_FREE)
            break;
        queue_pop();
    }

    LOG_APPREQ_QUEUE();
}
Ejemplo n.º 3
0
/* Poll a pending event.
 * Returns true if a response is ready (from any event in the queue).
 * If this function fails (returns false) all buffers are unmodified. */
bool framework_event_poll(uint8_t* buf, uint16_t size, uint16_t* olen, nabto_connect** con)
{
    queue_entry             *entry;
    application_event_result ret;
    application_request     *req;
    struct naf_handle_s     *handle;
    request_query            find;

    if (queue_empty()) {
        // no requests queued in this framework,
        // hence no requests pending in application
        return false;
    }

    //Loop through the queue and find the running (IN_APP) request,
    //if any - and find the first waiting request. Then do the below.
    //OLD: entry = queue_top();
    entry = find_any_request_in_queue();
    if (!entry) {
        return false;
    }

    switch (entry->state) {
        case APPREQ_FREE:
            // first request has been released,
            // hence no requests pending in application
            return false;
    
        case APPREQ_IN_APP:
            // A request is pending in the application, continue 
            break;

      default:
        // Unknown state - ???
        UNABTO_ASSERT(0);
        return false;
    }

    //The application is waiting for this framework to call it.

    //Ask for the request in the application
    req = NULL;
    if (!application_poll_query(&req)) {
        // The application isn't ready with a response yet, poll again later
        return false;
    }
    //If application_poll_query returns true - it must return a request handle
    if (!req) {
        LOG_APPERR_0(entry, "Response dropped because the application returned a NULL request !?");
        goto drop_poll;
    }

    //Find the handle holding the given request
    find.req = (const application_request*) req;
    find.found = NULL;
    queue_enum(find_request_cb, &find);
    handle = find.found;
    if (!handle) {
        LOG_APPERR_0(entry, "Response dropped because the application returned a request that isn't known by the framework");
        goto drop_poll;
    }
    UNABTO_ASSERT(req == &handle->applicationRequest);

    entry = queue_find_entry(handle);
    //The request must be part of a handle in the queue
    if (!entry) {
        LOG_APPERR_0(entry, "Response dropped because the application returned a request that isn't known by the framework queue");
        goto drop_poll;
    }
    UNABTO_ASSERT(handle == &entry->data);

    if (handle->connection->spnsi != handle->spnsi) {
        // the connection has changed, the request/response is dropped
        NABTO_LOG_TRACE(("Response dropped because the connection (" PRI_client_id ") is gone", CLIENT_ID_ARGH(*handle)));
        goto drop_poll;
    }
 
    NABTO_LOG_TRACE(("APPREQ: polling=%" PRI_index, queue_index(entry)));

    ret = framework_poll_event(&entry->data, buf, size, olen);

  if (ret != AER_REQ_RESPONSE_READY) {
      // pass the result to caller to become an exception
      if (!framework_write_exception(ret, &entry->data.header, buf, size, olen)) {
            LOG_APPERR_1(entry, "Response dropped because an exception packet with error code %i couldn't be generated", (int)ret);
            goto drop_poll;
      }
  }

    *con = entry->data.connection;
    framework_release_handle(handle);
    LOG_APPREQ_BYTES("framework_event_poll", "true", entry, *olen);
    LOG_APPREQ_QUEUE();
    return true;

drop_poll:
    application_poll_drop(req);
    framework_release_handle(&entry->data);
    LOG_APPREQ_BYTES("framework_event_poll", "false", entry, 0);
    LOG_APPREQ_QUEUE();
    return false;
}
Ejemplo n.º 4
0
/* Handle application event in ASYNC model.
 * Initialize the handle and call applicaion_event. */
application_event_result framework_event(naf_handle           handle,
                                         uint8_t*             iobuf,
                                         uint16_t             size,
                                         uint16_t             ilen,
                                         uint16_t*            olen,
                                         nabto_connect*       con,
                                         nabto_packet_header* hdr)
{
    queue_entry*             entry;
    unabto_buffer                 w_buf;
    unabto_query_response           w_b;
    application_event_result ret;

    /* Find the entry containing the handle */
    entry = queue_find_entry(handle);
    /* The given handle must belong to the queue */
    UNABTO_ASSERT(entry);

    /* Handle must have been returned by framework_event_query(). */
    if (entry->state != APPREQ_WAITING) {
        LOG_APPREQ_QUEUE();
        LOG_APPREQ_EWAIT("framework_event", entry);
    }

    /* Initialize entry in queue. */
    entry->data.connection = con;
    if (con && hdr) {
        memcpy(&entry->data.header, (const void*)hdr, sizeof(entry->data.header));
        entry->data.spnsi  = con->spnsi;
    } else {
        memset(&entry->data.header, 0, sizeof(entry->data.header));
        entry->data.spnsi  = 0;
    }

    /* Set up a write buffer to write into iobuf. */
    unabto_buffer_init(&w_buf, iobuf, size);
    unabto_query_response_init(&w_b, &w_buf);

    /* Set up a read buffer that reads from local space or iobuf. */
    unabto_buffer_init(&entry->data.applicationRequestBuffer, iobuf, ilen);
    unabto_query_request_init(&entry->data.readBuffer, &entry->data.applicationRequestBuffer);

    ret = framework_try_event(entry, &entry->data.readBuffer, &w_b, con, hdr);

    /* Handle errors */
    switch (ret) {
        case AER_REQ_RESPONSE_READY:
            //ok - do nothing
            break;

        case AER_REQ_ACCEPTED:
            LOG_APPREQ_LEAVE("framework_event", ret, handle);
            LOG_APPREQ_QUEUE();
            return ret;

        default:
            // pass the result to caller as an exception
            unabto_query_response_init(&w_b, &w_buf); // reset the response
            unabto_query_write_uint32(&w_b, ret);
            hdr->flags |= NP_PACKET_HDR_FLAG_EXCEPTION; // caller copies flags to send buffer!
            NABTO_LOG_TRACE(("Inserting EXCEPTION %i in buffer: %" PRItext, ret, result_s(ret)));
            break;
    }

    *olen = unabto_query_response_used(&w_b);

    LOG_APPREQ_LEAVE("framework_event", ret, handle);
    LOG_APPREQ_QUEUE();
    return ret;
}