diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-08-01 18:05:17 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-08-01 18:05:17 +0200 |
commit | b8f3cf79d55cbf985780e6ccec0b0aec74160ce2 (patch) | |
tree | 69ba17440229fd9de30c2e95572240a3664fcc1a /src/microhttpd/mhd_send.c | |
parent | 8ad5fab2e8173476b78c3fda9a416540b925cd0f (diff) | |
download | libmicrohttpd-b8f3cf79d55cbf985780e6ccec0b0aec74160ce2.tar.gz libmicrohttpd-b8f3cf79d55cbf985780e6ccec0b0aec74160ce2.zip |
fixes, comments, FIXMEs
Diffstat (limited to 'src/microhttpd/mhd_send.c')
-rw-r--r-- | src/microhttpd/mhd_send.c | 147 |
1 files changed, 94 insertions, 53 deletions
diff --git a/src/microhttpd/mhd_send.c b/src/microhttpd/mhd_send.c index a41586d9..10cb97cb 100644 --- a/src/microhttpd/mhd_send.c +++ b/src/microhttpd/mhd_send.c | |||
@@ -51,8 +51,6 @@ pre_cork_setsockopt (struct MHD_Connection *connection, | |||
51 | #if HAVE_MSG_MORE | 51 | #if HAVE_MSG_MORE |
52 | #else | 52 | #else |
53 | int ret; | 53 | int ret; |
54 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | ||
55 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | ||
56 | 54 | ||
57 | /* If sk_cork_on is already what we pass in, return. */ | 55 | /* If sk_cork_on is already what we pass in, return. */ |
58 | if (connection->sk_cork_on == want_cork) | 56 | if (connection->sk_cork_on == want_cork) |
@@ -64,33 +62,72 @@ pre_cork_setsockopt (struct MHD_Connection *connection, | |||
64 | ret = -1; | 62 | ret = -1; |
65 | #if TCP_CORK | 63 | #if TCP_CORK |
66 | if (want_cork) | 64 | if (want_cork) |
65 | { | ||
66 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | ||
67 | |||
67 | ret = setsockopt (connection->socket_fd, | 68 | ret = setsockopt (connection->socket_fd, |
68 | IPPROTO_TCP, | 69 | IPPROTO_TCP, |
69 | TCP_CORK, | 70 | TCP_CORK, |
70 | (const void *) &on_val, | 71 | (const void *) &on_val, |
71 | sizeof (on_val)); | 72 | sizeof (on_val)); |
73 | } | ||
72 | #elif TCP_NODELAY | 74 | #elif TCP_NODELAY |
73 | ret = setsockopt (connection->socket_fd, | 75 | { |
74 | IPPROTO_TCP, | 76 | const MHD_SCKT_OPT_BOOL_ off_val = 0; |
75 | TCP_NODELAY, | 77 | const MHD_SCKT_OPT_BOOL_ on_val = 1; |
76 | (const void *) want_cork ? &off_val : &on_val, | 78 | |
77 | sizeof (on_val)); | 79 | ret = setsockopt (connection->socket_fd, |
80 | IPPROTO_TCP, | ||
81 | TCP_NODELAY, | ||
82 | (const void *) want_cork ? &off_val : &on_val, | ||
83 | sizeof (on_val)); | ||
84 | } | ||
78 | #elif TCP_NOPUSH | 85 | #elif TCP_NOPUSH |
79 | ret = setsockopt (connection->socket_fd, | 86 | { |
80 | IPPROTO_TCP, | 87 | const MHD_SCKT_OPT_BOOL_ on_val = 1; |
81 | TCP_NOPUSH, | ||
82 | (const void *) &on_val, | ||
83 | sizeof (on_val)); | ||
84 | #endif | ||
85 | 88 | ||
89 | // FIXME: this must be wrong, set unconditionally irrespective of 'want_cork'! | ||
90 | ret = setsockopt (connection->socket_fd, | ||
91 | IPPROTO_TCP, | ||
92 | TCP_NOPUSH, | ||
93 | (const void *) &on_val, | ||
94 | sizeof (on_val)); | ||
95 | } | ||
96 | #endif | ||
86 | if (0 == ret) | 97 | if (0 == ret) |
87 | { | 98 | { |
88 | connection->sk_cork_on = want_cork; | 99 | connection->sk_cork_on = want_cork; |
89 | } | 100 | } |
101 | else | ||
102 | { | ||
103 | switch (errno) | ||
104 | { | ||
105 | case ENOTSOCK: | ||
106 | /* FIXME: Could be we are talking to a pipe, maybe remember this | ||
107 | and avoid all setsockopt() in the future? */ | ||
108 | break; | ||
109 | case EBADF: | ||
110 | /* FIXME: should we die hard here? */ | ||
111 | break; | ||
112 | case EINVAL: | ||
113 | /* FIXME: optlen invalid, should at least log this, maybe die */ | ||
114 | break; | ||
115 | case EFAULT: | ||
116 | /* FIXME: wopsie, should at leats log this, maybe die */ | ||
117 | break; | ||
118 | case ENOPROTOOPT: | ||
119 | /* FIXME: optlen unknown, should at least log this */ | ||
120 | break; | ||
121 | default: | ||
122 | /* any others? man page does not list more... */ | ||
123 | break; | ||
124 | } | ||
125 | } | ||
90 | return; | 126 | return; |
91 | #endif /* MSG_MORE */ | 127 | #endif /* MSG_MORE */ |
92 | } | 128 | } |
93 | 129 | ||
130 | |||
94 | /** | 131 | /** |
95 | * Handle setsockopt calls. | 132 | * Handle setsockopt calls. |
96 | * | 133 | * |
@@ -104,8 +141,6 @@ post_cork_setsockopt (struct MHD_Connection *connection, | |||
104 | #if HAVE_MSG_MORE | 141 | #if HAVE_MSG_MORE |
105 | #else | 142 | #else |
106 | int ret; | 143 | int ret; |
107 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | ||
108 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | ||
109 | 144 | ||
110 | /* If sk_cork_on is already what we pass in, return. */ | 145 | /* If sk_cork_on is already what we pass in, return. */ |
111 | if (connection->sk_cork_on == want_cork) | 146 | if (connection->sk_cork_on == want_cork) |
@@ -116,19 +151,29 @@ post_cork_setsockopt (struct MHD_Connection *connection, | |||
116 | ret = -1; | 151 | ret = -1; |
117 | #if TCP_CORK | 152 | #if TCP_CORK |
118 | if (! want_cork) | 153 | if (! want_cork) |
154 | { | ||
155 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | ||
156 | |||
119 | ret = setsockopt (connection->socket_fd, | 157 | ret = setsockopt (connection->socket_fd, |
120 | IPPROTO_TCP, | 158 | IPPROTO_TCP, |
121 | TCP_CORK, | 159 | TCP_CORK, |
122 | &off_val, | 160 | &off_val, |
123 | sizeof (off_val)); | 161 | sizeof (off_val)); |
162 | } | ||
124 | #elif TCP_NODELAY | 163 | #elif TCP_NODELAY |
125 | /* nothing to do */ | 164 | /* nothing to do */ |
126 | #elif TCP_NOPUSH | 165 | #elif TCP_NOPUSH |
127 | ret = setsockopt (connection->socket_fd, | 166 | // FIXME: this must be wrong, set unconditionally irrespective of 'want_cork'! |
128 | IPPROTO_TCP, | 167 | { |
129 | TCP_NOPUSH, | 168 | const MHD_SCKT_OPT_BOOL_ off_val = 0; |
130 | (const void *) &off_val, | 169 | const MHD_SCKT_OPT_BOOL_ on_val = 1; |
131 | sizeof (off_val)); | 170 | |
171 | ret = setsockopt (connection->socket_fd, | ||
172 | IPPROTO_TCP, | ||
173 | TCP_NOPUSH, | ||
174 | (const void *) &off_val, | ||
175 | sizeof (off_val)); | ||
176 | } | ||
132 | #endif | 177 | #endif |
133 | if (0 == ret) | 178 | if (0 == ret) |
134 | { | 179 | { |
@@ -138,6 +183,7 @@ post_cork_setsockopt (struct MHD_Connection *connection, | |||
138 | #endif /* MSG_MORE */ | 183 | #endif /* MSG_MORE */ |
139 | } | 184 | } |
140 | 185 | ||
186 | |||
141 | /** | 187 | /** |
142 | * Send buffer on connection, and remember the current state of | 188 | * Send buffer on connection, and remember the current state of |
143 | * the socket options; only call setsockopt when absolutely | 189 | * the socket options; only call setsockopt when absolutely |
@@ -164,11 +210,8 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
164 | enum MHD_SendSocketOptions options) | 210 | enum MHD_SendSocketOptions options) |
165 | { | 211 | { |
166 | bool want_cork; | 212 | bool want_cork; |
167 | bool using_tls = false; | ||
168 | MHD_socket s = connection->socket_fd; | 213 | MHD_socket s = connection->socket_fd; |
169 | ssize_t ret; | 214 | ssize_t ret; |
170 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | ||
171 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | ||
172 | 215 | ||
173 | /* error handling from send_param_adapter() */ | 216 | /* error handling from send_param_adapter() */ |
174 | if ((MHD_INVALID_SOCKET == s) || (MHD_CONNECTION_CLOSED == connection->state)) | 217 | if ((MHD_INVALID_SOCKET == s) || (MHD_CONNECTION_CLOSED == connection->state)) |
@@ -197,21 +240,15 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
197 | break; | 240 | break; |
198 | } | 241 | } |
199 | 242 | ||
200 | /* ! could be avoided by redefining the variable. */ | ||
201 | // bool have_cork = ! connection->sk_tcp_nodelay_on; | ||
202 | bool have_cork = ! connection->sk_cork_on; | ||
203 | |||
204 | #ifdef HTTPS_SUPPORT | ||
205 | using_tls = (0 != (connection->daemon->options & MHD_USE_TLS)); | ||
206 | #endif | ||
207 | |||
208 | #ifdef HTTPS_SUPPORT | 243 | #ifdef HTTPS_SUPPORT |
209 | if (using_tls) | 244 | if (0 != (connection->daemon->options & MHD_USE_TLS)) |
210 | { | 245 | { |
246 | bool have_cork = connection->sk_cork_on; | ||
247 | |||
211 | if (want_cork && ! have_cork) | 248 | if (want_cork && ! have_cork) |
212 | { | 249 | { |
213 | gnutls_record_cork (connection->tls_session); | 250 | gnutls_record_cork (connection->tls_session); |
214 | connection->sk_cork_on = false; | 251 | connection->sk_cork_on = true; |
215 | } | 252 | } |
216 | if (buffer_size > SSIZE_MAX) | 253 | if (buffer_size > SSIZE_MAX) |
217 | buffer_size = SSIZE_MAX; | 254 | buffer_size = SSIZE_MAX; |
@@ -242,7 +279,7 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
242 | if (! want_cork && have_cork) | 279 | if (! want_cork && have_cork) |
243 | { | 280 | { |
244 | (void) gnutls_record_uncork (connection->tls_session, 0); | 281 | (void) gnutls_record_uncork (connection->tls_session, 0); |
245 | connection->sk_cork_on = true; | 282 | connection->sk_cork_on = false; |
246 | } | 283 | } |
247 | } | 284 | } |
248 | else | 285 | else |
@@ -285,8 +322,8 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
285 | else if (buffer_size > (size_t) ret) | 322 | else if (buffer_size > (size_t) ret) |
286 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | 323 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; |
287 | #endif /* EPOLL_SUPPORT */ | 324 | #endif /* EPOLL_SUPPORT */ |
288 | 325 | if (ret == buffer_size) | |
289 | post_cork_setsockopt (connection, want_cork); | 326 | post_cork_setsockopt (connection, want_cork); |
290 | } | 327 | } |
291 | 328 | ||
292 | return ret; | 329 | return ret; |
@@ -319,28 +356,26 @@ MHD_send_on_connection2_ (struct MHD_Connection *connection, | |||
319 | { | 356 | { |
320 | #if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV) | 357 | #if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV) |
321 | MHD_socket s = connection->socket_fd; | 358 | MHD_socket s = connection->socket_fd; |
322 | bool want_cork; | ||
323 | int iovcnt; | 359 | int iovcnt; |
324 | int eno; | ||
325 | ssize_t ret; | 360 | ssize_t ret; |
326 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | ||
327 | struct iovec vector[2]; | 361 | struct iovec vector[2]; |
328 | 362 | ||
329 | want_cork = ! connection->sk_cork_on; | 363 | /* Since we generally give the fully answer, we do not want |
330 | 364 | corking to happen */ | |
331 | pre_cork_setsockopt (connection, want_cork); | 365 | pre_cork_setsockopt (connection, false); |
332 | 366 | ||
333 | vector[0].iov_base = (void *) header; | 367 | vector[0].iov_base = (void *) header; |
334 | vector[0].iov_len = strlen (header); | 368 | vector[0].iov_len = header_size; |
335 | vector[1].iov_base = (void *) buffer; | 369 | vector[1].iov_base = (void *) buffer; |
336 | vector[1].iov_len = strlen (buffer); | 370 | vector[1].iov_len = buffer_size; |
337 | 371 | ||
338 | #if HAVE_SENDMSG | 372 | #if HAVE_SENDMSG |
339 | struct msghdr msg; | 373 | { |
340 | memset(&msg, 0, sizeof(struct msghdr)); | 374 | struct msghdr msg; |
341 | 375 | ||
342 | msg.msg_iov = vector; | 376 | memset(&msg, 0, sizeof(struct msghdr)); |
343 | msg.msg_iovlen = 2; | 377 | msg.msg_iov = vector; |
378 | msg.msg_iovlen = 2; | ||
344 | 379 | ||
345 | /* | 380 | /* |
346 | * questionable for this case, bus maybe worth considering for now: | 381 | * questionable for this case, bus maybe worth considering for now: |
@@ -349,21 +384,23 @@ MHD_send_on_connection2_ (struct MHD_Connection *connection, | |||
349 | * If you set msg_control to nonnull, NetBSD expects you to have | 384 | * If you set msg_control to nonnull, NetBSD expects you to have |
350 | * msg_controllen > 0. (sys/kern/uipc_syscalls.c in do_sys_sendmsg_so) | 385 | * msg_controllen > 0. (sys/kern/uipc_syscalls.c in do_sys_sendmsg_so) |
351 | * for reference. Thanks to pDNS (for FreeBSD), Riastradh for NetBSD. | 386 | * for reference. Thanks to pDNS (for FreeBSD), Riastradh for NetBSD. |
387 | * FIXME: this is unnecessary, see the memset() above? | ||
352 | */ | 388 | */ |
353 | /* | 389 | /* |
354 | msg.msg_control = 0; | 390 | msg.msg_control = 0; |
355 | msg.msg_controllen = 0; | 391 | msg.msg_controllen = 0; |
356 | */ | 392 | */ |
357 | ret = sendmsg (s, &msg, MAYBE_MSG_NOSIGNAL); | 393 | ret = sendmsg (s, &msg, MAYBE_MSG_NOSIGNAL); |
394 | } | ||
358 | #elif HAVE_WRITEV | 395 | #elif HAVE_WRITEV |
359 | iovcnt = sizeof (vector) / sizeof (struct iovec); | 396 | iovcnt = sizeof (vector) / sizeof (struct iovec); |
360 | ret = writev (s, vector, iovcnt); | 397 | ret = writev (s, vector, iovcnt); |
361 | #endif | 398 | #endif |
362 | 399 | ||
400 | /* Only if we succeeded sending the full buffer, we need to make sure that | ||
401 | the OS flushes at the end */ | ||
363 | if (ret == header_size + buffer_size) | 402 | if (ret == header_size + buffer_size) |
364 | want_cork = false; | 403 | post_cork_setsockopt (connection, false); |
365 | |||
366 | post_cork_setsockopt (connection, want_cork); | ||
367 | 404 | ||
368 | return ret; | 405 | return ret; |
369 | 406 | ||
@@ -407,6 +444,7 @@ static int freebsd_sendfile_flags_thd_p_c_; | |||
407 | * @param connection the MHD connection structure | 444 | * @param connection the MHD connection structure |
408 | * @return actual number of bytes sent | 445 | * @return actual number of bytes sent |
409 | */ | 446 | */ |
447 | // FIXME: rename... | ||
410 | ssize_t | 448 | ssize_t |
411 | sendfile_adapter (struct MHD_Connection *connection) | 449 | sendfile_adapter (struct MHD_Connection *connection) |
412 | { | 450 | { |
@@ -579,7 +617,10 @@ sendfile_adapter (struct MHD_Connection *connection) | |||
579 | ret = (ssize_t)len; | 617 | ret = (ssize_t)len; |
580 | #endif /* HAVE_FREEBSD_SENDFILE */ | 618 | #endif /* HAVE_FREEBSD_SENDFILE */ |
581 | 619 | ||
582 | post_cork_setsockopt (connection, false); | 620 | /* Make sure we send the data without delay ONLY if we |
621 | provided the complete response (not on partial write) */ | ||
622 | if (ret == left) | ||
623 | post_cork_setsockopt (connection, false); | ||
583 | 624 | ||
584 | return ret; | 625 | return ret; |
585 | } | 626 | } |