ostream.h revision bf87a5247ca33660ab8f20c12556ad16d7159395
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#ifndef OSTREAM_H
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#define OSTREAM_H
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#include "ioloop.h"
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenstruct ostream {
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainen /* Number of bytes sent via o_stream_send*() and similar functions.
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainen This is counting the input data. For example with a compressed
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen ostream this is counting the uncompressed bytes. The compressed
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen bytes could be counted from the parent ostream's offset.
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen Seeking to a specified offset only makes sense if there is no
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen difference between input and output data sizes (e.g. there are no
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen wrapper ostreams changing the data). */
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen uoff_t offset;
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen
a4ac325c2802693c6b761e5a8fda961e5d7490eaTimo Sirainen /* errno for the last operation send/seek operation. cleared before
a4ac325c2802693c6b761e5a8fda961e5d7490eaTimo Sirainen each call. */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen int stream_errno;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen /* overflow is set when some of the data given to send()
86bea1f8bffc2d98196f8655eecea9174c4f458aTimo Sirainen functions was neither sent nor buffered. It's never unset inside
86bea1f8bffc2d98196f8655eecea9174c4f458aTimo Sirainen ostream code. */
86bea1f8bffc2d98196f8655eecea9174c4f458aTimo Sirainen unsigned int overflow:1;
86bea1f8bffc2d98196f8655eecea9174c4f458aTimo Sirainen /* o_stream_send() writes all the data or returns failure */
86bea1f8bffc2d98196f8655eecea9174c4f458aTimo Sirainen unsigned int blocking:1;
86bea1f8bffc2d98196f8655eecea9174c4f458aTimo Sirainen unsigned int closed:1;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen struct ostream_private *real_stream;
b82474d60c15409eda71c55971710fd3b12b8a0fTimo Sirainen};
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen/* Returns 1 if all data is sent (not necessarily flushed), 0 if not.
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen Pretty much the only real reason to return 0 is if you wish to send more
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen data to client which isn't buffered, eg. o_stream_send_istream(). */
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainentypedef int stream_flush_callback_t(void *context);
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainentypedef void ostream_callback_t(void *context);
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen
22535a9e685e29214082878e37a267157044618eTimo Sirainen/* Create new output stream from given file descriptor.
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen If max_buffer_size is 0, an "optimal" buffer size is used (max 128kB). */
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenstruct ostream *
b321df9603081896b70ec44635af96d674a9839aTimo Siraineno_stream_create_fd(int fd, size_t max_buffer_size, bool autoclose_fd);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen/* The fd is set to -1 immediately to avoid accidentally closing it twice. */
b321df9603081896b70ec44635af96d674a9839aTimo Sirainenstruct ostream *o_stream_create_fd_autoclose(int *fd, size_t max_buffer_size);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen/* Create an output stream from a regular file which begins at given offset.
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen If offset==(uoff_t)-1, the current offset isn't known. */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenstruct ostream *
25757faf029c369a8318349dafe952e2358df1d8Timo Siraineno_stream_create_fd_file(int fd, uoff_t offset, bool autoclose_fd);
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainenstruct ostream *o_stream_create_fd_file_autoclose(int *fd, uoff_t offset);
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen/* Create an output stream to a buffer. */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenstruct ostream *o_stream_create_buffer(buffer_t *buf);
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen/* Create an output streams that always fails the writes. */
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainenstruct ostream *o_stream_create_error(int stream_errno);
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainenstruct ostream *
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Siraineno_stream_create_error_str(int stream_errno, const char *fmt, ...)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen ATTR_FORMAT(2, 3);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen/* Create an output stream that simply passes through data. This is mainly
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen useful as a wrapper when combined with destroy callbacks. */
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainenstruct ostream *o_stream_create_passthrough(struct ostream *output);
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen/* Set name (e.g. path) for output stream. */
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainenvoid o_stream_set_name(struct ostream *stream, const char *name);
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen/* Get output stream's name. Returns "" if stream has no name. */
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainenconst char *o_stream_get_name(struct ostream *stream);
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen/* Return file descriptor for stream, or -1 if none is available. */
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainenint o_stream_get_fd(struct ostream *stream);
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen/* Returns error string for the previous error. */
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainenconst char *o_stream_get_error(struct ostream *stream);
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen/* Close this stream (but not its parents) and unreference it. */
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainenvoid o_stream_destroy(struct ostream **stream);
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen/* Reference counting. References start from 1, so calling o_stream_unref()
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen destroys the stream if o_stream_ref() is never used. */
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenvoid o_stream_ref(struct ostream *stream);
dc9bfb7dc057964238e181d3d8b08751527bb08aTimo Sirainen/* Unreferences the stream and sets stream pointer to NULL. */
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainenvoid o_stream_unref(struct ostream **stream);
473080c7c0d25ddfdf77e7dfa0ba8f73c6c669d5Timo Sirainen/* Call the given callback function when stream is destroyed. */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenvoid o_stream_add_destroy_callback(struct ostream *stream,
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen ostream_callback_t *callback, void *context)
0af3274706d337b2930bd34f0377f2cc2dbcd18aTimo Sirainen ATTR_NULL(3);
157bce86d0a01477bb8ebd0d380e6b2297f326f7Timo Sirainen#define o_stream_add_destroy_callback(stream, callback, context) \
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen o_stream_add_destroy_callback(stream + \
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen (ostream_callback_t *)callback, context)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen/* Remove the destroy callback. */
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainenvoid o_stream_remove_destroy_callback(struct ostream *stream,
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainen void (*callback)());
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
/* Mark the stream and all of its parent streams closed. Nothing will be
sent after this call. */
void o_stream_close(struct ostream *stream);
/* Set IO_WRITE callback. Default will just try to flush the output and
finishes when the buffer is empty. */
void o_stream_set_flush_callback(struct ostream *stream,
stream_flush_callback_t *callback,
void *context) ATTR_NULL(3);
#define o_stream_set_flush_callback(stream, callback, context) \
o_stream_set_flush_callback(stream + \
CALLBACK_TYPECHECK(callback, int (*)(typeof(context))), \
(stream_flush_callback_t *)callback, context)
void o_stream_unset_flush_callback(struct ostream *stream);
/* Change the maximum size for stream's output buffer to grow. */
void o_stream_set_max_buffer_size(struct ostream *stream, size_t max_size);
/* Returns the current max. buffer size. */
size_t o_stream_get_max_buffer_size(struct ostream *stream);
/* Delays sending as far as possible, writing only full buffers. Also sets
TCP_CORK on if supported. */
void o_stream_cork(struct ostream *stream);
void o_stream_uncork(struct ostream *stream);
bool o_stream_is_corked(struct ostream *stream);
/* Try to flush the output stream. Returns 1 if all sent, 0 if not,
-1 if error. */
int o_stream_flush(struct ostream *stream);
/* Set "flush pending" state of stream. If set, the flush callback is called
when more data is allowed to be sent, even if the buffer itself is empty. */
void o_stream_set_flush_pending(struct ostream *stream, bool set);
/* Returns number of bytes currently in buffer. */
size_t o_stream_get_buffer_used_size(const struct ostream *stream) ATTR_PURE;
/* Returns number of bytes we can still write without failing. */
size_t o_stream_get_buffer_avail_size(const struct ostream *stream) ATTR_PURE;
/* Seek to specified position from beginning of file. This works only for
files. Returns 1 if successful, -1 if error. */
int o_stream_seek(struct ostream *stream, uoff_t offset);
/* Returns number of bytes sent, -1 = error */
ssize_t o_stream_send(struct ostream *stream, const void *data, size_t size);
ssize_t o_stream_sendv(struct ostream *stream, const struct const_iovec *iov,
unsigned int iov_count);
ssize_t o_stream_send_str(struct ostream *stream, const char *str);
/* Send with delayed error handling. o_stream_nfinish() or
o_stream_ignore_last_errors() must be called after these functions before
the stream is destroyed. If any of the data can't be sent due to stream's
buffer getting full, all further nsends are ignores and o_stream_nfinish()
will fail. */
void o_stream_nsend(struct ostream *stream, const void *data, size_t size);
void o_stream_nsendv(struct ostream *stream, const struct const_iovec *iov,
unsigned int iov_count);
void o_stream_nsend_str(struct ostream *stream, const char *str);
void o_stream_nflush(struct ostream *stream);
/* Marks the stream's error handling as completed. Flushes the stream and
returns -1 if stream->stream_errno is non-zero. Returns failure if any of
the o_stream_nsend*() didn't write all data. */
int o_stream_nfinish(struct ostream *stream);
/* Marks the stream's error handling as completed to avoid i_panic() on
destroy. */
void o_stream_ignore_last_errors(struct ostream *stream);
/* If error handling is disabled, the i_panic() on destroy is never called.
This function can be called immediately after the stream is created.
When creating wrapper streams, they copy this behavior from the parent
stream. */
void o_stream_set_no_error_handling(struct ostream *stream, bool set);
/* Send data from input stream. Returns 1 if the entire instream was sent
without errors, 0 if either instream or outstream is nonblocking and not
everything was sent, or -1 if either instream or outstream failed (see their
stream_errno for which one).
On non-failure instream is skips over all data written to outstream.
This means that the number of bytes written to outstream is always equal to
the number of bytes skipped in instream.
For non-blocking outstreams: Note that this function may not add anything to
the output buffer, so if you want the flush callback to be called when more
data can be written, you'll need to call o_stream_set_flush_pending()
explicitly.
It's also possible to use this function to copy data within same file
descriptor, even if the source and destination overlaps. If the file must
be grown, you have to do it manually before calling this function. */
int o_stream_send_istream(struct ostream *outstream, struct istream *instream);
/* Same as o_stream_send_istream(), but assume that reads and writes will
succeed. If not, o_stream_nfinish() will fail with the correct error
message (even istream's). */
void o_stream_nsend_istream(struct ostream *outstream, struct istream *instream);
/* Write data to specified offset. Returns 0 if successful, -1 if error. */
int o_stream_pwrite(struct ostream *stream, const void *data, size_t size,
uoff_t offset);
/* If there are any I/O loop items associated with the stream, move all of
them to current_ioloop. */
void o_stream_switch_ioloop(struct ostream *stream);
#endif