diff options
author | iphydf <iphydf@users.noreply.github.com> | 2018-01-21 22:38:08 +0000 |
---|---|---|
committer | iphydf <iphydf@users.noreply.github.com> | 2018-02-01 23:35:44 +0000 |
commit | 83779a21eaf19bbf6aa5d61d8f59681a306e4f65 (patch) | |
tree | b713524d8ce29ca05500fb95f315de94a4d4ae75 /toxav/rtp.c | |
parent | d9413d557696e3aecde9d019e1738e99882d4579 (diff) |
Manually serialise RTPHeader struct instead of memcpy.
Diffstat (limited to 'toxav/rtp.c')
-rw-r--r-- | toxav/rtp.c | 183 |
1 files changed, 124 insertions, 59 deletions
diff --git a/toxav/rtp.c b/toxav/rtp.c index 01d4258a..650fbaf0 100644 --- a/toxav/rtp.c +++ b/toxav/rtp.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright © 2016-2017 The TokTok team. | 2 | * Copyright © 2016-2018 The TokTok team. |
3 | * Copyright © 2013-2015 Tox project. | 3 | * Copyright © 2013-2015 Tox project. |
4 | * | 4 | * |
5 | * This file is part of Tox, the free peer to peer instant messenger. | 5 | * This file is part of Tox, the free peer to peer instant messenger. |
@@ -34,6 +34,67 @@ | |||
34 | #include <stdlib.h> | 34 | #include <stdlib.h> |
35 | 35 | ||
36 | 36 | ||
37 | size_t rtp_header_pack(uint8_t *const rdata, const struct RTPHeader *header) | ||
38 | { | ||
39 | uint8_t *p = rdata; | ||
40 | *p++ = (header->protocol_version & 3) << 6 | ||
41 | | (header->pe & 1) << 5 | ||
42 | | (header->xe & 1) << 4 | ||
43 | | (header->cc & 0xf); | ||
44 | *p++ = (header->ma & 1) << 7 | ||
45 | | (header->pt & 0x7f); | ||
46 | |||
47 | p += net_pack_u16(p, header->sequnum); | ||
48 | p += net_pack_u32(p, header->timestamp); | ||
49 | p += net_pack_u32(p, header->ssrc); | ||
50 | p += net_pack_u64(p, header->flags); | ||
51 | p += net_pack_u32(p, header->offset_full); | ||
52 | p += net_pack_u32(p, header->data_length_full); | ||
53 | p += net_pack_u32(p, header->received_length_full); | ||
54 | |||
55 | for (size_t i = 0; i < sizeof header->csrc / sizeof header->csrc[0]; i++) { | ||
56 | p += net_pack_u32(p, header->csrc[i]); | ||
57 | } | ||
58 | |||
59 | p += net_pack_u16(p, header->offset_lower); | ||
60 | p += net_pack_u16(p, header->data_length_lower); | ||
61 | assert(p == rdata + RTP_HEADER_SIZE); | ||
62 | return p - rdata; | ||
63 | } | ||
64 | |||
65 | |||
66 | size_t rtp_header_unpack(const uint8_t *data, struct RTPHeader *header) | ||
67 | { | ||
68 | const uint8_t *p = data; | ||
69 | header->protocol_version = (*p >> 6) & 3; | ||
70 | header->pe = (*p >> 5) & 1; | ||
71 | header->xe = (*p >> 4) & 1; | ||
72 | header->cc = *p & 0xf; | ||
73 | ++p; | ||
74 | |||
75 | header->ma = (*p >> 7) & 1; | ||
76 | header->pt = *p & 0x7f; | ||
77 | ++p; | ||
78 | |||
79 | p += net_unpack_u16(p, &header->sequnum); | ||
80 | p += net_unpack_u32(p, &header->timestamp); | ||
81 | p += net_unpack_u32(p, &header->ssrc); | ||
82 | p += net_unpack_u64(p, &header->flags); | ||
83 | p += net_unpack_u32(p, &header->offset_full); | ||
84 | p += net_unpack_u32(p, &header->data_length_full); | ||
85 | p += net_unpack_u32(p, &header->received_length_full); | ||
86 | |||
87 | for (size_t i = 0; i < sizeof header->csrc / sizeof header->csrc[0]; i++) { | ||
88 | p += net_unpack_u32(p, &header->csrc[i]); | ||
89 | } | ||
90 | |||
91 | p += net_unpack_u16(p, &header->offset_lower); | ||
92 | p += net_unpack_u16(p, &header->data_length_lower); | ||
93 | assert(p == data + RTP_HEADER_SIZE); | ||
94 | return p - data; | ||
95 | } | ||
96 | |||
97 | |||
37 | int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object); | 98 | int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object); |
38 | 99 | ||
39 | 100 | ||
@@ -116,36 +177,37 @@ int rtp_send_data(RTPSession *session, const uint8_t *data, uint16_t length, Log | |||
116 | return -1; | 177 | return -1; |
117 | } | 178 | } |
118 | 179 | ||
119 | VLA(uint8_t, rdata, length + sizeof(struct RTPHeader) + 1); | 180 | VLA(uint8_t, rdata, length + RTP_HEADER_SIZE + 1); |
120 | memset(rdata, 0, SIZEOF_VLA(rdata)); | 181 | memset(rdata, 0, SIZEOF_VLA(rdata)); |
121 | 182 | ||
122 | rdata[0] = session->payload_type; | 183 | rdata[0] = session->payload_type; |
123 | 184 | ||
124 | struct RTPHeader *header = (struct RTPHeader *)(rdata + 1); | 185 | struct RTPHeader header = {0}; |
125 | 186 | ||
126 | header->protocol_version = 2; | 187 | header.protocol_version = 2; |
127 | header->pe = 0; | 188 | header.pe = 0; |
128 | header->xe = 0; | 189 | header.xe = 0; |
129 | header->cc = 0; | 190 | header.cc = 0; |
130 | 191 | ||
131 | header->ma = 0; | 192 | header.ma = 0; |
132 | header->pt = session->payload_type % 128; | 193 | header.pt = session->payload_type % 128; |
133 | 194 | ||
134 | header->sequnum = net_htons(session->sequnum); | 195 | header.sequnum = session->sequnum; |
135 | header->timestamp = net_htonl(current_time_monotonic()); | 196 | header.timestamp = current_time_monotonic(); |
136 | header->ssrc = net_htonl(session->ssrc); | 197 | header.ssrc = session->ssrc; |
137 | 198 | ||
138 | header->offset_lower = 0; | 199 | header.offset_lower = 0; |
139 | header->data_length_lower = net_htons(length); | 200 | header.data_length_lower = length; |
140 | 201 | ||
141 | if (MAX_CRYPTO_DATA_SIZE > length + sizeof(struct RTPHeader) + 1) { | 202 | if (MAX_CRYPTO_DATA_SIZE > length + RTP_HEADER_SIZE + 1) { |
142 | 203 | ||
143 | /** | 204 | /** |
144 | * The length is lesser than the maximum allowed length (including header) | 205 | * The length is lesser than the maximum allowed length (including header) |
145 | * Send the packet in single piece. | 206 | * Send the packet in single piece. |
146 | */ | 207 | */ |
147 | 208 | ||
148 | memcpy(rdata + 1 + sizeof(struct RTPHeader), data, length); | 209 | rtp_header_pack(rdata + 1, &header); |
210 | memcpy(rdata + 1 + RTP_HEADER_SIZE, data, length); | ||
149 | 211 | ||
150 | if (-1 == m_send_custom_lossy_packet(session->m, session->friend_number, rdata, SIZEOF_VLA(rdata))) { | 212 | if (-1 == m_send_custom_lossy_packet(session->m, session->friend_number, rdata, SIZEOF_VLA(rdata))) { |
151 | LOGGER_WARNING(session->m->log, "RTP send failed (len: %d)! std error: %s", SIZEOF_VLA(rdata), strerror(errno)); | 213 | LOGGER_WARNING(session->m->log, "RTP send failed (len: %d)! std error: %s", SIZEOF_VLA(rdata), strerror(errno)); |
@@ -158,31 +220,33 @@ int rtp_send_data(RTPSession *session, const uint8_t *data, uint16_t length, Log | |||
158 | */ | 220 | */ |
159 | 221 | ||
160 | uint16_t sent = 0; | 222 | uint16_t sent = 0; |
161 | uint16_t piece = MAX_CRYPTO_DATA_SIZE - (sizeof(struct RTPHeader) + 1); | 223 | uint16_t piece = MAX_CRYPTO_DATA_SIZE - (RTP_HEADER_SIZE + 1); |
162 | 224 | ||
163 | while ((length - sent) + sizeof(struct RTPHeader) + 1 > MAX_CRYPTO_DATA_SIZE) { | 225 | while ((length - sent) + RTP_HEADER_SIZE + 1 > MAX_CRYPTO_DATA_SIZE) { |
164 | memcpy(rdata + 1 + sizeof(struct RTPHeader), data + sent, piece); | 226 | rtp_header_pack(rdata + 1, &header); |
227 | memcpy(rdata + 1 + RTP_HEADER_SIZE, data + sent, piece); | ||
165 | 228 | ||
166 | if (-1 == m_send_custom_lossy_packet(session->m, session->friend_number, | 229 | if (-1 == m_send_custom_lossy_packet(session->m, session->friend_number, |
167 | rdata, piece + sizeof(struct RTPHeader) + 1)) { | 230 | rdata, piece + RTP_HEADER_SIZE + 1)) { |
168 | LOGGER_WARNING(session->m->log, "RTP send failed (len: %d)! std error: %s", | 231 | LOGGER_WARNING(session->m->log, "RTP send failed (len: %d)! std error: %s", |
169 | piece + sizeof(struct RTPHeader) + 1, strerror(errno)); | 232 | piece + RTP_HEADER_SIZE + 1, strerror(errno)); |
170 | } | 233 | } |
171 | 234 | ||
172 | sent += piece; | 235 | sent += piece; |
173 | header->offset_lower = net_htons(sent); | 236 | header.offset_lower = sent; |
174 | } | 237 | } |
175 | 238 | ||
176 | /* Send remaining */ | 239 | /* Send remaining */ |
177 | piece = length - sent; | 240 | piece = length - sent; |
178 | 241 | ||
179 | if (piece) { | 242 | if (piece) { |
180 | memcpy(rdata + 1 + sizeof(struct RTPHeader), data + sent, piece); | 243 | rtp_header_pack(rdata + 1, &header); |
244 | memcpy(rdata + 1 + RTP_HEADER_SIZE, data + sent, piece); | ||
181 | 245 | ||
182 | if (-1 == m_send_custom_lossy_packet(session->m, session->friend_number, rdata, | 246 | if (-1 == m_send_custom_lossy_packet(session->m, session->friend_number, rdata, |
183 | piece + sizeof(struct RTPHeader) + 1)) { | 247 | piece + RTP_HEADER_SIZE + 1)) { |
184 | LOGGER_WARNING(session->m->log, "RTP send failed (len: %d)! std error: %s", | 248 | LOGGER_WARNING(session->m->log, "RTP send failed (len: %d)! std error: %s", |
185 | piece + sizeof(struct RTPHeader) + 1, strerror(errno)); | 249 | piece + RTP_HEADER_SIZE + 1, strerror(errno)); |
186 | } | 250 | } |
187 | } | 251 | } |
188 | } | 252 | } |
@@ -194,10 +258,10 @@ int rtp_send_data(RTPSession *session, const uint8_t *data, uint16_t length, Log | |||
194 | 258 | ||
195 | static bool chloss(const RTPSession *session, const struct RTPHeader *header) | 259 | static bool chloss(const RTPSession *session, const struct RTPHeader *header) |
196 | { | 260 | { |
197 | if (net_ntohl(header->timestamp) < session->rtimestamp) { | 261 | if (header->timestamp < session->rtimestamp) { |
198 | uint16_t hosq, lost = 0; | 262 | uint16_t hosq, lost = 0; |
199 | 263 | ||
200 | hosq = net_ntohs(header->sequnum); | 264 | hosq = header->sequnum; |
201 | 265 | ||
202 | lost = (hosq > session->rsequnum) ? | 266 | lost = (hosq > session->rsequnum) ? |
203 | (session->rsequnum + 65535) - hosq : | 267 | (session->rsequnum + 65535) - hosq : |
@@ -218,21 +282,20 @@ static struct RTPMessage *new_message(size_t allocate_len, const uint8_t *data, | |||
218 | { | 282 | { |
219 | assert(allocate_len >= data_length); | 283 | assert(allocate_len >= data_length); |
220 | 284 | ||
221 | struct RTPMessage *msg = (struct RTPMessage *)calloc(sizeof(struct RTPMessage) + (allocate_len - sizeof( | 285 | struct RTPMessage *msg = (struct RTPMessage *)calloc(sizeof(struct RTPMessage) + |
222 | struct RTPHeader)), 1); | 286 | (allocate_len - RTP_HEADER_SIZE), 1); |
223 | |||
224 | msg->len = data_length - sizeof(struct RTPHeader); | ||
225 | memcpy(&msg->header, data, data_length); | ||
226 | 287 | ||
227 | msg->header.sequnum = net_ntohs(msg->header.sequnum); | 288 | if (msg == nullptr) { |
228 | msg->header.timestamp = net_ntohl(msg->header.timestamp); | 289 | return nullptr; |
229 | msg->header.ssrc = net_ntohl(msg->header.ssrc); | 290 | } |
230 | 291 | ||
231 | msg->header.offset_lower = net_ntohs(msg->header.offset_lower); | 292 | msg->len = data_length - RTP_HEADER_SIZE; |
232 | msg->header.data_length_lower = net_ntohs(msg->header.data_length_lower); | 293 | rtp_header_unpack(data, &msg->header); |
294 | memcpy(msg->data, data + RTP_HEADER_SIZE, allocate_len - RTP_HEADER_SIZE); | ||
233 | 295 | ||
234 | return msg; | 296 | return msg; |
235 | } | 297 | } |
298 | |||
236 | int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object) | 299 | int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object) |
237 | { | 300 | { |
238 | (void) m; | 301 | (void) m; |
@@ -243,38 +306,40 @@ int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, | |||
243 | data ++; | 306 | data ++; |
244 | length--; | 307 | length--; |
245 | 308 | ||
246 | if (!session || length < sizeof(struct RTPHeader)) { | 309 | if (!session || length < RTP_HEADER_SIZE) { |
247 | LOGGER_WARNING(m->log, "No session or invalid length of received buffer!"); | 310 | LOGGER_WARNING(m->log, "No session or invalid length of received buffer!"); |
248 | return -1; | 311 | return -1; |
249 | } | 312 | } |
250 | 313 | ||
251 | const struct RTPHeader *header = (const struct RTPHeader *) data; | 314 | struct RTPHeader header; |
315 | |||
316 | rtp_header_unpack(data, &header); | ||
252 | 317 | ||
253 | if (header->pt != session->payload_type % 128) { | 318 | if (header.pt != session->payload_type % 128) { |
254 | LOGGER_WARNING(m->log, "Invalid payload type with the session"); | 319 | LOGGER_WARNING(m->log, "Invalid payload type with the session"); |
255 | return -1; | 320 | return -1; |
256 | } | 321 | } |
257 | 322 | ||
258 | if (net_ntohs(header->offset_lower) >= net_ntohs(header->data_length_lower)) { | 323 | if (header.offset_lower >= header.data_length_lower) { |
259 | /* Never allow this case to happen */ | 324 | /* Never allow this case to happen */ |
260 | return -1; | 325 | return -1; |
261 | } | 326 | } |
262 | 327 | ||
263 | bwc_feed_avg(session->bwc, length); | 328 | bwc_feed_avg(session->bwc, length); |
264 | 329 | ||
265 | if (net_ntohs(header->data_length_lower) == length - sizeof(struct RTPHeader)) { | 330 | if (header.data_length_lower == length - RTP_HEADER_SIZE) { |
266 | /* The message is sent in single part */ | 331 | /* The message is sent in single part */ |
267 | 332 | ||
268 | /* Only allow messages which have arrived in order; | 333 | /* Only allow messages which have arrived in order; |
269 | * drop late messages | 334 | * drop late messages |
270 | */ | 335 | */ |
271 | if (chloss(session, header)) { | 336 | if (chloss(session, &header)) { |
272 | return 0; | 337 | return 0; |
273 | } | 338 | } |
274 | 339 | ||
275 | /* Message is not late; pick up the latest parameters */ | 340 | /* Message is not late; pick up the latest parameters */ |
276 | session->rsequnum = net_ntohs(header->sequnum); | 341 | session->rsequnum = header.sequnum; |
277 | session->rtimestamp = net_ntohl(header->timestamp); | 342 | session->rtimestamp = header.timestamp; |
278 | 343 | ||
279 | bwc_add_recv(session->bwc, length); | 344 | bwc_add_recv(session->bwc, length); |
280 | 345 | ||
@@ -311,23 +376,23 @@ int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, | |||
311 | * processing message | 376 | * processing message |
312 | */ | 377 | */ |
313 | 378 | ||
314 | if (session->mp->header.sequnum == net_ntohs(header->sequnum) && | 379 | if (session->mp->header.sequnum == header.sequnum && |
315 | session->mp->header.timestamp == net_ntohl(header->timestamp)) { | 380 | session->mp->header.timestamp == header.timestamp) { |
316 | /* First case */ | 381 | /* First case */ |
317 | 382 | ||
318 | /* Make sure we have enough allocated memory */ | 383 | /* Make sure we have enough allocated memory */ |
319 | if (session->mp->header.data_length_lower - session->mp->len < length - sizeof(struct RTPHeader) || | 384 | if (session->mp->header.data_length_lower - session->mp->len < length - RTP_HEADER_SIZE || |
320 | session->mp->header.data_length_lower <= net_ntohs(header->offset_lower)) { | 385 | session->mp->header.data_length_lower <= header.offset_lower) { |
321 | /* There happened to be some corruption on the stream; | 386 | /* There happened to be some corruption on the stream; |
322 | * continue wihtout this part | 387 | * continue wihtout this part |
323 | */ | 388 | */ |
324 | return 0; | 389 | return 0; |
325 | } | 390 | } |
326 | 391 | ||
327 | memcpy(session->mp->data + net_ntohs(header->offset_lower), data + sizeof(struct RTPHeader), | 392 | memcpy(session->mp->data + header.offset_lower, data + RTP_HEADER_SIZE, |
328 | length - sizeof(struct RTPHeader)); | 393 | length - RTP_HEADER_SIZE); |
329 | 394 | ||
330 | session->mp->len += length - sizeof(struct RTPHeader); | 395 | session->mp->len += length - RTP_HEADER_SIZE; |
331 | 396 | ||
332 | bwc_add_recv(session->bwc, length); | 397 | bwc_add_recv(session->bwc, length); |
333 | 398 | ||
@@ -346,7 +411,7 @@ int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, | |||
346 | } else { | 411 | } else { |
347 | /* Second case */ | 412 | /* Second case */ |
348 | 413 | ||
349 | if (session->mp->header.timestamp > net_ntohl(header->timestamp)) { | 414 | if (session->mp->header.timestamp > header.timestamp) { |
350 | /* The received message part is from the old message; | 415 | /* The received message part is from the old message; |
351 | * discard it. | 416 | * discard it. |
352 | */ | 417 | */ |
@@ -359,7 +424,7 @@ int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, | |||
359 | 424 | ||
360 | /* Must account sizes of rtp headers too */ | 425 | /* Must account sizes of rtp headers too */ |
361 | ((session->mp->header.data_length_lower - session->mp->len) / | 426 | ((session->mp->header.data_length_lower - session->mp->len) / |
362 | MAX_CRYPTO_DATA_SIZE) * sizeof(struct RTPHeader)); | 427 | MAX_CRYPTO_DATA_SIZE) * RTP_HEADER_SIZE); |
363 | 428 | ||
364 | /* Push the previous message for processing */ | 429 | /* Push the previous message for processing */ |
365 | if (session->mcb) { | 430 | if (session->mcb) { |
@@ -381,21 +446,21 @@ NEW_MULTIPARTED: | |||
381 | /* Only allow messages which have arrived in order; | 446 | /* Only allow messages which have arrived in order; |
382 | * drop late messages | 447 | * drop late messages |
383 | */ | 448 | */ |
384 | if (chloss(session, header)) { | 449 | if (chloss(session, &header)) { |
385 | return 0; | 450 | return 0; |
386 | } | 451 | } |
387 | 452 | ||
388 | /* Message is not late; pick up the latest parameters */ | 453 | /* Message is not late; pick up the latest parameters */ |
389 | session->rsequnum = net_ntohs(header->sequnum); | 454 | session->rsequnum = header.sequnum; |
390 | session->rtimestamp = net_ntohl(header->timestamp); | 455 | session->rtimestamp = header.timestamp; |
391 | 456 | ||
392 | bwc_add_recv(session->bwc, length); | 457 | bwc_add_recv(session->bwc, length); |
393 | 458 | ||
394 | /* Again, only store message if handler is present | 459 | /* Again, only store message if handler is present |
395 | */ | 460 | */ |
396 | if (session->mcb) { | 461 | if (session->mcb) { |
397 | session->mp = new_message(net_ntohs(header->data_length_lower) + sizeof(struct RTPHeader), data, length); | 462 | session->mp = new_message(header.data_length_lower + RTP_HEADER_SIZE, data, length); |
398 | memmove(session->mp->data + net_ntohs(header->offset_lower), session->mp->data, session->mp->len); | 463 | memmove(session->mp->data + header.offset_lower, session->mp->data, session->mp->len); |
399 | } | 464 | } |
400 | } | 465 | } |
401 | 466 | ||