Пример #1
0
LWMsgStatus
lwmsg_assoc_send(
    LWMsgAssoc* assoc,
    LWMsgTag type,
    void* object
    )
{
    LWMsgMessage message = LWMSG_MESSAGE_INITIALIZER;

    message.tag = type;
    message.data = object;

    return lwmsg_assoc_send_message(assoc, &message);
}
Пример #2
0
static
LWMsgStatus
lwmsg_peer_task_dispatch_calls(
    PeerAssocTask* task
    )
{
    LWMsgStatus status = LWMSG_STATUS_PENDING;
    PeerCall* call = NULL;
    LWMsgCookie cookie = 0;
    LWMsgMessage message = LWMSG_MESSAGE_INITIALIZER;
    LWMsgRing* ring = NULL;
    LWMsgRing* next = NULL;
    LWMsgSessionString sessid = {0};

    for (ring = task->active_outgoing_calls.next;
         ring != &task->active_outgoing_calls;
         ring = next)
    {
        next = ring->next;
        lwmsg_ring_remove(ring);

        call = LWMSG_OBJECT_FROM_MEMBER(ring, PeerCall, queue_ring);

        /* Undispatched outgoing call -- send request*/
        if (!(call->state & PEER_CALL_DISPATCHED))
        {
            call->state |= PEER_CALL_DISPATCHED;

            lwmsg_message_init(&task->outgoing_message);
            task->outgoing_message.tag = call->params.outgoing.in->tag;
            task->outgoing_message.data = call->params.outgoing.in->data;
            task->outgoing_message.cookie = call->cookie;
            task->outgoing_message.status = call->status;

            lwmsg_peer_log_message(task, &task->outgoing_message, LWMSG_TRUE);
            status = lwmsg_assoc_send_message(task->assoc, &task->outgoing_message);
            switch (status)
            {
            case LWMSG_STATUS_SUCCESS:
                break;
            case LWMSG_STATUS_PENDING:
                task->outgoing = LWMSG_TRUE;
                BAIL_ON_ERROR(status);
                break;
            case LWMSG_STATUS_MALFORMED:
            case LWMSG_STATUS_INVALID_HANDLE:
                /* The association should still be usable, so just fail the call */
                lwmsg_message_init(&message);
                message.status = status;
                message.flags = LWMSG_MESSAGE_FLAG_REPLY | LWMSG_MESSAGE_FLAG_SYNTHETIC;
                message.cookie = call->cookie;
                lwmsg_peer_call_complete_outgoing(call, &message);
                status = LWMSG_STATUS_SUCCESS;
                break;
            default:
                BAIL_ON_ERROR(status);
            }
        }
        /* Cancelled outgoing call -- send cancel request */
        else if ((call->state & PEER_CALL_DISPATCHED) &&
                 (call->state & PEER_CALL_CANCELLED) &&
                 call->status != LWMSG_STATUS_CANCELLED)
        {
            call->status = LWMSG_STATUS_CANCELLED;

            lwmsg_message_init(&task->outgoing_message);
            task->outgoing_message.flags = LWMSG_MESSAGE_FLAG_CONTROL;
            task->outgoing_message.status = LWMSG_STATUS_CANCELLED;
            task->outgoing_message.cookie = call->cookie;

            lwmsg_peer_log_message(task, &task->outgoing_message, LWMSG_TRUE);
            status = lwmsg_assoc_send_message(task->assoc, &task->outgoing_message);
            switch (status)
            {
            case LWMSG_STATUS_SUCCESS:
                break;
            case LWMSG_STATUS_PENDING:
                task->outgoing = LWMSG_TRUE;
                BAIL_ON_ERROR(status);
                break;
            default:
                BAIL_ON_ERROR(status);
            }
        }
    }

    for (ring = task->active_incoming_calls.next;
         ring != &task->active_incoming_calls;
         ring = next)
    {
        next = ring->next;
        lwmsg_ring_remove(ring);

        call = LWMSG_OBJECT_FROM_MEMBER(ring, PeerCall, queue_ring);

        /* Completed incoming call -- send reply */
        if ((call->state & PEER_CALL_COMPLETED) &&
            (call->state & PEER_CALL_DISPATCHED))
        {
            /* Trace call completion */
            if (call->task->session->peer->trace_end)
            {
                call->task->session->peer->trace_end(
                    LWMSG_CALL(call),
                    &call->params.incoming.out,
                    call->status,
                    call->task->session->peer->trace_data);
            }

            lwmsg_message_init(&task->outgoing_message);
            task->outgoing_message.flags = LWMSG_MESSAGE_FLAG_REPLY;
            task->outgoing_message.tag = call->params.incoming.out.tag;
            task->outgoing_message.data = call->params.incoming.out.data;
            task->outgoing_message.cookie = call->cookie;
            task->outgoing_message.status = call->status;

            cookie = call->cookie;

            /* It's now safe to destroy the incoming call parameters */
            message.tag = call->params.incoming.in.tag;
            message.data = call->params.incoming.in.data;
            lwmsg_assoc_destroy_message(task->assoc, &message);

            /* Delete the call structure */
            lwmsg_hash_remove_entry(&task->incoming_calls, call);
            lwmsg_peer_call_delete(call);

            do
            {
                status = lwmsg_assoc_send_message(task->assoc, &task->outgoing_message);
                switch (status)
                {
                case LWMSG_STATUS_SUCCESS:
                    lwmsg_peer_log_message(task, &task->outgoing_message, LWMSG_FALSE);
                    lwmsg_assoc_destroy_message(task->assoc, &task->outgoing_message);
                    break;
                case LWMSG_STATUS_PENDING:
                    task->outgoing = LWMSG_TRUE;
                    task->destroy_outgoing = LWMSG_TRUE;
                    BAIL_ON_ERROR(status);
                    break;
                case LWMSG_STATUS_MALFORMED:
                case LWMSG_STATUS_INVALID_HANDLE:
                case LWMSG_STATUS_OVERFLOW:
                case LWMSG_STATUS_UNDERFLOW:
                    /* Our reply could not be sent because the dispatch function gave us
                       bogus response parameters.  Send a synthetic reply instead so the
                       caller at least knows the call is complete */
                    lwmsg_peer_session_string_for_session((LWMsgSession*) task->session, sessid);
                    LWMSG_LOG_WARNING(task->session->peer->context,
                                      "(session:%s >> %u) Response payload could not be sent: %s",
                                      sessid,
                                      cookie,
                                      lwmsg_status_name(status));
                    lwmsg_assoc_destroy_message(task->assoc, &task->outgoing_message);
                    lwmsg_message_init(&task->outgoing_message);
                    task->outgoing_message.flags = LWMSG_MESSAGE_FLAG_REPLY | LWMSG_MESSAGE_FLAG_SYNTHETIC;
                    task->outgoing_message.status = status;
                    task->outgoing_message.cookie = cookie;
                    status = LWMSG_STATUS_AGAIN;
                    break;
                default:
                    BAIL_ON_ERROR(status);
                }
            } while (status == LWMSG_STATUS_AGAIN);
        }
    }

error:

    return status;
}