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 < 2) { |
| 84 return; |
| 85 } |
| 86 |
| 87 int family = data[1]; |
| 88 ASSERT(family == AF_INET || family == AF_INET6); |
| 89 if ((family == AF_INET && *len < kNATEncodedIPv4AddressSize) || |
| 90 (family == AF_INET6 && *len < kNATEncodedIPv6AddressSize)) { |
| 91 return; |
| 92 } |
| 93 |
| 94 SocketAddress dest_addr; |
| 95 size_t address_length = UnpackAddressFromNAT(data, *len, &dest_addr); |
| 96 |
| 97 *len -= address_length; |
| 98 if (*len > 0) { |
| 99 memmove(data, data + address_length, *len); |
| 100 } |
| 101 |
| 102 bool remainder = (*len > 0); |
| 103 BufferInput(false); |
| 104 SignalConnectRequest(this, dest_addr); |
| 105 if (remainder) { |
| 106 SignalReadEvent(this); |
| 107 } |
| 108 } |
| 109 |
| 110 }; |
| 111 |
| 112 class NATProxyServer : public ProxyServer { |
| 113 public: |
| 114 NATProxyServer(SocketFactory* int_factory, const SocketAddress& int_addr, |
| 115 SocketFactory* ext_factory, const SocketAddress& ext_ip) |
| 116 : ProxyServer(int_factory, int_addr, ext_factory, ext_ip) { |
| 117 } |
| 118 |
| 119 protected: |
| 120 AsyncProxyServerSocket* WrapSocket(AsyncSocket* socket) override { |
| 121 return new NATProxyServerSocket(socket); |
| 122 } |
| 123 }; |
| 124 |
66 NATServer::NATServer( | 125 NATServer::NATServer( |
67 NATType type, SocketFactory* internal, const SocketAddress& internal_addr, | 126 NATType type, SocketFactory* internal, |
| 127 const SocketAddress& internal_udp_addr, |
| 128 const SocketAddress& internal_tcp_addr, |
68 SocketFactory* external, const SocketAddress& external_ip) | 129 SocketFactory* external, const SocketAddress& external_ip) |
69 : external_(external), external_ip_(external_ip.ipaddr(), 0) { | 130 : external_(external), external_ip_(external_ip.ipaddr(), 0) { |
70 nat_ = NAT::Create(type); | 131 nat_ = NAT::Create(type); |
71 | 132 |
72 server_socket_ = AsyncUDPSocket::Create(internal, internal_addr); | 133 udp_server_socket_ = AsyncUDPSocket::Create(internal, internal_udp_addr); |
73 server_socket_->SignalReadPacket.connect(this, &NATServer::OnInternalPacket); | 134 udp_server_socket_->SignalReadPacket.connect(this, |
| 135 &NATServer::OnInternalUDPPacket); |
| 136 tcp_proxy_server_ = new NATProxyServer(internal, internal_tcp_addr, external, |
| 137 external_ip); |
74 | 138 |
75 int_map_ = new InternalMap(RouteCmp(nat_)); | 139 int_map_ = new InternalMap(RouteCmp(nat_)); |
76 ext_map_ = new ExternalMap(); | 140 ext_map_ = new ExternalMap(); |
77 } | 141 } |
78 | 142 |
79 NATServer::~NATServer() { | 143 NATServer::~NATServer() { |
80 for (InternalMap::iterator iter = int_map_->begin(); | 144 for (InternalMap::iterator iter = int_map_->begin(); |
81 iter != int_map_->end(); | 145 iter != int_map_->end(); |
82 iter++) | 146 iter++) |
83 delete iter->second; | 147 delete iter->second; |
84 | 148 |
85 delete nat_; | 149 delete nat_; |
86 delete server_socket_; | 150 delete udp_server_socket_; |
| 151 delete tcp_proxy_server_; |
87 delete int_map_; | 152 delete int_map_; |
88 delete ext_map_; | 153 delete ext_map_; |
89 } | 154 } |
90 | 155 |
91 void NATServer::OnInternalPacket( | 156 void NATServer::OnInternalUDPPacket( |
92 AsyncPacketSocket* socket, const char* buf, size_t size, | 157 AsyncPacketSocket* socket, const char* buf, size_t size, |
93 const SocketAddress& addr, const PacketTime& packet_time) { | 158 const SocketAddress& addr, const PacketTime& packet_time) { |
94 | |
95 // Read the intended destination from the wire. | 159 // Read the intended destination from the wire. |
96 SocketAddress dest_addr; | 160 SocketAddress dest_addr; |
97 size_t length = UnpackAddressFromNAT(buf, size, &dest_addr); | 161 size_t length = UnpackAddressFromNAT(buf, size, &dest_addr); |
98 | 162 |
99 // Find the translation for these addresses (allocating one if necessary). | 163 // Find the translation for these addresses (allocating one if necessary). |
100 SocketAddressPair route(addr, dest_addr); | 164 SocketAddressPair route(addr, dest_addr); |
101 InternalMap::iterator iter = int_map_->find(route); | 165 InternalMap::iterator iter = int_map_->find(route); |
102 if (iter == int_map_->end()) { | 166 if (iter == int_map_->end()) { |
103 Translate(route); | 167 Translate(route); |
104 iter = int_map_->find(route); | 168 iter = int_map_->find(route); |
105 } | 169 } |
106 ASSERT(iter != int_map_->end()); | 170 ASSERT(iter != int_map_->end()); |
107 | 171 |
108 // Allow the destination to send packets back to the source. | 172 // Allow the destination to send packets back to the source. |
109 iter->second->WhitelistInsert(dest_addr); | 173 iter->second->WhitelistInsert(dest_addr); |
110 | 174 |
111 // Send the packet to its intended destination. | 175 // Send the packet to its intended destination. |
112 rtc::PacketOptions options; | 176 rtc::PacketOptions options; |
113 iter->second->socket->SendTo(buf + length, size - length, dest_addr, options); | 177 iter->second->socket->SendTo(buf + length, size - length, dest_addr, options); |
114 } | 178 } |
115 | 179 |
116 void NATServer::OnExternalPacket( | 180 void NATServer::OnExternalUDPPacket( |
117 AsyncPacketSocket* socket, const char* buf, size_t size, | 181 AsyncPacketSocket* socket, const char* buf, size_t size, |
118 const SocketAddress& remote_addr, const PacketTime& packet_time) { | 182 const SocketAddress& remote_addr, const PacketTime& packet_time) { |
119 | |
120 SocketAddress local_addr = socket->GetLocalAddress(); | 183 SocketAddress local_addr = socket->GetLocalAddress(); |
121 | 184 |
122 // Find the translation for this addresses. | 185 // Find the translation for this addresses. |
123 ExternalMap::iterator iter = ext_map_->find(local_addr); | 186 ExternalMap::iterator iter = ext_map_->find(local_addr); |
124 ASSERT(iter != ext_map_->end()); | 187 ASSERT(iter != ext_map_->end()); |
125 | 188 |
126 // Allow the NAT to reject this packet. | 189 // Allow the NAT to reject this packet. |
127 if (ShouldFilterOut(iter->second, remote_addr)) { | 190 if (ShouldFilterOut(iter->second, remote_addr)) { |
128 LOG(LS_INFO) << "Packet from " << remote_addr.ToSensitiveString() | 191 LOG(LS_INFO) << "Packet from " << remote_addr.ToSensitiveString() |
129 << " was filtered out by the NAT."; | 192 << " was filtered out by the NAT."; |
130 return; | 193 return; |
131 } | 194 } |
132 | 195 |
133 // Forward this packet to the internal address. | 196 // Forward this packet to the internal address. |
134 // First prepend the address in a quasi-STUN format. | 197 // First prepend the address in a quasi-STUN format. |
135 scoped_ptr<char[]> real_buf(new char[size + kNATEncodedIPv6AddressSize]); | 198 scoped_ptr<char[]> real_buf(new char[size + kNATEncodedIPv6AddressSize]); |
136 size_t addrlength = PackAddressForNAT(real_buf.get(), | 199 size_t addrlength = PackAddressForNAT(real_buf.get(), |
137 size + kNATEncodedIPv6AddressSize, | 200 size + kNATEncodedIPv6AddressSize, |
138 remote_addr); | 201 remote_addr); |
139 // Copy the data part after the address. | 202 // Copy the data part after the address. |
140 rtc::PacketOptions options; | 203 rtc::PacketOptions options; |
141 memcpy(real_buf.get() + addrlength, buf, size); | 204 memcpy(real_buf.get() + addrlength, buf, size); |
142 server_socket_->SendTo(real_buf.get(), size + addrlength, | 205 udp_server_socket_->SendTo(real_buf.get(), size + addrlength, |
143 iter->second->route.source(), options); | 206 iter->second->route.source(), options); |
144 } | 207 } |
145 | 208 |
146 void NATServer::Translate(const SocketAddressPair& route) { | 209 void NATServer::Translate(const SocketAddressPair& route) { |
147 AsyncUDPSocket* socket = AsyncUDPSocket::Create(external_, external_ip_); | 210 AsyncUDPSocket* socket = AsyncUDPSocket::Create(external_, external_ip_); |
148 | 211 |
149 if (!socket) { | 212 if (!socket) { |
150 LOG(LS_ERROR) << "Couldn't find a free port!"; | 213 LOG(LS_ERROR) << "Couldn't find a free port!"; |
151 return; | 214 return; |
152 } | 215 } |
153 | 216 |
154 TransEntry* entry = new TransEntry(route, socket, nat_); | 217 TransEntry* entry = new TransEntry(route, socket, nat_); |
155 (*int_map_)[route] = entry; | 218 (*int_map_)[route] = entry; |
156 (*ext_map_)[socket->GetLocalAddress()] = entry; | 219 (*ext_map_)[socket->GetLocalAddress()] = entry; |
157 socket->SignalReadPacket.connect(this, &NATServer::OnExternalPacket); | 220 socket->SignalReadPacket.connect(this, &NATServer::OnExternalUDPPacket); |
158 } | 221 } |
159 | 222 |
160 bool NATServer::ShouldFilterOut(TransEntry* entry, | 223 bool NATServer::ShouldFilterOut(TransEntry* entry, |
161 const SocketAddress& ext_addr) { | 224 const SocketAddress& ext_addr) { |
162 return entry->WhitelistContains(ext_addr); | 225 return entry->WhitelistContains(ext_addr); |
163 } | 226 } |
164 | 227 |
165 NATServer::TransEntry::TransEntry( | 228 NATServer::TransEntry::TransEntry( |
166 const SocketAddressPair& r, AsyncUDPSocket* s, NAT* nat) | 229 const SocketAddressPair& r, AsyncUDPSocket* s, NAT* nat) |
167 : route(r), socket(s) { | 230 : route(r), socket(s) { |
168 whitelist = new AddressSet(AddrCmp(nat)); | 231 whitelist = new AddressSet(AddrCmp(nat)); |
169 } | 232 } |
170 | 233 |
171 NATServer::TransEntry::~TransEntry() { | 234 NATServer::TransEntry::~TransEntry() { |
172 delete whitelist; | 235 delete whitelist; |
173 delete socket; | 236 delete socket; |
174 } | 237 } |
175 | 238 |
176 void NATServer::TransEntry::WhitelistInsert(const SocketAddress& addr) { | 239 void NATServer::TransEntry::WhitelistInsert(const SocketAddress& addr) { |
177 CritScope cs(&crit_); | 240 CritScope cs(&crit_); |
178 whitelist->insert(addr); | 241 whitelist->insert(addr); |
179 } | 242 } |
180 | 243 |
181 bool NATServer::TransEntry::WhitelistContains(const SocketAddress& ext_addr) { | 244 bool NATServer::TransEntry::WhitelistContains(const SocketAddress& ext_addr) { |
182 CritScope cs(&crit_); | 245 CritScope cs(&crit_); |
183 return whitelist->find(ext_addr) == whitelist->end(); | 246 return whitelist->find(ext_addr) == whitelist->end(); |
184 } | 247 } |
185 | 248 |
186 } // namespace rtc | 249 } // namespace rtc |
OLD | NEW |