Ejemplo n.º 1
0
static int program_client_program_output(struct program_client *pclient)
{
	struct istream *input = pclient->input;
	struct ostream *output = pclient->program_output;
	const unsigned char *data;
	size_t size;
	int ret = 0;

	if ((ret = o_stream_flush(output)) <= 0) {
		if (ret < 0)
			program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
		return ret;
	}

	if ( input != NULL && output != NULL ) {
		do {
			while ( (data=i_stream_get_data(input, &size)) != NULL ) {
				ssize_t sent;
	
				if ( (sent=o_stream_send(output, data, size)) < 0 ) {
					program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
					return -1;
				}
	
				if ( sent == 0 )
					return 0;
				i_stream_skip(input, sent);
			}
		} while ( (ret=i_stream_read(input)) > 0 );

		if ( ret == 0 )
			return 1;

		if ( ret < 0 ) {
			if ( !input->eof ) {
				program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
				return -1;
			} else if ( !i_stream_have_bytes_left(input) ) {
				i_stream_unref(&pclient->input);
				input = NULL;

				if ( (ret = o_stream_flush(output)) <= 0 ) {
					if ( ret < 0 )
						program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
					return ret;
				}
			} 
		}
	}

	if ( input == NULL ) {
		if ( !program_client_input_pending(pclient) ) {
			program_client_disconnect(pclient, FALSE);
		} else if (program_client_close_output(pclient) < 0) {
			program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
		}
	}
	return 1;
}
Ejemplo n.º 2
0
static int server_connection_send_cmd_input_more(struct server_connection *conn)
{
    off_t ret;

    /* ostream-dot writes only up to max buffer size, so keep it non-zero */
    o_stream_set_max_buffer_size(conn->cmd_output, IO_BLOCK_SIZE);
    ret = o_stream_send_istream(conn->cmd_output, conn->cmd_input);
    o_stream_set_max_buffer_size(conn->cmd_output, (size_t)-1);

    if (ret >= 0 && i_stream_have_bytes_left(conn->cmd_input)) {
        o_stream_set_flush_pending(conn->cmd_output, TRUE);
        return 0;
    }
    if (conn->cmd_input->stream_errno != 0) {
        i_error("read(%s) failed: %s",
                i_stream_get_name(conn->cmd_input),
                i_stream_get_error(conn->cmd_input));
    } else if (conn->cmd_output->stream_errno != 0 ||
               o_stream_flush(conn->cmd_output) < 0) {
        i_error("write(%s) failed: %s",
                o_stream_get_name(conn->cmd_output),
                o_stream_get_error(conn->cmd_output));
    }

    i_stream_destroy(&conn->cmd_input);
    o_stream_destroy(&conn->cmd_output);
    return ret < 0 ? -1 : 1;
}
int script_client_run(struct script_client *sclient)
{
	int ret;

	sclient->ioloop = io_loop_create();

	if ( script_client_connect(sclient) >= 0 ) {
		/* run output */
		ret = 1;		
		if ( sclient->script_output != NULL &&
			(ret=o_stream_flush(sclient->script_output)) == 0 ) {
			o_stream_set_flush_callback
				(sclient->script_output, script_client_script_output, sclient);
		}

		/* run i/o event loop */
		if ( ret < 0 ) {
			sclient->error = SCRIPT_CLIENT_ERROR_IO;
		} else if ( sclient->io != NULL || ret == 0 ) {
			io_loop_run(sclient->ioloop);
		}

		/* finished */
		script_client_disconnect(sclient, FALSE);
	}

	io_loop_destroy(&sclient->ioloop);

	if ( sclient->error != SCRIPT_CLIENT_ERROR_NONE )
		return -1;

	return sclient->exit_code;
}
Ejemplo n.º 4
0
int client_output(struct client *client)
{
	int ret;

	i_assert(!client->destroyed);

	client->last_output = ioloop_time;
	timeout_reset(client->to_idle);
	if (client->to_idle_output != NULL)
		timeout_reset(client->to_idle_output);

	o_stream_cork(client->output);
	if ((ret = o_stream_flush(client->output)) < 0) {
		client_destroy(client, NULL);
		return 1;
	}

	client_output_commands(client);
	(void)cmd_sync_delayed(client);

	o_stream_uncork(client->output);
	imap_refresh_proctitle();
	if (client->disconnected)
		client_destroy(client, NULL);
	else
		client_continue_pending_input(client);
	return ret;
}
Ejemplo n.º 5
0
static int client_run_url(struct client *client)
{
	const unsigned char *data;
	size_t size;
	ssize_t ret = 0;

	while (i_stream_read_data(client->msg_part_input, &data, &size, 0) > 0) {
		if ((ret = o_stream_send(client->output, data, size)) < 0)
			break;
		i_stream_skip(client->msg_part_input, ret);

		if (o_stream_get_buffer_used_size(client->output) >= 4096) {
			if ((ret = o_stream_flush(client->output)) < 0)
				break;
			if (ret == 0)
				return 0;
		}
	}

	if (client->output->closed || ret < 0) {
		imap_msgpart_url_free(&client->url);
		return -1;
	}

	if (client->msg_part_input->eof) {
		o_stream_send(client->output, "\n", 1);
		imap_msgpart_url_free(&client->url);
		return 1;
	}
	return 0;
}
Ejemplo n.º 6
0
void o_stream_nflush(struct ostream *stream)
{
	if (unlikely(stream->closed || stream->stream_errno != 0))
		return;
	(void)o_stream_flush(stream);
	stream->real_stream->last_errors_not_checked = TRUE;
}
Ejemplo n.º 7
0
void client_cmd_starttls(struct client *client)
{
	if (client->tls) {
		client->v.notify_starttls(client, FALSE, "TLS is already active.");
		return;
	}

	if (!client_is_tls_enabled(client)) {
		client->v.notify_starttls(client, FALSE, "TLS support isn't enabled.");
		return;
	}

	/* remove input handler, SSL proxy gives us a new fd. we also have to
	   remove it in case we have to wait for buffer to be flushed */
	if (client->io != NULL)
		io_remove(&client->io);

	client->v.notify_starttls(client, TRUE, "Begin TLS negotiation now.");

	/* uncork the old fd */
	o_stream_uncork(client->output);

	if (o_stream_flush(client->output) <= 0) {
		/* the buffer has to be flushed */
		o_stream_set_flush_pending(client->output, TRUE);
		o_stream_set_flush_callback(client->output,
					    client_output_starttls, client);
	} else {
		client_start_tls(client);
	}
}
Ejemplo n.º 8
0
static int replicator_output(struct replicator_connection *conn)
{
	enum replication_priority p;

	if (o_stream_flush(conn->output) < 0) {
		replicator_connection_disconnect(conn);
		return 1;
	}

	for (p = REPLICATION_PRIORITY_SYNC;;) {
		if (o_stream_get_buffer_used_size(conn->output) > 0) {
			o_stream_set_flush_pending(conn->output, TRUE);
			break;
		}
		/* output buffer is empty, send more data */
		if (conn->queue[p]->used > 0) {
			if (!replicator_send_buf(conn, conn->queue[p]))
				break;
		} else {
			if (p == REPLICATION_PRIORITY_LOW)
				break;
			p--;
		}
	}
	return 1;
}
Ejemplo n.º 9
0
static int iostream_pump_flush(struct iostream_pump *pump)
{
	int ret;

	if ((ret = o_stream_flush(pump->output)) <= 0) {
		if (ret < 0) {
			pump->callback(IOSTREAM_PUMP_STATUS_OUTPUT_ERROR,
				       pump->context);
		}
		return ret;
	}
	pump->waiting_output = FALSE;
	if (pump->completed) {
		pump->callback(IOSTREAM_PUMP_STATUS_INPUT_EOF, pump->context);
		return 1;
	}

	if (pump->input->blocking)
		iostream_pump_copy(pump);
	else if (pump->io == NULL) {
		pump->io = io_add_istream(pump->input,
					  iostream_pump_copy, pump);
		io_set_pending(pump->io);
	}
	return ret;
}
Ejemplo n.º 10
0
static int client_output(struct client *client)
{
	if (o_stream_flush(client->output) < 0) {
		if (client->ctrl_output != NULL)
			(void)o_stream_send_str(client->ctrl_output, "DISCONNECTED\n");
		client_destroy(client);
		return 1;
	}
	timeout_reset(client->to_idle);

	if (client->url != NULL) {
		if (client_run_url(client) < 0) {
			client_destroy(client);
			return 1;
		}

		if (client->url == NULL && client->waiting_input) {
			if (!client_handle_input(client)) {
				/* client got destroyed */
				return 1;
			}
		}
	}

	if (client->url != NULL) {
		/* url not finished yet */
		return 0;
	} else if (client->io == NULL) {
		/* data still in output buffer, get back here to add IO */
		return 0;
	} else {
		return 1;
	}
}
Ejemplo n.º 11
0
static void test_ostream_dot_one(const struct dot_test *test)
{
	struct istream *test_input;
	struct ostream *output, *test_output;
	buffer_t *output_data;
	const unsigned char *data;
	size_t size;
	ssize_t ret;

	test_input = test_istream_create(test->input);
	output_data = buffer_create_dynamic(pool_datastack_create(), 1024);
	test_output = o_stream_create_buffer(output_data);

	output = o_stream_create_dot(test_output, FALSE);

	while ((ret = i_stream_read(test_input)) > 0 || ret == -2) {
		data = i_stream_get_data(test_input, &size);
		ret = o_stream_send(output, data, size);
		test_assert(ret >= 0);
		if (ret <= 0)
			break;
		i_stream_skip(test_input, ret);
	}

	test_assert(test_input->eof);

	test_assert(o_stream_flush(output) > 0);
	o_stream_unref(&output);
	o_stream_unref(&test_output);

	test_assert(strcmp(str_c(output_data), test->output) == 0);

	i_stream_unref(&test_input);
}
Ejemplo n.º 12
0
static void openssl_iostream_destroy(struct ssl_iostream *ssl_io)
{
    (void)SSL_shutdown(ssl_io->ssl);
    (void)openssl_iostream_more(ssl_io);
    (void)o_stream_flush(ssl_io->plain_output);

    ssl_iostream_unref(&ssl_io);
}
Ejemplo n.º 13
0
static void test_ostream_file_random(void)
{
	struct ostream *output;
	string_t *path = t_str_new(128);
	char buf[MAX_BUFSIZE*4], buf2[MAX_BUFSIZE*4], randbuf[MAX_BUFSIZE];
	unsigned int i, offset, size;
	ssize_t ret;
	int fd;

	memset(buf, 0, sizeof(buf));
	fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1);
	if (fd == -1)
		i_fatal("safe_mkstemp(%s) failed: %m", str_c(path));
	if (unlink(str_c(path)) < 0)
		i_fatal("unlink(%s) failed: %m", str_c(path));
	output = o_stream_create_fd(fd, MAX_BUFSIZE, FALSE);
	o_stream_cork(output);

	size = (rand() % MAX_BUFSIZE) + 1;
	random_fill_weak(randbuf, size);
	memcpy(buf, randbuf, size);
	test_assert(o_stream_send(output, buf, size) > 0);

	for (i = 0; i < 10; i++) {
		offset = rand() % (MAX_BUFSIZE*3);
		size = (rand() % MAX_BUFSIZE) + 1;
		random_fill_weak(randbuf, size);
		memcpy(buf + offset, randbuf, size);
		test_assert(o_stream_pwrite(output, randbuf, size, offset) == 0);
		if (rand() % 10 == 0)
			test_assert(o_stream_flush(output) > 0);
	}

	test_assert(o_stream_flush(output) > 0);
	o_stream_uncork(output);
	ret = pread(fd, buf2, sizeof(buf2), 0);
	if (ret < 0)
		i_fatal("pread() failed: %m");
	else {
		i_assert(ret > 0);
		test_assert(memcmp(buf, buf2, ret) == 0);
	}
	o_stream_unref(&output);
	i_close_fd(&fd);
}
Ejemplo n.º 14
0
static void o_stream_default_close(struct iostream_private *stream,
				   bool close_parent)
{
	struct ostream_private *_stream = (struct ostream_private *)stream;

	(void)o_stream_flush(&_stream->ostream);
	if (close_parent && _stream->parent != NULL)
		o_stream_close(_stream->parent);
}
Ejemplo n.º 15
0
static int mbox_write_content_length(struct mbox_save_context *ctx)
{
	uoff_t end_offset;
	const char *str;
	size_t len;

	i_assert(ctx->eoh_offset != (uoff_t)-1);

	if (ctx->mbox->mbox_writeonly) {
		/* we can't seek, don't set Content-Length */
		return 0;
	}

	end_offset = ctx->output->offset;

	/* write Content-Length headers */
	str = t_strdup_printf("\nContent-Length: %s",
			      dec2str(end_offset - ctx->eoh_offset));
	len = strlen(str);

	/* flush manually here so that we don't confuse seek() errors with
	   buffer flushing errors */
	if (o_stream_flush(ctx->output) < 0) {
		write_error(ctx);
		return -1;
	}
	if (o_stream_seek(ctx->output, ctx->extra_hdr_offset +
			  ctx->space_end_idx - len) < 0) {
		mbox_set_syscall_error(ctx->mbox, "lseek()");
		return -1;
	}

	if (o_stream_send(ctx->output, str, len) < 0 ||
	    o_stream_flush(ctx->output) < 0) {
		write_error(ctx);
		return -1;
	}

	if (o_stream_seek(ctx->output, end_offset) < 0) {
		mbox_set_syscall_error(ctx->mbox, "lseek()");
		return -1;
	}
	return 0;
}
Ejemplo n.º 16
0
static void iostream_pump_copy(struct iostream_pump *pump)
{
	enum ostream_send_istream_result res;
	size_t old_size;

	o_stream_cork(pump->output);
	old_size = o_stream_get_max_buffer_size(pump->output);
	o_stream_set_max_buffer_size(pump->output,
		I_MIN(IO_BLOCK_SIZE,
		      o_stream_get_max_buffer_size(pump->output)));
	res = o_stream_send_istream(pump->output, pump->input);
	o_stream_set_max_buffer_size(pump->output, old_size);
	o_stream_uncork(pump->output);

	switch(res) {
	case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT:
		io_remove(&pump->io);
		pump->callback(IOSTREAM_PUMP_STATUS_INPUT_ERROR,
			       pump->context);
		return;
	case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT:
		io_remove(&pump->io);
		pump->callback(IOSTREAM_PUMP_STATUS_OUTPUT_ERROR,
			       pump->context);
		return;
	case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT:
		i_assert(!pump->output->blocking);
		pump->waiting_output = TRUE;
		io_remove(&pump->io);
		return;
	case OSTREAM_SEND_ISTREAM_RESULT_FINISHED:
		pump->waiting_output = FALSE;
		io_remove(&pump->io);
		/* flush it */
		switch (o_stream_flush(pump->output)) {
		case -1:
			pump->callback(IOSTREAM_PUMP_STATUS_OUTPUT_ERROR,
				       pump->context);
			break;
		case 0:
			pump->waiting_output = TRUE;
			pump->completed = TRUE;
			break;
		default:
			pump->callback(IOSTREAM_PUMP_STATUS_INPUT_EOF,
				       pump->context);
			break;
		}
		return;
	case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT:
		i_assert(!pump->input->blocking);
		pump->waiting_output = FALSE;
		return;
	}
	i_unreached();
}
Ejemplo n.º 17
0
static void o_stream_zlib_close(struct iostream_private *stream,
				bool close_parent)
{
	struct zlib_ostream *zstream = (struct zlib_ostream *)stream;

	(void)o_stream_flush(&zstream->ostream.ostream);
	(void)deflateEnd(&zstream->zs);
	if (close_parent)
		o_stream_close(zstream->ostream.parent);
}
Ejemplo n.º 18
0
static void o_stream_lzma_close(struct iostream_private *stream,
				bool close_parent)
{
	struct lzma_ostream *zstream = (struct lzma_ostream *)stream;

	(void)o_stream_flush(&zstream->ostream.ostream);
	lzma_end(&zstream->strm);
	if (close_parent)
		o_stream_close(zstream->ostream.parent);
}
Ejemplo n.º 19
0
static void o_stream_bzlib_close(struct iostream_private *stream,
				 bool close_parent)
{
	struct bzlib_ostream *zstream = (struct bzlib_ostream *)stream;

	(void)o_stream_flush(&zstream->ostream.ostream);
	(void)BZ2_bzCompressEnd(&zstream->zs);
	if (close_parent)
		o_stream_close(zstream->ostream.parent);
}
Ejemplo n.º 20
0
static int client_output_flush(struct ostream *output)
{
	if (o_stream_flush(output) == 0) {
		/* more to come */
		return 0;
	}
	/* finished / disconnected */
	client_deinit(output);
	return -1;
}
Ejemplo n.º 21
0
static void o_stream_zlib_close(struct iostream_private *stream)
{
	struct zlib_ostream *zstream = (struct zlib_ostream *)stream;

	if (zstream->output == NULL)
		return;

	o_stream_flush(&zstream->ostream.ostream);
	o_stream_unref(&zstream->output);
	(void)deflateEnd(&zstream->zs);
}
Ejemplo n.º 22
0
static int server_connection_output(struct server_connection *conn)
{
	int ret;

	ret = o_stream_flush(conn->output);
	if (ret > 0 && conn->cmd_input != NULL && conn->delayed_cmd == NULL)
		ret = server_connection_send_cmd_input_more(conn);
	if (ret < 0)
		server_connection_destroy(&conn);
	return ret;
}
Ejemplo n.º 23
0
static int o_stream_default_flush(struct ostream_private *_stream)
{
	int ret;

	if (_stream->parent == NULL)
		return 1;

	if ((ret = o_stream_flush(_stream->parent)) < 0)
		o_stream_copy_error_from_parent(_stream);
	return ret;
}
Ejemplo n.º 24
0
bool client_is_busy(struct client *client)
{
	client->iter_count++;
	if (client->iter_count % CLIENT_MAX_SIMULTANEOUS_ITER_COUNT == 0)
		return TRUE;
	if (o_stream_get_buffer_used_size(client->output) < OUTBUF_THROTTLE_SIZE)
		return FALSE;
	if (o_stream_flush(client->output) < 0)
		return TRUE;
	return o_stream_get_buffer_used_size(client->output) >= OUTBUF_THROTTLE_SIZE;
}
Ejemplo n.º 25
0
static void o_stream_zlib_cork(struct ostream_private *stream, bool set)
{
	struct zlib_ostream *zstream = (struct zlib_ostream *)stream;

	stream->corked = set;
	if (set)
		o_stream_cork(zstream->output);
	else {
		(void)o_stream_flush(&stream->ostream);
		o_stream_uncork(zstream->output);
	}
}
Ejemplo n.º 26
0
static void openssl_iostream_destroy(struct ssl_iostream *ssl_io)
{
	(void)SSL_shutdown(ssl_io->ssl);
	(void)openssl_iostream_more(ssl_io);
	(void)o_stream_flush(ssl_io->plain_output);
	/* close the plain i/o streams, because their fd may be closed soon,
	   but we may still keep this ssl-iostream referenced until later. */
	i_stream_close(ssl_io->plain_input);
	o_stream_close(ssl_io->plain_output);

	ssl_iostream_unref(&ssl_io);
}
Ejemplo n.º 27
0
static int
o_stream_escaped_flush(struct ostream_private *stream)
{
	struct escaped_ostream *estream = (struct escaped_ostream *)stream;
	int ret;

	if ((ret = o_stream_escaped_send_outbuf(estream)) <= 0)
		return ret;
	if ((ret = o_stream_flush(stream->parent)) < 0)
		o_stream_copy_error_from_parent(stream);
	return ret;
}
Ejemplo n.º 28
0
static void o_stream_default_cork(struct ostream_private *_stream, bool set)
{
	_stream->corked = set;
	if (set) {
		if (_stream->parent != NULL)
			o_stream_cork(_stream->parent);
	} else {
		(void)o_stream_flush(&_stream->ostream);
		if (_stream->parent != NULL)
			o_stream_uncork(_stream->parent);
	}
}
Ejemplo n.º 29
0
static int auth_worker_list_output(struct auth_worker_list_context *ctx)
{
	int ret;

	if ((ret = o_stream_flush(ctx->client->output)) < 0) {
		list_iter_deinit(ctx);
		return 1;
	}
	if (ret > 0)
		ctx->userdb->iface->iterate_next(ctx->iter);
	return 1;
}
Ejemplo n.º 30
0
static void
http_transfer_chunked_ostream_close(struct iostream_private *stream,
				    bool close_parent)
{
	struct http_transfer_chunked_ostream *tcstream =
		(struct http_transfer_chunked_ostream *)stream;

	(void)o_stream_send(tcstream->ostream.parent, "0\r\n\r\n", 5);
	(void)o_stream_flush(&tcstream->ostream.ostream);
	if (close_parent)
		o_stream_close(tcstream->ostream.parent);
}