-
Notifications
You must be signed in to change notification settings - Fork 2.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
Add a Transport::TCP class for tcp-based communication. #2689
Add a Transport::TCP class for tcp-based communication. #2689
Conversation
…tion oriented transports need disconnection support
… at least they compile
…es to control the size of those buffers
…receive implementation starting point
…but unit tests pass so TCP is maybe ok
@@ -48,7 +48,7 @@ enum class Type | |||
kUndefined, | |||
kUdp, | |||
kBle, | |||
// More constants to be added later, such as TCP |
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.
Should we maintain this comment or is TCP the last constant we plan to add?
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 am not aware of anything else we could add as chip spec. I believe a comment would be 'add more stuff here if needed' however that seems redundant as any enum would be 'add more if needed'.
src/transport/TCP.h
Outdated
// Called when a connection has been completed | ||
static void OnConnectionComplete(Inet::TCPEndPoint * endPoint, INET_ERROR err); | ||
|
||
// Called when a connection has been closed |
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.
Might be worth documenting how this differs from OnPeerClosed
...
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 updated this mentioning this originates from TCPEndPoint.
That class has two callbacks. I am actually unsure why - peerclosed is on read 0 (peer closed) however I am unclear how this one is called (OnClose and OnAbort actually null-out the callbacks with the comment 'application called close explicitly')
src/transport/tests/TestTCP.cpp
Outdated
err = tcp.SendMessage(header, Transport::PeerAddress::TCP(addr), buffer); | ||
if (err == System::MapErrorPOSIX(EADDRNOTAVAIL)) | ||
{ | ||
// TODO: the underlying system does not support IPV6. This early return should |
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 file an issue tracking this.
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 is a copy and paste from TestUDP ... at that time we had errors in CI, which should already have tracking issues.
I will update the wording.
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.
Added an issue after all, since I believe the original issue for CI is already addressed in a curent PR which likely will not touch TestTCP/UDP.
Opened issue is #2698 and is now referenced in the TODO.
@bzbarsky-apple I have addressed all comments. Will double check on freeing paths ... I wish we had some 'smart pointer' like constructs instead of raw pointers. Tracking buffer usage manually seems error prone to me. Maybe topic for the future. |
SecureSession does indeed Free the passed in buffer, so right now all our paths seem to behave correctly (after my updates to the test). |
src/transport/PeerAddress.h
Outdated
{ | ||
return (mTransportType == other.mTransportType) && (mIPAddress == other.mIPAddress) && (mPort == other.mPort); | ||
return (mTransportType == other.mTransportType) && (mIPAddress == other.mIPAddress) && (mPort == other.mPort) && | ||
((mInterface == INET_NULL_INTERFACEID) || (other.mInterface == INET_NULL_INTERFACEID) || |
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 think this field should be matched exactly.
We shouldn't understand equality of addresses to mean "could these addresses send to the same destination" and we couldn't answer that question in general.
It should just mean "these addresses are identical", including zone identifier.
Weaker matches can be separate functions, not equality.
mActiveConnectionsSize(bufferSize), mPendingPackets(packetBuffers), mPendingPacketsSize(packetsBuffersSize) | ||
{ | ||
PendingPacket emptyPending{ | ||
.peerAddress = PeerAddress::Uninitialized(), |
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 reason it compiles it's been a GNU extension for ages (and we've been compiling with GNU extensions).
…CP as it is more than just peer data but rather a complete state that can never be recovered on the server side
Yes, indeed. I filed #2707 |
VerifyOrExit(buffer->DataLength() >= messageSize, err = CHIP_ERROR_INTERNAL); | ||
|
||
err = ProcessSingleMessageFromBufferHead(peerAddress, buffer, messageSize); | ||
buffer->ConsumeHead(messageSize); |
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.
Hmm. It occurs to me: Should this call to ConsumeHead
still happen even if ProcessSingleMessageFromBufferHead
failed? We're about to push this buffer back to the endpoint, no? I would not think we want to consume data from it... Though maybe the idea is to push back only the data after the failed message? In that case that should be clearly documented.
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 thought to keep it because I alrady skipped over the size. If processsinglemessage fails on a buffer, there seems to be reasonable expectation that it will fail in the future as well. This also guarantees that we empty buffers in time.
I.e. I think this is correct and it would be more work to not consume on error.
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.
OK. That seems fine, but worth a comment explaining why we are doing what we are doing.
if (err != CHIP_NO_ERROR) | ||
{ | ||
ChipLogError(Inet, "Connection complete encountered an error: %s", ErrorStr(err)); | ||
endPoint->Free(); |
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.
Yes, I agree with making the endpoint count stuff better in a followup. For now, file an issue and add a TODO comment at the member declaration pointing to the issue?
mActiveConnectionsSize(bufferSize), mPendingPackets(packetBuffers), mPendingPacketsSize(packetsBuffersSize) | ||
{ | ||
PendingPacket emptyPending{ | ||
.peerAddress = PeerAddress::Uninitialized(), |
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 guess it's ok until someone complains that it doesn't compile for their hardware. ;)
uint16_t messageSize); | ||
|
||
// Callback handler for TCPEndPoint. TCP message receive handler. | ||
static void OnTcpReceive(Inet::TCPEndPoint * endPoint, System::PacketBuffer * buffer); |
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 should probably document ownership semantics too...
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.
Should be handled by TCPEndPoint. That documents it as:
* A data reception event handler must acknowledge data processed using
* the \c AckReceive method. The \c Free method on the data buffer must
* also be invoked unless the \c PutBackReceivedData is used instead
I think we should not try to duplicate docs lest they become out of sync.
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.
OK, sounds good! Could add a pointer to the TCPEndPoint documentation from here.
Created #2708 for better active count usage. |
Problem
CHIP requires the ability to communicate over TCP (for key negotiations, for faster data transfers when supported (e.g. OTA)).
Summary of Changes
Implements a TCP-based transport, with equivalent functionality as the current Transport::UDP.
fixes #2664