示例#1
0
static
LWMsgStatus
lwmsg_connection_accept(
    LWMsgAssoc* assoc,
    LWMsgSession* session
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    ConnectionPrivate* priv = CONNECTION_PRIVATE(assoc);

    if (!session)
    {
        if (!priv->default_session)
        {
            BAIL_ON_ERROR(status = lwmsg_assoc_session_new(assoc, &priv->default_session));
        }

        session = priv->default_session;
    }

    priv->params.establish.session = session;
    
    BAIL_ON_ERROR(status = lwmsg_connection_run(assoc, CONNECTION_EVENT_ACCEPT));

error:

    return status;
}
示例#2
0
LWMsgStatus
lwmsg_connection_set_fd(
    LWMsgAssoc* assoc,
    LWMsgConnectionMode mode,
    int fd
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    ConnectionPrivate* priv = CONNECTION_PRIVATE(assoc);

    if (fd < 0)
    {
        ASSOC_RAISE_ERROR(assoc, status = LWMSG_STATUS_INVALID_PARAMETER, "Invalid file descriptor");
    }

    if (priv->fd != -1 || priv->endpoint != NULL)
    {
        ASSOC_RAISE_ERROR(assoc, status = LWMSG_STATUS_INVALID_STATE, "Connection parameters already set");
    }

    priv->fd = fd;
    priv->mode = mode;

error:

    return status;
}
示例#3
0
LWMsgStatus
lwmsg_connection_new(
    const LWMsgContext* context,
    LWMsgProtocol* prot,
    LWMsgAssoc** out_assoc
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    LWMsgAssoc* assoc = NULL;
    ConnectionPrivate* priv = NULL;

    BAIL_ON_ERROR(status = lwmsg_assoc_new(context, prot, &connection_class, sizeof(*priv), &assoc));

    priv = CONNECTION_PRIVATE(assoc);
    priv->state = CONNECTION_STATE_START;

    *out_assoc = assoc;

done:

    return status;

error:

    goto done;
}
示例#4
0
static
LWMsgStatus
lwmsg_peer_task_run_drop(
    LWMsgPeer* peer,
    PeerAssocTask* task,
    LWMsgTaskTrigger trigger,
    LWMsgTaskTrigger* next_trigger,
    LWMsgTime* next_timeout
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    int fd = CONNECTION_PRIVATE(task->assoc)->fd;

    BAIL_ON_ERROR(status = lwmsg_peer_task_rundown(peer, task, trigger, next_trigger, next_timeout));

    if (fd >= 0)
    {
        lwmsg_task_unset_trigger_fd(task->event_task, fd);
    }

    task->type = PEER_TASK_DONE;

error:

    return status;
}
示例#5
0
static LWMsgStatus
lwmsg_connection_set_nonblock(
    LWMsgAssoc* assoc,
    LWMsgBool nonblock
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    ConnectionPrivate* priv = CONNECTION_PRIVATE(assoc);

    switch (lwmsg_assoc_get_state(assoc))
    {
    case LWMSG_ASSOC_STATE_NOT_ESTABLISHED:
    case LWMSG_ASSOC_STATE_IDLE:
    case LWMSG_ASSOC_STATE_CLOSED:
        priv->is_nonblock = nonblock;
        break;
    default:
        ASSOC_RAISE_ERROR(assoc, status = LWMSG_STATUS_INVALID_STATE,
                          "Cannot set blocking while connection is busy");
    }

error:

    return status;
}
示例#6
0
LWMsgStatus
lwmsg_connection_set_endpoint(
    LWMsgAssoc* assoc,
    LWMsgConnectionMode mode,
    const char* endpoint
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    ConnectionPrivate* priv = CONNECTION_PRIVATE(assoc);

    if (priv->fd != -1 || priv->endpoint != NULL)
    {
        ASSOC_RAISE_ERROR(assoc, status = LWMSG_STATUS_INVALID_STATE, "Connection parameters already set");
    }

    priv->endpoint = strdup(endpoint);
    
    if (!priv->endpoint)
    {
        BAIL_ON_ERROR(status = LWMSG_STATUS_MEMORY);
    }

    priv->mode = mode;

error:

    return status;
}
示例#7
0
static LWMsgStatus
lwmsg_connection_finish(
    LWMsgAssoc* assoc,
    LWMsgMessage** message
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    ConnectionPrivate* priv = CONNECTION_PRIVATE(assoc);
    
    if (message)
    {
        priv->params.message = NULL;
    }
    
    BAIL_ON_ERROR(status = lwmsg_connection_run(assoc, CONNECTION_EVENT_FINISH));

    if (message)
    {
        *message = priv->params.message;
    }

error:

    return status;
}
示例#8
0
static
LWMsgStatus
lwmsg_peer_task_run_connect(
    LWMsgPeer* peer,
    PeerAssocTask* task,
    LWMsgTaskTrigger trigger,
    LWMsgTaskTrigger* next_trigger,
    LWMsgTime* next_timeout
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;

    status = lwmsg_assoc_connect(task->assoc, (LWMsgSession*) task->session);

    switch (status)
    {
    case LWMSG_STATUS_SUCCESS:
        task->type = PEER_TASK_DISPATCH;
        BAIL_ON_ERROR(status = lwmsg_peer_log_connect(task));
        /* Set up the fd the assoc just created for events */
        BAIL_ON_ERROR(status = lwmsg_task_set_trigger_fd(task->event_task, CONNECTION_PRIVATE(task->assoc)->fd));
        break;
    case LWMSG_STATUS_PENDING:
        task->type = PEER_TASK_FINISH_CONNECT;
        /* Even if the connect pended, the fd is now available.  Set it up for events */
        BAIL_ON_ERROR(status = lwmsg_task_set_trigger_fd(task->event_task, CONNECTION_PRIVATE(task->assoc)->fd));
        /* Restore status code */
        status = LWMSG_STATUS_PENDING;
        lwmsg_peer_task_set_timeout(peer, task, &peer->timeout.establish, trigger, next_trigger, next_timeout);
        break;
    default:
        BAIL_ON_ERROR(status = lwmsg_peer_task_handle_assoc_error(
                          peer,
                          task,
                          status));
        break;
    }

done:

    return status;

error:

    goto done;
}
示例#9
0
static LWMsgAssocState
lwmsg_connection_get_state(
    LWMsgAssoc* assoc
    )
{
    ConnectionPrivate* priv = CONNECTION_PRIVATE(assoc);
    LWMsgBool need_send = LWMSG_FALSE;
    LWMsgBool need_recv = LWMSG_FALSE;

    switch (priv->state)
    {
    case CONNECTION_STATE_NONE:
        return LWMSG_ASSOC_STATE_NONE;
    case CONNECTION_STATE_START:
        return LWMSG_ASSOC_STATE_NOT_ESTABLISHED;
    case CONNECTION_STATE_ESTABLISHED:
        need_send = (priv->sendbuffer.current != NULL || !lwmsg_ring_is_empty(&priv->sendbuffer.fragments));
        need_recv = (priv->recvbuffer.current != NULL);
        if (need_send && need_recv)
        {
            return LWMSG_ASSOC_STATE_BLOCKED_SEND_RECV;
        }
        else if (need_send)
        {
            return LWMSG_ASSOC_STATE_BLOCKED_SEND;
        }
        else if (need_recv)
        {
            return LWMSG_ASSOC_STATE_BLOCKED_RECV;
        }
        else
        {
            return LWMSG_ASSOC_STATE_IDLE;
        }
    case CONNECTION_STATE_FINISH_CONNECT_SOCKET:
        return LWMSG_ASSOC_STATE_BLOCKED_SEND;
    case CONNECTION_STATE_FINISH_SEND_CONNECT:
    case CONNECTION_STATE_FINISH_SEND_ACCEPT:
        return LWMSG_ASSOC_STATE_BLOCKED_SEND_RECV;
    case CONNECTION_STATE_FINISH_RECV_CONNECT:
    case CONNECTION_STATE_FINISH_RECV_ACCEPT:
        return LWMSG_ASSOC_STATE_BLOCKED_RECV;
    case CONNECTION_STATE_CLOSED:
        return LWMSG_ASSOC_STATE_CLOSED;
    case CONNECTION_STATE_ERROR:
        return LWMSG_ASSOC_STATE_ERROR;
    default:
        return LWMSG_ASSOC_STATE_BUSY;
    }
}
示例#10
0
static LWMsgStatus
lwmsg_connection_recv_msg(
    LWMsgAssoc* assoc,
    LWMsgMessage* message
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    ConnectionPrivate* priv = CONNECTION_PRIVATE(assoc);
    
    priv->params.message = message;

    BAIL_ON_ERROR(status = lwmsg_connection_run(assoc, CONNECTION_EVENT_RECV));

error:

    return status;
}
示例#11
0
static
LWMsgStatus
lwmsg_connection_set_timeout(
    LWMsgAssoc* assoc,
    LWMsgTimeout type,
    LWMsgTime* value
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    ConnectionPrivate* priv = CONNECTION_PRIVATE(assoc);
    LWMsgTime* target = NULL;

    if (value != NULL &&
        (value->seconds < 0 || value->microseconds < 0))
    {
        ASSOC_RAISE_ERROR(assoc, status = LWMSG_STATUS_INVALID_PARAMETER,
                          "Invalid (negative) timeout value");
    }

    switch (type)
    {
    case LWMSG_TIMEOUT_MESSAGE:
        target = &priv->timeout.message;
        break;
    case LWMSG_TIMEOUT_ESTABLISH:
        target = &priv->timeout.establish;
        break;
    default:
        ASSOC_RAISE_ERROR(assoc, status = LWMSG_STATUS_UNSUPPORTED,
                          "Unsupported timeout type");
    }

    if (value)
    {
        *target = *value;
    }
    else
    {
        memset(target, 0xFF, sizeof(*target));
    }

error:

    return status;
}
示例#12
0
static
LWMsgStatus
lwmsg_peer_task_run_accept(
    LWMsgPeer* peer,
    PeerAssocTask* task,
    LWMsgTaskTrigger trigger,
    LWMsgTaskTrigger* next_trigger,
    LWMsgTime* next_timeout
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;

    /* We already have the fd when accepting a connection, so set it up for events now */
    BAIL_ON_ERROR(status = lwmsg_task_set_trigger_fd(task->event_task, CONNECTION_PRIVATE(task->assoc)->fd));

    status = lwmsg_assoc_accept(task->assoc, (LWMsgSession*) task->session);

    switch (status)
    {
    case LWMSG_STATUS_SUCCESS:
        task->type = PEER_TASK_DISPATCH;
        BAIL_ON_ERROR(status = lwmsg_peer_log_accept(task));
        break;
    case LWMSG_STATUS_PENDING:
        task->type = PEER_TASK_FINISH_ACCEPT;
        lwmsg_peer_task_set_timeout(peer, task, &peer->timeout.establish, trigger, next_trigger, next_timeout);
        break;
    default:
        BAIL_ON_ERROR(status = lwmsg_peer_task_handle_assoc_error(
                          peer,
                          task,
                          status));
        break;
    }

done:

    return status;

error:

    goto done;
}
示例#13
0
LWMsgStatus
lwmsg_connection_set_packet_size(
    LWMsgAssoc* assoc,
    size_t size
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    ConnectionPrivate* priv = CONNECTION_PRIVATE(assoc);

    if (priv->active_session)
    {
        ASSOC_RAISE_ERROR(assoc, status = LWMSG_STATUS_INVALID_STATE, "Cannot change packet size of established connection");
    }

    priv->packet_size = size;

error:

    return status;
}
示例#14
0
static LWMsgStatus
lwmsg_connection_get_session(
    LWMsgAssoc* assoc,
    LWMsgSession** session
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    ConnectionPrivate* priv = CONNECTION_PRIVATE(assoc);
    
    if (!priv->active_session)
    {
        BAIL_ON_ERROR(status = LWMSG_STATUS_INVALID_STATE);
    }
    
    *session = priv->active_session;

error:

    return status;
}
示例#15
0
static LWMsgStatus
lwmsg_connection_construct(
    LWMsgAssoc* assoc
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    ConnectionPrivate* priv = CONNECTION_PRIVATE(assoc);

    BAIL_ON_ERROR(status = lwmsg_connection_buffer_construct(&priv->sendbuffer));
    BAIL_ON_ERROR(status = lwmsg_connection_buffer_construct(&priv->recvbuffer));

    priv->packet_size = 8192;
    priv->fd = -1;
    priv->mode = LWMSG_CONNECTION_MODE_NONE;
    
    memset(&priv->timeout.establish, 0xFF, sizeof(priv->timeout.establish));
    memset(&priv->timeout.message, 0xFF, sizeof(priv->timeout.message));

error:

    return status;
}
示例#16
0
static void
lwmsg_connection_destruct(
    LWMsgAssoc* assoc
    )
{
    ConnectionPrivate* priv = CONNECTION_PRIVATE(assoc);

    lwmsg_connection_buffer_destruct(&priv->sendbuffer);
    lwmsg_connection_buffer_destruct(&priv->recvbuffer);

    if (priv->fd != -1)
    {
        close(priv->fd);
        priv->fd = -1;
    }

    if (priv->endpoint)
    {
        free(priv->endpoint);
        priv->endpoint = NULL;
    }

    if (priv->active_session)
    {
        lwmsg_session_release(priv->active_session);
    }

    if (priv->default_session)
    {
        lwmsg_session_release(priv->default_session);
    }

    if (priv->marshal_context)
    {
        lwmsg_data_context_delete(priv->marshal_context);
    }
}
示例#17
0
static
LWMsgStatus
lwmsg_peer_task_run_finish(
    LWMsgPeer* peer,
    PeerAssocTask* task,
    LWMsgTaskTrigger trigger,
    LWMsgTaskTrigger* next_trigger,
    LWMsgTime* next_timeout
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    int fd = CONNECTION_PRIVATE(task->assoc)->fd;

#if 0
    /* When the peer runs out of available client slots, it will
       wake all of its tasks so that it can begin enforcing timeouts
       where it previously did not bother.  Tell the task manager to
       begin waking us up on timeout events if this is the case */
    if ((trigger & LWMSG_TASK_TRIGGER_EXPLICIT) &&
        lwmsg_peer_task_subject_to_timeout(peer, task, trigger))
    {
        *next_trigger |= LWMSG_TASK_TRIGGER_TIME;
    }
#endif

    /* Did we hit a timeout? */
    if (trigger & LWMSG_TASK_TRIGGER_TIME)
    {
        BAIL_ON_ERROR(status = lwmsg_peer_task_handle_assoc_error(
                          peer,
                          task,
                          LWMSG_STATUS_TIMEOUT));
    }
    /* Are we shutting down? */
    else if (trigger & LWMSG_TASK_TRIGGER_CANCEL)
    {
        /* Drop the task unceremoniously in the interest
           of shutting down quickly */
        task->type = PEER_TASK_DROP;
    }
    /* Is the task unblocked? */
    else if (!task->recv_blocked || !task->send_blocked)
    {
        switch (task->type)
        {
        case PEER_TASK_FINISH_CLOSE:
        case PEER_TASK_FINISH_RESET:
            /* We are going to close the fd, so unset it on task */
            if (fd >= 0)
            {
                lwmsg_task_unset_trigger_fd(task->event_task, fd);
            }
            break;
        default:
            break;
        }

        status = lwmsg_assoc_finish(task->assoc, NULL);

        switch (status)
        {
        case LWMSG_STATUS_SUCCESS:
            switch (task->type)
            {
            case PEER_TASK_FINISH_ACCEPT:
                BAIL_ON_ERROR(status = lwmsg_peer_log_accept(task));
                task->type = PEER_TASK_DISPATCH;
                break;
            case PEER_TASK_FINISH_CONNECT:
                BAIL_ON_ERROR(status = lwmsg_peer_log_connect(task));
                task->type = PEER_TASK_DISPATCH;
                break;
            case PEER_TASK_FINISH_CLOSE:
            case PEER_TASK_FINISH_RESET:
                task->type = PEER_TASK_DROP;
                break;
            default:
                break;
            }
            break;
        case LWMSG_STATUS_PENDING:
            switch (task->type)
            {
            case PEER_TASK_FINISH_CLOSE:
            case PEER_TASK_FINISH_RESET:
                /* Nevermind, set the fd on the task again */
                if (fd >= 0)
                {
                    BAIL_ON_ERROR(status = lwmsg_task_set_trigger_fd(task->event_task, fd));
                }
                break;
            default:
                break;
            }
            break;
        default:
            BAIL_ON_ERROR(status = lwmsg_peer_task_handle_assoc_error(
                              peer,
                              task,
                              status));
            break;
        }
    }
    /* Nothing to do */
    else
    {
        BAIL_ON_ERROR(status = LWMSG_STATUS_PENDING);
    }

error:

    return status;
}
示例#18
0
static
LWMsgStatus
lwmsg_peer_task_run_shutdown(
    LWMsgPeer* peer,
    PeerAssocTask* task,
    LWMsgTaskTrigger trigger,
    LWMsgTaskTrigger* next_trigger,
    LWMsgTime* next_timeout
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    int fd = CONNECTION_PRIVATE(task->assoc)->fd;

    /* Before we close the assoc, we need to free any data it allocated */

    /* First, make sure any calls are canceled, completed, and freed */
    BAIL_ON_ERROR(status = lwmsg_peer_task_rundown(peer, task, trigger, next_trigger, next_timeout));

    /* Destroy any incoming message we never got around to dispatching */
    lwmsg_assoc_destroy_message(task->assoc, &task->incoming_message);

    /* Destroy any outgoing message we never got around to sending */
    if (task->destroy_outgoing)
    {
        lwmsg_assoc_destroy_message(task->assoc, &task->outgoing_message);
    }

    /* We are going to close the fd, so unset it now */
    if (fd >= 0)
    {
        lwmsg_task_unset_trigger_fd(task->event_task, fd);
    }

    switch (task->type)
    {
    case PEER_TASK_BEGIN_CLOSE:
        status = lwmsg_assoc_close(task->assoc);
        break;
    case PEER_TASK_BEGIN_RESET:
        status = lwmsg_assoc_reset(task->assoc);
        break;
    default:
        BAIL_ON_ERROR(status = LWMSG_STATUS_INTERNAL);
    }

    switch (status)
    {
    case LWMSG_STATUS_SUCCESS:
        task->type = PEER_TASK_DROP;
        break;
    case LWMSG_STATUS_PENDING:
        /* Oops, we still need to wait for fd events, so set it on the task again */
        if (fd >= 0)
        {
            BAIL_ON_ERROR(status = lwmsg_task_set_trigger_fd(task->event_task, fd));
        }
        task->type = PEER_TASK_FINISH_CLOSE;
        lwmsg_peer_task_set_timeout(peer, task, &peer->timeout.establish, trigger, next_trigger, next_timeout);
        break;
    default:
        BAIL_ON_ERROR(status);
        break;
    }

done:

    return status;

error:

    goto done;
}