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; }
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; }
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; }
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; }
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; }
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); } }
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; }
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; }
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; } }
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); }
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); }
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); }
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); }
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; }
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(); }
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); }
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); }
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); }
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; }
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); }
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; }
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; }
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; }
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); } }
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); }
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; }
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); } }
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; }
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); }