summaryrefslogtreecommitdiff
path: root/src/transport/tcp_server_mst_legacy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/tcp_server_mst_legacy.c')
-rw-r--r--src/transport/tcp_server_mst_legacy.c329
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 */
41struct GNUNET_SERVER_MessageStreamTokenizer 41struct 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 */
85struct GNUNET_SERVER_MessageStreamTokenizer * 82struct GNUNET_SERVER_MessageStreamTokenizer *
86GNUNET_SERVER_mst_create (GNUNET_SERVER_MessageTokenizerCallback cb, 83GNUNET_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 */
115int 112int
116GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst, 113GNUNET_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 {
138do_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 135do_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 }
272copy: 269copy:
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 */
302void 299void
303GNUNET_SERVER_mst_destroy (struct GNUNET_SERVER_MessageStreamTokenizer *mst) 300GNUNET_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