/src/dovecot/src/lib/ostream.h
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef OSTREAM_H |
2 | | #define OSTREAM_H |
3 | | |
4 | | #include "ioloop.h" |
5 | | |
6 | | struct iostream_fd; |
7 | | |
8 | | enum ostream_send_istream_result { |
9 | | /* All of the istream was successfully sent to ostream. */ |
10 | | OSTREAM_SEND_ISTREAM_RESULT_FINISHED, |
11 | | /* Caller needs to wait for more input from non-blocking istream. */ |
12 | | OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT, |
13 | | /* Caller needs to wait for output to non-blocking ostream. |
14 | | o_stream_set_flush_pending() is automatically called. */ |
15 | | OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT, |
16 | | /* Read from istream failed. See istream->stream_errno. */ |
17 | | OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT, |
18 | | /* Write to ostream failed. See ostream->stream_errno. */ |
19 | | OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT |
20 | | }; |
21 | | |
22 | | enum ostream_create_file_flags { |
23 | | /* without append, file is truncated */ |
24 | | OSTREAM_CREATE_FILE_FLAG_APPEND = BIT(0), |
25 | | }; |
26 | | |
27 | | struct ostream { |
28 | | /* Number of bytes sent via o_stream_send*() and similar functions. |
29 | | This is counting the input data. For example with a compressed |
30 | | ostream this is counting the uncompressed bytes. The compressed |
31 | | bytes could be counted from the parent ostream's offset. |
32 | | |
33 | | Seeking to a specified offset only makes sense if there is no |
34 | | difference between input and output data sizes (e.g. there are no |
35 | | wrapper ostreams changing the data). */ |
36 | | uoff_t offset; |
37 | | |
38 | | /* errno for the last operation send/seek operation. cleared before |
39 | | each call. */ |
40 | | int stream_errno; |
41 | | |
42 | | /* overflow is set when some of the data given to send() |
43 | | functions was neither sent nor buffered. It's never unset inside |
44 | | ostream code. */ |
45 | | bool overflow:1; |
46 | | /* o_stream_send() writes all the data or returns failure */ |
47 | | bool blocking:1; |
48 | | bool closed:1; |
49 | | |
50 | | struct ostream_private *real_stream; |
51 | | }; |
52 | | |
53 | | /* Returns 1 if all data is sent (not necessarily flushed), 0 if not. |
54 | | Pretty much the only real reason to return 0 is if you wish to send more |
55 | | data to client which isn't buffered, eg. o_stream_send_istream(). */ |
56 | | typedef int stream_flush_callback_t(void *context); |
57 | | typedef void ostream_callback_t(void *context); |
58 | | |
59 | | /* Create new output stream from given file descriptor. |
60 | | If max_buffer_size is 0, an "optimal" buffer size is used (max 128kB). */ |
61 | | struct ostream *o_stream_create_fd(int fd, size_t max_buffer_size); |
62 | | /* The fd is set to -1 immediately to avoid accidentally closing it twice. */ |
63 | | struct ostream *o_stream_create_fd_autoclose(int *fd, size_t max_buffer_size); |
64 | | /* Autoclose the fd once ref's refcount drops to 0. This function increases the |
65 | | refcount, so the caller is expected to unref it as well. */ |
66 | | struct ostream *o_stream_create_fd_ref_autoclose(struct iostream_fd *ref, |
67 | | size_t max_buffer_size); |
68 | | /* Create an output stream from a regular file which begins at given offset. |
69 | | If offset==UOFF_T_MAX, the current offset isn't known. */ |
70 | | struct ostream * |
71 | | o_stream_create_fd_file(int fd, uoff_t offset, bool autoclose_fd); |
72 | | struct ostream *o_stream_create_fd_file_autoclose(int *fd, uoff_t offset); |
73 | | /* Create ostream for file. If append flag is not set, file will be truncated. */ |
74 | | struct ostream *o_stream_create_file(const char *path, uoff_t offset, mode_t mode, |
75 | | enum ostream_create_file_flags flags); |
76 | | /* Create ostream for a blocking (network) fd. It assumes that all the output |
77 | | can be written to the fd. If not, the ostream fails. */ |
78 | | struct ostream *o_stream_create_fd_blocking(int fd); |
79 | | /* Create an output stream to a buffer. Note that the buffer is treated as the |
80 | | ostream's internal buffer. This means that o_stream_get_buffer_used_size() |
81 | | returns buf->used, and _get_buffer_avail_size() returns how many bytes can |
82 | | be written until the buffer's max size is reached. This behavior may make |
83 | | ostream-buffer unsuitable for code that assumes that having bytes in the |
84 | | internal buffer means that ostream isn't finished flushing its internal |
85 | | buffer. Especially o_stream_flush_parent_if_needed() (used by |
86 | | lib-compression ostreams) don't work with this. */ |
87 | | struct ostream *o_stream_create_buffer(buffer_t *buf); |
88 | | /* Create an output streams that always fails the writes. */ |
89 | | struct ostream *o_stream_create_error(int stream_errno); |
90 | | struct ostream * |
91 | | o_stream_create_error_str(int stream_errno, const char *fmt, ...) |
92 | | ATTR_FORMAT(2, 3); |
93 | | /* Create an output stream that simply passes through data. This is mainly |
94 | | useful as a wrapper when combined with destroy callbacks. */ |
95 | | struct ostream *o_stream_create_passthrough(struct ostream *output); |
96 | | |
97 | | /* Set name (e.g. path) for output stream. */ |
98 | | void o_stream_set_name(struct ostream *stream, const char *name); |
99 | | /* Get output stream's name. Returns "" if stream has no name. */ |
100 | | const char *o_stream_get_name(struct ostream *stream); |
101 | | |
102 | | /* Return file descriptor for stream, or -1 if none is available. */ |
103 | | int o_stream_get_fd(struct ostream *stream); |
104 | | /* Returns error string for the previous error. */ |
105 | | const char *o_stream_get_error(struct ostream *stream); |
106 | | /* Returns human-readable reason for why ostream was disconnected. |
107 | | The output is either "Connection closed" for clean disconnections or |
108 | | "Connection closed: <error>" for unclean disconnections. This is an |
109 | | alternative to o_stream_get_error(), which is preferred to be used when |
110 | | logging errors about client connections. */ |
111 | | const char *o_stream_get_disconnect_reason(struct ostream *stream); |
112 | | |
113 | | /* Close this stream (but not its parents) and unreference it. */ |
114 | | void o_stream_destroy(struct ostream **stream); |
115 | | /* Reference counting. References start from 1, so calling o_stream_unref() |
116 | | destroys the stream if o_stream_ref() is never used. */ |
117 | | void o_stream_ref(struct ostream *stream); |
118 | | /* Unreferences the stream and sets stream pointer to NULL. */ |
119 | | void o_stream_unref(struct ostream **stream); |
120 | | /* Call the given callback function when stream is destroyed. */ |
121 | | void o_stream_add_destroy_callback(struct ostream *stream, |
122 | | ostream_callback_t *callback, void *context) |
123 | | ATTR_NULL(3); |
124 | | #define o_stream_add_destroy_callback(stream, callback, context) \ |
125 | | o_stream_add_destroy_callback(stream - \ |
126 | | CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \ |
127 | | (ostream_callback_t *)callback, context) |
128 | | /* Remove the destroy callback. */ |
129 | | void o_stream_remove_destroy_callback(struct ostream *stream, |
130 | | void (*callback)()); |
131 | | |
132 | | /* Mark the stream and all of its parent streams closed. Nothing will be |
133 | | sent after this call. When using ostreams that require writing a trailer, |
134 | | o_stream_finish() must be used before the stream is closed. When ostream |
135 | | is destroyed, it's also closed but its parents aren't. |
136 | | |
137 | | Closing the ostream (also via destroy) will first flush the ostream, and |
138 | | afterwards requires one of: a) stream has failed, b) there is no more |
139 | | buffered data, c) o_stream_set_no_error_handling() has been called. */ |
140 | | void o_stream_close(struct ostream *stream); |
141 | | |
142 | | /* Set IO_WRITE callback. Default will just try to flush the output and |
143 | | finishes when the buffer is empty. */ |
144 | | void o_stream_set_flush_callback(struct ostream *stream, |
145 | | stream_flush_callback_t *callback, |
146 | | void *context) ATTR_NULL(3); |
147 | | #define o_stream_set_flush_callback(stream, callback, context) \ |
148 | 0 | o_stream_set_flush_callback(stream - \ |
149 | 0 | CALLBACK_TYPECHECK(callback, int (*)(typeof(context))), \ |
150 | 0 | (stream_flush_callback_t *)callback, context) |
151 | | void o_stream_unset_flush_callback(struct ostream *stream); |
152 | | /* Get the current flush callback, returns NULL if none set. */ |
153 | | stream_flush_callback_t * |
154 | | o_stream_get_flush_callback(struct ostream *stream, void **context_r); |
155 | | |
156 | | /* Change the maximum size for stream's output buffer to grow. */ |
157 | | void o_stream_set_max_buffer_size(struct ostream *stream, size_t max_size); |
158 | | /* Returns the current max. buffer size. */ |
159 | | size_t o_stream_get_max_buffer_size(struct ostream *stream); |
160 | | |
161 | | /* Delays sending as far as possible, writing only full buffers. Also sets |
162 | | TCP_CORK on if supported. */ |
163 | | void o_stream_cork(struct ostream *stream); |
164 | | /* Try to flush the buffer by calling o_stream_flush() and remove TCP_CORK. |
165 | | Note that after this o_stream_flush() must be called, unless the stream |
166 | | ignores errors. */ |
167 | | void o_stream_uncork(struct ostream *stream); |
168 | | bool o_stream_is_corked(struct ostream *stream); |
169 | | /* Try to flush the output stream. If o_stream_nsend*() had been used and |
170 | | the stream had overflown, return error. Returns 1 if all data is sent, |
171 | | 0 there's still buffered data, -1 if error. */ |
172 | | int o_stream_flush(struct ostream *stream); |
173 | | /* Wrapper to easily both uncork and flush. */ |
174 | | static inline int o_stream_uncork_flush(struct ostream *stream) |
175 | 0 | { |
176 | 0 | o_stream_uncork(stream); |
177 | 0 | return o_stream_flush(stream); |
178 | 0 | } Unexecuted instantiation: fuzzer.c:o_stream_uncork_flush Unexecuted instantiation: iostream-pump.c:o_stream_uncork_flush Unexecuted instantiation: ostream.c:o_stream_uncork_flush Unexecuted instantiation: ostream-file.c:o_stream_uncork_flush Unexecuted instantiation: iostream.c:o_stream_uncork_flush |
179 | | |
180 | | /* Set "flush pending" state of stream. If set, the flush callback is called |
181 | | when more data is allowed to be sent, even if the buffer itself is empty. |
182 | | Note that if the stream is corked, the flush callback won't be called until |
183 | | the stream is first uncorked. */ |
184 | | void o_stream_set_flush_pending(struct ostream *stream, bool set); |
185 | | /* Returns the number of bytes currently in all the pending write buffers of |
186 | | this ostream, including its parent streams. This function is commonly used |
187 | | by callers to determine when they've filled up the ostream so they can stop |
188 | | writing to it. Because of this, the return value shouldn't include buffers |
189 | | that are expected to be filled up before they send anything to their parent |
190 | | stream. Otherwise the callers may stop writing to the stream too early and |
191 | | hang. Such an example could be a compression ostream that won't send |
192 | | anything to its parent stream before an internal compression buffer is |
193 | | full. */ |
194 | | size_t o_stream_get_buffer_used_size(const struct ostream *stream) ATTR_PURE; |
195 | | /* Returns the (minimum) number of bytes we can still write without failing. |
196 | | This is commonly used by callers to find out how many bytes they're |
197 | | guaranteed to be able to send, and then generate that much data and send |
198 | | it. */ |
199 | | size_t o_stream_get_buffer_avail_size(const struct ostream *stream) ATTR_PURE; |
200 | | |
201 | | /* Seek to specified position from beginning of file. This works only for |
202 | | files. Returns 1 if successful, -1 if error. */ |
203 | | int o_stream_seek(struct ostream *stream, uoff_t offset); |
204 | | /* Returns number of bytes sent, -1 = error */ |
205 | | ssize_t o_stream_send(struct ostream *stream, const void *data, size_t size) |
206 | | ATTR_WARN_UNUSED_RESULT; |
207 | | ssize_t o_stream_sendv(struct ostream *stream, const struct const_iovec *iov, |
208 | | unsigned int iov_count) ATTR_WARN_UNUSED_RESULT; |
209 | | ssize_t o_stream_send_str(struct ostream *stream, const char *str) |
210 | | ATTR_WARN_UNUSED_RESULT; |
211 | | /* Send with delayed error handling. o_stream_flush() or |
212 | | o_stream_ignore_last_errors() must be called after these functions before |
213 | | the stream is destroyed. If any of the data can't be sent due to stream's |
214 | | buffer getting full, all further nsends are ignores and o_stream_flush() |
215 | | will fail. */ |
216 | | void o_stream_nsend(struct ostream *stream, const void *data, size_t size); |
217 | | void o_stream_nsendv(struct ostream *stream, const struct const_iovec *iov, |
218 | | unsigned int iov_count); |
219 | | void o_stream_nsend_str(struct ostream *stream, const char *str); |
220 | | /* Mark the ostream as finished and flush it. If the ostream has a footer, |
221 | | it's written here. Any further write attempts to the ostream will |
222 | | assert-crash. Returns the same as o_stream_flush(). Afterwards any calls to |
223 | | this function are identical to o_stream_flush(). */ |
224 | | int o_stream_finish(struct ostream *stream); |
225 | | /* Specify whether calling o_stream_finish() will cause the parent stream to |
226 | | be finished as well. The default is yes. */ |
227 | | void o_stream_set_finish_also_parent(struct ostream *stream, bool set); |
228 | | /* Specify whether calling o_stream_finish() on a child stream will cause |
229 | | this stream to be finished as well. The default is yes. */ |
230 | | void o_stream_set_finish_via_child(struct ostream *stream, bool set); |
231 | | /* Marks the stream's error handling as completed to avoid i_panic() on |
232 | | destroy. */ |
233 | | void o_stream_ignore_last_errors(struct ostream *stream); |
234 | | /* Abort writing to the ostream, also marking any previous error handling as |
235 | | completed. If the stream hasn't already failed, sets the stream_errno=EPIPE. |
236 | | This is necessary when aborting write to streams that require finishing. */ |
237 | | void o_stream_abort(struct ostream *stream); |
238 | | /* If error handling is disabled, the i_panic() on destroy is never called. |
239 | | This function can be called immediately after the stream is created. |
240 | | When creating wrapper streams, they copy this behavior from the parent |
241 | | stream. */ |
242 | | void o_stream_set_no_error_handling(struct ostream *stream, bool set); |
243 | | /* Send all of the instream to outstream. |
244 | | |
245 | | On non-failure instream is skips over all data written to outstream. |
246 | | This means that the number of bytes written to outstream is always equal to |
247 | | the number of bytes skipped in instream. |
248 | | |
249 | | It's also possible to use this function to copy data within same file |
250 | | descriptor, even if the source and destination overlaps. If the file must |
251 | | be grown, you have to do it manually before calling this function. */ |
252 | | enum ostream_send_istream_result ATTR_WARN_UNUSED_RESULT |
253 | | o_stream_send_istream(struct ostream *outstream, struct istream *instream); |
254 | | /* Same as o_stream_send_istream(), but assume that reads and writes will |
255 | | succeed. If not, o_stream_flush() will fail with the correct error |
256 | | message (even istream's). */ |
257 | | void o_stream_nsend_istream(struct ostream *outstream, struct istream *instream); |
258 | | |
259 | | /* Write data to specified offset. Returns 0 if successful, -1 if error. */ |
260 | | int o_stream_pwrite(struct ostream *stream, const void *data, size_t size, |
261 | | uoff_t offset); |
262 | | |
263 | | /* Return the last timestamp when something was successfully sent to the |
264 | | ostream's internal buffers (no guarantees that anything was sent further). |
265 | | The timestamp is 0 if nothing has ever been written. */ |
266 | | void o_stream_get_last_write_time(struct ostream *stream, struct timeval *tv_r); |
267 | | |
268 | | /* If there are any I/O loop items associated with the stream, move all of |
269 | | them to provided/current ioloop. */ |
270 | | void o_stream_switch_ioloop_to(struct ostream *stream, struct ioloop *ioloop); |
271 | | void o_stream_switch_ioloop(struct ostream *stream); |
272 | | |
273 | | #endif |