/src/lighttpd1.4/src/chunk.h
Line | Count | Source |
1 | | #ifndef _CHUNK_H_ |
2 | | #define _CHUNK_H_ |
3 | | #include "first.h" |
4 | | |
5 | | #include "buffer.h" |
6 | | #include "array.h" |
7 | | #include "fdlog.h" |
8 | | |
9 | | /* both should be way smaller than SSIZE_MAX :) */ |
10 | | #define MAX_READ_LIMIT (256*1024) |
11 | | #define MAX_WRITE_LIMIT (256*1024) |
12 | | |
13 | | typedef struct chunk_file_view { |
14 | | char *mptr; /* base pointer of mmap'ed area */ |
15 | | off_t mlen; /* length of mmap'ed area */ |
16 | | off_t foff; /* offset from the start of the file */ |
17 | | int refcnt; |
18 | | } chunk_file_view; |
19 | | |
20 | | typedef struct chunk { |
21 | | struct chunk *next; |
22 | | enum { MEM_CHUNK, FILE_CHUNK } type; |
23 | | |
24 | | buffer *mem; /* either the storage of the mem-chunk or the name of the file */ |
25 | | |
26 | | /* the size of the chunk is either: |
27 | | * - mem-chunk: buffer_string_length(chunk::mem) - c->offset |
28 | | * - file-chunk: chunk::file.length - c->offset |
29 | | */ |
30 | | off_t offset; |
31 | | |
32 | | struct { |
33 | | /* filechunk */ |
34 | | off_t length; /* end pos + 1 in file (octets to send: file.length - c->offset) */ |
35 | | |
36 | | int fd; |
37 | | uint8_t is_temp; /* file is temporary and will be deleted if on cleanup */ |
38 | | uint8_t busy; /* file chunk not in page cache; reading might block */ |
39 | | uint8_t flagmask;/* (internal; used with preadv2() RWF_NOWAIT) */ |
40 | | #if defined(HAVE_MMAP) || defined(_WIN32) /*(see local sys-mmap.h)*/ |
41 | | chunk_file_view *view; |
42 | | #endif |
43 | | void *ref; |
44 | | void(*refchg)(void *, int); |
45 | | } file; |
46 | | } chunk; |
47 | | |
48 | | typedef struct chunkqueue { |
49 | | chunk *first; |
50 | | chunk *last; |
51 | | |
52 | | off_t bytes_in, bytes_out; |
53 | | |
54 | | off_t upload_temp_file_size; |
55 | | unsigned int tempdir_idx; |
56 | | } chunkqueue; |
57 | | |
58 | | ssize_t chunk_file_pread (int fd, void *buf, size_t count, off_t offset); |
59 | | |
60 | | /* attempts non-blocking preadv2 RWF_NOWAIT on Linux, else chunk_file_pread() */ |
61 | | ssize_t chunk_file_pread_chunk (chunk *c, void *buf, size_t count); |
62 | | |
63 | | __attribute_returns_nonnull__ |
64 | | buffer * chunk_buffer_acquire(void); |
65 | | |
66 | | void chunk_buffer_release(buffer *b); |
67 | | |
68 | | __attribute_nonnull__() |
69 | | void chunk_buffer_yield(buffer *b); |
70 | | |
71 | | size_t chunk_buffer_prepare_append (buffer *b, size_t sz); |
72 | | |
73 | | void chunkqueue_chunk_pool_clear(void); |
74 | | void chunkqueue_chunk_pool_free(void); |
75 | | |
76 | | __attribute_returns_nonnull__ |
77 | | chunkqueue *chunkqueue_init(chunkqueue *cq); |
78 | | |
79 | | __attribute_cold__ |
80 | | void chunkqueue_set_chunk_size (size_t sz); |
81 | | |
82 | | __attribute_cold__ |
83 | | void chunkqueue_set_tempdirs_default_reset (void); |
84 | | |
85 | | __attribute_cold__ |
86 | | void chunkqueue_set_tempdirs_default (const array *tempdirs, off_t upload_temp_file_size); |
87 | | |
88 | | void chunkqueue_set_tempdirs(chunkqueue * restrict cq, off_t upload_temp_file_size); |
89 | | |
90 | | __attribute_cold__ |
91 | | const char *chunkqueue_env_tmpdir(void); |
92 | | |
93 | | void chunkqueue_append_file(chunkqueue * restrict cq, const buffer * restrict fn, off_t offset, off_t len); /* copies "fn" */ |
94 | | void chunkqueue_append_file_fd(chunkqueue * restrict cq, const buffer * restrict fn, int fd, off_t offset, off_t len); /* copies "fn" */ |
95 | | void chunkqueue_append_mem(chunkqueue * restrict cq, const char * restrict mem, size_t len); /* copies memory */ |
96 | | void chunkqueue_append_mem_min(chunkqueue * restrict cq, const char * restrict mem, size_t len); /* copies memory */ |
97 | | |
98 | | __attribute_nonnull__() |
99 | | void chunkqueue_append_buffer(chunkqueue * restrict cq, buffer * restrict mem); /* may reset "mem" */ |
100 | | |
101 | | __attribute_nonnull__() |
102 | | void chunkqueue_append_chunkqueue(chunkqueue * restrict cq, chunkqueue * restrict src); |
103 | | |
104 | | __attribute_returns_nonnull__ |
105 | | buffer * chunkqueue_prepend_buffer_open_sz(chunkqueue *cq, size_t sz); |
106 | | |
107 | | __attribute_returns_nonnull__ |
108 | | buffer * chunkqueue_prepend_buffer_open(chunkqueue *cq); |
109 | | |
110 | | void chunkqueue_prepend_buffer_commit(chunkqueue *cq); |
111 | | |
112 | | __attribute_returns_nonnull__ |
113 | | buffer * chunkqueue_append_buffer_open_sz(chunkqueue *cq, size_t sz); |
114 | | |
115 | | __attribute_returns_nonnull__ |
116 | | buffer * chunkqueue_append_buffer_open(chunkqueue *cq); |
117 | | |
118 | | void chunkqueue_append_buffer_commit(chunkqueue *cq); |
119 | | |
120 | | int chunkqueue_append_mem_to_tempfile(chunkqueue * restrict cq, const char * restrict mem, size_t len, log_error_st * const restrict errh); |
121 | | |
122 | | #ifdef HAVE_SPLICE |
123 | | ssize_t chunkqueue_append_splice_pipe_tempfile(chunkqueue * restrict cq, int fd, unsigned int len, log_error_st * restrict errh); |
124 | | ssize_t chunkqueue_append_splice_sock_tempfile(chunkqueue * restrict cq, int fd, unsigned int len, log_error_st * restrict errh); |
125 | | __attribute_cold__ |
126 | | void chunkqueue_internal_pipes(int init); |
127 | | #else |
128 | | #define chunkqueue_internal_pipes(init) do { } while (0) |
129 | | #endif |
130 | | |
131 | | /* functions to handle buffers to read into: */ |
132 | | /* obtain/reserve memory in chunkqueue at least len (input) size, |
133 | | * return pointer to memory with len (output) available for use |
134 | | * modifying the chunkqueue invalidates the memory area. |
135 | | * should always be followed by chunkqueue_get_memory(), |
136 | | * even if nothing was read. |
137 | | * pass 0 in len for mem at least half of chunk_buf_sz |
138 | | */ |
139 | | __attribute_returns_nonnull__ |
140 | | char * chunkqueue_get_memory(chunkqueue * restrict cq, size_t * restrict len); |
141 | | /* commit len bytes of mem obtained from chunkqueue_get_memory() */ |
142 | | void chunkqueue_use_memory(chunkqueue * restrict cq, chunk *ckpt, size_t len); |
143 | | void chunkqueue_update_file(chunkqueue * restrict cq, chunk *c, off_t len); |
144 | | |
145 | | /* mark first "len" bytes as written (incrementing chunk offsets) |
146 | | * and remove finished chunks |
147 | | */ |
148 | | void chunkqueue_mark_written(chunkqueue *cq, off_t len); |
149 | | |
150 | | void chunkqueue_remove_finished_chunks(chunkqueue *cq); |
151 | | |
152 | | __attribute_cold__ |
153 | | void chunkqueue_remove_empty_chunks(chunkqueue *cq); |
154 | | |
155 | | void chunkqueue_steal(chunkqueue * restrict dest, chunkqueue * restrict src, off_t len); |
156 | | int chunkqueue_steal_with_tempfiles(chunkqueue * restrict dest, chunkqueue * restrict src, off_t len, log_error_st * const restrict errh); |
157 | | void chunkqueue_append_cq_range (chunkqueue *dst, const chunkqueue *src, off_t offset, off_t len); |
158 | | |
159 | | int chunk_open_file_chunk(chunk * restrict c, log_error_st * restrict errh); |
160 | | |
161 | | void chunkqueue_compact_mem_offset(chunkqueue *cq); |
162 | | void chunkqueue_compact_mem(chunkqueue *cq, size_t clen); |
163 | | |
164 | | void chunkqueue_small_resp_optim (chunkqueue * restrict cq); |
165 | | |
166 | | ssize_t chunkqueue_write_chunk (int fd, chunkqueue * restrict cq, log_error_st * restrict errh); |
167 | | ssize_t chunkqueue_write_chunk_to_pipe (int fd, chunkqueue * restrict cq, log_error_st * restrict errh); |
168 | | |
169 | | int chunkqueue_peek_data (chunkqueue *cq, char **data, uint32_t *dlen, log_error_st * restrict errh, int nowait); |
170 | | int chunkqueue_read_data (chunkqueue *cq, char *data, uint32_t dlen, log_error_st * restrict errh); |
171 | | |
172 | | chunk * chunkqueue_read_squash (chunkqueue * restrict cq, log_error_st * restrict errh); |
173 | | |
174 | | __attribute_pure__ |
175 | | __attribute_nonnull__() |
176 | | static inline off_t chunkqueue_length(const chunkqueue *cq); |
177 | 0 | static inline off_t chunkqueue_length(const chunkqueue *cq) { |
178 | 0 | return cq->bytes_in - cq->bytes_out; |
179 | 0 | } Unexecuted instantiation: fuzz_request.c:chunkqueue_length Unexecuted instantiation: request.c:chunkqueue_length Unexecuted instantiation: http_header.c:chunkqueue_length |
180 | | |
181 | | __attribute_cold__ |
182 | | void chunkqueue_free(chunkqueue *cq); |
183 | | |
184 | | void chunkqueue_reset(chunkqueue *cq); |
185 | | |
186 | | __attribute_pure__ |
187 | | __attribute_nonnull__() |
188 | | static inline int chunkqueue_is_empty(const chunkqueue *cq); |
189 | 0 | static inline int chunkqueue_is_empty(const chunkqueue *cq) { |
190 | 0 | return NULL == cq->first; |
191 | 0 | } Unexecuted instantiation: fuzz_request.c:chunkqueue_is_empty Unexecuted instantiation: request.c:chunkqueue_is_empty Unexecuted instantiation: http_header.c:chunkqueue_is_empty |
192 | | |
193 | | const chunk_file_view * chunkqueue_chunk_file_viewadj (chunk *c, off_t n, log_error_st * restrict errh); |
194 | | |
195 | | __attribute_pure__ |
196 | | __attribute_nonnull__() |
197 | | static inline char * |
198 | | chunk_file_view_dptr (const chunk_file_view * const cfv, off_t offset); |
199 | | static inline char * |
200 | | chunk_file_view_dptr (const chunk_file_view * const cfv, off_t offset) |
201 | 0 | { |
202 | 0 | return cfv->mptr - cfv->foff + offset; |
203 | 0 | } Unexecuted instantiation: fuzz_request.c:chunk_file_view_dptr Unexecuted instantiation: request.c:chunk_file_view_dptr Unexecuted instantiation: http_header.c:chunk_file_view_dptr |
204 | | |
205 | | __attribute_pure__ |
206 | | __attribute_nonnull__() |
207 | | static inline off_t |
208 | | chunk_file_view_dlen (const chunk_file_view * const cfv, off_t offset); |
209 | | static inline off_t |
210 | | chunk_file_view_dlen (const chunk_file_view * const cfv, off_t offset) |
211 | 0 | { |
212 | 0 | return cfv->mlen + cfv->foff - offset; |
213 | 0 | } Unexecuted instantiation: fuzz_request.c:chunk_file_view_dlen Unexecuted instantiation: request.c:chunk_file_view_dlen Unexecuted instantiation: http_header.c:chunk_file_view_dlen |
214 | | |
215 | | static inline const chunk_file_view * |
216 | | chunkqueue_chunk_file_view (chunk * const c, const off_t n, log_error_st * const restrict errh); |
217 | | static inline const chunk_file_view * |
218 | | chunkqueue_chunk_file_view (chunk * const c, const off_t n, log_error_st * const restrict errh) |
219 | 0 | { |
220 | 0 | /*assert(c->type == FILE_CHUNK);*/ |
221 | 0 | #if defined(HAVE_MMAP) || defined(_WIN32) /*(see local sys-mmap.h)*/ |
222 | 0 | /* mmap buffer if offset is outside old mmap area or not mapped at all */ |
223 | 0 | const chunk_file_view * const restrict cfv = c->file.view; |
224 | 0 | if (NULL == cfv |
225 | 0 | ? c->file.length - c->offset >= 131072 /* TBD: min chunk size to mmap */ |
226 | 0 | : (c->offset - cfv->foff < 0 |
227 | 0 | || chunk_file_view_dlen(cfv, c->offset) < (n ? n : 1))) |
228 | 0 | return chunkqueue_chunk_file_viewadj(c, n, errh); |
229 | 0 | return cfv; |
230 | 0 | #else |
231 | 0 | UNUSED(c); |
232 | 0 | UNUSED(n); |
233 | 0 | UNUSED(errh); |
234 | 0 | return NULL; |
235 | 0 | #endif |
236 | 0 | } Unexecuted instantiation: fuzz_request.c:chunkqueue_chunk_file_view Unexecuted instantiation: request.c:chunkqueue_chunk_file_view Unexecuted instantiation: http_header.c:chunkqueue_chunk_file_view |
237 | | |
238 | | #endif |