| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license | |
| 5 * that can be found in the LICENSE file in the root of the source | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #include <memory> | |
| 12 | |
| 13 #include "webrtc/base/checks.h" | |
| 14 #include "webrtc/base/natsocketfactory.h" | |
| 15 #include "webrtc/base/natserver.h" | |
| 16 #include "webrtc/base/logging.h" | |
| 17 #include "webrtc/base/socketadapters.h" | |
| 18 | |
| 19 namespace rtc { | |
| 20 | |
| 21 RouteCmp::RouteCmp(NAT* nat) : symmetric(nat->IsSymmetric()) { | |
| 22 } | |
| 23 | |
| 24 size_t RouteCmp::operator()(const SocketAddressPair& r) const { | |
| 25 size_t h = r.source().Hash(); | |
| 26 if (symmetric) | |
| 27 h ^= r.destination().Hash(); | |
| 28 return h; | |
| 29 } | |
| 30 | |
| 31 bool RouteCmp::operator()( | |
| 32 const SocketAddressPair& r1, const SocketAddressPair& r2) const { | |
| 33 if (r1.source() < r2.source()) | |
| 34 return true; | |
| 35 if (r2.source() < r1.source()) | |
| 36 return false; | |
| 37 if (symmetric && (r1.destination() < r2.destination())) | |
| 38 return true; | |
| 39 if (symmetric && (r2.destination() < r1.destination())) | |
| 40 return false; | |
| 41 return false; | |
| 42 } | |
| 43 | |
| 44 AddrCmp::AddrCmp(NAT* nat) | |
| 45 : use_ip(nat->FiltersIP()), use_port(nat->FiltersPort()) { | |
| 46 } | |
| 47 | |
| 48 size_t AddrCmp::operator()(const SocketAddress& a) const { | |
| 49 size_t h = 0; | |
| 50 if (use_ip) | |
| 51 h ^= HashIP(a.ipaddr()); | |
| 52 if (use_port) | |
| 53 h ^= a.port() | (a.port() << 16); | |
| 54 return h; | |
| 55 } | |
| 56 | |
| 57 bool AddrCmp::operator()( | |
| 58 const SocketAddress& a1, const SocketAddress& a2) const { | |
| 59 if (use_ip && (a1.ipaddr() < a2.ipaddr())) | |
| 60 return true; | |
| 61 if (use_ip && (a2.ipaddr() < a1.ipaddr())) | |
| 62 return false; | |
| 63 if (use_port && (a1.port() < a2.port())) | |
| 64 return true; | |
| 65 if (use_port && (a2.port() < a1.port())) | |
| 66 return false; | |
| 67 return false; | |
| 68 } | |
| 69 | |
| 70 // Proxy socket that will capture the external destination address intended for | |
| 71 // a TCP connection to the NAT server. | |
| 72 class NATProxyServerSocket : public AsyncProxyServerSocket { | |
| 73 public: | |
| 74 NATProxyServerSocket(AsyncSocket* socket) | |
| 75 : AsyncProxyServerSocket(socket, kNATEncodedIPv6AddressSize) { | |
| 76 BufferInput(true); | |
| 77 } | |
| 78 | |
| 79 void SendConnectResult(int err, const SocketAddress& addr) override { | |
| 80 char code = err ? 1 : 0; | |
| 81 BufferedReadAdapter::DirectSend(&code, sizeof(char)); | |
| 82 } | |
| 83 | |
| 84 protected: | |
| 85 void ProcessInput(char* data, size_t* len) override { | |
| 86 if (*len < 2) { | |
| 87 return; | |
| 88 } | |
| 89 | |
| 90 int family = data[1]; | |
| 91 RTC_DCHECK(family == AF_INET || family == AF_INET6); | |
| 92 if ((family == AF_INET && *len < kNATEncodedIPv4AddressSize) || | |
| 93 (family == AF_INET6 && *len < kNATEncodedIPv6AddressSize)) { | |
| 94 return; | |
| 95 } | |
| 96 | |
| 97 SocketAddress dest_addr; | |
| 98 size_t address_length = UnpackAddressFromNAT(data, *len, &dest_addr); | |
| 99 | |
| 100 *len -= address_length; | |
| 101 if (*len > 0) { | |
| 102 memmove(data, data + address_length, *len); | |
| 103 } | |
| 104 | |
| 105 bool remainder = (*len > 0); | |
| 106 BufferInput(false); | |
| 107 SignalConnectRequest(this, dest_addr); | |
| 108 if (remainder) { | |
| 109 SignalReadEvent(this); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 }; | |
| 114 | |
| 115 class NATProxyServer : public ProxyServer { | |
| 116 public: | |
| 117 NATProxyServer(SocketFactory* int_factory, const SocketAddress& int_addr, | |
| 118 SocketFactory* ext_factory, const SocketAddress& ext_ip) | |
| 119 : ProxyServer(int_factory, int_addr, ext_factory, ext_ip) { | |
| 120 } | |
| 121 | |
| 122 protected: | |
| 123 AsyncProxyServerSocket* WrapSocket(AsyncSocket* socket) override { | |
| 124 return new NATProxyServerSocket(socket); | |
| 125 } | |
| 126 }; | |
| 127 | |
| 128 NATServer::NATServer( | |
| 129 NATType type, SocketFactory* internal, | |
| 130 const SocketAddress& internal_udp_addr, | |
| 131 const SocketAddress& internal_tcp_addr, | |
| 132 SocketFactory* external, const SocketAddress& external_ip) | |
| 133 : external_(external), external_ip_(external_ip.ipaddr(), 0) { | |
| 134 nat_ = NAT::Create(type); | |
| 135 | |
| 136 udp_server_socket_ = AsyncUDPSocket::Create(internal, internal_udp_addr); | |
| 137 udp_server_socket_->SignalReadPacket.connect(this, | |
| 138 &NATServer::OnInternalUDPPacket); | |
| 139 tcp_proxy_server_ = new NATProxyServer(internal, internal_tcp_addr, external, | |
| 140 external_ip); | |
| 141 | |
| 142 int_map_ = new InternalMap(RouteCmp(nat_)); | |
| 143 ext_map_ = new ExternalMap(); | |
| 144 } | |
| 145 | |
| 146 NATServer::~NATServer() { | |
| 147 for (InternalMap::iterator iter = int_map_->begin(); | |
| 148 iter != int_map_->end(); | |
| 149 iter++) | |
| 150 delete iter->second; | |
| 151 | |
| 152 delete nat_; | |
| 153 delete udp_server_socket_; | |
| 154 delete tcp_proxy_server_; | |
| 155 delete int_map_; | |
| 156 delete ext_map_; | |
| 157 } | |
| 158 | |
| 159 void NATServer::OnInternalUDPPacket( | |
| 160 AsyncPacketSocket* socket, const char* buf, size_t size, | |
| 161 const SocketAddress& addr, const PacketTime& packet_time) { | |
| 162 // Read the intended destination from the wire. | |
| 163 SocketAddress dest_addr; | |
| 164 size_t length = UnpackAddressFromNAT(buf, size, &dest_addr); | |
| 165 | |
| 166 // Find the translation for these addresses (allocating one if necessary). | |
| 167 SocketAddressPair route(addr, dest_addr); | |
| 168 InternalMap::iterator iter = int_map_->find(route); | |
| 169 if (iter == int_map_->end()) { | |
| 170 Translate(route); | |
| 171 iter = int_map_->find(route); | |
| 172 } | |
| 173 RTC_DCHECK(iter != int_map_->end()); | |
| 174 | |
| 175 // Allow the destination to send packets back to the source. | |
| 176 iter->second->WhitelistInsert(dest_addr); | |
| 177 | |
| 178 // Send the packet to its intended destination. | |
| 179 rtc::PacketOptions options; | |
| 180 iter->second->socket->SendTo(buf + length, size - length, dest_addr, options); | |
| 181 } | |
| 182 | |
| 183 void NATServer::OnExternalUDPPacket( | |
| 184 AsyncPacketSocket* socket, const char* buf, size_t size, | |
| 185 const SocketAddress& remote_addr, const PacketTime& packet_time) { | |
| 186 SocketAddress local_addr = socket->GetLocalAddress(); | |
| 187 | |
| 188 // Find the translation for this addresses. | |
| 189 ExternalMap::iterator iter = ext_map_->find(local_addr); | |
| 190 RTC_DCHECK(iter != ext_map_->end()); | |
| 191 | |
| 192 // Allow the NAT to reject this packet. | |
| 193 if (ShouldFilterOut(iter->second, remote_addr)) { | |
| 194 LOG(LS_INFO) << "Packet from " << remote_addr.ToSensitiveString() | |
| 195 << " was filtered out by the NAT."; | |
| 196 return; | |
| 197 } | |
| 198 | |
| 199 // Forward this packet to the internal address. | |
| 200 // First prepend the address in a quasi-STUN format. | |
| 201 std::unique_ptr<char[]> real_buf(new char[size + kNATEncodedIPv6AddressSize]); | |
| 202 size_t addrlength = PackAddressForNAT(real_buf.get(), | |
| 203 size + kNATEncodedIPv6AddressSize, | |
| 204 remote_addr); | |
| 205 // Copy the data part after the address. | |
| 206 rtc::PacketOptions options; | |
| 207 memcpy(real_buf.get() + addrlength, buf, size); | |
| 208 udp_server_socket_->SendTo(real_buf.get(), size + addrlength, | |
| 209 iter->second->route.source(), options); | |
| 210 } | |
| 211 | |
| 212 void NATServer::Translate(const SocketAddressPair& route) { | |
| 213 AsyncUDPSocket* socket = AsyncUDPSocket::Create(external_, external_ip_); | |
| 214 | |
| 215 if (!socket) { | |
| 216 LOG(LS_ERROR) << "Couldn't find a free port!"; | |
| 217 return; | |
| 218 } | |
| 219 | |
| 220 TransEntry* entry = new TransEntry(route, socket, nat_); | |
| 221 (*int_map_)[route] = entry; | |
| 222 (*ext_map_)[socket->GetLocalAddress()] = entry; | |
| 223 socket->SignalReadPacket.connect(this, &NATServer::OnExternalUDPPacket); | |
| 224 } | |
| 225 | |
| 226 bool NATServer::ShouldFilterOut(TransEntry* entry, | |
| 227 const SocketAddress& ext_addr) { | |
| 228 return entry->WhitelistContains(ext_addr); | |
| 229 } | |
| 230 | |
| 231 NATServer::TransEntry::TransEntry( | |
| 232 const SocketAddressPair& r, AsyncUDPSocket* s, NAT* nat) | |
| 233 : route(r), socket(s) { | |
| 234 whitelist = new AddressSet(AddrCmp(nat)); | |
| 235 } | |
| 236 | |
| 237 NATServer::TransEntry::~TransEntry() { | |
| 238 delete whitelist; | |
| 239 delete socket; | |
| 240 } | |
| 241 | |
| 242 void NATServer::TransEntry::WhitelistInsert(const SocketAddress& addr) { | |
| 243 CritScope cs(&crit_); | |
| 244 whitelist->insert(addr); | |
| 245 } | |
| 246 | |
| 247 bool NATServer::TransEntry::WhitelistContains(const SocketAddress& ext_addr) { | |
| 248 CritScope cs(&crit_); | |
| 249 return whitelist->find(ext_addr) == whitelist->end(); | |
| 250 } | |
| 251 | |
| 252 } // namespace rtc | |
| OLD | NEW |