MockNetworkLayer.cpp (6413B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 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 "MockNetworkLayer.h" 8 #include "MockNetworkLayerController.h" 9 #include "nsSocketTransportService2.h" 10 #include "prmem.h" 11 #include "prio.h" 12 13 namespace mozilla::net { 14 15 static PRDescIdentity sMockNetworkLayerIdentity; 16 static PRIOMethods sMockNetworkLayeyMethods; 17 static PRIOMethods* sMockNetworkLayeyMethodsPtr = nullptr; 18 19 // Not used for now. 20 class MockNetworkSecret { 21 public: 22 MockNetworkSecret() = default; 23 }; 24 25 static PRStatus MockNetworkConnect(PRFileDesc* fd, const PRNetAddr* addr, 26 PRIntervalTime to) { 27 PRStatus status; 28 mozilla::net::NetAddr netAddr(addr); 29 MockNetworkSecret* secret = reinterpret_cast<MockNetworkSecret*>(fd->secret); 30 nsAutoCString addrPort; 31 netAddr.ToAddrPortString(addrPort); 32 SOCKET_LOG( 33 ("MockNetworkConnect %p connect to [%s]\n", secret, addrPort.get())); 34 mozilla::net::NetAddr redirected; 35 if (FindNetAddrOverride(netAddr, redirected)) { 36 redirected.ToAddrPortString(addrPort); 37 SOCKET_LOG( 38 ("MockNetworkConnect %p redirect to [%s]\n", secret, addrPort.get())); 39 PRNetAddr prAddr; 40 NetAddrToPRNetAddr(&redirected, &prAddr); 41 status = fd->lower->methods->connect(fd->lower, &prAddr, to); 42 } else { 43 status = fd->lower->methods->connect(fd->lower, addr, to); 44 } 45 46 return status; 47 } 48 49 static PRInt32 MockNetworkSend(PRFileDesc* fd, const void* buf, PRInt32 amount, 50 PRIntn flags, PRIntervalTime timeout) { 51 MOZ_RELEASE_ASSERT(fd->identity == sMockNetworkLayerIdentity); 52 53 MockNetworkSecret* secret = reinterpret_cast<MockNetworkSecret*>(fd->secret); 54 SOCKET_LOG(("MockNetworkSend %p\n", secret)); 55 56 PRInt32 rv = 57 (fd->lower->methods->send)(fd->lower, buf, amount, flags, timeout); 58 return rv; 59 } 60 61 static PRInt32 MockNetworkWrite(PRFileDesc* fd, const void* buf, 62 PRInt32 amount) { 63 return MockNetworkSend(fd, buf, amount, 0, PR_INTERVAL_NO_WAIT); 64 } 65 66 static PRInt32 MockNetworkRecv(PRFileDesc* fd, void* buf, PRInt32 amount, 67 PRIntn flags, PRIntervalTime timeout) { 68 MOZ_RELEASE_ASSERT(fd->identity == sMockNetworkLayerIdentity); 69 70 MockNetworkSecret* secret = reinterpret_cast<MockNetworkSecret*>(fd->secret); 71 SOCKET_LOG(("MockNetworkRecv %p\n", secret)); 72 73 PRInt32 rv = 74 (fd->lower->methods->recv)(fd->lower, buf, amount, flags, timeout); 75 return rv; 76 } 77 78 static PRInt32 MockNetworkRead(PRFileDesc* fd, void* buf, PRInt32 amount) { 79 return MockNetworkRecv(fd, buf, amount, 0, PR_INTERVAL_NO_WAIT); 80 } 81 82 static PRStatus MockNetworkClose(PRFileDesc* fd) { 83 if (!fd) { 84 return PR_FAILURE; 85 } 86 87 PRFileDesc* layer = PR_PopIOLayer(fd, PR_TOP_IO_LAYER); 88 89 MOZ_RELEASE_ASSERT(layer && layer->identity == sMockNetworkLayerIdentity, 90 "MockNetwork Layer not on top of stack"); 91 92 MockNetworkSecret* secret = 93 reinterpret_cast<MockNetworkSecret*>(layer->secret); 94 SOCKET_LOG(("MockNetworkClose %p\n", secret)); 95 layer->secret = nullptr; 96 layer->dtor(layer); 97 delete secret; 98 return fd->methods->close(fd); 99 } 100 101 static PRInt32 MockNetworkSendTo(PRFileDesc* fd, const void* buf, 102 PRInt32 amount, PRIntn flags, 103 const PRNetAddr* addr, 104 PRIntervalTime timeout) { 105 MOZ_RELEASE_ASSERT(fd->identity == sMockNetworkLayerIdentity); 106 107 MockNetworkSecret* secret = reinterpret_cast<MockNetworkSecret*>(fd->secret); 108 SOCKET_LOG(("MockNetworkSendTo %p", secret)); 109 mozilla::net::NetAddr netAddr(addr); 110 if (FindBlockedUDPAddr(netAddr)) { 111 nsAutoCString addrPort; 112 netAddr.ToAddrPortString(addrPort); 113 SOCKET_LOG( 114 ("MockNetworkSendTo %p addr [%s] is blocked", secret, addrPort.get())); 115 return PR_SUCCESS; 116 } 117 return (fd->lower->methods->sendto)(fd->lower, buf, amount, flags, addr, 118 timeout); 119 } 120 121 static PRInt32 PR_CALLBACK MockNetworkRecvFrom(PRFileDesc* fd, void* buf, 122 PRInt32 amount, PRIntn flags, 123 PRNetAddr* addr, 124 PRIntervalTime timeout) { 125 MOZ_RELEASE_ASSERT(fd->identity == sMockNetworkLayerIdentity); 126 127 MockNetworkSecret* secret = reinterpret_cast<MockNetworkSecret*>(fd->secret); 128 SOCKET_LOG(("MockNetworkRecvFrom %p\n", secret)); 129 mozilla::net::NetAddr netAddr(addr); 130 if (FindBlockedUDPAddr(netAddr)) { 131 nsAutoCString addrPort; 132 netAddr.ToAddrPortString(addrPort); 133 SOCKET_LOG(("MockNetworkRecvFrom %p addr [%s] is blocked", secret, 134 addrPort.get())); 135 return PR_SUCCESS; 136 } 137 return (fd->lower->methods->recvfrom)(fd->lower, buf, amount, flags, addr, 138 timeout); 139 } 140 141 nsresult AttachMockNetworkLayer(PRFileDesc* fd) { 142 if (!sMockNetworkLayeyMethodsPtr) { 143 sMockNetworkLayerIdentity = PR_GetUniqueIdentity("MockNetwork Layer"); 144 sMockNetworkLayeyMethods = *PR_GetDefaultIOMethods(); 145 sMockNetworkLayeyMethods.connect = MockNetworkConnect; 146 sMockNetworkLayeyMethods.send = MockNetworkSend; 147 sMockNetworkLayeyMethods.write = MockNetworkWrite; 148 sMockNetworkLayeyMethods.recv = MockNetworkRecv; 149 sMockNetworkLayeyMethods.read = MockNetworkRead; 150 sMockNetworkLayeyMethods.close = MockNetworkClose; 151 sMockNetworkLayeyMethods.sendto = MockNetworkSendTo; 152 sMockNetworkLayeyMethods.recvfrom = MockNetworkRecvFrom; 153 sMockNetworkLayeyMethodsPtr = &sMockNetworkLayeyMethods; 154 } 155 156 PRFileDesc* layer = PR_CreateIOLayerStub(sMockNetworkLayerIdentity, 157 sMockNetworkLayeyMethodsPtr); 158 159 if (!layer) { 160 return NS_ERROR_FAILURE; 161 } 162 163 MockNetworkSecret* secret = new MockNetworkSecret(); 164 165 layer->secret = reinterpret_cast<PRFilePrivate*>(secret); 166 167 PRStatus status = PR_PushIOLayer(fd, PR_NSPR_IO_LAYER, layer); 168 169 if (status == PR_FAILURE) { 170 delete secret; 171 PR_Free(layer); // PR_CreateIOLayerStub() uses PR_Malloc(). 172 return NS_ERROR_FAILURE; 173 } 174 return NS_OK; 175 } 176 177 } // namespace mozilla::net