diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-08-01 20:44:41 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-08-01 20:44:41 +0200 |
commit | c5081fb276b52fc9d48b9ba441686727eafaaad8 (patch) | |
tree | d8741e84111ed226c2bc2426e18d4e90bbd85184 /src/microhttpd/mhd_send.c | |
parent | da7cb682a24915a4bc37faf2c76583996fe26aea (diff) | |
download | libmicrohttpd-c5081fb276b52fc9d48b9ba441686727eafaaad8.tar.gz libmicrohttpd-c5081fb276b52fc9d48b9ba441686727eafaaad8.zip |
always set nodelay, except if we cannot cork
Diffstat (limited to 'src/microhttpd/mhd_send.c')
-rw-r--r-- | src/microhttpd/mhd_send.c | 166 |
1 files changed, 62 insertions, 104 deletions
diff --git a/src/microhttpd/mhd_send.c b/src/microhttpd/mhd_send.c index 7ca2b506..9b07115c 100644 --- a/src/microhttpd/mhd_send.c +++ b/src/microhttpd/mhd_send.c | |||
@@ -49,7 +49,8 @@ pre_cork_setsockopt (struct MHD_Connection *connection, | |||
49 | bool want_cork) | 49 | bool want_cork) |
50 | { | 50 | { |
51 | #if HAVE_MSG_MORE | 51 | #if HAVE_MSG_MORE |
52 | #else | 52 | /* We use the MSG_MORE option for corking, no need for extra syscalls! */ |
53 | #elif defined(MHD_TCP_CORK_NOPUSH) | ||
53 | int ret; | 54 | int ret; |
54 | 55 | ||
55 | /* If sk_cork_on is already what we pass in, return. */ | 56 | /* If sk_cork_on is already what we pass in, return. */ |
@@ -58,84 +59,38 @@ pre_cork_setsockopt (struct MHD_Connection *connection, | |||
58 | /* nothing to do, success! */ | 59 | /* nothing to do, success! */ |
59 | return; | 60 | return; |
60 | } | 61 | } |
61 | 62 | if (! want_cork) | |
62 | ret = -1; | 63 | return; /* nothing to do *pre* syscall! */ |
63 | #if TCP_CORK | 64 | ret = MHD_socket_cork_ (connection->socket_fd, |
64 | if (want_cork) | 65 | true); |
65 | { | ||
66 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | ||
67 | |||
68 | ret = setsockopt (connection->socket_fd, | ||
69 | IPPROTO_TCP, | ||
70 | TCP_CORK, | ||
71 | (const void *) &on_val, | ||
72 | sizeof (on_val)); | ||
73 | } | ||
74 | #elif TCP_NOPUSH | ||
75 | if (want_cork) | ||
76 | { | ||
77 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | ||
78 | /* TCP_NOPUSH has the same logic as MSG_MSG_MORE. | ||
79 | * The two are more or less equivalent by a source | ||
80 | * transformation (ie | ||
81 | * send(MSG_MORE) => "set TCP_NOPUSH + send() + clear TCP_NOPUSH". | ||
82 | * Both of them are really fairly "local", but TCP_NOPUSH has a | ||
83 | * _notion_ of persistency that is entirely lacking in MSG_MORE. | ||
84 | * ... with TCP_NOPUSH you basically have to know what your last | ||
85 | * write is, and clear the bit _before_ that write if you want | ||
86 | * to avoid bad latencies. | ||
87 | * https://yarchive.net/comp/linux/sendfile.html A thread from 2001, | ||
88 | * take with 18 grains of salt. */ | ||
89 | |||
90 | ret = setsockopt (connection->socket_fd, | ||
91 | IPPROTO_TCP, | ||
92 | TCP_NOPUSH, | ||
93 | (const void *) &on_val, | ||
94 | sizeof (on_val)); | ||
95 | } | ||
96 | #elif TCP_NODELAY | ||
97 | { | ||
98 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | ||
99 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | ||
100 | |||
101 | ret = setsockopt (connection->socket_fd, | ||
102 | IPPROTO_TCP, | ||
103 | TCP_NODELAY, | ||
104 | (const void *) want_cork ? &off_val : &on_val, | ||
105 | sizeof (on_val)); | ||
106 | } | ||
107 | #endif | ||
108 | if (0 == ret) | 66 | if (0 == ret) |
109 | { | 67 | { |
110 | connection->sk_cork_on = want_cork; | 68 | connection->sk_cork_on = true; |
69 | return; | ||
111 | } | 70 | } |
112 | else | 71 | switch (errno) |
113 | { | 72 | { |
114 | switch (errno) | 73 | case ENOTSOCK: |
115 | { | 74 | /* FIXME: Could be we are talking to a pipe, maybe remember this |
116 | case ENOTSOCK: | 75 | and avoid all setsockopt() in the future? */ |
117 | /* FIXME: Could be we are talking to a pipe, maybe remember this | 76 | break; |
118 | and avoid all setsockopt() in the future? */ | 77 | case EBADF: |
119 | break; | 78 | /* FIXME: should we die hard here? */ |
120 | case EBADF: | 79 | break; |
121 | /* FIXME: should we die hard here? */ | 80 | case EINVAL: |
122 | break; | 81 | /* FIXME: optlen invalid, should at least log this, maybe die */ |
123 | case EINVAL: | 82 | break; |
124 | /* FIXME: optlen invalid, should at least log this, maybe die */ | 83 | case EFAULT: |
125 | break; | 84 | /* FIXME: wopsie, should at leats log this, maybe die */ |
126 | case EFAULT: | 85 | break; |
127 | /* FIXME: wopsie, should at leats log this, maybe die */ | 86 | case ENOPROTOOPT: |
128 | break; | 87 | /* FIXME: optlen unknown, should at least log this */ |
129 | case ENOPROTOOPT: | 88 | break; |
130 | /* FIXME: optlen unknown, should at least log this */ | 89 | default: |
131 | break; | 90 | /* any others? man page does not list more... */ |
132 | default: | 91 | break; |
133 | /* any others? man page does not list more... */ | ||
134 | break; | ||
135 | } | ||
136 | } | 92 | } |
137 | return; | 93 | #endif |
138 | #endif /* MSG_MORE */ | ||
139 | } | 94 | } |
140 | 95 | ||
141 | 96 | ||
@@ -150,7 +105,8 @@ post_cork_setsockopt (struct MHD_Connection *connection, | |||
150 | bool want_cork) | 105 | bool want_cork) |
151 | { | 106 | { |
152 | #if HAVE_MSG_MORE | 107 | #if HAVE_MSG_MORE |
153 | #else | 108 | /* We use the MSG_MORE option for corking, no need for extra syscalls! */ |
109 | #elif defined(MHD_TCP_CORK_NOPUSH) | ||
154 | int ret; | 110 | int ret; |
155 | 111 | ||
156 | /* If sk_cork_on is already what we pass in, return. */ | 112 | /* If sk_cork_on is already what we pass in, return. */ |
@@ -159,38 +115,40 @@ post_cork_setsockopt (struct MHD_Connection *connection, | |||
159 | /* nothing to do, success! */ | 115 | /* nothing to do, success! */ |
160 | return; | 116 | return; |
161 | } | 117 | } |
162 | ret = -1; | 118 | if (want_cork) |
163 | #if TCP_CORK | 119 | return; /* nothing to do *post* syscall (in fact, we should never |
164 | if (! want_cork) | 120 | get here, as sk_cork_on should have succeeded in the |
165 | { | 121 | pre-syscall) */ |
166 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | 122 | ret = MHD_socket_cork_ (connection->socket_fd, |
167 | 123 | false); | |
168 | ret = setsockopt (connection->socket_fd, | ||
169 | IPPROTO_TCP, | ||
170 | TCP_CORK, | ||
171 | &off_val, | ||
172 | sizeof (off_val)); | ||
173 | } | ||
174 | #elif TCP_NOPUSH | ||
175 | if (! want_cork) | ||
176 | { | ||
177 | const MHD_SCKT_OPT_BOOL_ off_val = 0; | ||
178 | |||
179 | ret = setsockopt (connection->socket_fd, | ||
180 | IPPROTO_TCP, | ||
181 | TCP_NOPUSH, | ||
182 | (const void *) &off_val, | ||
183 | sizeof (off_val)); | ||
184 | } | ||
185 | #elif TCP_NODELAY | ||
186 | /* nothing to do */ | ||
187 | #endif | ||
188 | if (0 == ret) | 124 | if (0 == ret) |
189 | { | 125 | { |
190 | connection->sk_cork_on = want_cork; | 126 | connection->sk_cork_on = false; |
127 | return; | ||
128 | } | ||
129 | switch (errno) | ||
130 | { | ||
131 | case ENOTSOCK: | ||
132 | /* FIXME: Could be we are talking to a pipe, maybe remember this | ||
133 | and avoid all setsockopt() in the future? */ | ||
134 | break; | ||
135 | case EBADF: | ||
136 | /* FIXME: should we die hard here? */ | ||
137 | break; | ||
138 | case EINVAL: | ||
139 | /* FIXME: optlen invalid, should at least log this, maybe die */ | ||
140 | break; | ||
141 | case EFAULT: | ||
142 | /* FIXME: wopsie, should at leats log this, maybe die */ | ||
143 | break; | ||
144 | case ENOPROTOOPT: | ||
145 | /* FIXME: optlen unknown, should at least log this */ | ||
146 | break; | ||
147 | default: | ||
148 | /* any others? man page does not list more... */ | ||
149 | break; | ||
191 | } | 150 | } |
192 | return; | 151 | #endif |
193 | #endif /* MSG_MORE */ | ||
194 | } | 152 | } |
195 | 153 | ||
196 | 154 | ||