LCOV - code coverage report
Current view: top level - media/mtransport - test_nr_socket.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 28 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=2 et sw=2 tw=80: */
       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 file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : /*
       7             : */
       8             : 
       9             : /*
      10             : Based partially on original code from nICEr and nrappkit.
      11             : 
      12             : nICEr copyright:
      13             : 
      14             : Copyright (c) 2007, Adobe Systems, Incorporated
      15             : All rights reserved.
      16             : 
      17             : Redistribution and use in source and binary forms, with or without
      18             : modification, are permitted provided that the following conditions are
      19             : met:
      20             : 
      21             : * Redistributions of source code must retain the above copyright
      22             :   notice, this list of conditions and the following disclaimer.
      23             : 
      24             : * Redistributions in binary form must reproduce the above copyright
      25             :   notice, this list of conditions and the following disclaimer in the
      26             :   documentation and/or other materials provided with the distribution.
      27             : 
      28             : * Neither the name of Adobe Systems, Network Resonance nor the names of its
      29             :   contributors may be used to endorse or promote products derived from
      30             :   this software without specific prior written permission.
      31             : 
      32             : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      33             : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      34             : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      35             : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      36             : OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      37             : SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      38             : LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      39             : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      40             : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      41             : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      42             : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      43             : 
      44             : 
      45             : nrappkit copyright:
      46             : 
      47             :    Copyright (C) 2001-2003, Network Resonance, Inc.
      48             :    Copyright (C) 2006, Network Resonance, Inc.
      49             :    All Rights Reserved
      50             : 
      51             :    Redistribution and use in source and binary forms, with or without
      52             :    modification, are permitted provided that the following conditions
      53             :    are met:
      54             : 
      55             :    1. Redistributions of source code must retain the above copyright
      56             :       notice, this list of conditions and the following disclaimer.
      57             :    2. Redistributions in binary form must reproduce the above copyright
      58             :       notice, this list of conditions and the following disclaimer in the
      59             :       documentation and/or other materials provided with the distribution.
      60             :    3. Neither the name of Network Resonance, Inc. nor the name of any
      61             :       contributors to this software may be used to endorse or promote
      62             :       products derived from this software without specific prior written
      63             :       permission.
      64             : 
      65             :    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
      66             :    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      67             :    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      68             :    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      69             :    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      70             :    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      71             :    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      72             :    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      73             :    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      74             :    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      75             :    POSSIBILITY OF SUCH DAMAGE.
      76             : 
      77             : 
      78             :    ekr@rtfm.com  Thu Dec 20 20:14:49 2001
      79             : */
      80             : 
      81             : // Original author: bcampen@mozilla.com [:bwc]
      82             : 
      83             : #ifndef test_nr_socket__
      84             : #define test_nr_socket__
      85             : 
      86             : extern "C" {
      87             : #include "transport_addr.h"
      88             : }
      89             : 
      90             : #include "nr_socket_prsock.h"
      91             : 
      92             : extern "C" {
      93             : #include "nr_socket.h"
      94             : }
      95             : 
      96             : #include <set>
      97             : #include <vector>
      98             : #include <map>
      99             : #include <list>
     100             : #include <string>
     101             : 
     102             : #include "mozilla/UniquePtr.h"
     103             : #include "prinrval.h"
     104             : 
     105             : namespace mozilla {
     106             : 
     107             : class TestNrSocket;
     108             : 
     109             : /**
     110             :  * A group of TestNrSockets that behave as if they were behind the same NAT.
     111             :  * @note We deliberately avoid addref/release of TestNrSocket here to avoid
     112             :  *       masking lifetime errors elsewhere.
     113             : */
     114             : class TestNat {
     115             :   public:
     116             : 
     117             :     /**
     118             :       * This allows TestNat traffic to be passively inspected.
     119             :       * If a non-zero (error) value is returned, the packet will be dropped,
     120             :       * allowing for tests to extend how packet manipulation is done by
     121             :       * TestNat with having to modify TestNat itself.
     122             :     */
     123             :     class NatDelegate {
     124             :     public:
     125             :       virtual int on_read(TestNat *nat, void *buf, size_t maxlen, size_t *len) = 0;
     126             :       virtual int on_sendto(TestNat *nat, const void *msg, size_t len,
     127             :                     int flags, nr_transport_addr *to) = 0;
     128             :       virtual int on_write(TestNat *nat, const void *msg, size_t len, size_t *written) = 0;
     129             :     };
     130             : 
     131             :     typedef enum {
     132             :       /** For mapping, one port is used for all destinations.
     133             :        *  For filtering, allow any external address/port. */
     134             :       ENDPOINT_INDEPENDENT,
     135             : 
     136             :       /** For mapping, one port for each destination address (for any port).
     137             :        *  For filtering, allow incoming traffic from addresses that outgoing
     138             :        *  traffic has been sent to. */
     139             :       ADDRESS_DEPENDENT,
     140             : 
     141             :       /** For mapping, one port for each destination address/port.
     142             :        *  For filtering, allow incoming traffic only from addresses/ports that
     143             :        *  outgoing traffic has been sent to. */
     144             :       PORT_DEPENDENT,
     145             :     } NatBehavior;
     146             : 
     147           0 :     TestNat() :
     148             :       enabled_(false),
     149             :       filtering_type_(ENDPOINT_INDEPENDENT),
     150             :       mapping_type_(ENDPOINT_INDEPENDENT),
     151             :       mapping_timeout_(30000),
     152             :       allow_hairpinning_(false),
     153             :       refresh_on_ingress_(false),
     154             :       block_udp_(false),
     155             :       block_stun_(false),
     156             :       block_tcp_(false),
     157             :       delay_stun_resp_ms_(0),
     158             :       nat_delegate_(nullptr),
     159           0 :       sockets_() {}
     160             : 
     161             :     bool has_port_mappings() const;
     162             : 
     163             :     // Helps determine whether we're hairpinning
     164             :     bool is_my_external_tuple(const nr_transport_addr &addr) const;
     165             :     bool is_an_internal_tuple(const nr_transport_addr &addr) const;
     166             : 
     167             :     int create_socket_factory(nr_socket_factory **factorypp);
     168             : 
     169           0 :     void insert_socket(TestNrSocket *socket) {
     170           0 :       sockets_.insert(socket);
     171           0 :     }
     172             : 
     173           0 :     void erase_socket(TestNrSocket *socket) {
     174           0 :       sockets_.erase(socket);
     175           0 :     }
     176             : 
     177           0 :     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestNat);
     178             : 
     179             :     static NatBehavior ToNatBehavior(const std::string& type);
     180             : 
     181             :     bool enabled_;
     182             :     TestNat::NatBehavior filtering_type_;
     183             :     TestNat::NatBehavior mapping_type_;
     184             :     uint32_t mapping_timeout_;
     185             :     bool allow_hairpinning_;
     186             :     bool refresh_on_ingress_;
     187             :     bool block_udp_;
     188             :     bool block_stun_;
     189             :     bool block_tcp_;
     190             :     /* Note: this can only delay a single response so far (bug 1253657) */
     191             :     uint32_t delay_stun_resp_ms_;
     192             : 
     193             :     NatDelegate* nat_delegate_;
     194             : 
     195             :   private:
     196             :     std::set<TestNrSocket*> sockets_;
     197             : 
     198           0 :     ~TestNat(){}
     199             : };
     200             : 
     201             : /**
     202             :  * Subclass of NrSocketBase that can simulate things like being behind a NAT,
     203             :  * packet loss, latency, packet rewriting, etc. Also exposes some stuff that
     204             :  * assists in diagnostics.
     205             :  * This is accomplished by wrapping an "internal" socket (that handles traffic
     206             :  * behind the NAT), and a collection of "external" sockets (that handle traffic
     207             :  * into/out of the NAT)
     208             :  */
     209             : class TestNrSocket : public NrSocketBase {
     210             :   public:
     211             :     explicit TestNrSocket(TestNat *nat);
     212             : 
     213             :     bool has_port_mappings() const;
     214             :     bool is_my_external_tuple(const nr_transport_addr &addr) const;
     215             : 
     216             :     // Overrides of NrSocketBase
     217             :     int create(nr_transport_addr *addr) override;
     218             :     int sendto(const void *msg, size_t len,
     219             :                int flags, nr_transport_addr *to) override;
     220             :     int recvfrom(void * buf, size_t maxlen,
     221             :                  size_t *len, int flags,
     222             :                  nr_transport_addr *from) override;
     223             :     int getaddr(nr_transport_addr *addrp) override;
     224             :     void close() override;
     225             :     int connect(nr_transport_addr *addr) override;
     226             :     int write(const void *msg, size_t len, size_t *written) override;
     227             :     int read(void *buf, size_t maxlen, size_t *len) override;
     228             : 
     229             :     int listen(int backlog) override;
     230             :     int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
     231             :     int async_wait(int how, NR_async_cb cb, void *cb_arg,
     232             :                    char *function, int line) override;
     233             :     int cancel(int how) override;
     234             : 
     235             :     // Need override since this is virtual in NrSocketBase
     236           0 :     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestNrSocket, override)
     237             : 
     238             :   private:
     239             :     virtual ~TestNrSocket();
     240             : 
     241             :     class UdpPacket {
     242             :       public:
     243           0 :         UdpPacket(const void *msg, size_t len, const nr_transport_addr &addr) :
     244           0 :           buffer_(new DataBuffer(static_cast<const uint8_t*>(msg), len)) {
     245             :           // TODO(bug 1170299): Remove const_cast when no longer necessary
     246           0 :           nr_transport_addr_copy(&remote_address_,
     247           0 :                                  const_cast<nr_transport_addr*>(&addr));
     248           0 :         }
     249             : 
     250             :         nr_transport_addr remote_address_;
     251             :         UniquePtr<DataBuffer> buffer_;
     252             : 
     253           0 :         NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UdpPacket);
     254             :       private:
     255           0 :         ~UdpPacket(){}
     256             :     };
     257             : 
     258             :     class PortMapping {
     259             :       public:
     260             :         PortMapping(const nr_transport_addr &remote_address,
     261             :                     const RefPtr<NrSocketBase> &external_socket);
     262             : 
     263             :         int sendto(const void *msg, size_t len, const nr_transport_addr &to);
     264             :         int async_wait(int how, NR_async_cb cb, void *cb_arg,
     265             :                        char *function, int line);
     266             :         int cancel(int how);
     267             :         int send_from_queue();
     268           0 :         NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PortMapping);
     269             : 
     270             :         PRIntervalTime last_used_;
     271             :         RefPtr<NrSocketBase> external_socket_;
     272             :         // For non-symmetric, most of the data here doesn't matter
     273             :         nr_transport_addr remote_address_;
     274             : 
     275             :       private:
     276           0 :         ~PortMapping() {
     277           0 :           external_socket_->close();
     278           0 :         }
     279             : 
     280             :         // If external_socket_ returns E_WOULDBLOCK, we don't want to propagate
     281             :         // that to the code using the TestNrSocket. We can also perhaps use this
     282             :         // to help simulate things like latency.
     283             :         std::list<RefPtr<UdpPacket>> send_queue_;
     284             :     };
     285             : 
     286           0 :     struct DeferredPacket {
     287           0 :       DeferredPacket(TestNrSocket *sock,
     288             :                      const void *data, size_t len,
     289             :                      int flags,
     290             :                      nr_transport_addr *addr,
     291           0 :                      RefPtr<NrSocketBase> internal_socket) :
     292             :           socket_(sock),
     293             :           buffer_(reinterpret_cast<const uint8_t *>(data), len),
     294             :           flags_(flags),
     295           0 :           internal_socket_(internal_socket) {
     296           0 :         nr_transport_addr_copy(&to_, addr);
     297           0 :       }
     298             : 
     299             :       TestNrSocket *socket_;
     300             :       DataBuffer buffer_;
     301             :       int flags_;
     302             :       nr_transport_addr to_;
     303             :       RefPtr<NrSocketBase> internal_socket_;
     304             :     };
     305             : 
     306             :     bool is_port_mapping_stale(const PortMapping &port_mapping) const;
     307             :     bool allow_ingress(const nr_transport_addr &from,
     308             :                        PortMapping **port_mapping_used) const;
     309             :     void destroy_stale_port_mappings();
     310             : 
     311             :     static void socket_readable_callback(void *real_sock_v,
     312             :                                          int how,
     313             :                                          void *test_sock_v);
     314             :     void on_socket_readable(NrSocketBase *external_or_internal_socket);
     315             :     void fire_readable_callback();
     316             : 
     317             :     static void port_mapping_tcp_passthrough_callback(void *ext_sock_v,
     318             :                                                       int how,
     319             :                                                       void *test_sock_v);
     320             :     void cancel_port_mapping_async_wait(int how);
     321             : 
     322             :     static void port_mapping_writeable_callback(void *ext_sock_v,
     323             :                                                 int how,
     324             :                                                 void *test_sock_v);
     325             :     void write_to_port_mapping(NrSocketBase *external_socket);
     326             :     bool is_tcp_connection_behind_nat() const;
     327             : 
     328             :     PortMapping* get_port_mapping(const nr_transport_addr &remote_addr,
     329             :                                   TestNat::NatBehavior filter) const;
     330             :     PortMapping* create_port_mapping(
     331             :         const nr_transport_addr &remote_addr,
     332             :         const RefPtr<NrSocketBase> &external_socket) const;
     333             :     RefPtr<NrSocketBase> create_external_socket(
     334             :         const nr_transport_addr &remote_addr) const;
     335             : 
     336             :     static void process_delayed_cb(NR_SOCKET s, int how, void *cb_arg);
     337             : 
     338             :     RefPtr<NrSocketBase> readable_socket_;
     339             :     // The socket for the "internal" address; used to talk to stuff behind the
     340             :     // same nat.
     341             :     RefPtr<NrSocketBase> internal_socket_;
     342             :     RefPtr<TestNat> nat_;
     343             :     bool tls_;
     344             :     // Since our comparison logic is different depending on what kind of NAT
     345             :     // we simulate, and the STL does not make it very easy to switch out the
     346             :     // comparison function at runtime, and these lists are going to be very
     347             :     // small anyway, we just brute-force it.
     348             :     std::list<RefPtr<PortMapping>> port_mappings_;
     349             : 
     350             :     void *timer_handle_;
     351             : };
     352             : 
     353             : } // namespace mozilla
     354             : 
     355             : #endif // test_nr_socket__
     356             : 

Generated by: LCOV version 1.13