tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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