// Packs the given socketaddress into the buffer in buf, in the quasi-STUN // format that the natserver uses. // Returns 0 if an invalid address is passed. void PackAddressForNAT(const SocketAddress& remote_addr, Buffer& buf) { const IPAddress& ip = remote_addr.ipaddr(); int family = ip.family();
// Decodes the remote address from a packet that has been encoded with the nat's // quasi-STUN format. Returns the length of the address (i.e., the offset into // data where the original packet starts).
size_t UnpackAddressFromNAT(std::span<const uint8_t> buf,
SocketAddress* remote_addr) {
RTC_CHECK(buf.size() >= 8);
RTC_DCHECK(buf.data()[0] == 0); int family = buf[1];
uint16_t port =
NetworkToHost16(*(reinterpret_cast<const uint16_t*>(&buf.data()[2]))); if (family == AF_INET) { const in_addr* v4addr = reinterpret_cast<const in_addr*>(&buf.data()[4]);
*remote_addr = SocketAddress(IPAddress(*v4addr), port); return kNATEncodedIPv4AddressSize;
} elseif (family == AF_INET6) {
RTC_DCHECK(buf.size() >= 20); const in6_addr* v6addr = reinterpret_cast<const in6_addr*>(&buf.data()[4]);
*remote_addr = SocketAddress(IPAddress(*v6addr), port); return kNATEncodedIPv6AddressSize;
} return0U;
}
// NATSocket class NATSocket : public Socket {
public: explicit NATSocket(NATInternalSocketFactory* sf, int family, int type)
: sf_(sf),
family_(family),
type_(type),
connected_(false),
socket_(nullptr) {}
SocketAddress GetRemoteAddress() const override { return remote_addr_; // will be NIL if not connected
}
int Bind(const SocketAddress& addr) override { if (socket_) { // already bound, bubble up error return -1;
}
return BindInternal(addr);
}
int Connect(const SocketAddress& addr) override { int result = 0; // If we're not already bound (meaning `socket_` is null), bind to ANY // address. if (!socket_) {
result = BindInternal(SocketAddress(GetAnyIP(family_), 0)); if (result < 0) { return result;
}
}
if (type_ == SOCK_STREAM) {
result = socket_->Connect(server_addr_.IsNil() ? addr : server_addr_);
} else {
connected_ = true;
}
int RecvFrom(void* data,
size_t size,
SocketAddress* out_addr,
int64_t* timestamp) override { if (server_addr_.IsNil() || type_ == SOCK_STREAM) { return socket_->RecvFrom(data, size, out_addr, timestamp);
} // Make sure we have enough room to read the requested amount plus the // largest possible header address.
buf_.EnsureCapacity(size + kNATEncodedIPv6AddressSize);
// Read the packet from the socket.
Socket::ReceiveBuffer receive_buffer(buf_); int result = socket_->RecvFrom(receive_buffer); if (result >= 0) {
RTC_DCHECK(receive_buffer.source_address == server_addr_);
*timestamp =
receive_buffer.arrival_time.value_or(Timestamp::Micros(0)).us();
// Decode the wire packet into the actual results.
SocketAddress real_remote_addr;
size_t addrlength = UnpackAddressFromNAT(buf_, &real_remote_addr);
memcpy(data, buf_.data() + addrlength, result - addrlength);
// Make sure this packet should be delivered before returning it. if (!connected_ || (real_remote_addr == remote_addr_)) { if (out_addr)
*out_addr = real_remote_addr;
result = result - static_cast<int>(addrlength);
} else {
RTC_LOG(LS_ERROR) << "Dropping packet from unknown remote address: "
<< real_remote_addr.ToString();
result = 0; // Tell the caller we didn't read anything
}
}
return result;
}
int Close() override { int result = 0; if (socket_) {
result = socket_->Close(); if (result >= 0) {
connected_ = false;
remote_addr_ = SocketAddress(); delete socket_;
socket_ = nullptr;
}
} return result;
}
// Sends the destination address to the server to tell it to connect. void SendConnectRequest() {
Buffer buf = Buffer::CreateWithCapacity(kNATEncodedIPv6AddressSize);
PackAddressForNAT(remote_addr_, buf);
socket_->Send(buf.data(), buf.size());
}
// Handles the byte sent back from the server and fires the appropriate event. void HandleConnectReply() { char code;
socket_->Recv(&code, sizeof(code), nullptr); if (code == 0) {
connected_ = true;
NotifyConnectEvent(this);
} else {
Close();
NotifyCloseEvent(this, code);
}
}
NATInternalSocketFactory* sf_; int family_; int type_; bool connected_;
SocketAddress remote_addr_;
SocketAddress server_addr_; // address of the NAT server
Socket* socket_; // Need to hold error in case it occurs before the socket is created. int error_ = 0;
Buffer buf_;
};
// NATSocketServer::Translator
NATSocketServer::Translator::Translator(const Environment& env,
NATSocketServer* server,
NATType type, const SocketAddress& int_ip,
Thread& external_socket_thread,
SocketFactory* ext_factory, const SocketAddress& ext_ip)
: server_(server) { // Create a new private network, and a NATServer running on the private // network that bridges to the external network. Also tell the private // network to use the same message queue as us.
internal_server_ = std::make_unique<VirtualSocketServer>();
internal_server_->SetMessageQueue(server_->queue());
nat_server_ = std::make_unique<NATServer>(
env, type, *server->queue(), internal_server_.get(), int_ip, int_ip,
external_socket_thread, ext_factory, ext_ip);
}
bool NATSocketServer::Translator::AddClient(const SocketAddress& int_ip) { // Fail if a client already exists with this internal address. if (clients_.find(int_ip) != clients_.end()) returnfalse;
clients_.insert(int_ip); return true;
}
void NATSocketServer::Translator::RemoveClient(const SocketAddress& int_ip) {
std::set<SocketAddress>::iterator it = clients_.find(int_ip); if (it != clients_.end()) {
clients_.erase(it);
}
}
NATSocketServer::Translator* NATSocketServer::Translator::FindClient( const SocketAddress& int_ip) { // See if we have the requested IP, or any of our children do. return (clients_.find(int_ip) != clients_.end()) ? this
: nats_.FindClient(int_ip);
}
// NATSocketServer::TranslatorMap
NATSocketServer::TranslatorMap::~TranslatorMap() { for (TranslatorMap::iterator it = begin(); it != end(); ++it) { delete it->second;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.