diff --git a/src/inet/TCPEndPointImplLwIP.cpp b/src/inet/TCPEndPointImplLwIP.cpp index 763f2eb9613078..af543c2ce90c12 100644 --- a/src/inet/TCPEndPointImplLwIP.cpp +++ b/src/inet/TCPEndPointImplLwIP.cpp @@ -39,9 +39,6 @@ static_assert(LWIP_VERSION_MAJOR > 1, "CHIP requires LwIP 2.0 or later"); -// TODO: Update to use RunOnTCPIP. -static_assert(LWIP_TCPIP_CORE_LOCKING, "CHIP requires config LWIP_TCPIP_CORE_LOCKING enabled"); - namespace chip { namespace Inet { @@ -58,16 +55,13 @@ void nil_tcpip_callback(void * _aContext) {} err_t start_tcp_timers(void) { - return tcpip_callback(nil_tcpip_callback, NULL); + return tcpip_callback(nil_tcpip_callback, nullptr); } } // anonymous namespace CHIP_ERROR TCPEndPointImplLwIP::BindImpl(IPAddressType addrType, const IPAddress & addr, uint16_t port, bool reuseAddr) { - // Lock LwIP stack - LOCK_TCPIP_CORE(); - // Get the appropriate type of PCB. CHIP_ERROR res = GetPCB(addrType); @@ -77,32 +71,41 @@ CHIP_ERROR TCPEndPointImplLwIP::BindImpl(IPAddressType addrType, const IPAddress { if (reuseAddr) { - ip_set_option(mTCP, SOF_REUSEADDR); + RunOnTCPIP([this]() { ip_set_option(mTCP, SOF_REUSEADDR); }); } res = addr.ToLwIPAddr(addrType, ipAddr); } if (res == CHIP_NO_ERROR) { - res = chip::System::MapErrorLwIP(tcp_bind(mTCP, &ipAddr, port)); + res = chip::System::MapErrorLwIP(RunOnTCPIPRet([this, &ipAddr, port]() { return tcp_bind(mTCP, &ipAddr, port); })); } - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); return res; } CHIP_ERROR TCPEndPointImplLwIP::ListenImpl(uint16_t backlog) { - // Start listening for incoming connections. - mTCP = tcp_listen(mTCP); mLwIPEndPointType = LwIPEndPointType::TCP; - - tcp_arg(mTCP, this); - - tcp_accept(mTCP, LwIPHandleIncomingConnection); - - return CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + if (!mPreAllocatedConnectEP) + { + // Pre allocate a TCP EndPoint for TCP connection, it will be released under either of the two conditions: + // - The Listen EndPoint receives a connection and the connection will use this endpoint. The endpoint will be release when + // the connection is released. + // - The Listen Endpoint is closed. + err = GetEndPointManager().NewEndPoint(&mPreAllocatedConnectEP); + } + if (err == CHIP_NO_ERROR) + { + RunOnTCPIP([this]() { + // Start listening for incoming connections. + mTCP = tcp_listen(mTCP); + tcp_arg(mTCP, this); + tcp_accept(mTCP, LwIPHandleIncomingConnection); + }); + } + return err; } CHIP_ERROR TCPEndPointImplLwIP::ConnectImpl(const IPAddress & addr, uint16_t port, InterfaceId intfId) @@ -130,18 +133,16 @@ CHIP_ERROR TCPEndPointImplLwIP::ConnectImpl(const IPAddress & addr, uint16_t por return res; } - // Lock LwIP stack - LOCK_TCPIP_CORE(); - res = GetPCB(addrType); if (res == CHIP_NO_ERROR) { - tcp_arg(mTCP, this); - tcp_err(mTCP, LwIPHandleError); - ip_addr_t lwipAddr = addr.ToLwIPAddr(); - res = chip::System::MapErrorLwIP(tcp_connect(mTCP, &lwipAddr, port, LwIPHandleConnectComplete)); + res = chip::System::MapErrorLwIP(RunOnTCPIPRet([this, &lwipAddr, port]() { + tcp_arg(mTCP, this); + tcp_err(mTCP, LwIPHandleError); + return tcp_connect(mTCP, &lwipAddr, port, LwIPHandleConnectComplete); + })); // Ensure that TCP timers are started if (res == CHIP_NO_ERROR) @@ -160,8 +161,6 @@ CHIP_ERROR TCPEndPointImplLwIP::ConnectImpl(const IPAddress & addr, uint16_t por } } - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); return res; } @@ -169,42 +168,30 @@ CHIP_ERROR TCPEndPointImplLwIP::GetPeerInfo(IPAddress * retAddr, uint16_t * retP { VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE); - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - CHIP_ERROR res = CHIP_ERROR_CONNECTION_ABORTED; if (mTCP != nullptr) { - *retPort = mTCP->remote_port; - *retAddr = IPAddress(mTCP->remote_ip); - res = CHIP_NO_ERROR; + RunOnTCPIP([this, &retAddr, &retPort]() { + *retPort = mTCP->remote_port; + *retAddr = IPAddress(mTCP->remote_ip); + }); + return CHIP_NO_ERROR; } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - - return res; + return CHIP_ERROR_CONNECTION_ABORTED; } CHIP_ERROR TCPEndPointImplLwIP::GetLocalInfo(IPAddress * retAddr, uint16_t * retPort) const { VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE); - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - CHIP_ERROR res = CHIP_ERROR_CONNECTION_ABORTED; if (mTCP != nullptr) { - *retPort = mTCP->local_port; - *retAddr = IPAddress(mTCP->local_ip); - res = CHIP_NO_ERROR; + RunOnTCPIP([this, &retAddr, &retPort]() { + *retPort = mTCP->local_port; + *retAddr = IPAddress(mTCP->local_ip); + }); + return CHIP_NO_ERROR; } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - - return res; + return CHIP_ERROR_CONNECTION_ABORTED; } CHIP_ERROR TCPEndPointImplLwIP::GetInterfaceId(InterfaceId * retInterface) @@ -234,21 +221,12 @@ CHIP_ERROR TCPEndPointImplLwIP::SendQueuedImpl(bool queueWasEmpty) CHIP_ERROR TCPEndPointImplLwIP::EnableNoDelay() { VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE); - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - CHIP_ERROR res = CHIP_ERROR_CONNECTION_ABORTED; if (mTCP != nullptr) { - tcp_nagle_disable(mTCP); - res = CHIP_NO_ERROR; + RunOnTCPIP([this]() { tcp_nagle_disable(mTCP); }); + return CHIP_NO_ERROR; } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - - return res; + return CHIP_ERROR_CONNECTION_ABORTED; } CHIP_ERROR TCPEndPointImplLwIP::EnableKeepAlive(uint16_t interval, uint16_t timeoutCount) @@ -257,33 +235,27 @@ CHIP_ERROR TCPEndPointImplLwIP::EnableKeepAlive(uint16_t interval, uint16_t time CHIP_ERROR res = CHIP_ERROR_NOT_IMPLEMENTED; #if LWIP_TCP_KEEPALIVE - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - if (mTCP != NULL) + if (mTCP != nullptr) { - // Set the idle interval - mTCP->keep_idle = (uint32_t) interval * 1000; + RunOnTCPIP([this, interval, timeoutCount]() { + // Set the idle interval + mTCP->keep_idle = (uint32_t) interval * 1000; - // Set the probe retransmission interval. - mTCP->keep_intvl = (uint32_t) interval * 1000; + // Set the probe retransmission interval. + mTCP->keep_intvl = (uint32_t) interval * 1000; - // Set the probe timeout count - mTCP->keep_cnt = timeoutCount; + // Set the probe timeout count + mTCP->keep_cnt = timeoutCount; - // Enable keepalives for the connection. - ip_set_option(mTCP, SOF_KEEPALIVE); + // Enable keepalives for the connection. + ip_set_option(mTCP, SOF_KEEPALIVE); + }); res = CHIP_NO_ERROR; } else { res = CHIP_ERROR_CONNECTION_ABORTED; } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - #endif // LWIP_TCP_KEEPALIVE return res; @@ -295,24 +267,16 @@ CHIP_ERROR TCPEndPointImplLwIP::DisableKeepAlive() CHIP_ERROR res = CHIP_ERROR_NOT_IMPLEMENTED; #if LWIP_TCP_KEEPALIVE - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - if (mTCP != NULL) + if (mTCP != nullptr) { // Disable keepalives on the connection. - ip_reset_option(mTCP, SOF_KEEPALIVE); + RunOnTCPIP([this]() { ip_reset_option(mTCP, SOF_KEEPALIVE); }); res = CHIP_NO_ERROR; } else { res = CHIP_ERROR_CONNECTION_ABORTED; } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - #endif // LWIP_TCP_KEEPALIVE return res; @@ -326,17 +290,14 @@ CHIP_ERROR TCPEndPointImplLwIP::SetUserTimeoutImpl(uint32_t userTimeoutMillis) CHIP_ERROR TCPEndPointImplLwIP::DriveSendingImpl() { CHIP_ERROR err = CHIP_NO_ERROR; - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - // If the connection hasn't been aborted ... - if (mTCP != NULL) + if (mTCP != nullptr) { err_t lwipErr; // Determine the current send window size. This is the maximum amount we can write to the connection. - uint16_t sendWindowSize = tcp_sndbuf(mTCP); + uint16_t sendWindowSize; + RunOnTCPIP([this, &sendWindowSize]() { sendWindowSize = tcp_sndbuf(mTCP); }); // If there's data to be sent and the send window is open... bool canSend = (RemainingToSend() > 0 && sendWindowSize > 0); @@ -368,7 +329,9 @@ CHIP_ERROR TCPEndPointImplLwIP::DriveSendingImpl() // backing. Using TCP_WRITE_FLAG_COPY would eliminate this requirement, but overall // requires many more memory allocations which may be problematic when very // memory-constrained or when using pool-based allocations. - lwipErr = tcp_write(mTCP, sendData, sendLen, (canSend) ? TCP_WRITE_FLAG_MORE : 0); + lwipErr = RunOnTCPIPRet([this, sendData, sendLen, canSend]() { + return tcp_write(mTCP, sendData, sendLen, (canSend) ? TCP_WRITE_FLAG_MORE : 0); + }); if (lwipErr != ERR_OK) { err = chip::System::MapErrorLwIP(lwipErr); @@ -400,7 +363,7 @@ CHIP_ERROR TCPEndPointImplLwIP::DriveSendingImpl() if (err == CHIP_NO_ERROR) { - lwipErr = tcp_output(mTCP); + lwipErr = RunOnTCPIPRet([this]() { return tcp_output(mTCP); }); if (lwipErr != ERR_OK) err = chip::System::MapErrorLwIP(lwipErr); @@ -412,19 +375,16 @@ CHIP_ERROR TCPEndPointImplLwIP::DriveSendingImpl() // If in the SendShutdown state and the unsent queue is now empty, shutdown the PCB for sending. if (mState == State::kSendShutdown && (RemainingToSend() == 0)) { - lwipErr = tcp_shutdown(mTCP, 0, 1); + lwipErr = RunOnTCPIPRet([this]() { return tcp_shutdown(mTCP, 0, 1); }); if (lwipErr != ERR_OK) err = chip::System::MapErrorLwIP(lwipErr); } } } - else + { err = CHIP_ERROR_CONNECTION_ABORTED; - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - + } return err; } @@ -432,18 +392,15 @@ void TCPEndPointImplLwIP::HandleConnectCompleteImpl() {} void TCPEndPointImplLwIP::DoCloseImpl(CHIP_ERROR err, State oldState) { - // Lock LwIP stack - LOCK_TCPIP_CORE(); - // If the LwIP PCB hasn't been closed yet... - if (mTCP != NULL) + if (mTCP != nullptr) { // If the endpoint was a connection endpoint (vs. a listening endpoint)... if (oldState != State::kListening) { // Prevent further callbacks for incoming data. This has the effect of instructing // LwIP to discard any further data received from the peer. - tcp_recv(mTCP, NULL); + RunOnTCPIP([this]() { tcp_recv(mTCP, NULL); }); // If entering the Closed state... if (mState == State::kClosed) @@ -460,24 +417,23 @@ void TCPEndPointImplLwIP::DoCloseImpl(CHIP_ERROR err, State oldState) // when LwIP will no longer make callbacks to its user. Thus we must block further // callbacks to prevent them from happening after the endpoint has been freed. // - tcp_err(mTCP, NULL); + RunOnTCPIP([this]() { tcp_err(mTCP, nullptr); }); // If the endpoint is being closed without error, THEN call tcp_close() to close the underlying // TCP connection gracefully, preserving any in-transit send data. if (err == CHIP_NO_ERROR) { - tcp_close(mTCP); + RunOnTCPIP([this]() { tcp_close(mTCP); }); } - // OTHERWISE, call tcp_abort() to abort the TCP connection, discarding any in-transit data. else { - tcp_abort(mTCP); + RunOnTCPIP([this]() { tcp_abort(mTCP); }); } // Discard the reference to the PCB to ensure there is no further interaction with it // after this point. - mTCP = NULL; + mTCP = nullptr; mLwIPEndPointType = LwIPEndPointType::Unknown; } } @@ -485,18 +441,21 @@ void TCPEndPointImplLwIP::DoCloseImpl(CHIP_ERROR err, State oldState) // OTHERWISE the endpoint was being used for listening, so simply close it. else { - tcp_close(mTCP); + RunOnTCPIP([this]() { tcp_close(mTCP); }); // Discard the reference to the PCB to ensure there is no further interaction with it // after this point. - mTCP = NULL; + mTCP = nullptr; mLwIPEndPointType = LwIPEndPointType::Unknown; } } - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - + if (mPreAllocatedConnectEP) + { + // If the Listen EndPoint has a pre-allocated connect EndPoint, release it for the Retain() in the constructor + mPreAllocatedConnectEP->Free(); + mPreAllocatedConnectEP = nullptr; + } if (mState == State::kClosed) { mUnackedLength = 0; @@ -506,22 +465,14 @@ void TCPEndPointImplLwIP::DoCloseImpl(CHIP_ERROR err, State oldState) CHIP_ERROR TCPEndPointImplLwIP::AckReceive(size_t len) { VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE); - CHIP_ERROR res = CHIP_NO_ERROR; - VerifyOrReturnError(CanCastTo(len), CHIP_ERROR_INVALID_ARGUMENT); - // Lock LwIP stack - LOCK_TCPIP_CORE(); - if (mTCP != nullptr) - tcp_recved(mTCP, static_cast(len)); - else - res = CHIP_ERROR_CONNECTION_ABORTED; - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - - return res; + { + RunOnTCPIP([this, len]() { tcp_recved(mTCP, static_cast(len)); }); + return CHIP_NO_ERROR; + } + return CHIP_ERROR_CONNECTION_ABORTED; } #if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT @@ -542,14 +493,10 @@ uint16_t TCPEndPointImplLwIP::RemainingToSend() { return 0; } - else - { - // We can never have reported more unacked data than there is pending - // in the send queue! This would indicate a critical accounting bug. - VerifyOrDie(mUnackedLength <= mSendQueue->TotalLength()); - - return static_cast(mSendQueue->TotalLength() - mUnackedLength); - } + // We can never have reported more unacked data than there is pending + // in the send queue! This would indicate a critical accounting bug. + VerifyOrDie(mUnackedLength <= mSendQueue->TotalLength()); + return static_cast(mSendQueue->TotalLength() - mUnackedLength); } TCPEndPointImplLwIP::BufferOffset TCPEndPointImplLwIP::FindStartOfUnsent() @@ -596,17 +543,17 @@ TCPEndPointImplLwIP::BufferOffset TCPEndPointImplLwIP::FindStartOfUnsent() CHIP_ERROR TCPEndPointImplLwIP::GetPCB(IPAddressType addrType) { // IMMPORTANT: This method MUST be called with the LwIP stack LOCKED! - if (mTCP == NULL) + if (mTCP == nullptr) { switch (addrType) { case IPAddressType::kIPv6: - mTCP = tcp_new_ip_type(IPADDR_TYPE_V6); + RunOnTCPIP([this]() { mTCP = tcp_new_ip_type(IPADDR_TYPE_V6); }); break; #if INET_CONFIG_ENABLE_IPV4 case IPAddressType::kIPv4: - mTCP = tcp_new_ip_type(IPADDR_TYPE_V4); + RunOnTCPIP([this]() { mTCP = tcp_new_ip_type(IPADDR_TYPE_V4); }); break; #endif // INET_CONFIG_ENABLE_IPV4 @@ -614,14 +561,11 @@ CHIP_ERROR TCPEndPointImplLwIP::GetPCB(IPAddressType addrType) return INET_ERROR_WRONG_ADDRESS_TYPE; } - if (mTCP == NULL) + if (mTCP == nullptr) { return CHIP_ERROR_NO_MEMORY; } - else - { - mLwIPEndPointType = LwIPEndPointType::TCP; - } + mLwIPEndPointType = LwIPEndPointType::TCP; } else { @@ -659,7 +603,7 @@ void TCPEndPointImplLwIP::HandleDataSent(uint16_t lenSent) DoClose(CHIP_ERROR_UNEXPECTED_EVENT, false); return; } - else if (mSendQueue.IsNull()) + if (mSendQueue.IsNull()) { ChipLogError(Inet, "Got ACK for %d bytes but data backing gone", (int) lenSent); DoClose(CHIP_ERROR_UNEXPECTED_EVENT, false); @@ -694,16 +638,20 @@ void TCPEndPointImplLwIP::HandleDataSent(uint16_t lenSent) MarkActive(); // If requested, call the app's OnDataSent callback. - if (OnDataSent != NULL) + if (OnDataSent != nullptr) + { OnDataSent(this, lenSent); - + } // If unsent data exists, attempt to send it now... if (RemainingToSend() > 0) + { DriveSending(); - + } // If in the closing state and the send queue is now empty, attempt to transition to closed. if ((mState == State::kClosing) && (RemainingToSend() == 0)) + { DoClose(CHIP_NO_ERROR, false); + } } } @@ -739,14 +687,19 @@ void TCPEndPointImplLwIP::HandleDataReceived(System::PacketBufferHandle && buf) // the app to decide whether to keep the send side of the connection open after // the peer has closed. If no OnPeerClose is provided, we assume that the app // wants to close both directions and automatically enter the Closing state. - if (mState == State::kConnected && OnPeerClose != NULL) + if (mState == State::kConnected && OnPeerClose != nullptr) + { mState = State::kReceiveShutdown; + } else + { mState = State::kClosing; - + } // Call the app's OnPeerClose. if (OnPeerClose != NULL) + { OnPeerClose(this); + } } // Drive the received data into the app. @@ -763,45 +716,57 @@ void TCPEndPointImplLwIP::HandleIncomingConnection(TCPEndPoint * conEP) if (mState == State::kListening) { // If there's no callback available, fail with an error. - if (OnConnectionReceived == NULL) + if (OnConnectionReceived == nullptr) + { err = CHIP_ERROR_NO_CONNECTION_HANDLER; - + } // Extract the peer's address information. if (err == CHIP_NO_ERROR) + { err = conEP->GetPeerInfo(&peerAddr, &peerPort); - + } // If successful, call the app's callback function. if (err == CHIP_NO_ERROR) + { OnConnectionReceived(this, conEP, peerAddr, peerPort); - + } // Otherwise clean up and call the app's error callback. - else if (OnAcceptError != NULL) + else if (OnAcceptError != nullptr) + { OnAcceptError(this, err); + } } else + { err = CHIP_ERROR_INCORRECT_STATE; - + } // If something failed above, abort and free the connection end point. if (err != CHIP_NO_ERROR) + { conEP->Free(); + } } void TCPEndPointImplLwIP::HandleError(CHIP_ERROR err) { if (mState == State::kListening) { - if (OnAcceptError != NULL) + if (OnAcceptError != nullptr) + { OnAcceptError(this, err); + } } else + { DoClose(err, false); + } } err_t TCPEndPointImplLwIP::LwIPHandleConnectComplete(void * arg, struct tcp_pcb * tpcb, err_t lwipErr) { err_t res = ERR_OK; - if (arg != NULL) + if (arg != nullptr) { TCPEndPointImplLwIP * ep = static_cast(arg); @@ -825,11 +790,13 @@ err_t TCPEndPointImplLwIP::LwIPHandleConnectComplete(void * arg, struct tcp_pcb } } else + { res = ERR_ABRT; - + } if (res != ERR_OK) + { tcp_abort(tpcb); - + } return res; } @@ -837,16 +804,17 @@ err_t TCPEndPointImplLwIP::LwIPHandleIncomingConnection(void * arg, struct tcp_p { CHIP_ERROR err = chip::System::MapErrorLwIP(lwipErr); - if (arg != NULL) + if (arg != nullptr) { TCPEndPointImplLwIP * listenEP = static_cast(arg); - TCPEndPointImplLwIP * conEP = NULL; + TCPEndPointImplLwIP * conEP = nullptr; System::Layer & lSystemLayer = listenEP->GetSystemLayer(); // Tell LwIP we've accepted the connection so it can decrement the listen PCB's pending_accepts counter. tcp_accepted(listenEP->mTCP); - // If we did in fact receive a connection, rather than an error, attempt to allocate an end point object. + // If we did in fact receive a connection, rather than an error, use the pre-allocated end point object for the incoming + // connection. // // NOTE: Although most of the LwIP callbacks defer the real work to happen on the endpoint's thread // (by posting events to the thread's event queue) we can't do that here because as soon as this @@ -855,9 +823,13 @@ err_t TCPEndPointImplLwIP::LwIPHandleIncomingConnection(void * arg, struct tcp_p // if (err == CHIP_NO_ERROR) { - TCPEndPoint * connectEndPoint = nullptr; - err = listenEP->GetEndPointManager().NewEndPoint(&connectEndPoint); - conEP = static_cast(connectEndPoint); + conEP = static_cast(listenEP->mPreAllocatedConnectEP); + if (conEP == nullptr) + { + // The listen endpoint received a new incoming connection before it had a chance to pre-allocate a new connection + // endpoint. + err = CHIP_ERROR_BUSY; + } } // Ensure that TCP timers have been started @@ -888,8 +860,18 @@ err_t TCPEndPointImplLwIP::LwIPHandleIncomingConnection(void * arg, struct tcp_p // Post a callback to the HandleConnectionReceived() function, passing it the new end point. listenEP->Retain(); conEP->Retain(); + // Hand over the implied ref from constructing mPreAllocatedConnectEP to + // ongoing connection. + listenEP->mPreAllocatedConnectEP = nullptr; + err = lSystemLayer.ScheduleLambda([listenEP, conEP] { listenEP->HandleIncomingConnection(conEP); + // Pre-allocate another endpoint for next connection if current connection is established + CHIP_ERROR error = listenEP->GetEndPointManager().NewEndPoint(&listenEP->mPreAllocatedConnectEP); + if (error != CHIP_NO_ERROR) + { + listenEP->HandleError(error); + } conEP->Release(); listenEP->Release(); }); @@ -899,7 +881,6 @@ err_t TCPEndPointImplLwIP::LwIPHandleIncomingConnection(void * arg, struct tcp_p listenEP->Release(); err = CHIP_ERROR_CONNECTION_ABORTED; conEP->Release(); // for the Retain() above - conEP->Release(); // for the implied Retain() on construction } } @@ -918,24 +899,23 @@ err_t TCPEndPointImplLwIP::LwIPHandleIncomingConnection(void * arg, struct tcp_p } } else + { err = CHIP_ERROR_CONNECTION_ABORTED; + } - if (err != CHIP_NO_ERROR && tpcb != NULL) + if (err != CHIP_NO_ERROR && tpcb != nullptr) { tcp_abort(tpcb); return ERR_ABRT; } - else - { - return ERR_OK; - } + return ERR_OK; } err_t TCPEndPointImplLwIP::LwIPHandleDataReceived(void * arg, struct tcp_pcb * tpcb, struct pbuf * p, err_t _err) { err_t res = ERR_OK; - if (arg != NULL) + if (arg != nullptr) { TCPEndPointImplLwIP * ep = static_cast(arg); @@ -952,7 +932,9 @@ err_t TCPEndPointImplLwIP::LwIPHandleDataReceived(void * arg, struct tcp_pcb * t } } else + { res = ERR_ABRT; + } if (res != ERR_OK) { @@ -970,7 +952,7 @@ err_t TCPEndPointImplLwIP::LwIPHandleDataSent(void * arg, struct tcp_pcb * tpcb, { err_t res = ERR_OK; - if (arg != NULL) + if (arg != nullptr) { TCPEndPointImplLwIP * ep = static_cast(arg); @@ -987,27 +969,31 @@ err_t TCPEndPointImplLwIP::LwIPHandleDataSent(void * arg, struct tcp_pcb * tpcb, } } else + { res = ERR_ABRT; + } if (res != ERR_OK) + { tcp_abort(tpcb); + } return res; } void TCPEndPointImplLwIP::LwIPHandleError(void * arg, err_t lwipErr) { - if (arg != NULL) + if (arg != nullptr) { - TCPEndPointImplLwIP * ep = static_cast(arg); - System::LayerFreeRTOS & lSystemLayer = static_cast(ep->GetSystemLayer()); + TCPEndPointImplLwIP * ep = static_cast(arg); + System::Layer & lSystemLayer = ep->GetSystemLayer(); // At this point LwIP has already freed the PCB. Since the thread that owns the TCPEndPoint may // try to use the PCB before it receives the TCPError event posted below, we set the PCB to NULL // as a means to signal the other thread that the connection has been aborted. The implication // of this is that the mTCP field is shared state between the two threads and thus must only be // accessed with the LwIP lock held. - ep->mTCP = NULL; + ep->mTCP = nullptr; ep->mLwIPEndPointType = LwIPEndPointType::Unknown; // Post callback to HandleError. @@ -1017,7 +1003,9 @@ void TCPEndPointImplLwIP::LwIPHandleError(void * arg, err_t lwipErr) ep->Release(); }); if (err != CHIP_NO_ERROR) + { ep->Release(); + } } } diff --git a/src/inet/TCPEndPointImplLwIP.h b/src/inet/TCPEndPointImplLwIP.h index 86a151f591d303..7054add653fe0c 100644 --- a/src/inet/TCPEndPointImplLwIP.h +++ b/src/inet/TCPEndPointImplLwIP.h @@ -41,7 +41,7 @@ class TCPEndPointImplLwIP : public TCPEndPoint, public EndPointStateLwIP { public: TCPEndPointImplLwIP(EndPointManager & endPointManager) : - TCPEndPoint(endPointManager), mUnackedLength(0), mTCP(nullptr) + TCPEndPoint(endPointManager), mUnackedLength(0), mTCP(nullptr), mPreAllocatedConnectEP(nullptr) {} // TCPEndPoint overrides. @@ -82,6 +82,9 @@ class TCPEndPointImplLwIP : public TCPEndPoint, public EndPointStateLwIP uint16_t mUnackedLength; // Amount sent but awaiting ACK. Used as a form of reference count // to hang-on to backing packet buffers until they are no longer needed. tcp_pcb * mTCP; // LwIP Transmission control protocol (TCP) control block. + // For TCP Listen endpoint, we will pre-allocate a connection endpoint to assign the incoming connection to it. + // when there is a new TCP connection established. + TCPEndPoint * mPreAllocatedConnectEP; uint16_t RemainingToSend(); BufferOffset FindStartOfUnsent();