📄 port_unittest.cc
字号:
#include "talk/base/helpers.h"#include "talk/base/host.h"#include "talk/base/natserver.h"#include "talk/base/natsocketfactory.h"#include "talk/base/socketaddress.h"#include "talk/base/thread.h"#include "talk/base/virtualsocketserver.h"#include "talk/p2p/base/udpport.h"#include "talk/p2p/base/relayport.h"#include "talk/p2p/base/relayserver.h"#include "talk/p2p/base/stunport.h"#include "talk/p2p/base/stunserver.h"#include <iostream>using namespace cricket;const uint32 MSG_CONNECT = 1;const uint32 MSG_PREP_ADDRESS = 2;const uint32 MSG_CREATE_CONN = 3;const uint32 MSG_ACCEPT_CONN = 4;const uint32 MSG_PING = 5;Candidate GetCandidate(Port* port) { assert(port->candidates().size() == 1); return port->candidates()[0];}talk_base::SocketAddress GetAddress(Port* port) { return GetCandidate(port).address();}struct Foo : public talk_base::MessageHandler, public sigslot::has_slots<> { int count; talk_base::SocketAddress address; StunMessage* request; std::string remote_frag; talk_base::Thread* thread; Port* port1; Port* port2; Connection* conn; Foo(talk_base::Thread* th, Port* p1, Port* p2) : count(0), thread(th), port1(p1), port2(p2), conn(0) { } void OnAddressReady(Port* port) { count += 1; } void OnUnknownAddress( Port* port, const talk_base::SocketAddress& addr, StunMessage* msg, const std::string& rf) { assert(port == port1); if (!address.IsAny()) { assert(addr == address); delete request; } address = addr; request = msg; remote_frag = rf; } void OnMessage(talk_base::Message* pmsg) { assert(talk_base::Thread::Current() == thread); switch (pmsg->message_id) { case MSG_CONNECT: port1->SignalAddressReady.connect(this, &Foo::OnAddressReady); port1->SignalUnknownAddress.connect(this, &Foo::OnUnknownAddress); break; case MSG_PREP_ADDRESS: port1->PrepareAddress(); break; case MSG_CREATE_CONN: conn = port1->CreateConnection(GetCandidate(port2), Port::ORIGIN_MESSAGE); assert(conn); conn->Ping(0); break; case MSG_PING: assert(conn); conn->Ping(0); break; case MSG_ACCEPT_CONN: { Candidate c = GetCandidate(port2); c.set_address(address); conn = port1->CreateConnection(c, Port::ORIGIN_MESSAGE); assert(conn); port1->SendBindingResponse(request, address); conn->Ping(0); delete request; break; } default: assert(false); break; } }};void test(talk_base::Thread* pthMain, const char* name1, Port* port1, talk_base::Thread* pthBack, const char* name2, Port* port2, bool accept = true, bool same_addr = true) { Foo* foo1 = new Foo(pthMain, port1, port2); Foo* foo2 = new Foo(pthBack, port2, port1); std::cout << "Test: " << name1 << " to " << name2 << ": "; std::cout.flush(); pthBack->Start(); pthMain->Post(foo1, MSG_CONNECT); pthBack->Post(foo2, MSG_CONNECT); pthMain->ProcessMessages(10); assert(foo1->count == 0); assert(foo2->count == 0); pthMain->Post(foo1, MSG_PREP_ADDRESS); pthMain->ProcessMessages(200); assert(foo1->count == 1); pthBack->Post(foo2, MSG_PREP_ADDRESS); pthMain->ProcessMessages(200); assert(foo2->count == 1); pthMain->Post(foo1, MSG_CREATE_CONN); pthMain->ProcessMessages(200); if (accept) { assert(foo1->address.IsAny()); assert(foo2->remote_frag == port1->username_fragment()); assert(!same_addr || (foo2->address == GetAddress(port1))); pthBack->Post(foo2, MSG_ACCEPT_CONN); pthMain->ProcessMessages(200); } else { assert(foo1->address.IsAny()); assert(foo2->address.IsAny()); pthBack->Post(foo2, MSG_CREATE_CONN); pthMain->ProcessMessages(200); if (same_addr) { assert(foo1->conn->read_state() == Connection::STATE_READABLE); assert(foo2->conn->write_state() == Connection::STATE_WRITABLE); // First connection may not be writable if the first ping did not get // through. So we will have to do another. if (foo1->conn->write_state() == Connection::STATE_WRITE_CONNECT) { pthMain->Post(foo1, MSG_PING); pthMain->ProcessMessages(200); } } else { assert(foo1->address.IsAny()); assert(foo2->address.IsAny()); pthMain->Post(foo1, MSG_PING); pthMain->ProcessMessages(200); assert(foo1->address.IsAny()); assert(!foo2->address.IsAny()); pthBack->Post(foo2, MSG_ACCEPT_CONN); pthMain->ProcessMessages(200); } } assert(foo1->conn->read_state() == Connection::STATE_READABLE); assert(foo1->conn->write_state() == Connection::STATE_WRITABLE); assert(foo2->conn->read_state() == Connection::STATE_READABLE); assert(foo2->conn->write_state() == Connection::STATE_WRITABLE); pthBack->Stop(); delete port1; delete port2; delete foo1; delete foo2; std::cout << "PASS" << std::endl;}const talk_base::SocketAddress local_addr = talk_base::SocketAddress("127.0.0.1", 0);const talk_base::SocketAddress relay_int_addr = talk_base::SocketAddress("127.0.0.1", 5000);const talk_base::SocketAddress relay_ext_addr = talk_base::SocketAddress("127.0.0.1", 5001);const talk_base::SocketAddress stun_addr = talk_base::SocketAddress("127.0.0.1", STUN_SERVER_PORT);const talk_base::SocketAddress nat_addr = talk_base::SocketAddress("127.0.0.1", talk_base::NAT_SERVER_PORT);void test_udp() { talk_base::Thread* pthMain = talk_base::Thread::Current(); talk_base::Thread* pthBack = new talk_base::Thread(); talk_base::Network* network = new talk_base::Network("network", local_addr.ip()); test(pthMain, "udp", new UDPPort(pthMain, NULL, network, local_addr), pthBack, "udp", new UDPPort(pthBack, NULL, network, local_addr)); delete pthBack;}void test_relay() { talk_base::Thread* pthMain = talk_base::Thread::Current(); talk_base::Thread* pthBack = new talk_base::Thread(); talk_base::Network* network = new talk_base::Network("network", local_addr.ip()); RelayServer relay_server(pthBack); talk_base::AsyncUDPSocket* int_socket = talk_base::CreateAsyncUDPSocket(pthBack->socketserver()); assert(int_socket->Bind(relay_int_addr) >= 0); relay_server.AddInternalSocket(int_socket); talk_base::AsyncUDPSocket* ext_socket = talk_base::CreateAsyncUDPSocket(pthBack->socketserver()); assert(ext_socket->Bind(relay_ext_addr) >= 0); relay_server.AddExternalSocket(ext_socket); std::string username = CreateRandomString(16); std::string password = CreateRandomString(16); RelayPort* rport = new RelayPort(pthBack, NULL, network, local_addr, username, password, ""); rport->AddServerAddress(ProtocolAddress(relay_int_addr, PROTO_UDP)); test(pthMain, "udp", new UDPPort(pthMain, NULL, network, local_addr), pthBack, "relay", rport); delete pthBack;}const char* NATName(talk_base::NATType type) { switch (type) { case talk_base::NAT_OPEN_CONE: return "open cone"; case talk_base::NAT_ADDR_RESTRICTED: return "addr restricted"; case talk_base::NAT_PORT_RESTRICTED: return "port restricted"; case talk_base::NAT_SYMMETRIC: return "symmetric"; default: assert(false); return 0; }}void test_stun(talk_base::NATType nat_type) { talk_base::Thread* pthMain = talk_base::Thread::Current(); talk_base::Thread* pthBack = new talk_base::Thread(); talk_base::Network* network = new talk_base::Network("network", local_addr.ip()); talk_base::NATServer* nat = new talk_base::NATServer( nat_type, pthMain->socketserver(), nat_addr, pthMain->socketserver(), nat_addr); talk_base::NATSocketFactory* nat_factory = new talk_base::NATSocketFactory(pthMain->socketserver(), nat_addr); StunPort* stun_port = new StunPort(pthMain, nat_factory, network, local_addr, stun_addr); talk_base::AsyncUDPSocket* stun_socket = talk_base::CreateAsyncUDPSocket(pthMain->socketserver()); assert(stun_socket->Bind(stun_addr) >= 0); StunServer* stun_server = new StunServer(stun_socket); char name[256]; sprintf(name, "stun (%s)", NATName(nat_type)); test(pthMain, name, stun_port, pthBack, "udp", new UDPPort(pthBack, NULL, network, local_addr), true, nat_type != talk_base::NAT_SYMMETRIC); delete stun_server; delete stun_socket; delete nat; delete nat_factory; delete pthBack;}void test_stun(talk_base::NATType nat1_type, talk_base::NATType nat2_type) { talk_base::Thread* pthMain = talk_base::Thread::Current(); talk_base::Thread* pthBack = new talk_base::Thread(); talk_base::Network* network = new talk_base::Network("network", local_addr.ip()); talk_base::SocketAddress local_addr1(talk_base::LocalHost().networks()[0]->ip(), 0); talk_base::SocketAddress local_addr2(talk_base::LocalHost().networks()[1]->ip(), 0); talk_base::SocketAddress nat1_addr(local_addr1.ip(), talk_base::NAT_SERVER_PORT); talk_base::SocketAddress nat2_addr(local_addr2.ip(), talk_base::NAT_SERVER_PORT); talk_base::SocketAddress stun1_addr(local_addr1.ip(), STUN_SERVER_PORT); talk_base::SocketAddress stun2_addr(local_addr2.ip(), STUN_SERVER_PORT); talk_base::NATServer* nat1 = new talk_base::NATServer( nat1_type, pthMain->socketserver(), nat1_addr, pthMain->socketserver(), nat1_addr); talk_base::NATSocketFactory* nat1_factory = new talk_base::NATSocketFactory(pthMain->socketserver(), nat1_addr); StunPort* stun1_port = new StunPort(pthMain, nat1_factory, network, local_addr1, stun1_addr); talk_base::NATServer* nat2 = new talk_base::NATServer( nat2_type, pthBack->socketserver(), nat2_addr, pthBack->socketserver(), nat2_addr); talk_base::NATSocketFactory* nat2_factory = new talk_base::NATSocketFactory(pthBack->socketserver(), nat2_addr); StunPort* stun2_port = new StunPort(pthMain, nat2_factory, network, local_addr2, stun2_addr); talk_base::AsyncUDPSocket* stun1_socket = talk_base::CreateAsyncUDPSocket(pthMain->socketserver()); assert(stun1_socket->Bind(stun_addr) >= 0); StunServer* stun1_server = new StunServer(stun1_socket); talk_base::AsyncUDPSocket* stun2_socket = talk_base::CreateAsyncUDPSocket(pthBack->socketserver()); assert(stun2_socket->Bind(stun2_addr) >= 0); StunServer* stun2_server = new StunServer(stun2_socket); char name1[256], name2[256]; sprintf(name1, "stun (%s)", NATName(nat1_type)); sprintf(name2, "stun (%s)", NATName(nat2_type)); test(pthMain, name1, stun1_port, pthBack, name2, stun2_port, nat2_type == talk_base::NAT_OPEN_CONE, nat1_type != talk_base::NAT_SYMMETRIC); delete stun1_server; delete stun1_socket; delete stun2_server; delete stun2_socket; delete nat1; delete nat1_factory; delete nat2; delete nat2_factory; delete pthBack;}int main(int argc, char* argv[]) { InitRandom(NULL, 0); test_udp(); test_relay(); test_stun(talk_base::NAT_OPEN_CONE); test_stun(talk_base::NAT_ADDR_RESTRICTED); test_stun(talk_base::NAT_PORT_RESTRICTED); test_stun(talk_base::NAT_SYMMETRIC); test_stun(talk_base::NAT_OPEN_CONE, talk_base::NAT_OPEN_CONE); test_stun(talk_base::NAT_ADDR_RESTRICTED, talk_base::NAT_OPEN_CONE); test_stun(talk_base::NAT_PORT_RESTRICTED, talk_base::NAT_OPEN_CONE); test_stun(talk_base::NAT_SYMMETRIC, talk_base::NAT_OPEN_CONE); test_stun(talk_base::NAT_ADDR_RESTRICTED, talk_base::NAT_ADDR_RESTRICTED); test_stun(talk_base::NAT_PORT_RESTRICTED, talk_base::NAT_ADDR_RESTRICTED); test_stun(talk_base::NAT_PORT_RESTRICTED, talk_base::NAT_PORT_RESTRICTED); test_stun(talk_base::NAT_SYMMETRIC, talk_base::NAT_ADDR_RESTRICTED); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -