Fixed close for socket to properly release the socket context structure and the handle.
authorlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 8 Oct 2012 21:39:35 +0000 (21:39 +0000)
committerlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 8 Oct 2012 21:39:35 +0000 (21:39 +0000)
Signed-off-by: lpleahy
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13802 6f19259b-4bc3-4df7-8a09-765794883524

StdLib/BsdSocketLib/close.c
StdLib/EfiSocketLib/DxeSupport.c
StdLib/EfiSocketLib/Socket.c
StdLib/EfiSocketLib/Socket.h
StdLib/EfiSocketLib/UseEfiSocketLib.c
StdLib/Include/Protocol/EfiSocket.h
StdLib/UseSocketDxe/UseSocketDxe.c

index f3f7e98..01eb48e 100644 (file)
@@ -31,7 +31,6 @@ BslSocketCloseWork (
   IN int * pErrno\r
   )\r
 {\r
-  EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;\r
   EFI_STATUS Status;\r
 \r
   //\r
@@ -50,21 +49,9 @@ BslSocketCloseWork (
   }\r
   if ( !EFI_ERROR ( Status )) {\r
     //\r
-    //  Locate the socket protocol\r
+    //  Release the socket resources\r
     //\r
-    Status = gBS->LocateProtocol ( &gEfiSocketServiceBindingProtocolGuid,\r
-                                   NULL,\r
-                                   (VOID **) &pServiceBinding );\r
-    if ( !EFI_ERROR ( Status )) {\r
-      //\r
-      //  Release the handle\r
-      //\r
-      Status = pServiceBinding->DestroyChild ( pServiceBinding,\r
-                                               pSocketProtocol->SocketHandle );\r
-    }\r
-    if ( EFI_ERROR ( Status )) {\r
-      *pErrno = EIO;\r
-    }\r
+    *pErrno = EslServiceFreeProtocol ( pSocketProtocol );\r
   }\r
   else {\r
     DEBUG (( DEBUG_ERROR,\r
index 284fa9c..808b710 100644 (file)
@@ -91,11 +91,8 @@ EslDxeDestroyChild (
   )\r
 {\r
   ESL_LAYER * pLayer;\r
-  ESL_SOCKET * pSocket;\r
-  ESL_SOCKET * pSocketPrevious;\r
   EFI_SOCKET_PROTOCOL * pSocketProtocol;\r
   EFI_STATUS Status;\r
-  EFI_TPL TplPrevious;\r
 \r
   DBG_ENTER ( );\r
 \r
@@ -112,101 +109,10 @@ EslDxeDestroyChild (
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                   );\r
   if ( !EFI_ERROR ( Status )) {\r
-    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
-\r
-    //\r
-    //  Synchronize with the socket layer\r
-    //\r
-    RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-    //\r
-    //  Walk the socket list\r
-    //\r
-    pSocketPrevious = pLayer->pSocketList;\r
-    if ( NULL != pSocketPrevious ) {\r
-      if ( pSocket == pSocketPrevious ) {\r
-        //\r
-        //  Remove the socket from the head of the list\r
-        //\r
-        pLayer->pSocketList = pSocket->pNext;\r
-      }\r
-      else {\r
-        //\r
-        //  Find the socket in the middle of the list\r
-        //\r
-        while (( NULL != pSocketPrevious )\r
-          && ( pSocket != pSocketPrevious->pNext )) {\r
-          //\r
-          //  Set the next socket\r
-          //\r
-          pSocketPrevious = pSocketPrevious->pNext;\r
-        }\r
-        if ( NULL != pSocketPrevious ) {\r
-          //\r
-          //  Remove the socket from the middle of the list\r
-          //\r
-          pSocketPrevious = pSocket->pNext;\r
-        }\r
-      }\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
-                "ERROR - Socket list is empty!\r\n" ));\r
-    }\r
-\r
-    //\r
-    //  Release the socket layer synchronization\r
-    //\r
-    RESTORE_TPL ( TplPrevious );\r
-\r
     //\r
-    //  Determine if the socket was found\r
+    //  Free the socket resources\r
     //\r
-    if ( NULL != pSocketPrevious ) {\r
-      pSocket->pNext = NULL;\r
-\r
-      //\r
-      //  Remove the socket protocol\r
-      //\r
-      Status = gBS->UninstallMultipleProtocolInterfaces (\r
-                ChildHandle,\r
-                &gEfiSocketProtocolGuid,\r
-                &pSocket->SocketProtocol,\r
-                NULL );\r
-      if ( !EFI_ERROR ( Status )) {\r
-        DEBUG (( DEBUG_POOL | DEBUG_INFO,\r
-                    "Removed:   gEfiSocketProtocolGuid from 0x%08x\r\n",\r
-                    ChildHandle ));\r
-\r
-        //\r
-        //  Free the socket structure\r
-        //\r
-        Status = gBS->FreePool ( pSocket );\r
-        if ( !EFI_ERROR ( Status )) {\r
-          DEBUG (( DEBUG_POOL,\r
-                    "0x%08x: Free pSocket, %d bytes\r\n",\r
-                    pSocket,\r
-                    sizeof ( *pSocket )));\r
-        }\r
-        else {\r
-          DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
-                    "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",\r
-                    pSocket,\r
-                    Status ));\r
-        }\r
-      }\r
-      else {\r
-        DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,\r
-                    "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",\r
-                    ChildHandle,\r
-                    Status ));\r
-      }\r
-    }\r
-    else {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r
-                "ERROR - The socket was not in the socket list!\r\n" ));\r
-      Status = EFI_NOT_FOUND;\r
-    }\r
+    Status = EslSocketFree ( pSocketProtocol, NULL );\r
   }\r
   else {\r
     DEBUG (( DEBUG_ERROR,\r
index e718e9b..52e5f29 100644 (file)
@@ -1945,6 +1945,168 @@ EslSocketCopyFragmentedBuffer (
 }\r
 \r
 \r
+/**\r
+  Free the socket.\r
+\r
+  This routine frees the socket structure and handle resources.\r
+\r
+  The ::close routine calls EslServiceFreeProtocol which then calls\r
+  this routine to free the socket context structure and close the\r
+  handle.\r
+\r
+  @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
+  \r
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS   The socket resources were returned successfully.\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketFree (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  EFI_HANDLE ChildHandle;\r
+  int errno;\r
+  ESL_LAYER * pLayer;\r
+  ESL_SOCKET * pSocket;\r
+  ESL_SOCKET * pSocketPrevious;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume failure\r
+  //\r
+  errno = EIO;\r
+  pSocket = NULL;\r
+  Status = EFI_INVALID_PARAMETER;\r
+\r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pLayer = &mEslLayer;\r
+  if ( NULL != pSocketProtocol ) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+    //\r
+    //  Synchronize with the socket layer\r
+    //\r
+    RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+    //\r
+    //  Walk the socket list\r
+    //\r
+    pSocketPrevious = pLayer->pSocketList;\r
+    if ( NULL != pSocketPrevious ) {\r
+      if ( pSocket == pSocketPrevious ) {\r
+        //\r
+        //  Remove the socket from the head of the list\r
+        //\r
+        pLayer->pSocketList = pSocket->pNext;\r
+      }\r
+      else {\r
+        //\r
+        //  Find the socket in the middle of the list\r
+        //\r
+        while (( NULL != pSocketPrevious )\r
+          && ( pSocket != pSocketPrevious->pNext )) {\r
+          //\r
+          //  Set the next socket\r
+          //\r
+          pSocketPrevious = pSocketPrevious->pNext;\r
+        }\r
+        if ( NULL != pSocketPrevious ) {\r
+          //\r
+          //  Remove the socket from the middle of the list\r
+          //\r
+          pSocketPrevious = pSocket->pNext;\r
+        }\r
+      }\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
+                "ERROR - Socket list is empty!\r\n" ));\r
+    }\r
+\r
+    //\r
+    //  Release the socket layer synchronization\r
+    //\r
+    RESTORE_TPL ( TplPrevious );\r
+\r
+    //\r
+    //  Determine if the socket was found\r
+    //\r
+    if ( NULL != pSocketPrevious ) {\r
+      pSocket->pNext = NULL;\r
+\r
+      //\r
+      //  Remove the socket protocol\r
+      //\r
+      ChildHandle = pSocket->SocketProtocol.SocketHandle;\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                ChildHandle,\r
+                &gEfiSocketProtocolGuid,\r
+                &pSocket->SocketProtocol,\r
+                NULL );\r
+      if ( !EFI_ERROR ( Status )) {\r
+        DEBUG (( DEBUG_POOL | DEBUG_INFO,\r
+                    "Removed:   gEfiSocketProtocolGuid from 0x%08x\r\n",\r
+                    ChildHandle ));\r
+\r
+        //\r
+        //  Free the socket structure\r
+        //\r
+        Status = gBS->FreePool ( pSocket );\r
+        if ( !EFI_ERROR ( Status )) {\r
+          DEBUG (( DEBUG_POOL,\r
+                    "0x%08x: Free pSocket, %d bytes\r\n",\r
+                    pSocket,\r
+                    sizeof ( *pSocket )));\r
+          errno = 0;\r
+        }\r
+        else {\r
+          DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
+                    "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",\r
+                    pSocket,\r
+                    Status ));\r
+        }\r
+      }\r
+      else {\r
+        DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,\r
+                    "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",\r
+                    ChildHandle,\r
+                    Status ));\r
+      }\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r
+                "ERROR - The socket was not in the socket list!\r\n" ));\r
+      Status = EFI_NOT_FOUND;\r
+    }\r
+  }\r
+  else {\r
+    DEBUG (( DEBUG_ERROR,\r
+              "ERROR - Invalid parameter pSocketProtocol is NULL\r\n" ));\r
+  }\r
+\r
+  //\r
+  //  Return the errno value if possible\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    *pErrno = errno;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
 /**\r
   Get the local address.\r
 \r
index f2fbdb5..43a7084 100644 (file)
@@ -1187,6 +1187,28 @@ EslSocketCopyFragmentedBuffer (
   OUT size_t * pDataLength\r
   );\r
 \r
+/**\r
+  Free the socket.\r
+\r
+  This routine frees the socket structure and handle resources.\r
+\r
+  The ::close routine calls EslServiceFreeProtocol which then calls\r
+  this routine to free the socket context structure and close the\r
+  handle.\r
+\r
+  @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
+  \r
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS   The socket resources were returned successfully.\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketFree (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN int * pErrno\r
+  );\r
+\r
 /**\r
   Free the ESL_IO_MGMT event and structure\r
 \r
index e44a720..060598a 100644 (file)
@@ -68,6 +68,40 @@ CONST EFI_GUID mEslUdp6ServiceGuid __attribute__((weak)) = {
 };\r
 \r
 \r
+/**\r
+  Free the socket resources\r
+\r
+  This releases the socket resources allocated by calling\r
+  EslServiceGetProtocol.\r
+\r
+  This routine is called from the ::close routine in BsdSocketLib\r
+  to release the socket resources.\r
+\r
+  @param [in] pSocketProtocol   Address of an ::EFI_SOCKET_PROTOCOL\r
+                                structure\r
+\r
+  @return       Value for ::errno, zero (0) indicates success.\r
+\r
+ **/\r
+int\r
+EslServiceFreeProtocol (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol\r
+  )\r
+{\r
+  int RetVal;\r
+\r
+  //\r
+  //  Release the socket resources\r
+  //\r
+  EslSocketFree ( pSocketProtocol, &RetVal );\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return RetVal;\r
+}\r
+\r
+\r
 /**\r
   Connect to the EFI socket library\r
 \r
index 2664f01..022a6a5 100644 (file)
@@ -612,6 +612,26 @@ AcceptNB (
   socklen_t * address_len\r
   );\r
 \r
+/**\r
+  Free the socket resources\r
+\r
+  This releases the socket resources allocated by calling\r
+  EslServiceGetProtocol.\r
+\r
+  This routine is called from the ::close routine in BsdSocketLib\r
+  to release the socket resources.\r
+\r
+  @param [in] pSocketProtocol   Address of an ::EFI_SOCKET_PROTOCOL\r
+                                structure\r
+\r
+  @return       Value for ::errno, zero (0) indicates success.\r
+\r
+ **/\r
+int\r
+EslServiceFreeProtocol (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol\r
+  );\r
+\r
 /**\r
   Connect to the EFI socket library\r
 \r
index 6074143..423419c 100644 (file)
 #include <Protocol/ServiceBinding.h>\r
 \r
 \r
+/**\r
+  Free the socket resources\r
+\r
+  This releases the socket resources allocated by calling\r
+  EslServiceGetProtocol.\r
+\r
+  This routine is called from the ::close routine in BsdSocketLib\r
+  to release the socket resources.\r
+\r
+  @param [in] pSocketProtocol   Address of an ::EFI_SOCKET_PROTOCOL\r
+                                structure\r
+\r
+  @return       Value for ::errno, zero (0) indicates success.\r
+\r
+ **/\r
+int\r
+EslServiceFreeProtocol (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol\r
+  )\r
+{\r
+  EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;\r
+  int RetVal;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  //  Assume success\r
+  //\r
+  RetVal = 0;\r
+\r
+  //\r
+  //  Locate the socket protocol\r
+  //\r
+  Status = gBS->LocateProtocol ( &gEfiSocketServiceBindingProtocolGuid,\r
+                                 NULL,\r
+                                 (VOID **) &pServiceBinding );\r
+  if ( !EFI_ERROR ( Status )) {\r
+    //\r
+    //  Release the handle\r
+    //\r
+    Status = pServiceBinding->DestroyChild ( pServiceBinding,\r
+                                             pSocketProtocol->SocketHandle );\r
+  }\r
+  if ( EFI_ERROR ( Status )) {\r
+    RetVal = EIO;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  return RetVal;\r
+}\r
+\r
+\r
 /**\r
   Connect to the EFI socket library\r
 \r