ostream.h revision 9de176ef7f3d28ff486c2a8805110b84389e4f19
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch#ifndef OSTREAM_H
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#define OSTREAM_H
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
e130bb802c8bfb6c6cc44e5c8bc098b4fa5af789Timo Sirainen#include "ioloop.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstruct ostream {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen uoff_t offset;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* errno for the last operation send/seek operation. cleared before
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen each call. */
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen int stream_errno;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen /* overflow is set when some of the data given to send()
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen functions was neither sent nor buffered. It's never unset inside
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen ostream code. */
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen unsigned int overflow:1;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen unsigned int closed:1;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen struct ostream_private *real_stream;
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen};
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen/* Returns 1 if all data is sent (not necessarily flushed), 0 if not.
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen Pretty much the only real reason to return 0 is if you wish to send more
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen data to client which isn't buffered, eg. o_stream_send_istream(). */
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainentypedef int stream_flush_callback_t(void *context);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainentypedef void ostream_callback_t(void *context);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen/* Create new output stream from given file descriptor.
120e61ccce21fd33d6b55b6f27346e1690b64bd8Josef 'Jeff' Sipek If max_buffer_size is 0, an "optimal" buffer size is used (max 128kB). */
95d62f8d6d281cc488dc4f488d4388701e559012Josef 'Jeff' Sipekstruct ostream *
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Siraineno_stream_create_fd(int fd, size_t max_buffer_size, bool autoclose_fd);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen/* The fd is set to -1 immediately to avoid accidentally closing it twice. */
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenstruct ostream *o_stream_create_fd_autoclose(int *fd, size_t max_buffer_size);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen/* Create an output stream from a regular file which begins at given offset.
84a5175b9768da401404635c9b606264585739bdTimo Sirainen If offset==(uoff_t)-1, the current offset isn't known. */
84a5175b9768da401404635c9b606264585739bdTimo Sirainenstruct ostream *
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Siraineno_stream_create_fd_file(int fd, uoff_t offset, bool autoclose_fd);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenstruct ostream *o_stream_create_fd_file_autoclose(int *fd, uoff_t offset);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen/* Create an output stream to a buffer. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstruct ostream *o_stream_create_buffer(buffer_t *buf);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Create an output streams that always fails the writes. */
95d62f8d6d281cc488dc4f488d4388701e559012Josef 'Jeff' Sipekstruct ostream *o_stream_create_error(int stream_errno);
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainenstruct ostream *
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Siraineno_stream_create_error_str(int stream_errno, const char *fmt, ...)
5f4e547bb810403e8cfb19a49d8fe34713507ffdTimo Sirainen ATTR_FORMAT(2, 3);
5f4e547bb810403e8cfb19a49d8fe34713507ffdTimo Sirainen/* Create an output stream that simply passes through data. This is mainly
5f4e547bb810403e8cfb19a49d8fe34713507ffdTimo Sirainen useful as a wrapper when combined with destroy callbacks. */
5f4e547bb810403e8cfb19a49d8fe34713507ffdTimo Sirainenstruct ostream *o_stream_create_passthrough(struct ostream *output);
5f4e547bb810403e8cfb19a49d8fe34713507ffdTimo Sirainen
5f4e547bb810403e8cfb19a49d8fe34713507ffdTimo Sirainen/* Set name (e.g. path) for output stream. */
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainenvoid o_stream_set_name(struct ostream *stream, const char *name);
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen/* Get output stream's name. Returns "" if stream has no name. */
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainenconst char *o_stream_get_name(struct ostream *stream);
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Return file descriptor for stream, or -1 if none is available. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenint o_stream_get_fd(struct ostream *stream);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Returns error string for the previous error. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenconst char *o_stream_get_error(struct ostream *stream);
87490012895b4f371635ded00add04c9107dcfefJosef 'Jeff' Sipek
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen/* Close this stream (but not its parents) and unreference it. */
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainenvoid o_stream_destroy(struct ostream **stream);
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen/* Reference counting. References start from 1, so calling o_stream_unref()
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen destroys the stream if o_stream_ref() is never used. */
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainenvoid o_stream_ref(struct ostream *stream);
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen/* Unreferences the stream and sets stream pointer to NULL. */
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainenvoid o_stream_unref(struct ostream **stream);
d2cf6522779802d0edeab7dcf960ffea2f2e1828Timo Sirainen/* Call the given callback function when stream is destroyed. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid o_stream_add_destroy_callback(struct ostream *stream,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ostream_callback_t *callback, void *context)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ATTR_NULL(3);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#define o_stream_add_destroy_callback(stream, callback, context) \
87490012895b4f371635ded00add04c9107dcfefJosef 'Jeff' Sipek o_stream_add_destroy_callback(stream + \
95d62f8d6d281cc488dc4f488d4388701e559012Josef 'Jeff' Sipek CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen (ostream_callback_t *)callback, context)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Remove the destroy callback. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid o_stream_remove_destroy_callback(struct ostream *stream,
fcb5f4cd72b413a5356a8db55e679403c6a1adb5Timo Sirainen void (*callback)());
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Mark the stream and all of its parent streams closed. Nothing will be
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen sent after this call. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid o_stream_close(struct ostream *stream);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Set IO_WRITE callback. Default will just try to flush the output and
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen finishes when the buffer is empty. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid o_stream_set_flush_callback(struct ostream *stream,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen stream_flush_callback_t *callback,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen void *context) ATTR_NULL(3);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#define o_stream_set_flush_callback(stream, callback, context) \
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen o_stream_set_flush_callback(stream + \
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen CALLBACK_TYPECHECK(callback, int (*)(typeof(context))), \
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen (stream_flush_callback_t *)callback, context)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid o_stream_unset_flush_callback(struct ostream *stream);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Change the maximum size for stream's output buffer to grow. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid o_stream_set_max_buffer_size(struct ostream *stream, size_t max_size);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Returns the current max. buffer size. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainensize_t o_stream_get_max_buffer_size(struct ostream *stream);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Delays sending as far as possible, writing only full buffers. Also sets
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen TCP_CORK on if supported. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid o_stream_cork(struct ostream *stream);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid o_stream_uncork(struct ostream *stream);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenbool o_stream_is_corked(struct ostream *stream);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Try to flush the output stream. Returns 1 if all sent, 0 if not,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen -1 if error. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenint o_stream_flush(struct ostream *stream);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Set "flush pending" state of stream. If set, the flush callback is called
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen when more data is allowed to be sent, even if the buffer itself is empty. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid o_stream_set_flush_pending(struct ostream *stream, bool set);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Returns number of bytes currently in buffer. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainensize_t o_stream_get_buffer_used_size(const struct ostream *stream) ATTR_PURE;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Returns number of bytes we can still write without failing. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainensize_t o_stream_get_buffer_avail_size(const struct ostream *stream) ATTR_PURE;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Seek to specified position from beginning of file. This works only for
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen files. Returns 1 if successful, -1 if error. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenint o_stream_seek(struct ostream *stream, uoff_t offset);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* Returns number of bytes sent, -1 = error */
cee43a7b0fe3934efc863f533428989173682e0bTimo Sirainenssize_t o_stream_send(struct ostream *stream, const void *data, size_t size);
cee43a7b0fe3934efc863f533428989173682e0bTimo Sirainenssize_t o_stream_sendv(struct ostream *stream, const struct const_iovec *iov,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen unsigned int iov_count);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenssize_t o_stream_send_str(struct ostream *stream, const char *str);
5f8d497e88fae77fbeb625246bc18260f6775b83Timo Sirainen/* Send with delayed error handling. o_stream_nfinish() or
5f8d497e88fae77fbeb625246bc18260f6775b83Timo Sirainen o_stream_ignore_last_errors() must be called after these functions before
5f8d497e88fae77fbeb625246bc18260f6775b83Timo Sirainen the stream is destroyed. If any of the data can't be sent due to stream's
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen buffer getting full, all further nsends are ignores and o_stream_nfinish()
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen will fail. */
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenvoid o_stream_nsend(struct ostream *stream, const void *data, size_t size);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenvoid o_stream_nsendv(struct ostream *stream, const struct const_iovec *iov,
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen unsigned int iov_count);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenvoid o_stream_nsend_str(struct ostream *stream, const char *str);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenvoid o_stream_nflush(struct ostream *stream);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen/* Marks the stream's error handling as completed. Flushes the stream and
84a5175b9768da401404635c9b606264585739bdTimo Sirainen returns -1 if stream->stream_errno is non-zero. Returns failure if any of
f2686912e0156c04296d6dc306f39d61089a1363Timo Sirainen the o_stream_nsend*() didn't write all data. */
f2686912e0156c04296d6dc306f39d61089a1363Timo Sirainenint o_stream_nfinish(struct ostream *stream);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen/* Marks the stream's error handling as completed to avoid i_panic() on
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen destroy. */
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenvoid o_stream_ignore_last_errors(struct ostream *stream);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen/* If error handling is disabled, the i_panic() on destroy is never called.
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen This function can be called immediately after the stream is created.
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen When creating wrapper streams, they copy this behavior from the parent
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen stream. */
120e61ccce21fd33d6b55b6f27346e1690b64bd8Josef 'Jeff' Sipekvoid o_stream_set_no_error_handling(struct ostream *stream, bool set);
95d62f8d6d281cc488dc4f488d4388701e559012Josef 'Jeff' Sipek/* Send data from input stream. Returns number of bytes sent, or -1 if error
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen in either outstream or instream. Note that this function may block if either
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen instream or outstream is blocking.
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen Also note that this function may not add anything to the output buffer, so
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen if you want the flush callback to be called when more data can be written,
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen you'll need to call o_stream_set_flush_pending() manually.
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen It's also possible to use this function to copy data within same file
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen descriptor. If the file must be grown, you have to do it manually before
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen calling this function. */
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenoff_t o_stream_send_istream(struct ostream *outstream,
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen struct istream *instream);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen/* Write data to specified offset. Returns 0 if successful, -1 if error. */
84a5175b9768da401404635c9b606264585739bdTimo Sirainenint o_stream_pwrite(struct ostream *stream, const void *data, size_t size,
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen uoff_t offset);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
84a5175b9768da401404635c9b606264585739bdTimo Sirainen/* If there are any I/O loop items associated with the stream, move all of
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen them to current_ioloop. */
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainenvoid o_stream_switch_ioloop(struct ostream *stream);
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen#endif
afc77c5375cdb8f2bf0ab6280d9229ac27c933c6Timo Sirainen