Skip to content

Commit 9207254

Browse files
Added support for an Origin header in STUN messages.
For WebRTC there are instances where it may be desirable to provide information to the STUN/TURN server about the website that initiated a peer connection. This modification allows an origin string to be included in the MediaConstraints object provided by the browser, which is then passed as a STUN header in communications with the server. A separate change will be submitted to the Chromium project that uses and is dependent on this change, implementing IETF draft http://tools.ietf.org/html/draft-johnston-tram-stun-origin-02 Originally a patch from [email protected]. (https://webrtc-codereview.appspot.com/12839005/edit) [email protected] Review URL: https://webrtc-codereview.appspot.com/41409004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@8035 4adac7df-926f-26a2-2b94-8c16560cd09d
1 parent 78a4415 commit 9207254

23 files changed

+398
-227
lines changed

AUTHORS

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Christophe Dumez <[email protected]>
99
Colin Plumb
1010
Eric Rescorla, RTFM Inc.
1111
Giji Gangadharan <[email protected]>
12+
Graham Yoakum <[email protected]>
1213
James H. Brown <[email protected]>
1314
1415
Luke Weber
@@ -21,6 +22,7 @@ Rafael Lopez Diez <[email protected]>
2122
Ralph Giles <[email protected]>
2223
Robert Nagy
2324
Ron Rivest
25+
Ryan Yoakum <[email protected]>
2426
Sarah Thompson <[email protected]>
2527
Saul Kravitz <[email protected]>
2628
Silviu Caragea <[email protected]>

webrtc/libjingle/session/session_unittest.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,8 @@ class TestPortAllocatorSession : public cricket::PortAllocatorSession {
598598
ports_[i] = cricket::UDPPort::Create(
599599
rtc::Thread::Current(), &socket_factory_,
600600
&network_, address_.ipaddr(), GetPort(index), GetPort(index),
601-
GetUsername(index), GetPassword(index));
601+
GetUsername(index), GetPassword(index),
602+
std::string());
602603
AddPort(ports_[i]);
603604
}
604605
running_ = true;

webrtc/p2p/base/port.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ class Port : public PortInterface, public rtc::MessageHandler,
262262

263263
// Debugging description of this port
264264
virtual std::string ToString() const;
265-
rtc::IPAddress& ip() { return ip_; }
265+
const rtc::IPAddress& ip() const { return ip_; }
266266
uint16 min_port() { return min_port_; }
267267
uint16 max_port() { return max_port_; }
268268

webrtc/p2p/base/port_unittest.cc

+8-5
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ class TestChannel : public sigslot::has_slots<> {
207207
// Takes ownership of |p1| (but not |p2|).
208208
TestChannel(Port* p1, Port* p2)
209209
: ice_mode_(ICEMODE_FULL), src_(p1), dst_(p2), complete_count_(0),
210-
conn_(NULL), remote_request_(), nominated_(false) {
210+
conn_(NULL), remote_request_(), nominated_(false) {
211211
src_->SignalPortComplete.connect(
212212
this, &TestChannel::OnPortComplete);
213213
src_->SignalUnknownAddress.connect(this, &TestChannel::OnUnknownAddress);
@@ -413,7 +413,8 @@ class PortTest : public testing::Test, public sigslot::has_slots<> {
413413
UDPPort* CreateUdpPort(const SocketAddress& addr,
414414
PacketSocketFactory* socket_factory) {
415415
UDPPort* port = UDPPort::Create(main_, socket_factory, &network_,
416-
addr.ipaddr(), 0, 0, username_, password_);
416+
addr.ipaddr(), 0, 0, username_, password_,
417+
std::string());
417418
port->SetIceProtocolType(ice_protocol_);
418419
return port;
419420
}
@@ -436,7 +437,8 @@ class PortTest : public testing::Test, public sigslot::has_slots<> {
436437
stun_servers.insert(kStunAddr);
437438
StunPort* port = StunPort::Create(main_, factory, &network_,
438439
addr.ipaddr(), 0, 0,
439-
username_, password_, stun_servers);
440+
username_, password_, stun_servers,
441+
std::string());
440442
port->SetIceProtocolType(ice_protocol_);
441443
return port;
442444
}
@@ -461,8 +463,9 @@ class PortTest : public testing::Test, public sigslot::has_slots<> {
461463
TurnPort* port = TurnPort::Create(main_, socket_factory, &network_,
462464
addr.ipaddr(), 0, 0,
463465
username_, password_, ProtocolAddress(
464-
server_addr, PROTO_UDP),
465-
kRelayCredentials, 0);
466+
server_addr, PROTO_UDP),
467+
kRelayCredentials, 0,
468+
std::string());
466469
port->SetIceProtocolType(ice_protocol_);
467470
return port;
468471
}

webrtc/p2p/base/portallocator.h

+5
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ class PortAllocator : public sigslot::has_slots<> {
167167
return true;
168168
}
169169

170+
// Gets/Sets the Origin value used for WebRTC STUN requests.
171+
const std::string& origin() const { return origin_; }
172+
void set_origin(const std::string& origin) { origin_ = origin; }
173+
170174
protected:
171175
virtual PortAllocatorSession* CreateSessionInternal(
172176
const std::string& content_name,
@@ -185,6 +189,7 @@ class PortAllocator : public sigslot::has_slots<> {
185189
SessionMuxerMap muxers_;
186190
bool allow_tcp_listen_;
187191
uint32 candidate_filter_;
192+
std::string origin_;
188193
};
189194

190195
} // namespace cricket

webrtc/p2p/base/stun.cc

+1
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ StunAttributeValueType StunMessage::GetAttributeValueType(int type) const {
387387
case STUN_ATTR_SOFTWARE: return STUN_VALUE_BYTE_STRING;
388388
case STUN_ATTR_ALTERNATE_SERVER: return STUN_VALUE_ADDRESS;
389389
case STUN_ATTR_FINGERPRINT: return STUN_VALUE_UINT32;
390+
case STUN_ATTR_ORIGIN: return STUN_VALUE_BYTE_STRING;
390391
case STUN_ATTR_RETRANSMIT_COUNT: return STUN_VALUE_UINT32;
391392
default: return STUN_VALUE_UNKNOWN;
392393
}

webrtc/p2p/base/stun.h

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ enum StunAttributeType {
4848
STUN_ATTR_SOFTWARE = 0x8022, // ByteString
4949
STUN_ATTR_ALTERNATE_SERVER = 0x8023, // Address
5050
STUN_ATTR_FINGERPRINT = 0x8028, // UInt32
51+
STUN_ATTR_ORIGIN = 0x802F, // ByteString
5152
STUN_ATTR_RETRANSMIT_COUNT = 0xFF00 // UInt32
5253
};
5354

webrtc/p2p/base/stun_unittest.cc

+44
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,20 @@ static const unsigned char kStunMessageWithErrorAttribute[] = {
191191
0x69, 0x7a, 0x65, 0x64
192192
};
193193

194+
static const unsigned char kStunMessageWithOriginAttribute[] = {
195+
0x00, 0x01, 0x00, 0x18, // message header (binding request), length 24
196+
0x21, 0x12, 0xA4, 0x42, // magic cookie
197+
0x29, 0x1f, 0xcd, 0x7c, // transaction id
198+
0xba, 0x58, 0xab, 0xd7,
199+
0xf2, 0x41, 0x01, 0x00,
200+
0x80, 0x2f, 0x00, 0x12, // origin attribute (length 18)
201+
0x68, 0x74, 0x74, 0x70, // http://example.com
202+
0x3A, 0x2F, 0x2F, 0x65,
203+
0x78, 0x61, 0x6d, 0x70,
204+
0x6c, 0x65, 0x2e, 0x63,
205+
0x6f, 0x6d, 0x00, 0x00,
206+
};
207+
194208
// Sample messages with an invalid length Field
195209

196210
// The actual length in bytes of the invalid messages (including STUN header)
@@ -472,6 +486,7 @@ const in_addr kIPv4TestAddress1 = { { 0x0ac, 0x017, 0x044, 0x0e6 } };
472486
const char kTestUserName1[] = "abcdefgh";
473487
const char kTestUserName2[] = "abc";
474488
const char kTestErrorReason[] = "Unauthorized";
489+
const char kTestOrigin[] = "http://example.com";
475490
const int kTestErrorClass = 4;
476491
const int kTestErrorNumber = 1;
477492
const int kTestErrorCode = 401;
@@ -1020,6 +1035,16 @@ TEST_F(StunTest, ReadMessageWithAnUnknownAttribute) {
10201035
EXPECT_EQ(kTestUserName2, username->GetString());
10211036
}
10221037

1038+
TEST_F(StunTest, ReadMessageWithOriginAttribute) {
1039+
StunMessage msg;
1040+
size_t size = ReadStunMessage(&msg, kStunMessageWithOriginAttribute);
1041+
CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
1042+
const StunByteStringAttribute* origin =
1043+
msg.GetByteString(STUN_ATTR_ORIGIN);
1044+
ASSERT_TRUE(origin != NULL);
1045+
EXPECT_EQ(kTestOrigin, origin->GetString());
1046+
}
1047+
10231048
TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) {
10241049
StunMessage msg;
10251050
size_t size = sizeof(kStunMessageWithErrorAttribute);
@@ -1066,6 +1091,25 @@ TEST_F(StunTest, WriteMessageWithAUInt16ListAttribute) {
10661091
memcmp(out.Data(), kStunMessageWithUInt16ListAttribute, size - 2));
10671092
}
10681093

1094+
TEST_F(StunTest, WriteMessageWithOriginAttribute) {
1095+
StunMessage msg;
1096+
size_t size = sizeof(kStunMessageWithOriginAttribute);
1097+
1098+
msg.SetType(STUN_BINDING_REQUEST);
1099+
msg.SetTransactionID(
1100+
std::string(reinterpret_cast<const char*>(kTestTransactionId1),
1101+
kStunTransactionIdLength));
1102+
StunByteStringAttribute* origin =
1103+
new StunByteStringAttribute(STUN_ATTR_ORIGIN, kTestOrigin);
1104+
EXPECT_TRUE(msg.AddAttribute(origin));
1105+
1106+
rtc::ByteBuffer out;
1107+
EXPECT_TRUE(msg.Write(&out));
1108+
ASSERT_EQ(size, out.Length());
1109+
// Check everything up to the padding
1110+
ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithOriginAttribute, size - 2));
1111+
}
1112+
10691113
// Test that we fail to read messages with invalid lengths.
10701114
void CheckFailureToRead(const unsigned char* testcase, size_t length) {
10711115
StunMessage msg;

webrtc/p2p/base/stunport.cc

+6-2
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,16 @@ UDPPort::UDPPort(rtc::Thread* thread,
163163
rtc::Network* network,
164164
rtc::AsyncPacketSocket* socket,
165165
const std::string& username,
166-
const std::string& password)
166+
const std::string& password,
167+
const std::string& origin)
167168
: Port(thread, factory, network, socket->GetLocalAddress().ipaddr(),
168169
username, password),
169170
requests_(thread),
170171
socket_(socket),
171172
error_(0),
172173
ready_(false),
173174
stun_keepalive_delay_(KEEPALIVE_DELAY) {
175+
requests_.set_origin(origin);
174176
}
175177

176178
UDPPort::UDPPort(rtc::Thread* thread,
@@ -180,14 +182,16 @@ UDPPort::UDPPort(rtc::Thread* thread,
180182
uint16 min_port,
181183
uint16 max_port,
182184
const std::string& username,
183-
const std::string& password)
185+
const std::string& password,
186+
const std::string& origin)
184187
: Port(thread, LOCAL_PORT_TYPE, factory, network, ip, min_port, max_port,
185188
username, password),
186189
requests_(thread),
187190
socket_(NULL),
188191
error_(0),
189192
ready_(false),
190193
stun_keepalive_delay_(KEEPALIVE_DELAY) {
194+
requests_.set_origin(origin);
191195
}
192196

193197
bool UDPPort::Init() {

webrtc/p2p/base/stunport.h

+23-13
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ class UDPPort : public Port {
3333
rtc::Network* network,
3434
rtc::AsyncPacketSocket* socket,
3535
const std::string& username,
36-
const std::string& password) {
37-
UDPPort* port =
38-
new UDPPort(thread, factory, network, socket, username, password);
36+
const std::string& password,
37+
const std::string& origin) {
38+
UDPPort* port = new UDPPort(thread, factory, network, socket,
39+
username, password, origin);
3940
if (!port->Init()) {
4041
delete port;
4142
port = NULL;
@@ -50,15 +51,18 @@ class UDPPort : public Port {
5051
uint16 min_port,
5152
uint16 max_port,
5253
const std::string& username,
53-
const std::string& password) {
54-
UDPPort* port = new UDPPort(thread, factory, network, ip, min_port,
55-
max_port, username, password);
54+
const std::string& password,
55+
const std::string& origin) {
56+
UDPPort* port = new UDPPort(thread, factory, network,
57+
ip, min_port, max_port,
58+
username, password, origin);
5659
if (!port->Init()) {
5760
delete port;
5861
port = NULL;
5962
}
6063
return port;
6164
}
65+
6266
virtual ~UDPPort();
6367

6468
rtc::SocketAddress GetLocalAddress() const {
@@ -105,14 +109,16 @@ class UDPPort : public Port {
105109
uint16 min_port,
106110
uint16 max_port,
107111
const std::string& username,
108-
const std::string& password);
112+
const std::string& password,
113+
const std::string& origin);
109114

110115
UDPPort(rtc::Thread* thread,
111116
rtc::PacketSocketFactory* factory,
112117
rtc::Network* network,
113118
rtc::AsyncPacketSocket* socket,
114119
const std::string& username,
115-
const std::string& password);
120+
const std::string& password,
121+
const std::string& origin);
116122

117123
bool Init();
118124

@@ -208,9 +214,12 @@ class StunPort : public UDPPort {
208214
uint16 min_port, uint16 max_port,
209215
const std::string& username,
210216
const std::string& password,
211-
const ServerAddresses& servers) {
212-
StunPort* port = new StunPort(thread, factory, network, ip, min_port,
213-
max_port, username, password, servers);
217+
const ServerAddresses& servers,
218+
const std::string& origin) {
219+
StunPort* port = new StunPort(thread, factory, network,
220+
ip, min_port, max_port,
221+
username, password, servers,
222+
origin);
214223
if (!port->Init()) {
215224
delete port;
216225
port = NULL;
@@ -233,9 +242,10 @@ class StunPort : public UDPPort {
233242
uint16 max_port,
234243
const std::string& username,
235244
const std::string& password,
236-
const ServerAddresses& servers)
245+
const ServerAddresses& servers,
246+
const std::string& origin)
237247
: UDPPort(thread, factory, network, ip, min_port, max_port, username,
238-
password) {
248+
password, origin) {
239249
// UDPPort will set these to local udp, updating these to STUN.
240250
set_type(STUN_PORT_TYPE);
241251
set_server_addresses(servers);

webrtc/p2p/base/stunport_unittest.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class StunPortTest : public testing::Test,
6565
stun_port_.reset(cricket::StunPort::Create(
6666
rtc::Thread::Current(), &socket_factory_, &network_,
6767
kLocalAddr.ipaddr(), 0, 0, rtc::CreateRandomString(16),
68-
rtc::CreateRandomString(22), stun_servers));
68+
rtc::CreateRandomString(22), stun_servers, std::string()));
6969
stun_port_->set_stun_keepalive_delay(stun_keepalive_delay_);
7070
stun_port_->SignalPortComplete.connect(this,
7171
&StunPortTest::OnPortComplete);
@@ -81,7 +81,8 @@ class StunPortTest : public testing::Test,
8181
stun_port_.reset(cricket::UDPPort::Create(
8282
rtc::Thread::Current(), &socket_factory_,
8383
&network_, socket_.get(),
84-
rtc::CreateRandomString(16), rtc::CreateRandomString(22)));
84+
rtc::CreateRandomString(16), rtc::CreateRandomString(22),
85+
std::string()));
8586
ASSERT_TRUE(stun_port_ != NULL);
8687
ServerAddresses stun_servers;
8788
stun_servers.insert(server_addr);

webrtc/p2p/base/stunrequest.cc

+5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ void StunRequestManager::Send(StunRequest* request) {
4141
void StunRequestManager::SendDelayed(StunRequest* request, int delay) {
4242
request->set_manager(this);
4343
ASSERT(requests_.find(request->id()) == requests_.end());
44+
request->set_origin(origin_);
4445
request->Construct();
4546
requests_[request->id()] = request;
4647
thread_->PostDelayed(delay, request, MSG_STUN_SEND, NULL);
@@ -138,6 +139,10 @@ StunRequest::~StunRequest() {
138139

139140
void StunRequest::Construct() {
140141
if (msg_->type() == 0) {
142+
if (!origin_.empty()) {
143+
msg_->AddAttribute(new StunByteStringAttribute(STUN_ATTR_ORIGIN,
144+
origin_));
145+
}
141146
Prepare(msg_);
142147
ASSERT(msg_->type() != 0);
143148
}

0 commit comments

Comments
 (0)