Exemple #1
0
/* create a new mysocket, and find space in our mysocket descriptor table */
mysocket_t _mysock_new_mysocket(bool_t is_reliable)
{
    mysock_context_t *connection_context = _mysock_allocate_context();
    int k;

    if (!connection_context)
    {
        assert(0);
        return -1;
    }

    /* propagates down to new connections arriving on a listening socket */
    connection_context->network_state.is_reliable = is_reliable;

    /* search for a free mysocket descriptor */
    for (k = 0; k < MAX_NUM_CONNECTIONS; ++k)
    {
        if (!global_ctx[k])
        {
            global_ctx[k] = connection_context;
            connection_context->my_sd = k;
            return k;
        }
    }

    _mysock_free_context(connection_context);
    errno = EMFILE;
    return -1;
}
Exemple #2
0
/* allocate a new connection context.  this keeps track of the working state
 * between the transport and network layers for a particular connection.  the
 * context is subsequently freed on the network layer's exit.
 */
static mysock_context_t *_mysock_allocate_context(void)
{
    mysock_context_t *ctx = 0;

    ctx = (mysock_context_t *) calloc(1, sizeof(mysock_context_t));
    assert(ctx);

    /* by default, sockets are active */
    ctx->listen_sd = -1;

    /* initialise connection condition variable.  this is signaled when the
     * connection is established, i.e. myconnect() or myaccept() should
     * unblock and return to the calling application.
     */
    PTHREAD_CALL(pthread_cond_init(&ctx->blocking_cond, NULL));
    PTHREAD_CALL(pthread_mutex_init(&ctx->blocking_lock, NULL));

    /* initialise data ready condition variable.  this is signaled when
     * data is ready from the application or the network.
     */
    PTHREAD_CALL(pthread_cond_init(&ctx->data_ready_cond, NULL));
    PTHREAD_CALL(pthread_mutex_init(&ctx->data_ready_lock, NULL));

    ctx->blocking = TRUE;   /* we unblock once we're connected */


    /* initialise underlying network state.  this includes creating the actual
     * socket used for communication to the peer--this is analogous to the
     * underlying raw IP socket used by a real TCP implementation.
     */
    if (_network_init(ctx, &ctx->network_state) < 0)
    {
        _mysock_free_context(ctx);
        return NULL;
    }

    return ctx;
}
Exemple #3
0
/* close the given mysocket.  note that the semantics of myclose() differ
 * slightly from a regular close(); STCP doesn't implement WAIT_TIME, so
 * myclose() simply discards all knowledge of the connection once the
 * connection is terminated.
 */
int myclose(mysocket_t sd)
{
    mysock_context_t *ctx = _mysock_get_context(sd);

    DEBUG_LOG(("***myclose(%d)***\n", sd));
    MYSOCK_CHECK(ctx != NULL, EBADF);

    /* stcp_wait_for_event() needs to wake up on a socket close request */
    PTHREAD_CALL(pthread_mutex_lock(&ctx->data_ready_lock));
    ctx->close_requested = TRUE;
    PTHREAD_CALL(pthread_mutex_unlock(&ctx->data_ready_lock));
    PTHREAD_CALL(pthread_cond_broadcast(&ctx->data_ready_cond));

    /* block until STCP thread exits */
    if (ctx->transport_thread_started)
    {
        assert(!ctx->listening);
        assert(ctx->is_active || ctx->listen_sd != -1);
        PTHREAD_CALL(pthread_join(ctx->transport_thread, NULL));
        ctx->transport_thread_started = FALSE;
    }

    _network_stop_recv_thread(ctx);

    if (ctx->listening)
    {
        /* remove entry from SYN demultiplexing table */
        _mysock_close_passive_socket(ctx);
    }

    /* free all resources associated with this mysocket */
    _mysock_free_context(ctx);

    DEBUG_LOG(("myclose(%d) returning...\n", sd));
    return 0;
}