-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rtp header padding #1079
Rtp header padding #1079
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll review next week in depth but overall code doesn't respect existing code guidelines. Please run "make lint" and "make format" in worker/ folder. Also leave blank space after logs and use auto or auto* or const auto or const auto* where possible as in the whole code. In addition, comments must start with capital letter and end with a dot.
@@ -165,8 +165,9 @@ void Fuzzer::RTC::RtpPacket::Fuzz(const uint8_t* data, size_t len) | |||
packet->HasExtension(14); | |||
packet->GetExtension(14, extenLen); | |||
packet->ReadTransportWideCc01(wideSeqNumber); | |||
packet->UpdateTransportWideCc01(12345u); | |||
packet->SetExtensionLength(14, 2); | |||
//packet->UpdateTransportWideCc01(12345u); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are those tests commented? We cannot leave commented tests. Do they no longer work or what?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this two line can be replace by setExtensionValue(). should I just delete the 2 line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should test as much as possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should test as much as possible
Extremely agree. This is my first time writing C++, and I have been writing PHP before. So the more tests, the better
It's my first time to write pr of mediasoup. I will run make lint and make format. and I will check the format problem |
@buptlsp, since you've based the new And please write an explanatory comment at least on top of every condition (most of them are already present from original code). The code needs to be understood now and in the coming years, and having to go through all code lines to understand it makes it time consuming in the short and long term. |
in fact, I have reuse the code as much as I can. the method is differ to parseExtensions, I copy from two method mainly : ParseExtensions, setExtensions。 most structure and variable names cames from this two methods. but the method setExtensionValue is more complicated because the padding can be everywhere and the data may override. I can add some more comments to explain the code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll review this properly next week.
worker/src/RTC/RtpPacket.cpp
Outdated
|
||
if (len != currentLen) | ||
|
||
// If len == currentLen, just memcpy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments start with Uppercase and end with dot (.).
@buptlsp, few comments:
The previous point allows for In pseudo code, the new extensions would be rewritten as: // If len != currentLen, means we may need to shift extension or payload.
else
{
uint8_t* extensionStart = reinterpret_cast<uint8_t*>(this->headerExtension) + 4;
uint8_t* extensionEnd = extensionStart + GetHeaderExtensionLength();
uint8_t* ptr = extensionStart;
size_t extensionsTotalSize = 0;
while (ptr < extensionEnd)
{
const uint8_t tempExtensionId = (*ptr & 0xF0) >> 4;
const size_t tempExtensionLen = static_cast<size_t>(*ptr & 0x0F) + 1;
// tempExtensionId=15 in One-Byte extensions means "stop parsing here".
if (tempExtensionId == 15u)
{
break;
}
// Extension id 0. We already reached the end of the extension header.
// NOTE: Padding only exists at the end of the extension header for outgoing RTP packet.
if (tempExtensionId == 0u)
{
break:
}
// Valid extension id.
else
{
// This is the extension which length and value is being set.
if (tempExtensionId == id)
{
std::memmove(ptr, value.c_str(), len + 1);
ptr += len + 1;
extensionsTotalSize += len + 1;
}
else
{
ptr += tempExtensionLen + 1;
extensionsTotalSize += tempExtensionLen + 1;
}
// Store the One-Byte extension element.
// `-1` because we have 14 elements total 0..13 and `id` is in the range 1..14.
this->oneByteExtensions[tempExtensionId - 1] =
reinterpret_cast<OneByteExtension*>(ptr);
}
} This is much cleaner approach IMHO and reduces the number of |
It's an accidental padding in MID extension:
IMHO we should:
Do you agree @ibc? |
I don't think it‘s a good idea. Your method may be cleaner, but there are a lot of prerequisites. My method does not need to have prerequisites and assumptions like yours. One day, we may add other extensions, or we may introduce other padding, and at that time my method will still be valid. |
What prerequisites?
|
While @jmillan's proposal makes sense I would also like to know about those "prerequisites" and those potential problems if we add more extensions in the future. |
There are no prerequisites, but a single contract:
We already to that for every extension but for My proposal is that we set a default value of 0, with a length of 1 for MID. It will optionally be rewritten with a new value/length. In the future, we need to follow the same policy: always set a default value for new extensions. If that extension is optional, like MID, then use the smallest possible value. (value 0, length 1). |
Well, let's go along with your idea that the mid length is now 1 byte. The mid value can appear anywhere in the header. (It's the first header now, but you can't assume it's forever). Suppose the new mid value's length is 3. What do we need to do when updateMid()?
You've done a bunch of operations like setting the default value and setting it to the minimum, which just reduces the situation where you think the length will only increase and the payload will not move forward. and after all operation you have done, your code is not as clean as your think. now you have change the mid length to 3. but the Router has lots of consumers, this packet will update other mid after you have change it to length 3. not the new length is 1, what should you do now? My method is called setExtensionValue, and we may make an extension longer or shorter, and the payload may move forward or backward. Your method is entirely for setExtensions, not a method that can be used anywhere. |
No, my change was indeed for Then total extension length and padding needs to be recalculated, just as in your implementation. I can directly implement it when I get the time so we can simply compare it. |
I have already put my code online in my environment. the cpu, memory and bandwidth result I have give in the pr. So, I am not in a hurry to solve this problem. after all, I have already saved money for my company. I don't know your pseudo well. maybe when you complete the code ,we can compare and discuss later. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After re-reviewing I'm fine with the implementation.
I've added few change requests.
worker/src/RTC/RtpPacket.cpp
Outdated
uint8_t* extensionEnd = extensionStart + GetHeaderExtensionLength(); | ||
uint8_t* ptr = extensionStart; | ||
size_t extensionsTotalSize = static_cast<size_t>(len + 1); | ||
uint8_t* ptr1 = ptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, rename to lastExtension
, since it points exactly to the last extension that has been evaluated, while ptr
keeps moving forward among the 0s.
worker/src/RTC/RtpPacket.cpp
Outdated
*ptr1 = 0u; | ||
ptr1++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we add here a single memset
in order to fill with zeros at once?
worker/src/RTC/RtpPacket.cpp
Outdated
uint8_t* extensionEnd = extensionStart + GetHeaderExtensionLength(); | ||
uint8_t* ptr = extensionStart; | ||
size_t extensionsTotalSize = static_cast<size_t>(len + 2); | ||
uint8_t* ptr1 = ptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same naming changes please.
worker/src/RTC/RtpPacket.cpp
Outdated
*ptr1 = 0u; | ||
ptr1++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
single memset here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After re-reviewing I'm fine with the implementation.
I've added few change requests.
worker/src/RTC/RtpPacket.cpp
Outdated
// In One-Byte extensions value length 0 means 1. | ||
extension->len = len - 1; | ||
std::memmove(this->payload + shift, this->payload, this->payloadLength + this->payloadPadding); | ||
// Clear the shift place, if shift > currentLen, may create some strange extension. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Clear the shift place, if shift > currentLen, may create some strange extension. | |
// Fill padding with zeroes. |
|
||
// In One-Byte extensions value length 0 means 1. | ||
extension->len = len - 1; | ||
std::memmove(this->payload + shift, this->payload, this->payloadLength + this->payloadPadding); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is payloadPadding
needed here? it's only valid to point the padding for parsed packets, but has no relevance otherwise.
worker/src/RTC/RtpPacket.cpp
Outdated
{ | ||
// Means move has end. Fill the rest buffer to 0u. | ||
if (ptr >= extensionEnd) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In which case are we entering this condition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some cosmetic changes.
The PR is good to go for me. I'd like @ibc to review and approve it before merging.
worker/src/RTC/RtpPacket.cpp
Outdated
* This method only can set exists extension. if len of value changed, this method will | ||
* recaculate and fill padding. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* This method only can set exists extension. if len of value changed, this method will | |
* recaculate and fill padding. | |
* This method set the value for an existing extension. If the length of the current value changed, | |
* it will recalculate it and regenerate the header extension accordingly. |
worker/src/RTC/RtpPacket.cpp
Outdated
currentLen, | ||
value.c_str()); | ||
|
||
// If len == currentLen, just memcpy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// If len == currentLen, just memcpy. | |
// If len == currentLen, just copy the new value. |
worker/src/RTC/RtpPacket.cpp
Outdated
if (lastExtensionPtr < ptr) | ||
{ | ||
std::memmove(lastExtensionPtr, ptr, tempExtensionLen + 1); | ||
// the extension has move from ptr to lastExtensionPtr, store the One-Byte extension |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// the extension has move from ptr to lastExtensionPtr, store the One-Byte extension | |
// The extension has moved from ptr to lastExtensionPtr, store the One-Byte extension |
worker/src/RTC/RtpPacket.cpp
Outdated
} | ||
} | ||
|
||
// Means move has end. Fill the rest buffer to 0u. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Means move has end. Fill the rest buffer to 0u. | |
// Fill the rest buffer to 0u. |
worker/src/RTC/RtpPacket.cpp
Outdated
@@ -618,12 +705,82 @@ namespace RTC | |||
|
|||
auto* extension = it->second; | |||
auto currentLen = extension->len; | |||
// If len == currentLen, just memcpy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// If len == currentLen, just memcpy. | |
// If len == currentLen, just copy the new value. |
worker/src/RTC/RtpPacket.cpp
Outdated
uint8_t* ptr = extensionStart; | ||
size_t extensionsTotalSize = static_cast<size_t>(len + 2); | ||
uint8_t* lastExtensionPtr = ptr; | ||
// Clear current extension, valueLen + 2 byteheader. we will rewrite after move all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Clear current extension, valueLen + 2 byteheader. we will rewrite after move all | |
// Clear current extension, valueLen + 2 byteheader. We will rewrite after moving all |
worker/src/RTC/RtpPacket.cpp
Outdated
size_t extensionsTotalSize = static_cast<size_t>(len + 2); | ||
uint8_t* lastExtensionPtr = ptr; | ||
// Clear current extension, valueLen + 2 byteheader. we will rewrite after move all | ||
// extension in right place. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// extension in right place. | |
// extensions to the right place. |
worker/src/RTC/RtpPacket.cpp
Outdated
// Fill with 0's if new length is minor. | ||
if (len < currentLen) | ||
std::memset(extension->value + len, 0, currentLen - len); | ||
// Means move has end. Fill the rest buffer to 0u. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Means move has end. Fill the rest buffer to 0u. | |
// Fill the rest buffer to 0u. |
I'm on vacation so give some days before reviewing this. For now just some concerns:
|
@jmillan and me have had a long call today about this PR. We entirely understand the motivation and the goal, plus the code obviously works as expected. However we have decided to go another way and do it even better, so we are gonna close this PR. Please check this story in which I've documented what we are gonna do next: |
what I have done: