#include "talk/base/physicalsocketserver.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/socketaddress.h"
+#include "talk/base/ssladapter.h"
#include "talk/base/stringutils.h"
#include "talk/base/thread.h"
#include "talk/base/virtualsocketserver.h"
}
virtual int SendTo(
const void* data, size_t size, const talk_base::SocketAddress& addr,
- talk_base::DiffServCodePoint dscp, bool payload) {
+ const talk_base::PacketOptions& options, bool payload) {
if (!payload) {
IceMessage* msg = new IceMessage;
ByteBuffer* buf = new ByteBuffer(static_cast<const char*>(data), size);
protected:
static void SetUpTestCase() {
- // Ensure the RNG is inited.
- talk_base::InitRandom(NULL, 0);
+ talk_base::InitializeSSL();
}
+ static void TearDownTestCase() {
+ talk_base::CleanupSSL();
+ }
+
+
void TestLocalToLocal() {
Port* port1 = CreateUdpPort(kLocalAddr1);
Port* port2 = CreateUdpPort(kLocalAddr2);
// Send a packet.
virtual int Send(const void *pv, size_t cb,
- talk_base::DiffServCodePoint dscp) {
+ const talk_base::PacketOptions& options) {
return static_cast<int>(cb);
}
virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr,
- talk_base::DiffServCodePoint dscp) {
+ const talk_base::PacketOptions& options) {
return static_cast<int>(cb);
}
virtual int Close() {
// This test verifies DSCP value set through SetOption interface can be
// get through DefaultDscpValue.
TEST_F(PortTest, TestDefaultDscpValue) {
+ int dscp;
talk_base::scoped_ptr<UDPPort> udpport(CreateUdpPort(kLocalAddr1));
- udpport->SetOption(talk_base::Socket::OPT_DSCP, talk_base::DSCP_CS6);
- EXPECT_EQ(talk_base::DSCP_CS6, udpport->DefaultDscpValue());
+ EXPECT_EQ(0, udpport->SetOption(talk_base::Socket::OPT_DSCP,
+ talk_base::DSCP_CS6));
+ EXPECT_EQ(0, udpport->GetOption(talk_base::Socket::OPT_DSCP, &dscp));
talk_base::scoped_ptr<TCPPort> tcpport(CreateTcpPort(kLocalAddr1));
- tcpport->SetOption(talk_base::Socket::OPT_DSCP, talk_base::DSCP_AF31);
- EXPECT_EQ(talk_base::DSCP_AF31, tcpport->DefaultDscpValue());
+ EXPECT_EQ(0, tcpport->SetOption(talk_base::Socket::OPT_DSCP,
+ talk_base::DSCP_AF31));
+ EXPECT_EQ(0, tcpport->GetOption(talk_base::Socket::OPT_DSCP, &dscp));
+ EXPECT_EQ(talk_base::DSCP_AF31, dscp);
talk_base::scoped_ptr<StunPort> stunport(
CreateStunPort(kLocalAddr1, nat_socket_factory1()));
- stunport->SetOption(talk_base::Socket::OPT_DSCP, talk_base::DSCP_AF41);
- EXPECT_EQ(talk_base::DSCP_AF41, stunport->DefaultDscpValue());
- talk_base::scoped_ptr<TurnPort> turnport(CreateTurnPort(
+ EXPECT_EQ(0, stunport->SetOption(talk_base::Socket::OPT_DSCP,
+ talk_base::DSCP_AF41));
+ EXPECT_EQ(0, stunport->GetOption(talk_base::Socket::OPT_DSCP, &dscp));
+ EXPECT_EQ(talk_base::DSCP_AF41, dscp);
+ talk_base::scoped_ptr<TurnPort> turnport1(CreateTurnPort(
+ kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP));
+ // Socket is created in PrepareAddress.
+ turnport1->PrepareAddress();
+ EXPECT_EQ(0, turnport1->SetOption(talk_base::Socket::OPT_DSCP,
+ talk_base::DSCP_CS7));
+ EXPECT_EQ(0, turnport1->GetOption(talk_base::Socket::OPT_DSCP, &dscp));
+ EXPECT_EQ(talk_base::DSCP_CS7, dscp);
+ // This will verify correct value returned without the socket.
+ talk_base::scoped_ptr<TurnPort> turnport2(CreateTurnPort(
kLocalAddr1, nat_socket_factory1(), PROTO_UDP, PROTO_UDP));
- turnport->SetOption(talk_base::Socket::OPT_DSCP, talk_base::DSCP_CS7);
- EXPECT_EQ(talk_base::DSCP_CS7, turnport->DefaultDscpValue());
- // TODO(mallinath) - Test DSCP through GetOption.
+ EXPECT_EQ(0, turnport2->SetOption(talk_base::Socket::OPT_DSCP,
+ talk_base::DSCP_CS6));
+ EXPECT_EQ(0, turnport2->GetOption(talk_base::Socket::OPT_DSCP, &dscp));
+ EXPECT_EQ(talk_base::DSCP_CS6, dscp);
}
// Test sending STUN messages in GICE format.
out_msg->GetErrorCode()->reason());
}
+// This test verifies port can handle ICE messages in Hybrid mode and switches
+// ICEPROTO_RFC5245 mode after successfully handling the message.
+TEST_F(PortTest, TestHandleStunMessageAsIceInHybridMode) {
+ // Our port will act as the "remote" port.
+ talk_base::scoped_ptr<TestPort> port(
+ CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
+ port->SetIceProtocolType(ICEPROTO_HYBRID);
+
+ talk_base::scoped_ptr<IceMessage> in_msg, out_msg;
+ talk_base::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
+ talk_base::SocketAddress addr(kLocalAddr1);
+ std::string username;
+
+ // BINDING-REQUEST from local to remote with valid ICE username,
+ // MESSAGE-INTEGRITY, and FINGERPRINT.
+ in_msg.reset(CreateStunMessageWithUsername(STUN_BINDING_REQUEST,
+ "rfrag:lfrag"));
+ in_msg->AddMessageIntegrity("rpass");
+ in_msg->AddFingerprint();
+ WriteStunMessage(in_msg.get(), buf.get());
+ EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
+ out_msg.accept(), &username));
+ EXPECT_TRUE(out_msg.get() != NULL);
+ EXPECT_EQ("lfrag", username);
+ EXPECT_EQ(ICEPROTO_RFC5245, port->IceProtocol());
+}
+
+// This test verifies port can handle GICE messages in Hybrid mode and switches
+// ICEPROTO_GOOGLE mode after successfully handling the message.
+TEST_F(PortTest, TestHandleStunMessageAsGiceInHybridMode) {
+ // Our port will act as the "remote" port.
+ talk_base::scoped_ptr<TestPort> port(
+ CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
+ port->SetIceProtocolType(ICEPROTO_HYBRID);
+
+ talk_base::scoped_ptr<IceMessage> in_msg, out_msg;
+ talk_base::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
+ talk_base::SocketAddress addr(kLocalAddr1);
+ std::string username;
+
+ // BINDING-REQUEST from local to remote with valid GICE username and no M-I.
+ in_msg.reset(CreateStunMessageWithUsername(STUN_BINDING_REQUEST,
+ "rfraglfrag"));
+ WriteStunMessage(in_msg.get(), buf.get());
+ EXPECT_TRUE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
+ out_msg.accept(), &username));
+ EXPECT_TRUE(out_msg.get() != NULL); // Succeeds, since this is GICE.
+ EXPECT_EQ("lfrag", username);
+ EXPECT_EQ(ICEPROTO_GOOGLE, port->IceProtocol());
+}
+
+// Verify port is not switched out of RFC5245 mode if GICE message is received
+// in that mode.
+TEST_F(PortTest, TestHandleStunMessageAsGiceInIceMode) {
+ // Our port will act as the "remote" port.
+ talk_base::scoped_ptr<TestPort> port(
+ CreateTestPort(kLocalAddr2, "rfrag", "rpass"));
+ port->SetIceProtocolType(ICEPROTO_RFC5245);
+
+ talk_base::scoped_ptr<IceMessage> in_msg, out_msg;
+ talk_base::scoped_ptr<ByteBuffer> buf(new ByteBuffer());
+ talk_base::SocketAddress addr(kLocalAddr1);
+ std::string username;
+
+ // BINDING-REQUEST from local to remote with valid GICE username and no M-I.
+ in_msg.reset(CreateStunMessageWithUsername(STUN_BINDING_REQUEST,
+ "rfraglfrag"));
+ WriteStunMessage(in_msg.get(), buf.get());
+ // Should fail as there is no MI and fingerprint.
+ EXPECT_FALSE(port->GetStunMessage(buf->Data(), buf->Length(), addr,
+ out_msg.accept(), &username));
+ EXPECT_EQ(ICEPROTO_RFC5245, port->IceProtocol());
+}
+
+
// Tests handling of GICE binding requests with missing or incorrect usernames.
TEST_F(PortTest, TestHandleStunMessageAsGiceBadUsername) {
talk_base::scoped_ptr<TestPort> port(
// Data should be unsendable until the connection is accepted.
char data[] = "abcd";
int data_size = ARRAY_SIZE(data);
- EXPECT_EQ(SOCKET_ERROR,
- ch1.conn()->Send(data, data_size, talk_base::DSCP_NO_CHANGE));
+ talk_base::PacketOptions options;
+ EXPECT_EQ(SOCKET_ERROR, ch1.conn()->Send(data, data_size, options));
// Accept the connection to return the binding response, transition to
// writable, and allow data to be sent.
ch2.AcceptConnection();
EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, ch1.conn()->write_state(),
kTimeout);
- EXPECT_EQ(data_size,
- ch1.conn()->Send(data, data_size, talk_base::DSCP_NO_CHANGE));
+ EXPECT_EQ(data_size, ch1.conn()->Send(data, data_size, options));
// Ask the connection to update state as if enough time has passed to lose
// full writability and 5 pings went unresponded to. We'll accomplish the
EXPECT_EQ(Connection::STATE_WRITE_UNRELIABLE, ch1.conn()->write_state());
// Data should be able to be sent in this state.
- EXPECT_EQ(data_size,
- ch1.conn()->Send(data, data_size, talk_base::DSCP_NO_CHANGE));
+ EXPECT_EQ(data_size, ch1.conn()->Send(data, data_size, options));
// And now allow the other side to process the pings and send binding
// responses.
EXPECT_EQ(Connection::STATE_WRITE_TIMEOUT, ch1.conn()->write_state());
// Now that the connection has completely timed out, data send should fail.
- EXPECT_EQ(SOCKET_ERROR,
- ch1.conn()->Send(data, data_size, talk_base::DSCP_NO_CHANGE));
+ EXPECT_EQ(SOCKET_ERROR, ch1.conn()->Send(data, data_size, options));
ch1.Stop();
ch2.Stop();