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