Exemplo n.º 1
0
static void socket_connect(MVMThreadContext *tc, MVMOSHandle *h, MVMString *host, MVMint64 port) {
    MVMIOSyncSocketData *data = (MVMIOSyncSocketData *)h->body.data;
    if (!data->ss.handle) {
        struct sockaddr *dest    = MVM_io_resolve_host_name(tc, host, port);
        uv_tcp_t        *socket  = MVM_malloc(sizeof(uv_tcp_t));
        uv_connect_t    *connect = MVM_malloc(sizeof(uv_connect_t));
        int r;

        data->ss.cur_tc = tc;
        connect->data   = data;
        if ((r = uv_tcp_init(tc->loop, socket)) < 0 ||
                (r = uv_tcp_connect(connect, socket, dest, on_connect)) < 0) {
            MVM_free(socket);
            MVM_free(connect);
            MVM_free(dest);
            MVM_exception_throw_adhoc(tc, "Failed to connect: %s", uv_strerror(r));
        }
        uv_ref((uv_handle_t *)socket);
        uv_run(tc->loop, UV_RUN_DEFAULT);

        data->ss.handle = (uv_stream_t *)socket;

        MVM_free(connect);
        MVM_free(dest);
    }
    else {
        MVM_exception_throw_adhoc(tc, "Socket is already bound or connected");
    }
}
Exemplo n.º 2
0
static void socket_bind(MVMThreadContext *tc, MVMOSHandle *h, MVMString *host, MVMint64 port, MVMint32 backlog) {
    MVMIOSyncSocketData *data = (MVMIOSyncSocketData *)h->body.data;
    if (!data->ss.handle) {
        struct sockaddr *dest    = MVM_io_resolve_host_name(tc, host, port);
        uv_tcp_t        *socket  = MVM_malloc(sizeof(uv_tcp_t));
        int r;

        if ((r = uv_tcp_init(tc->loop, socket)) != 0 ||
                (r = uv_tcp_bind(socket, dest, 0)) != 0) {
            MVM_free(socket);
            MVM_free(dest);
            MVM_exception_throw_adhoc(tc, "Failed to bind: %s", uv_strerror(r));
        }
        MVM_free(dest);

        /* Start listening, but unref the socket so it won't get in the way of
         * other things we want to do on this event loop. */
        socket->data = data;
        if ((r = uv_listen((uv_stream_t *)socket, backlog, on_connection)) != 0) {
            MVM_free(socket);
            MVM_exception_throw_adhoc(tc, "Failed to listen: %s", uv_strerror(r));
        }
        uv_unref((uv_handle_t *)socket);

        data->ss.handle = (uv_stream_t *)socket;
    }
    else {
        MVM_exception_throw_adhoc(tc, "Socket is already bound or connected");
    }
}
Exemplo n.º 3
0
/* Establishes a connection. */
static void socket_connect(MVMThreadContext *tc, MVMOSHandle *h, MVMString *host, MVMint64 port) {
    MVMIOSyncSocketData *data = (MVMIOSyncSocketData *)h->body.data;
    unsigned int interval_id;

    interval_id = MVM_telemetry_interval_start(tc, "syncsocket connect");
    if (!data->handle) {
        struct sockaddr *dest = MVM_io_resolve_host_name(tc, host, port);
        int r;

        Socket s = socket(dest->sa_family , SOCK_STREAM , 0);
        if (MVM_IS_SOCKET_ERROR(s)) {
            MVM_free(dest);
            MVM_telemetry_interval_stop(tc, interval_id, "syncsocket connect");
            throw_error(tc, s, "create socket");
        }

        do {
            MVM_gc_mark_thread_blocked(tc);
            r = connect(s, dest, (socklen_t)get_struct_size_for_family(dest->sa_family));
            MVM_gc_mark_thread_unblocked(tc);
        } while(r == -1 && errno == EINTR);
        MVM_free(dest);
        if (MVM_IS_SOCKET_ERROR(r)) {
            MVM_telemetry_interval_stop(tc, interval_id, "syncsocket connect");
            throw_error(tc, s, "connect socket");
        }

        data->handle = s;
    }
    else {
        MVM_telemetry_interval_stop(tc, interval_id, "syncsocket didn't connect");
        MVM_exception_throw_adhoc(tc, "Socket is already bound or connected");
    }
}
Exemplo n.º 4
0
static void socket_bind(MVMThreadContext *tc, MVMOSHandle *h, MVMString *host, MVMint64 port, MVMint32 backlog) {
    MVMIOSyncSocketData *data = (MVMIOSyncSocketData *)h->body.data;
    if (!data->handle) {
        struct sockaddr *dest = MVM_io_resolve_host_name(tc, host, port);
        int r;

        Socket s = socket(dest->sa_family , SOCK_STREAM , 0);
        if (MVM_IS_SOCKET_ERROR(s)) {
            MVM_free(dest);
            throw_error(tc, s, "create socket");
        }

        /* On POSIX, we set the SO_REUSEADDR option, which allows re-use of
         * a port in TIME_WAIT state (modulo many hair details). Oringinally,
         * MoarVM used libuv, which does this automatically on non-Windows.
         * We have tests with bring up a server, then take it down, and then
         * bring another up on the same port, and we get test failures due
         * to racing to re-use the port without this. */
#ifndef _WIN32
        {
            int one = 1;
            setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
        }
#endif

        r = bind(s, dest, (socklen_t)get_struct_size_for_family(dest->sa_family));
        MVM_free(dest);
        if (MVM_IS_SOCKET_ERROR(r))
            throw_error(tc, s, "bind socket");

        r = listen(s, (int)backlog);
        if (MVM_IS_SOCKET_ERROR(r))
            throw_error(tc, s, "start listening on socket");

        data->handle = s;
    }
    else {
        MVM_exception_throw_adhoc(tc, "Socket is already bound or connected");
    }
}