RDKTV-28081 : [SocketPort] Close half-way open sockets
Reason for change:
1.[SocketPort] Gracefully shutdown connection
2.Ensure the socket is closed even if the other side is not reachable
3.Shutdown both, but listen for RDHUP as well
4. Just reuse the Close method
Test Procedure: verify using Jenkins build
Risks: HIGH
Change-Id: I89b3ca46bf0ebdeb5e106d0f013b579a1471f69d
Signed-off-by: Thamim Razith <tabbas651@cable.comcast.com>
(cherry picked from commit 8b70ada654ffbf74438fd349dad48f8f589fd075)
diff --git a/recipes-extended/wpe-framework/wpeframework/r4/PR_1268_Close_half_way_open_sockets.patch b/recipes-extended/wpe-framework/wpeframework/r4/PR_1268_Close_half_way_open_sockets.patch
new file mode 100644
index 0000000..0339d0c
--- /dev/null
+++ b/recipes-extended/wpe-framework/wpeframework/r4/PR_1268_Close_half_way_open_sockets.patch
@@ -0,0 +1,164 @@
+diff --git a/Source/core/SocketPort.cpp b/Source/core/SocketPort.cpp
+index 3ef900db..768cc1a8 100644
+--- a/Source/core/SocketPort.cpp
++++ b/Source/core/SocketPort.cpp
+@@ -274,6 +274,8 @@ namespace WPEFramework {
+ ::closesocket(socket);
+ #endif
+
++ TRACE_L3("Socket %u destroyed", static_cast<uint32_t>(socket));
++
+ socket = INVALID_SOCKET;
+ }
+
+@@ -282,7 +284,7 @@ namespace WPEFramework {
+ #ifdef __WINDOWS__
+ unsigned long l_Value = 1;
+ if (ioctlsocket(socket, FIONBIO, &l_Value) != 0) {
+- TRACE_L1("Error on port socket NON_BLOCKING call. Error %d", __ERRORRESULT__);
++ TRACE_L5("Error on port socket NON_BLOCKING call. Error %d", __ERRORRESULT__);
+ }
+ else {
+ return (true);
+@@ -398,6 +400,8 @@ namespace WPEFramework {
+ BufferAlignment(m_Socket);
+
+ m_State.store(SocketPort::LINK | SocketPort::OPEN | SocketPort::READ, Core::memory_order::memory_order_relaxed);
++
++ TRACE_L3("Socket %u constructed", m_Socket);
+ }
+ }
+
+@@ -409,6 +413,8 @@ namespace WPEFramework {
+ // the virtuals might be called, which are destructed at this point !!!!
+ ASSERT((m_Socket == INVALID_SOCKET) || (IsClosed()));
+
++ TRACE_L3("Socket %u constructed", static_cast<uint32_t>(m_Socket));
++
+ if (m_Socket != INVALID_SOCKET) {
+ DestroySocket(m_Socket);
+ }
+@@ -504,7 +510,7 @@ namespace WPEFramework {
+ }
+ else if (m_SocketType == LISTEN) {
+ if (::listen(m_Socket, MAX_LISTEN_QUEUE) == SOCKET_ERROR) {
+- TRACE_L5("Error on port socket LISTEN. Error %d", __ERRORRESULT__);
++ TRACE_L1("Error on port socket LISTEN. Error %d", __ERRORRESULT__);
+ }
+ else {
+ // Trigger state to Open
+@@ -525,14 +531,17 @@ namespace WPEFramework {
+ m_State.store(SocketPort::UPDATE | SocketPort::LINK | SocketPort::WRITE, Core::memory_order::memory_order_relaxed);
+ nStatus = Core::ERROR_INPROGRESS;
+ }
+- else if (l_Result == __ERROR_ISCONN__) {
+- nStatus = Core::ERROR_ALREADY_CONNECTED;
+- }
+- else if (l_Result == __ERROR_NETWORK_UNREACHABLE__) {
+- nStatus = Core::ERROR_UNREACHABLE_NETWORK;
+- }
+ else {
+- nStatus = Core::ERROR_ASYNC_FAILED;
++ if (l_Result == __ERROR_ISCONN__) {
++ nStatus = Core::ERROR_ALREADY_CONNECTED;
++ }
++ else if (l_Result == __ERROR_NETWORK_UNREACHABLE__) {
++ nStatus = Core::ERROR_UNREACHABLE_NETWORK;
++ }
++ else {
++ nStatus = Core::ERROR_ASYNC_FAILED;
++ }
++
+ TRACE_L1("Error on socket connect. Error %d", __ERRORRESULT__);
+ }
+ }
+@@ -580,6 +589,8 @@ namespace WPEFramework {
+
+ if ((m_State != 0) && ((m_State & SHUTDOWN) == 0)) {
+
++ TRACE_L3("Closing socket %u...", static_cast<uint32_t>(m_Socket));
++
+ if ((m_State & (LINK | OPEN)) != (LINK | OPEN)) {
+ // This is a connectionless link, do not expect a close from the otherside.
+ // No use to wait on anything !!, Signal a FORCED CLOSURE (EXCEPTION && SHUTDOWN)
+@@ -615,6 +626,8 @@ namespace WPEFramework {
+ ASSERT(closed == true);
+ }
+ }
++ } else {
++ TRACE_L3("Socket is already closed and destroyed");
+ }
+
+ m_syncAdmin.Unlock();
+@@ -655,7 +668,7 @@ namespace WPEFramework {
+ // Kernel doubles the buffer size, take that into account.
+ m_SocketReceiveBufferSize /= 2;
+ if (origSocketReceiveBufferSize != m_SocketReceiveBufferSize) {
+- TRACE_L2("Adjusted socket receive buffer size (%u->%u)", origSocketReceiveBufferSize, m_SocketReceiveBufferSize);
++ TRACE_L3("Adjusted socket receive buffer size (%u->%u)", origSocketReceiveBufferSize, m_SocketReceiveBufferSize);
+ }
+
+ if (m_ReceiveBufferSize == static_cast<uint16_t>(~0)) {
+@@ -677,7 +690,7 @@ namespace WPEFramework {
+ ::getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char*)&m_SocketSendBufferSize, &valueLength);
+ m_SocketSendBufferSize /= 2;
+ if (origSocketSendBufferSize != m_SocketSendBufferSize) {
+- TRACE_L2("Adjusted socket send buffer size (%u->%u)", origSocketSendBufferSize, m_SocketSendBufferSize);
++ TRACE_L3("Adjusted socket send buffer size (%u->%u)", origSocketSendBufferSize, m_SocketSendBufferSize);
+ }
+
+ if (m_SendBufferSize == static_cast<uint16_t>(~0)) {
+@@ -977,7 +990,7 @@ namespace WPEFramework {
+ #ifdef __WINDOWS__
+ result = FD_CLOSE;
+ #else
+- result = POLLHUP;
++ result = (POLLHUP | POLLRDHUP);
+ #endif
+ }
+ else if (m_State != 0) {
+@@ -1014,7 +1027,7 @@ namespace WPEFramework {
+ Write();
+ }
+ #ifdef __LINUX__
+- result |= ((m_State & SocketPort::LINK) != 0 ? POLLHUP : 0) | ((m_State & SocketPort::WRITE) != 0 ? POLLOUT : 0);
++ result |= ((m_State & SocketPort::LINK) != 0 ? (POLLHUP | POLLRDHUP) : 0) | ((m_State & SocketPort::WRITE) != 0 ? POLLOUT : 0);
+ #endif
+ }
+ }
+@@ -1053,9 +1066,17 @@ namespace WPEFramework {
+
+ #else
+ if ((flagsSet & POLLHUP) != 0) {
++ TRACE_L3("HUP event received on socket %u", static_cast<uint32_t>(m_Socket));
+ Closed();
+ }
+- else if (IsListening()) {
++ else if ((flagsSet & POLLRDHUP) != 0) {
++ TRACE_L3("RDHUP event received on socket %u", static_cast<uint32_t>(m_Socket));
++
++ // The other side wants to shut down the connection. Let's do the same then.
++ // Once the connection is shut down in both directions, a HUP event will arrive.
++ Close(0);
++ }
++ else if (IsListening()) {
+ if ((flagsSet & POLLIN) != 0) {
+ // This triggeres an Addition of clients
+ Accepted();
+@@ -1303,6 +1324,7 @@ namespace WPEFramework {
+
+ m_Socket = result;
+ m_State = (SocketPort::UPDATE | SocketPort::MONITOR | SocketPort::LINK | SocketPort::OPEN | SocketPort::READ | SocketPort::WRITESLOT);
++ TRACE_L3("Socket %u constructed", static_cast<uint32_t>(m_Socket));
+ }
+
+ return (newConnection);
+@@ -1327,7 +1349,7 @@ namespace WPEFramework {
+ NodeId remoteId;
+
+ if (::listen(m_Socket, MAX_LISTEN_QUEUE) == SOCKET_ERROR) {
+- TRACE_L5("Error on port socket LISTEN. Error %d", __ERRORRESULT__);
++ TRACE_L1("Error on port socket LISTEN. Error %d", __ERRORRESULT__);
+ }
+ else {
+ // Trigger state to Open
diff --git a/recipes-extended/wpe-framework/wpeframework_4.2.bb b/recipes-extended/wpe-framework/wpeframework_4.2.bb
index 8ad42f8..10f3088 100644
--- a/recipes-extended/wpe-framework/wpeframework_4.2.bb
+++ b/recipes-extended/wpe-framework/wpeframework_4.2.bb
@@ -39,6 +39,7 @@
file://r4/ONEM-31782_R4.patch \
file://r4/linking_messaging_library.patch \
file://r4/Enable_Thunder_Logging_R4.patch \
+ file://r4/PR_1268_Close_half_way_open_sockets.patch \
"
inherit systemd update-rc.d pythonnative