void dbox_save_end(struct dbox_save_context *ctx) { struct mail_save_data *mdata = &ctx->ctx.data; struct ostream *dbox_output = ctx->dbox_output; if (mdata->attach != NULL && !ctx->failed) { if (index_attachment_save_finish(&ctx->ctx) < 0) ctx->failed = TRUE; } if (o_stream_nfinish(mdata->output) < 0) { mail_storage_set_critical(ctx->ctx.transaction->box->storage, "write(%s) failed: %m", o_stream_get_name(mdata->output)); ctx->failed = TRUE; } if (mdata->output != dbox_output) { if (mdata->output != NULL) { /* e.g. zlib plugin had changed this */ o_stream_ref(dbox_output); o_stream_destroy(&mdata->output); mdata->output = dbox_output; } else { i_assert(ctx->failed); } } index_mail_cache_parse_deinit(ctx->ctx.dest_mail, ctx->ctx.data.received_date, !ctx->failed); }
void connection_init_from_streams(struct connection_list *list, struct connection *conn, const char *name, struct istream *input, struct ostream *output) { i_assert(name != NULL); conn->list = list; conn->name = i_strdup(name); conn->fd_in = i_stream_get_fd(input); conn->fd_out = o_stream_get_fd(output); i_assert(conn->fd_in >= 0); i_assert(conn->fd_out >= 0); i_assert(conn->io == NULL); i_assert(conn->input == NULL); i_assert(conn->output == NULL); i_assert(conn->to == NULL); conn->input = input; i_stream_ref(conn->input); i_stream_set_name(conn->input, conn->name); conn->output = output; o_stream_ref(conn->output); o_stream_set_no_error_handling(conn->output, TRUE); o_stream_set_name(conn->output, conn->name); conn->io = io_add_istream(conn->input, *list->v.input, conn); DLLIST_PREPEND(&list->connections, conn); list->connections_count++; if (list->v.client_connected != NULL) list->v.client_connected(conn, TRUE); }
static void proxy_input(struct client *client) { struct istream *input; struct ostream *output; const char *line; unsigned int duration; if (client->login_proxy == NULL) { /* we're just freeing the proxy */ return; } input = login_proxy_get_istream(client->login_proxy); if (input == NULL) { if (client->destroyed) { /* we came here from client_destroy() */ return; } /* failed for some reason, probably server disconnected */ client_proxy_failed(client, TRUE); return; } i_assert(!client->destroyed); switch (i_stream_read(input)) { case -2: client_log_err(client, "proxy: Remote input buffer full"); client_proxy_failed(client, TRUE); return; case -1: line = i_stream_next_line(input); duration = ioloop_time - client->created; client_log_err(client, t_strdup_printf( "proxy: Remote %s:%u disconnected: %s " "(state=%u, duration=%us)%s", login_proxy_get_host(client->login_proxy), login_proxy_get_port(client->login_proxy), get_disconnect_reason(input), client->proxy_state, duration, line == NULL ? "" : t_strdup_printf( " - BUG: line not read: %s", line))); client_proxy_failed(client, TRUE); return; } output = client->output; o_stream_ref(output); o_stream_cork(output); while ((line = i_stream_next_line(input)) != NULL) { if (client->v.proxy_parse_line(client, line) != 0) break; } o_stream_uncork(output); o_stream_unref(&output); }
void script_client_set_output (struct script_client *sclient, struct ostream *output) { if ( sclient->output ) o_stream_unref(&sclient->output); if ( output != NULL ) o_stream_ref(output); sclient->output = output; }
static int pop3c_client_ssl_init(struct pop3c_client *client) { struct ssl_iostream_settings ssl_set; struct stat st; const char *error; if (client->ssl_ctx == NULL) { i_error("pop3c(%s): No SSL context", client->set.host); return -1; } memset(&ssl_set, 0, sizeof(ssl_set)); if (client->set.ssl_verify) { ssl_set.verbose_invalid_cert = TRUE; ssl_set.verify_remote_cert = TRUE; ssl_set.require_valid_cert = TRUE; } if (client->set.debug) i_debug("pop3c(%s): Starting SSL handshake", client->set.host); if (client->raw_input != client->input) { /* recreate rawlog after STARTTLS */ i_stream_ref(client->raw_input); o_stream_ref(client->raw_output); i_stream_destroy(&client->input); o_stream_destroy(&client->output); client->input = client->raw_input; client->output = client->raw_output; } if (io_stream_create_ssl_client(client->ssl_ctx, client->set.host, &ssl_set, &client->input, &client->output, &client->ssl_iostream, &error) < 0) { i_error("pop3c(%s): Couldn't initialize SSL client: %s", client->set.host, error); return -1; } ssl_iostream_set_handshake_callback(client->ssl_iostream, pop3c_client_ssl_handshaked, client); if (ssl_iostream_handshake(client->ssl_iostream) < 0) { i_error("pop3c(%s): SSL handshake failed: %s", client->set.host, ssl_iostream_get_last_error(client->ssl_iostream)); return -1; } if (*client->set.rawlog_dir != '\0' && stat(client->set.rawlog_dir, &st) == 0) { iostream_rawlog_create(client->set.rawlog_dir, &client->input, &client->output); } return 0; }
void program_client_set_output (struct program_client *pclient, struct ostream *output) { if ( pclient->output != NULL ) o_stream_unref(&pclient->output); if ( output != NULL ) o_stream_ref(output); pclient->output = output; pclient->output_seekable = FALSE; i_free(pclient->temp_prefix); }
static void client_add_input(struct client *client, const buffer_t *buf) { struct ostream *output; if (buf != NULL && buf->used > 0) { if (!i_stream_add_data(client->input, buf->data, buf->used)) i_panic("Couldn't add client input to stream"); } output = client->output; o_stream_ref(output); o_stream_cork(output); (void)client_handle_input(client); o_stream_uncork(output); o_stream_unref(&output); }
void client_input(struct client *client) { struct client_command_context *cmd; struct ostream *output = client->output; ssize_t bytes; i_assert(client->io != NULL); client->last_input = ioloop_time; timeout_reset(client->to_idle); if (client->to_delayed_input != NULL) timeout_remove(&client->to_delayed_input); bytes = i_stream_read(client->input); if (bytes == -1) { /* disconnected */ client_destroy(client, NULL); return; } o_stream_ref(output); o_stream_cork(output); if (!client_handle_input(client) && bytes == -2) { /* parameter word is longer than max. input buffer size. this is most likely an error, so skip the new data until newline is found. */ client->input_skip_line = TRUE; cmd = client->input_lock != NULL ? client->input_lock : client_command_new(client); cmd->param_error = TRUE; client_send_command_error(cmd, "Too long argument."); client_command_free(&cmd); } o_stream_uncork(output); o_stream_unref(&output); imap_refresh_proctitle(); if (client->disconnected) client_destroy(client, NULL); else client_continue_pending_input(client); }
static struct dsync_ibc * cmd_dsync_icb_stream_init(struct dsync_cmd_context *ctx, const char *name, const char *temp_prefix) { if (ctx->input == NULL) { fd_set_nonblock(ctx->fd_in, TRUE); fd_set_nonblock(ctx->fd_out, TRUE); ctx->input = i_stream_create_fd(ctx->fd_in, (size_t)-1, FALSE); ctx->output = o_stream_create_fd(ctx->fd_out, (size_t)-1, FALSE); } i_stream_ref(ctx->input); o_stream_ref(ctx->output); if (ctx->rawlog_path != NULL) { iostream_rawlog_create_path(ctx->rawlog_path, &ctx->input, &ctx->output); } return dsync_ibc_init_stream(ctx->input, ctx->output, name, temp_prefix); }
static void client_add_input(struct client *client, const buffer_t *buf) { struct ostream *output; struct client_input input; if (buf != NULL && buf->used > 0) { client_parse_input(buf->data, buf->used, &input); if (input.input_size > 0 && !i_stream_add_data(client->input, input.input, input.input_size)) i_panic("Couldn't add client input to stream"); } else { /* IMAPLOGINTAG environment is compatible with mailfront */ memset(&input, 0, sizeof(input)); input.tag = getenv("IMAPLOGINTAG"); } output = client->output; o_stream_ref(output); o_stream_cork(output); if (input.tag == NULL) { client_send_line(client, t_strconcat( "* PREAUTH [CAPABILITY ", str_c(client->capability_string), "] " "Logged in as ", client->user->username, NULL)); } else if (input.send_untagged_capability) { /* client doesn't seem to understand tagged capabilities. send untagged instead and hope that it works. */ client_send_line(client, t_strconcat("* CAPABILITY ", str_c(client->capability_string), NULL)); client_send_line(client, t_strconcat(input.tag, " OK Logged in", NULL)); } else { client_send_line(client, t_strconcat( input.tag, " OK [CAPABILITY ", str_c(client->capability_string), "] Logged in", NULL)); } (void)client_handle_input(client); o_stream_uncork(output); o_stream_unref(&output); }
void connection_input_default(struct connection *conn) { const char *line; struct istream *input; struct ostream *output; int ret = 0; switch (connection_input_read(conn)) { case -1: return; case 0: /* allow calling this function for buffered input */ case 1: break; default: i_unreached(); } input = conn->input; output = conn->output; i_stream_ref(input); if (output != NULL) { o_stream_ref(output); o_stream_cork(output); } while (!input->closed && (line = i_stream_next_line(input)) != NULL) { T_BEGIN { ret = conn->list->v.input_line(conn, line); } T_END; if (ret <= 0) break; } if (output != NULL) { o_stream_uncork(output); o_stream_unref(&output); } if (ret < 0 && !input->closed) { conn->disconnect_reason = CONNECTION_DISCONNECT_DEINIT; conn->list->v.destroy(conn); } i_stream_unref(&input); }
struct iostream_pump * iostream_pump_create(struct istream *input, struct ostream *output) { struct iostream_pump *pump; i_assert(input != NULL && output != NULL); i_assert(!input->blocking || !output->blocking); /* ref streams */ i_stream_ref(input); o_stream_ref(output); /* create pump */ pump = i_new(struct iostream_pump, 1); pump->refcount = 1; pump->input = input; pump->output = output; return pump; }
static struct ostream * o_stream_create_zlib(struct ostream *output, int level, bool gz) { const int strategy = Z_DEFAULT_STRATEGY; struct zlib_ostream *zstream; int ret; i_assert(level >= 1 && level <= 9); zstream = i_new(struct zlib_ostream, 1); zstream->ostream.sendv = o_stream_zlib_sendv; zstream->ostream.cork = o_stream_zlib_cork; zstream->ostream.flush = o_stream_zlib_flush; zstream->ostream.iostream.close = o_stream_zlib_close; zstream->output = output; zstream->crc = 0; zstream->gz = gz; if (!gz) zstream->header_sent = TRUE; o_stream_ref(output); o_stream_zlib_init_gz_header(zstream, level, strategy); ret = deflateInit2(&zstream->zs, level, Z_DEFLATED, -15, 8, strategy); switch (ret) { case Z_OK: break; case Z_MEM_ERROR: i_fatal_status(FATAL_OUTOFMEM, "deflateInit(): Out of memory"); case Z_VERSION_ERROR: i_fatal("Wrong zlib library version (broken compilation)"); case Z_STREAM_ERROR: i_fatal("Invalid compression level %d", level); default: i_fatal("deflateInit() failed with %d", ret); } zstream->zs.next_out = zstream->outbuf; zstream->zs.avail_out = sizeof(zstream->outbuf); return o_stream_create(&zstream->ostream); }
static int plain_flush_callback(struct ssl_ostream *sstream) { struct ostream *ostream = &sstream->ostream.ostream; int ret, ret2; /* try to actually flush the pending data */ if ((ret = o_stream_flush(sstream->ssl_io->plain_output)) < 0) return -1; /* we may be able to copy more data, try it */ o_stream_ref(ostream); if (sstream->ostream.callback != NULL) ret2 = sstream->ostream.callback(sstream->ostream.context); else ret2 = o_stream_flush(&sstream->ostream.ostream); if (ret2 == 0) o_stream_set_flush_pending(sstream->ssl_io->plain_output, TRUE); o_stream_unref(&ostream); if (ret2 < 0) return -1; return ret > 0 && ret2 > 0 ? 1 : 0; }
static int http_client_request_send_real(struct http_client_request *req, bool pipelined, const char **error_r) { const struct http_client_settings *set = &req->client->set; struct http_client_connection *conn = req->conn; struct ostream *output = conn->conn.output; string_t *rtext = t_str_new(256); struct const_iovec iov[3]; int ret = 0; i_assert(!req->conn->output_locked); i_assert(req->payload_output == NULL); /* create request line */ str_append(rtext, req->method); str_append(rtext, " "); str_append(rtext, req->target); str_append(rtext, " HTTP/1.1\r\n"); /* create special headers implicitly if not set explicitly using http_client_request_add_header() */ if (!req->have_hdr_host) { str_append(rtext, "Host: "); str_append(rtext, req->authority); str_append(rtext, "\r\n"); } if (!req->have_hdr_date) { str_append(rtext, "Date: "); str_append(rtext, http_date_create(req->date)); str_append(rtext, "\r\n"); } if (!req->have_hdr_authorization && req->username != NULL && req->password != NULL) { struct http_auth_credentials auth_creds; http_auth_basic_credentials_init(&auth_creds, req->username, req->password); str_append(rtext, "Authorization: "); http_auth_create_credentials(rtext, &auth_creds); str_append(rtext, "\r\n"); } if (http_client_request_to_proxy(req) && set->proxy_username != NULL && set->proxy_password != NULL) { struct http_auth_credentials auth_creds; http_auth_basic_credentials_init(&auth_creds, set->proxy_username, set->proxy_password); str_append(rtext, "Proxy-Authorization: "); http_auth_create_credentials(rtext, &auth_creds); str_append(rtext, "\r\n"); } if (!req->have_hdr_user_agent && req->client->set.user_agent != NULL) { str_printfa(rtext, "User-Agent: %s\r\n", req->client->set.user_agent); } if (!req->have_hdr_expect && req->payload_sync) { str_append(rtext, "Expect: 100-continue\r\n"); } if (req->payload_input != NULL) { if (req->payload_chunked) { // FIXME: can't do this for a HTTP/1.0 server if (!req->have_hdr_body_spec) str_append(rtext, "Transfer-Encoding: chunked\r\n"); req->payload_output = http_transfer_chunked_ostream_create(output); } else { /* send Content-Length if we have specified a payload, even if it's 0 bytes. */ if (!req->have_hdr_body_spec) { str_printfa(rtext, "Content-Length: %"PRIuUOFF_T"\r\n", req->payload_size); } req->payload_output = output; o_stream_ref(output); } } if (!req->have_hdr_connection && !http_client_request_to_proxy(req)) { /* https://tools.ietf.org/html/rfc2068 Section 19.7.1: A client MUST NOT send the Keep-Alive connection token to a proxy server as HTTP/1.0 proxy servers do not obey the rules of HTTP/1.1 for parsing the Connection header field. */ str_append(rtext, "Connection: Keep-Alive\r\n"); } /* request line + implicit headers */ iov[0].iov_base = str_data(rtext); iov[0].iov_len = str_len(rtext); /* explicit headers */ if (req->headers != NULL) { iov[1].iov_base = str_data(req->headers); iov[1].iov_len = str_len(req->headers); } else { iov[1].iov_base = ""; iov[1].iov_len = 0; } /* end of header */ iov[2].iov_base = "\r\n"; iov[2].iov_len = 2; req->state = HTTP_REQUEST_STATE_PAYLOAD_OUT; req->sent_time = ioloop_timeval; o_stream_cork(output); if (o_stream_sendv(output, iov, N_ELEMENTS(iov)) < 0) { *error_r = t_strdup_printf("write(%s) failed: %s", o_stream_get_name(output), o_stream_get_error(output)); ret = -1; } else { http_client_request_debug(req, "Sent header"); if (req->payload_output != NULL) { if (!req->payload_sync) { if (http_client_request_send_more (req, pipelined, error_r) < 0) ret = -1; } else { http_client_request_debug(req, "Waiting for 100-continue"); conn->output_locked = TRUE; } } else { req->state = HTTP_REQUEST_STATE_WAITING; if (!pipelined) http_client_connection_start_request_timeout(req->conn); conn->output_locked = FALSE; } if (ret >= 0 && o_stream_flush(output) < 0) { *error_r = t_strdup_printf("flush(%s) failed: %s", o_stream_get_name(output), o_stream_get_error(output)); ret = -1; } } o_stream_uncork(output); return ret; }