diff options
Diffstat (limited to 'src/transport/tcp_server_mst_legacy.c')
-rw-r--r-- | src/transport/tcp_server_mst_legacy.c | 329 |
1 files changed, 163 insertions, 166 deletions
diff --git a/src/transport/tcp_server_mst_legacy.c b/src/transport/tcp_server_mst_legacy.c index 868f64d7c..03c02ff75 100644 --- a/src/transport/tcp_server_mst_legacy.c +++ b/src/transport/tcp_server_mst_legacy.c | |||
@@ -11,12 +11,12 @@ | |||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Affero General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Affero General Public License | 15 | You should have received a copy of the GNU Affero General Public License |
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | 17 | ||
18 | SPDX-License-Identifier: AGPL3.0-or-later | 18 | SPDX-License-Identifier: AGPL3.0-or-later |
19 | */ | 19 | */ |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @file util/server_mst.c | 22 | * @file util/server_mst.c |
@@ -38,9 +38,7 @@ | |||
38 | /** | 38 | /** |
39 | * Handle to a message stream tokenizer. | 39 | * Handle to a message stream tokenizer. |
40 | */ | 40 | */ |
41 | struct GNUNET_SERVER_MessageStreamTokenizer | 41 | struct GNUNET_SERVER_MessageStreamTokenizer { |
42 | { | ||
43 | |||
44 | /** | 42 | /** |
45 | * Function to call on completed messages. | 43 | * Function to call on completed messages. |
46 | */ | 44 | */ |
@@ -70,7 +68,6 @@ struct GNUNET_SERVER_MessageStreamTokenizer | |||
70 | * Beginning of the buffer. Typed like this to force alignment. | 68 | * Beginning of the buffer. Typed like this to force alignment. |
71 | */ | 69 | */ |
72 | struct GNUNET_MessageHeader *hdr; | 70 | struct GNUNET_MessageHeader *hdr; |
73 | |||
74 | }; | 71 | }; |
75 | 72 | ||
76 | 73 | ||
@@ -83,13 +80,13 @@ struct GNUNET_SERVER_MessageStreamTokenizer | |||
83 | * @return handle to tokenizer | 80 | * @return handle to tokenizer |
84 | */ | 81 | */ |
85 | struct GNUNET_SERVER_MessageStreamTokenizer * | 82 | struct GNUNET_SERVER_MessageStreamTokenizer * |
86 | GNUNET_SERVER_mst_create (GNUNET_SERVER_MessageTokenizerCallback cb, | 83 | GNUNET_SERVER_mst_create(GNUNET_SERVER_MessageTokenizerCallback cb, |
87 | void *cb_cls) | 84 | void *cb_cls) |
88 | { | 85 | { |
89 | struct GNUNET_SERVER_MessageStreamTokenizer *ret; | 86 | struct GNUNET_SERVER_MessageStreamTokenizer *ret; |
90 | 87 | ||
91 | ret = GNUNET_new (struct GNUNET_SERVER_MessageStreamTokenizer); | 88 | ret = GNUNET_new(struct GNUNET_SERVER_MessageStreamTokenizer); |
92 | ret->hdr = GNUNET_malloc (GNUNET_MIN_MESSAGE_SIZE); | 89 | ret->hdr = GNUNET_malloc(GNUNET_MIN_MESSAGE_SIZE); |
93 | ret->curr_buf = GNUNET_MIN_MESSAGE_SIZE; | 90 | ret->curr_buf = GNUNET_MIN_MESSAGE_SIZE; |
94 | ret->cb = cb; | 91 | ret->cb = cb; |
95 | ret->cb_cls = cb_cls; | 92 | ret->cb_cls = cb_cls; |
@@ -113,10 +110,10 @@ GNUNET_SERVER_mst_create (GNUNET_SERVER_MessageTokenizerCallback cb, | |||
113 | * #GNUNET_SYSERR if the data stream is corrupt | 110 | * #GNUNET_SYSERR if the data stream is corrupt |
114 | */ | 111 | */ |
115 | int | 112 | int |
116 | GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst, | 113 | GNUNET_SERVER_mst_receive(struct GNUNET_SERVER_MessageStreamTokenizer *mst, |
117 | void *client_identity, | 114 | void *client_identity, |
118 | const char *buf, size_t size, | 115 | const char *buf, size_t size, |
119 | int purge, int one_shot) | 116 | int purge, int one_shot) |
120 | { | 117 | { |
121 | const struct GNUNET_MessageHeader *hdr; | 118 | const struct GNUNET_MessageHeader *hdr; |
122 | size_t delta; | 119 | size_t delta; |
@@ -126,170 +123,170 @@ GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst, | |||
126 | unsigned long offset; | 123 | unsigned long offset; |
127 | int ret; | 124 | int ret; |
128 | 125 | ||
129 | GNUNET_assert (mst->off <= mst->pos); | 126 | GNUNET_assert(mst->off <= mst->pos); |
130 | GNUNET_assert (mst->pos <= mst->curr_buf); | 127 | GNUNET_assert(mst->pos <= mst->curr_buf); |
131 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 128 | LOG(GNUNET_ERROR_TYPE_DEBUG, |
132 | "Server-mst receives %u bytes with %u bytes already in private buffer\n", | 129 | "Server-mst receives %u bytes with %u bytes already in private buffer\n", |
133 | (unsigned int) size, (unsigned int) (mst->pos - mst->off)); | 130 | (unsigned int)size, (unsigned int)(mst->pos - mst->off)); |
134 | ret = GNUNET_OK; | 131 | ret = GNUNET_OK; |
135 | ibuf = (char *) mst->hdr; | 132 | ibuf = (char *)mst->hdr; |
136 | while (mst->pos > 0) | 133 | while (mst->pos > 0) |
137 | { | ||
138 | do_align: | ||
139 | GNUNET_assert (mst->pos >= mst->off); | ||
140 | if ((mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) || | ||
141 | (0 != (mst->off % ALIGN_FACTOR))) | ||
142 | { | ||
143 | /* need to align or need more space */ | ||
144 | mst->pos -= mst->off; | ||
145 | memmove (ibuf, &ibuf[mst->off], mst->pos); | ||
146 | mst->off = 0; | ||
147 | } | ||
148 | if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader)) | ||
149 | { | ||
150 | delta = | ||
151 | GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) - | ||
152 | (mst->pos - mst->off), size); | ||
153 | GNUNET_memcpy (&ibuf[mst->pos], buf, delta); | ||
154 | mst->pos += delta; | ||
155 | buf += delta; | ||
156 | size -= delta; | ||
157 | } | ||
158 | if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader)) | ||
159 | { | ||
160 | if (purge) | ||
161 | { | ||
162 | mst->off = 0; | ||
163 | mst->pos = 0; | ||
164 | } | ||
165 | return GNUNET_OK; | ||
166 | } | ||
167 | hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off]; | ||
168 | want = ntohs (hdr->size); | ||
169 | if (want < sizeof (struct GNUNET_MessageHeader)) | ||
170 | { | ||
171 | GNUNET_break_op (0); | ||
172 | return GNUNET_SYSERR; | ||
173 | } | ||
174 | if ( (mst->curr_buf - mst->off < want) && | ||
175 | (mst->off > 0) ) | ||
176 | { | ||
177 | /* can get more space by moving */ | ||
178 | mst->pos -= mst->off; | ||
179 | memmove (ibuf, &ibuf[mst->off], mst->pos); | ||
180 | mst->off = 0; | ||
181 | } | ||
182 | if (mst->curr_buf < want) | ||
183 | { | ||
184 | /* need to get more space by growing buffer */ | ||
185 | GNUNET_assert (0 == mst->off); | ||
186 | mst->hdr = GNUNET_realloc (mst->hdr, want); | ||
187 | ibuf = (char *) mst->hdr; | ||
188 | mst->curr_buf = want; | ||
189 | } | ||
190 | hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off]; | ||
191 | if (mst->pos - mst->off < want) | ||
192 | { | ||
193 | delta = GNUNET_MIN (want - (mst->pos - mst->off), size); | ||
194 | GNUNET_assert (mst->pos + delta <= mst->curr_buf); | ||
195 | GNUNET_memcpy (&ibuf[mst->pos], buf, delta); | ||
196 | mst->pos += delta; | ||
197 | buf += delta; | ||
198 | size -= delta; | ||
199 | } | ||
200 | if (mst->pos - mst->off < want) | ||
201 | { | ||
202 | if (purge) | ||
203 | { | ||
204 | mst->off = 0; | ||
205 | mst->pos = 0; | ||
206 | } | ||
207 | return GNUNET_OK; | ||
208 | } | ||
209 | if (one_shot == GNUNET_SYSERR) | ||
210 | { | 134 | { |
211 | /* cannot call callback again, but return value saying that | 135 | do_align: |
212 | * we have another full message in the buffer */ | 136 | GNUNET_assert(mst->pos >= mst->off); |
213 | ret = GNUNET_NO; | 137 | if ((mst->curr_buf - mst->off < sizeof(struct GNUNET_MessageHeader)) || |
214 | goto copy; | 138 | (0 != (mst->off % ALIGN_FACTOR))) |
215 | } | 139 | { |
216 | if (one_shot == GNUNET_YES) | 140 | /* need to align or need more space */ |
217 | one_shot = GNUNET_SYSERR; | 141 | mst->pos -= mst->off; |
218 | mst->off += want; | 142 | memmove(ibuf, &ibuf[mst->off], mst->pos); |
219 | if (GNUNET_SYSERR == mst->cb (mst->cb_cls, client_identity, hdr)) | 143 | mst->off = 0; |
220 | return GNUNET_SYSERR; | 144 | } |
221 | if (mst->off == mst->pos) | 145 | if (mst->pos - mst->off < sizeof(struct GNUNET_MessageHeader)) |
222 | { | 146 | { |
223 | /* reset to beginning of buffer, it's free right now! */ | 147 | delta = |
224 | mst->off = 0; | 148 | GNUNET_MIN(sizeof(struct GNUNET_MessageHeader) - |
225 | mst->pos = 0; | 149 | (mst->pos - mst->off), size); |
226 | } | 150 | GNUNET_memcpy(&ibuf[mst->pos], buf, delta); |
227 | } | 151 | mst->pos += delta; |
228 | GNUNET_assert (0 == mst->pos); | 152 | buf += delta; |
229 | while (size > 0) | 153 | size -= delta; |
230 | { | 154 | } |
231 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 155 | if (mst->pos - mst->off < sizeof(struct GNUNET_MessageHeader)) |
232 | "Server-mst has %u bytes left in inbound buffer\n", | 156 | { |
233 | (unsigned int) size); | 157 | if (purge) |
234 | if (size < sizeof (struct GNUNET_MessageHeader)) | 158 | { |
235 | break; | 159 | mst->off = 0; |
236 | offset = (unsigned long) buf; | 160 | mst->pos = 0; |
237 | need_align = (0 != (offset % ALIGN_FACTOR)) ? GNUNET_YES : GNUNET_NO; | 161 | } |
238 | if (GNUNET_NO == need_align) | 162 | return GNUNET_OK; |
239 | { | 163 | } |
240 | /* can try to do zero-copy and process directly from original buffer */ | 164 | hdr = (const struct GNUNET_MessageHeader *)&ibuf[mst->off]; |
241 | hdr = (const struct GNUNET_MessageHeader *) buf; | 165 | want = ntohs(hdr->size); |
242 | want = ntohs (hdr->size); | 166 | if (want < sizeof(struct GNUNET_MessageHeader)) |
243 | if (want < sizeof (struct GNUNET_MessageHeader)) | 167 | { |
244 | { | 168 | GNUNET_break_op(0); |
245 | GNUNET_break_op (0); | 169 | return GNUNET_SYSERR; |
246 | mst->off = 0; | 170 | } |
247 | return GNUNET_SYSERR; | 171 | if ((mst->curr_buf - mst->off < want) && |
248 | } | 172 | (mst->off > 0)) |
249 | if (size < want) | 173 | { |
250 | break; /* or not: buffer incomplete, so copy to private buffer... */ | 174 | /* can get more space by moving */ |
175 | mst->pos -= mst->off; | ||
176 | memmove(ibuf, &ibuf[mst->off], mst->pos); | ||
177 | mst->off = 0; | ||
178 | } | ||
179 | if (mst->curr_buf < want) | ||
180 | { | ||
181 | /* need to get more space by growing buffer */ | ||
182 | GNUNET_assert(0 == mst->off); | ||
183 | mst->hdr = GNUNET_realloc(mst->hdr, want); | ||
184 | ibuf = (char *)mst->hdr; | ||
185 | mst->curr_buf = want; | ||
186 | } | ||
187 | hdr = (const struct GNUNET_MessageHeader *)&ibuf[mst->off]; | ||
188 | if (mst->pos - mst->off < want) | ||
189 | { | ||
190 | delta = GNUNET_MIN(want - (mst->pos - mst->off), size); | ||
191 | GNUNET_assert(mst->pos + delta <= mst->curr_buf); | ||
192 | GNUNET_memcpy(&ibuf[mst->pos], buf, delta); | ||
193 | mst->pos += delta; | ||
194 | buf += delta; | ||
195 | size -= delta; | ||
196 | } | ||
197 | if (mst->pos - mst->off < want) | ||
198 | { | ||
199 | if (purge) | ||
200 | { | ||
201 | mst->off = 0; | ||
202 | mst->pos = 0; | ||
203 | } | ||
204 | return GNUNET_OK; | ||
205 | } | ||
251 | if (one_shot == GNUNET_SYSERR) | 206 | if (one_shot == GNUNET_SYSERR) |
252 | { | 207 | { |
253 | /* cannot call callback again, but return value saying that | 208 | /* cannot call callback again, but return value saying that |
254 | * we have another full message in the buffer */ | 209 | * we have another full message in the buffer */ |
255 | ret = GNUNET_NO; | 210 | ret = GNUNET_NO; |
256 | goto copy; | 211 | goto copy; |
257 | } | 212 | } |
258 | if (one_shot == GNUNET_YES) | 213 | if (one_shot == GNUNET_YES) |
259 | one_shot = GNUNET_SYSERR; | 214 | one_shot = GNUNET_SYSERR; |
260 | if (GNUNET_SYSERR == mst->cb (mst->cb_cls, client_identity, hdr)) | 215 | mst->off += want; |
216 | if (GNUNET_SYSERR == mst->cb(mst->cb_cls, client_identity, hdr)) | ||
261 | return GNUNET_SYSERR; | 217 | return GNUNET_SYSERR; |
262 | buf += want; | 218 | if (mst->off == mst->pos) |
263 | size -= want; | 219 | { |
220 | /* reset to beginning of buffer, it's free right now! */ | ||
221 | mst->off = 0; | ||
222 | mst->pos = 0; | ||
223 | } | ||
264 | } | 224 | } |
265 | else | 225 | GNUNET_assert(0 == mst->pos); |
226 | while (size > 0) | ||
266 | { | 227 | { |
267 | /* need to copy to private buffer to align; | 228 | LOG(GNUNET_ERROR_TYPE_DEBUG, |
268 | * yes, we go a bit more spagetti than usual here */ | 229 | "Server-mst has %u bytes left in inbound buffer\n", |
269 | goto do_align; | 230 | (unsigned int)size); |
231 | if (size < sizeof(struct GNUNET_MessageHeader)) | ||
232 | break; | ||
233 | offset = (unsigned long)buf; | ||
234 | need_align = (0 != (offset % ALIGN_FACTOR)) ? GNUNET_YES : GNUNET_NO; | ||
235 | if (GNUNET_NO == need_align) | ||
236 | { | ||
237 | /* can try to do zero-copy and process directly from original buffer */ | ||
238 | hdr = (const struct GNUNET_MessageHeader *)buf; | ||
239 | want = ntohs(hdr->size); | ||
240 | if (want < sizeof(struct GNUNET_MessageHeader)) | ||
241 | { | ||
242 | GNUNET_break_op(0); | ||
243 | mst->off = 0; | ||
244 | return GNUNET_SYSERR; | ||
245 | } | ||
246 | if (size < want) | ||
247 | break; /* or not: buffer incomplete, so copy to private buffer... */ | ||
248 | if (one_shot == GNUNET_SYSERR) | ||
249 | { | ||
250 | /* cannot call callback again, but return value saying that | ||
251 | * we have another full message in the buffer */ | ||
252 | ret = GNUNET_NO; | ||
253 | goto copy; | ||
254 | } | ||
255 | if (one_shot == GNUNET_YES) | ||
256 | one_shot = GNUNET_SYSERR; | ||
257 | if (GNUNET_SYSERR == mst->cb(mst->cb_cls, client_identity, hdr)) | ||
258 | return GNUNET_SYSERR; | ||
259 | buf += want; | ||
260 | size -= want; | ||
261 | } | ||
262 | else | ||
263 | { | ||
264 | /* need to copy to private buffer to align; | ||
265 | * yes, we go a bit more spagetti than usual here */ | ||
266 | goto do_align; | ||
267 | } | ||
270 | } | 268 | } |
271 | } | ||
272 | copy: | 269 | copy: |
273 | if ((size > 0) && (!purge)) | 270 | if ((size > 0) && (!purge)) |
274 | { | ||
275 | if (size + mst->pos > mst->curr_buf) | ||
276 | { | 271 | { |
277 | mst->hdr = GNUNET_realloc (mst->hdr, size + mst->pos); | 272 | if (size + mst->pos > mst->curr_buf) |
278 | ibuf = (char *) mst->hdr; | 273 | { |
279 | mst->curr_buf = size + mst->pos; | 274 | mst->hdr = GNUNET_realloc(mst->hdr, size + mst->pos); |
275 | ibuf = (char *)mst->hdr; | ||
276 | mst->curr_buf = size + mst->pos; | ||
277 | } | ||
278 | GNUNET_assert(size + mst->pos <= mst->curr_buf); | ||
279 | GNUNET_memcpy(&ibuf[mst->pos], buf, size); | ||
280 | mst->pos += size; | ||
280 | } | 281 | } |
281 | GNUNET_assert (size + mst->pos <= mst->curr_buf); | ||
282 | GNUNET_memcpy (&ibuf[mst->pos], buf, size); | ||
283 | mst->pos += size; | ||
284 | } | ||
285 | if (purge) | 282 | if (purge) |
286 | { | 283 | { |
287 | mst->off = 0; | 284 | mst->off = 0; |
288 | mst->pos = 0; | 285 | mst->pos = 0; |
289 | } | 286 | } |
290 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 287 | LOG(GNUNET_ERROR_TYPE_DEBUG, |
291 | "Server-mst leaves %u bytes in private buffer\n", | 288 | "Server-mst leaves %u bytes in private buffer\n", |
292 | (unsigned int) (mst->pos - mst->off)); | 289 | (unsigned int)(mst->pos - mst->off)); |
293 | return ret; | 290 | return ret; |
294 | } | 291 | } |
295 | 292 | ||
@@ -300,10 +297,10 @@ copy: | |||
300 | * @param mst tokenizer to destroy | 297 | * @param mst tokenizer to destroy |
301 | */ | 298 | */ |
302 | void | 299 | void |
303 | GNUNET_SERVER_mst_destroy (struct GNUNET_SERVER_MessageStreamTokenizer *mst) | 300 | GNUNET_SERVER_mst_destroy(struct GNUNET_SERVER_MessageStreamTokenizer *mst) |
304 | { | 301 | { |
305 | GNUNET_free (mst->hdr); | 302 | GNUNET_free(mst->hdr); |
306 | GNUNET_free (mst); | 303 | GNUNET_free(mst); |
307 | } | 304 | } |
308 | 305 | ||
309 | 306 | ||