aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/connection.c')
-rw-r--r--src/microhttpd/connection.c163
1 files changed, 96 insertions, 67 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index bd8af585..43a90ee0 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -154,25 +154,40 @@ socket_start_extra_buffering (struct MHD_Connection *connection)
154 return MHD_NO; 154 return MHD_NO;
155#if defined(TCP_NOPUSH) && !defined(TCP_CORK) 155#if defined(TCP_NOPUSH) && !defined(TCP_CORK)
156 /* Buffer data before sending */ 156 /* Buffer data before sending */
157 res = (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NOPUSH, (const void*)&on_val, 157 res = (0 == setsockopt (connection->socket_fd,
158 sizeof (on_val))) ? MHD_YES : MHD_NO; 158 IPPROTO_TCP,
159 TCP_NOPUSH,
160 (const void *) &on_val,
161 sizeof (on_val)))
162 ? MHD_YES : MHD_NO;
159#if defined(TCP_NODELAY) 163#if defined(TCP_NODELAY)
160 /* Enable Nagle's algorithm */ 164 /* Enable Nagle's algorithm */
161 /* TCP_NODELAY may interfere with TCP_NOPUSH */ 165 /* TCP_NODELAY may interfere with TCP_NOPUSH */
162 res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&off_val, 166 res &= (0 == setsockopt (connection->socket_fd,
163 sizeof (off_val))) ? MHD_YES : MHD_NO; 167 IPPROTO_TCP,
168 TCP_NODELAY,
169 (const void *) &off_val,
170 sizeof (off_val)))
171 ? MHD_YES : MHD_NO;
164#endif /* TCP_NODELAY */ 172#endif /* TCP_NODELAY */
165#else /* TCP_CORK */ 173#else /* TCP_CORK */
166#if defined(TCP_NODELAY) 174#if defined(TCP_NODELAY)
167 /* Enable Nagle's algorithm */ 175 /* Enable Nagle's algorithm */
168 /* TCP_NODELAY may prevent enabling TCP_CORK. Resulting buffering mode depends 176 /* TCP_NODELAY may prevent enabling TCP_CORK. Resulting buffering mode depends
169 solely on TCP_CORK result, so ignoring return code here. */ 177 solely on TCP_CORK result, so ignoring return code here. */
170 (void)setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&off_val, 178 (void) setsockopt (connection->socket_fd,
171 sizeof (off_val)); 179 IPPROTO_TCP,
180 TCP_NODELAY,
181 (const void *) &off_val,
182 sizeof (off_val));
172#endif /* TCP_NODELAY */ 183#endif /* TCP_NODELAY */
173 /* Send only full packets */ 184 /* Send only full packets */
174 res = (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, (const void*)&on_val, 185 res = (0 == setsockopt (connection->socket_fd,
175 sizeof (on_val))) ? MHD_YES : MHD_NO; 186 IPPROTO_TCP,
187 TCP_CORK,
188 (const void *) &on_val,
189 sizeof (on_val)))
190 ? MHD_YES : MHD_NO;
176#endif /* TCP_CORK */ 191#endif /* TCP_CORK */
177#endif /* TCP_CORK || TCP_NOPUSH */ 192#endif /* TCP_CORK || TCP_NOPUSH */
178 return res; 193 return res;
@@ -180,88 +195,86 @@ socket_start_extra_buffering (struct MHD_Connection *connection)
180 195
181 196
182/** 197/**
183 * Activate no buffering mode (no delay sending) on connection socket 198 * Activate no buffering mode (no delay sending) on connection socket.
184 * and push to client data pending in socket buffer.
185 * 199 *
186 * @param connection connection to be processed 200 * @param connection connection to be processed
187 * @return #MHD_YES on success, #MHD_NO otherwise 201 * @return #MHD_YES on success, #MHD_NO otherwise
188 */ 202 */
189static int 203static int
190socket_start_no_buffering_flush (struct MHD_Connection *connection) 204socket_start_no_buffering (struct MHD_Connection *connection)
191{ 205{
192#if defined(TCP_CORK) || defined(TCP_NOPUSH)
193 int res = MHD_YES;
194 const MHD_SCKT_OPT_BOOL_ off_val = 0;
195#if defined(TCP_NODELAY) 206#if defined(TCP_NODELAY)
207 int res = MHD_YES;
196 const MHD_SCKT_OPT_BOOL_ on_val = 1; 208 const MHD_SCKT_OPT_BOOL_ on_val = 1;
197#endif /* TCP_NODELAY */ 209#if defined(TCP_CORK) || defined(TCP_NOPUSH)
198#if !defined(TCP_CORK) 210 const MHD_SCKT_OPT_BOOL_ off_val = 0;
199 const int dummy = 0; 211#endif /* TCP_CORK || TCP_NOPUSH */
200#endif /* !TCP_CORK */ 212
201 if (!connection) 213 if (NULL == connection)
202 return MHD_NO; 214 return MHD_NO;
203#if defined(TCP_CORK) 215#if defined(TCP_CORK)
204 /* Flush buffered data, allow partial packets */ 216 /* Allow partial packets */
205 res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, (const void*)&off_val, 217 res &= (0 == setsockopt (connection->socket_fd,
206 sizeof (off_val))) ? MHD_YES : MHD_NO; 218 IPPROTO_TCP,
219 TCP_CORK,
220 (const void *) &off_val,
221 sizeof (off_val)))
222 ? MHD_YES : MHD_NO;
207#endif /* TCP_CORK */ 223#endif /* TCP_CORK */
208#if defined(TCP_NODELAY) 224#if defined(TCP_NODELAY)
209 /* Disable Nagle's algorithm */ 225 /* Disable Nagle's algorithm for sending packets without delay */
210 res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&on_val, 226 res &= (0 == setsockopt (connection->socket_fd,
211 sizeof (on_val))) ? MHD_YES : MHD_NO; 227 IPPROTO_TCP,
228 TCP_NODELAY,
229 (const void *) &on_val,
230 sizeof (on_val)))
231 ? MHD_YES : MHD_NO;
212#endif /* TCP_NODELAY */ 232#endif /* TCP_NODELAY */
213#if defined(TCP_NOPUSH) && !defined(TCP_CORK) 233#if defined(TCP_NOPUSH) && !defined(TCP_CORK)
214 /* Send data without extra buffering, may flush pending data on some platforms */ 234 /* Disable extra buffering */
215 res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NOPUSH, (const void*)&off_val, 235 res &= (0 == setsockopt (connection->socket_fd,
216 sizeof (off_val))) ? MHD_YES : MHD_NO; 236 IPPROTO_TCP,
217 /* Force flush data with zero send otherwise Darwin and some BSD systems 237 TCP_NOPUSH,
218 will add 5 seconds delay. Not required with TCP_CORK as switching off 238 (const void *) &off_val,
219 TCP_CORK always flushes socket buffer. */ 239 sizeof (off_val)))
220 res &= (0 <= send (connection->socket_fd, (const void*)&dummy, 0, 0)) ? MHD_YES : MHD_NO; 240 ? MHD_YES : MHD_NO;
221#endif /* TCP_NOPUSH && !TCP_CORK*/ 241#endif /* TCP_NOPUSH && !TCP_CORK */
222 return res; 242 return res;
223#else /* !TCP_CORK && !TCP_NOPUSH */ 243#else /* !TCP_NODELAY */
224 return MHD_NO; 244 return MHD_NO;
225#endif /* !TCP_CORK && !TCP_NOPUSH */ 245#endif /* !TCP_NODELAY */
226} 246}
227 247
228 248
229/** 249/**
230 * Activate no buffering mode (no delay sending) on connection socket. 250 * Activate no buffering mode (no delay sending) on connection socket
251 * and push to client data pending in socket buffer.
231 * 252 *
232 * @param connection connection to be processed 253 * @param connection connection to be processed
233 * @return #MHD_YES on success, #MHD_NO otherwise 254 * @return #MHD_YES on success, #MHD_NO otherwise
234 */ 255 */
235static int 256static int
236socket_start_no_buffering (struct MHD_Connection *connection) 257socket_start_no_buffering_flush (struct MHD_Connection *connection)
237{ 258{
238#if defined(TCP_NODELAY)
239 int res = MHD_YES; 259 int res = MHD_YES;
240 const MHD_SCKT_OPT_BOOL_ on_val = 1; 260#if defined(TCP_NOPUSH) && !defined(TCP_CORK)
241#if defined(TCP_CORK) || defined(TCP_NOPUSH) 261 const int dummy = 0;
242 const MHD_SCKT_OPT_BOOL_ off_val = 0; 262#endif /* !TCP_CORK */
243#endif /* TCP_CORK || TCP_NOPUSH */ 263
244 if (!connection) 264 if (NULL == connection)
245 return MHD_NO; 265 return MHD_NO;
246#if defined(TCP_CORK) 266 res = socket_start_no_buffering (connection);
247 /* Allow partial packets */
248 res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, (const void*)&off_val,
249 sizeof (off_val))) ? MHD_YES : MHD_NO;
250#endif /* TCP_CORK */
251#if defined(TCP_NODELAY)
252 /* Disable Nagle's algorithm for sending packets without delay */
253 res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&on_val,
254 sizeof (on_val))) ? MHD_YES : MHD_NO;
255#endif /* TCP_NODELAY */
256#if defined(TCP_NOPUSH) && !defined(TCP_CORK) 267#if defined(TCP_NOPUSH) && !defined(TCP_CORK)
257 /* Disable extra buffering */ 268 /* Force flush data with zero send otherwise Darwin and some BSD systems
258 res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NOPUSH, (const void*)&off_val, 269 will add 5 seconds delay. Not required with TCP_CORK as switching off
259 sizeof (off_val))) ? MHD_YES : MHD_NO; 270 TCP_CORK always flushes socket buffer. */
260#endif /* TCP_NOPUSH && !TCP_CORK */ 271 res &= (0 <= send (connection->socket_fd,
272 (const void *) &dummy,
273 0,
274 0))
275 ? MHD_YES : MHD_NO;
276#endif /* TCP_NOPUSH && !TCP_CORK*/
261 return res; 277 return res;
262#else /* !TCP_NODELAY */
263 return MHD_NO;
264#endif /* !TCP_NODELAY */
265} 278}
266 279
267 280
@@ -287,20 +300,36 @@ socket_start_normal_buffering (struct MHD_Connection *connection)
287 /* Allow partial packets */ 300 /* Allow partial packets */
288 /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before 301 /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before
289 so try to check current value of TCP_CORK to prevent unrequested flushing */ 302 so try to check current value of TCP_CORK to prevent unrequested flushing */
290 if ( (0 != getsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, (void*)&cork_val, &param_size)) || 303 if ( (0 != getsockopt (connection->socket_fd,
304 IPPROTO_TCP,
305 TCP_CORK,
306 (void*)&cork_val,
307 &param_size)) ||
291 (0 != cork_val)) 308 (0 != cork_val))
292 res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, (const void*)&off_val, 309 res &= (0 == setsockopt (connection->socket_fd,
293 sizeof (off_val))) ? MHD_YES : MHD_NO; 310 IPPROTO_TCP,
311 TCP_CORK,
312 (const void *) &off_val,
313 sizeof (off_val)))
314 ? MHD_YES : MHD_NO;
294#elif defined(TCP_NOPUSH) 315#elif defined(TCP_NOPUSH)
295 /* Disable extra buffering */ 316 /* Disable extra buffering */
296 /* No need to check current value as disabling TCP_NOPUSH will not flush partial 317 /* No need to check current value as disabling TCP_NOPUSH will not flush partial
297 packet if TCP_NOPUSH wasn't enabled before */ 318 packet if TCP_NOPUSH wasn't enabled before */
298 res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NOPUSH, (const void*)&off_val, 319 res &= (0 == setsockopt (connection->socket_fd,
299 sizeof (off_val))) ? MHD_YES : MHD_NO; 320 IPPROTO_TCP,
321 TCP_NOPUSH,
322 (const void *) &off_val,
323 sizeof (off_val)))
324 ? MHD_YES : MHD_NO;
300#endif /* TCP_NOPUSH && !TCP_CORK */ 325#endif /* TCP_NOPUSH && !TCP_CORK */
301 /* Enable Nagle's algorithm for normal buffering */ 326 /* Enable Nagle's algorithm for normal buffering */
302 res &= (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, (const void*)&off_val, 327 res &= (0 == setsockopt (connection->socket_fd,
303 sizeof (off_val))) ? MHD_YES : MHD_NO; 328 IPPROTO_TCP,
329 TCP_NODELAY,
330 (const void *) &off_val,
331 sizeof (off_val)))
332 ? MHD_YES : MHD_NO;
304 return res; 333 return res;
305#else /* !TCP_NODELAY */ 334#else /* !TCP_NODELAY */
306 return MHD_NO; 335 return MHD_NO;