Ejemplo n.º 1
0
static gboolean
client_out_event(G_GNUC_UNUSED GIOChannel *source, GIOCondition condition,
         gpointer data)
{
    struct client *client = data;

    assert(!client_is_expired(client));

    if (condition != G_IO_OUT) {
        client_set_expired(client);
        return false;
    }

    client_write_deferred(client);

    if (client_is_expired(client)) {
        client_close(client);
        return false;
    }

    g_timer_start(client->last_activity);

    if (g_queue_is_empty(client->deferred_send)) {
        /* done sending deferred buffers exist: schedule
           read */
        client->source_id = g_io_add_watch(client->channel,
                           G_IO_IN|G_IO_ERR|G_IO_HUP,
                           client_in_event, client);
        return false;
    }

    /* write more */
    return true;
}
Ejemplo n.º 2
0
static void client_defer_output(struct client *client,
				const void *data, size_t length)
{
	size_t alloc;
	struct deferred_buffer *buf;

	assert(length > 0);

	alloc = sizeof(*buf) - sizeof(buf->data) + length;
	client->deferred_bytes += alloc;
	if (client->deferred_bytes > client_max_output_buffer_size) {
		g_warning("[%u] output buffer size (%lu) is "
			  "larger than the max (%lu)",
			  client->num,
			  (unsigned long)client->deferred_bytes,
			  (unsigned long)client_max_output_buffer_size);
		/* cause client to close */
		client_set_expired(client);
		return;
	}

	buf = g_malloc(alloc);
	buf->size = length;
	memcpy(buf->data, data, length);

	g_queue_push_tail(client->deferred_send, buf);
}
Ejemplo n.º 3
0
static void client_write_direct(struct client *client,
				const char *data, size_t length)
{
	GError *error = NULL;
	GIOStatus status;
	gsize bytes_written;

	assert(client != NULL);
	assert(client->channel != NULL);
	assert(data != NULL);
	assert(length > 0);
	assert(g_queue_is_empty(client->deferred_send));

	status = g_io_channel_write_chars(client->channel, data, length,
					  &bytes_written, &error);
	switch (status) {
	case G_IO_STATUS_NORMAL:
	case G_IO_STATUS_AGAIN:
		break;

	case G_IO_STATUS_EOF:
		/* client has disconnected */

		client_set_expired(client);
		return;

	case G_IO_STATUS_ERROR:
		/* I/O error */

		client_set_expired(client);
		g_warning("failed to write to %i: %s",
			  client->num, error->message);
		g_error_free(error);
		return;
	}

	if (bytes_written < length)
		client_defer_output(client, data + bytes_written,
				    length - bytes_written);

	if (!g_queue_is_empty(client->deferred_send))
		g_debug("[%u] buffer created", client->num);
}
Ejemplo n.º 4
0
static size_t
client_write_deferred_buffer(struct client *client,
			     const struct deferred_buffer *buffer)
{
	GError *error = NULL;
	GIOStatus status;
	gsize bytes_written;

	assert(client != NULL);
	assert(client->channel != NULL);
	assert(buffer != NULL);

	status = g_io_channel_write_chars
		(client->channel, buffer->data, buffer->size,
		 &bytes_written, &error);
	switch (status) {
	case G_IO_STATUS_NORMAL:
		return bytes_written;

	case G_IO_STATUS_AGAIN:
		return 0;

	case G_IO_STATUS_EOF:
		/* client has disconnected */

		client_set_expired(client);
		return 0;

	case G_IO_STATUS_ERROR:
		/* I/O error */

		client_set_expired(client);
		g_warning("failed to flush buffer for %i: %s",
			  client->num, error->message);
		g_error_free(error);
		return 0;
	}

	/* unreachable */
	return 0;
}
Ejemplo n.º 5
0
gboolean
client_in_event(G_GNUC_UNUSED GIOChannel *source, GIOCondition condition,
        gpointer data)
{
    struct client *client = data;
    enum command_return ret;

    assert(!client_is_expired(client));

    if (condition != G_IO_IN) {
        client_set_expired(client);
        return false;
    }

    g_timer_start(client->last_activity);

    ret = client_read(client);
    switch (ret) {
    case COMMAND_RETURN_OK:
    case COMMAND_RETURN_ERROR:
        break;

    case COMMAND_RETURN_KILL:
        client_close(client);
        //g_main_loop_quit(main_loop);
        return false;

    case COMMAND_RETURN_CLOSE:
        client_close(client);
        return false;
    }

    if (client_is_expired(client)) {
        client_close(client);
        return false;
    }

    if (!g_queue_is_empty(client->deferred_send)) {
        /* deferred buffers exist: schedule write */
        client->source_id = g_io_add_watch(client->channel,
                           G_IO_OUT|G_IO_ERR|G_IO_HUP,
                           client_out_event, client);
        return false;
    }

    /* read more */
    return true;
}
Ejemplo n.º 6
0
Archivo: client.c Proyecto: azuwis/mpd
static void client_close(struct client *client)
{
    assert(num_clients > 0);
    assert(clients != NULL);

    clients = g_list_remove(clients, client);
    --num_clients;

    client_set_expired(client);

    if (client->cmd_list) {
        free_cmd_list(client->cmd_list);
        client->cmd_list = NULL;
    }

    g_queue_foreach(client->deferred_send, deferred_buffer_free, NULL);
    g_queue_free(client->deferred_send);

    g_log(G_LOG_DOMAIN, LOG_LEVEL_SECURE,
          "[%u] closed", client->num);
    g_free(client);
}
Ejemplo n.º 7
0
void
client_close(struct client *client)
{
	client_list_remove(client);

	client_set_expired(client);

	g_timer_destroy(client->last_activity);

	if (client->cmd_list) {
		free_cmd_list(client->cmd_list);
		client->cmd_list = NULL;
	}

	g_queue_foreach(client->deferred_send, deferred_buffer_free, NULL);
	g_queue_free(client->deferred_send);

	fifo_buffer_free(client->input);

	g_log(G_LOG_DOMAIN, LOG_LEVEL_SECURE,
	      "[%u] closed", client->num);
	g_free(client);
}