Ejemplo n.º 1
0
static void do_work(connection *c) {
    connection_assert_ref(c);

    if (c->dead)
        return;

    if (pa_iochannel_is_readable(c->io))
        if (do_read(c) < 0)
            goto fail;

    if (!c->sink_input && pa_iochannel_is_hungup(c->io))
        goto fail;

    if (pa_iochannel_is_writable(c->io))
        if (do_write(c) < 0)
            goto fail;

    return;

fail:

    if (c->sink_input) {

        /* If there is a sink input, we first drain what we already have read before shutting down the connection */
        c->dead = TRUE;

        pa_iochannel_free(c->io);
        c->io = NULL;

        pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_DISABLE_PREBUF, NULL, 0, NULL, NULL);
    } else
        connection_unlink(c);
}
Ejemplo n.º 2
0
static int do_write(struct userdata *u) {
    ssize_t r;
    pa_assert(u);

    if (!pa_iochannel_is_writable(u->io))
        return 0;

    if (u->write_data) {
        pa_assert(u->write_index < u->write_length);

        if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) <= 0) {
            pa_log("write() failed: %s", pa_cstrerror(errno));
            return -1;
        }

        u->write_index += (size_t) r;
        pa_assert(u->write_index <= u->write_length);

        if (u->write_index == u->write_length) {
            pa_xfree(u->write_data);
            u->write_data = NULL;
            u->write_index = u->write_length = 0;
        }
    }

    if (!u->write_data && u->state == STATE_PREPARE) {
        int so_sndbuf = 0;
        socklen_t sl = sizeof(int);

        /* OK, we're done with sending all control data we need to, so
         * let's hand the socket over to the IO thread now */

        pa_assert(u->fd < 0);
        u->fd = pa_iochannel_get_send_fd(u->io);

        pa_iochannel_set_noclose(u->io, TRUE);
        pa_iochannel_free(u->io);
        u->io = NULL;

        pa_make_tcp_socket_low_delay(u->fd);

        if (getsockopt(u->fd, SOL_SOCKET, SO_SNDBUF, &so_sndbuf, &sl) < 0)
            pa_log_warn("getsockopt(SO_SNDBUF) failed: %s", pa_cstrerror(errno));
        else {
            pa_log_debug("SO_SNDBUF is %zu.", (size_t) so_sndbuf);
            pa_sink_set_max_request(u->sink, PA_MAX((size_t) so_sndbuf, u->block_size));
        }

        pa_log_debug("Connection authenticated, handing fd to IO thread...");

        pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_PASS_SOCKET, NULL, 0, NULL, NULL);
        u->state = STATE_RUNNING;
    }

    return 0;
}