ShutdownLayer.cpp (2219B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/Assertions.h" 8 #include "ShutdownLayer.h" 9 #include "prerror.h" 10 #include "private/pprio.h" 11 #include "prmem.h" 12 #include <winsock2.h> 13 14 static PRDescIdentity sWinSockShutdownLayerIdentity; 15 static PRIOMethods sWinSockShutdownLayerMethods; 16 static PRIOMethods* sWinSockShutdownLayerMethodsPtr = nullptr; 17 18 namespace mozilla { 19 namespace net { 20 21 extern PRDescIdentity nsNamedPipeLayerIdentity; 22 23 } // namespace net 24 } // namespace mozilla 25 26 PRStatus WinSockClose(PRFileDesc* aFd) { 27 MOZ_RELEASE_ASSERT(aFd->identity == sWinSockShutdownLayerIdentity, 28 "Windows shutdown layer not on the top of the stack"); 29 30 PROsfd osfd = PR_FileDesc2NativeHandle(aFd); 31 if (osfd != -1) { 32 shutdown(osfd, SD_BOTH); 33 } 34 35 aFd->identity = PR_INVALID_IO_LAYER; 36 37 if (aFd->lower) { 38 return aFd->lower->methods->close(aFd->lower); 39 } else { 40 return PR_SUCCESS; 41 } 42 } 43 44 nsresult mozilla::net::AttachShutdownLayer(PRFileDesc* aFd) { 45 if (!sWinSockShutdownLayerMethodsPtr) { 46 sWinSockShutdownLayerIdentity = 47 PR_GetUniqueIdentity("windows shutdown call layer"); 48 sWinSockShutdownLayerMethods = *PR_GetDefaultIOMethods(); 49 sWinSockShutdownLayerMethods.close = WinSockClose; 50 sWinSockShutdownLayerMethodsPtr = &sWinSockShutdownLayerMethods; 51 } 52 53 if (mozilla::net::nsNamedPipeLayerIdentity && 54 PR_GetIdentitiesLayer(aFd, mozilla::net::nsNamedPipeLayerIdentity)) { 55 // Do not attach shutdown layer on named pipe layer, 56 // it is for PR_NSPR_IO_LAYER only. 57 return NS_OK; 58 } 59 60 PRFileDesc* layer; 61 PRStatus status; 62 63 layer = PR_CreateIOLayerStub(sWinSockShutdownLayerIdentity, 64 sWinSockShutdownLayerMethodsPtr); 65 if (!layer) { 66 return NS_OK; 67 } 68 69 status = PR_PushIOLayer(aFd, PR_NSPR_IO_LAYER, layer); 70 71 if (status == PR_FAILURE) { 72 PR_Free(layer); // PR_CreateIOLayerStub() uses PR_Malloc(). 73 return NS_ERROR_FAILURE; 74 } 75 return NS_OK; 76 }