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 skobalt@gmail.com.

(https://webrtc-codereview.appspot.com/12839005/edit)

R=juberti@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/41409004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@8035 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/AUTHORS b/AUTHORS
index abe7814..c5b7f72 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -9,6 +9,7 @@
 Colin Plumb
 Eric Rescorla, RTFM Inc.
 Giji Gangadharan <giji.g@samsung.com>
+Graham Yoakum <gyoakum@skobalt.com>
 James H. Brown <jbrown@burgoyne.com>
 Jie Mao <maojie0924@gmail.com>
 Luke Weber
@@ -21,6 +22,7 @@
 Ralph Giles <giles@ghostscript.com>
 Robert Nagy
 Ron Rivest
+Ryan Yoakum <ryoakum@skobalt.com>
 Sarah Thompson <sarah@telergy.com>
 Saul Kravitz <Saul.Kravitz@celera.com>
 Silviu Caragea <silviu.cpp@gmail.com>
diff --git a/webrtc/libjingle/session/session_unittest.cc b/webrtc/libjingle/session/session_unittest.cc
index c2ff1a7..e1168db 100644
--- a/webrtc/libjingle/session/session_unittest.cc
+++ b/webrtc/libjingle/session/session_unittest.cc
@@ -598,7 +598,8 @@
       ports_[i] = cricket::UDPPort::Create(
           rtc::Thread::Current(), &socket_factory_,
           &network_, address_.ipaddr(), GetPort(index), GetPort(index),
-          GetUsername(index), GetPassword(index));
+          GetUsername(index), GetPassword(index),
+          std::string());
       AddPort(ports_[i]);
     }
     running_ = true;
diff --git a/webrtc/p2p/base/port.h b/webrtc/p2p/base/port.h
index b78c2c5..4a5c899 100644
--- a/webrtc/p2p/base/port.h
+++ b/webrtc/p2p/base/port.h
@@ -262,7 +262,7 @@
 
   // Debugging description of this port
   virtual std::string ToString() const;
-  rtc::IPAddress& ip() { return ip_; }
+  const rtc::IPAddress& ip() const { return ip_; }
   uint16 min_port() { return min_port_; }
   uint16 max_port() { return max_port_; }
 
diff --git a/webrtc/p2p/base/port_unittest.cc b/webrtc/p2p/base/port_unittest.cc
index f09db28..26e46a6 100644
--- a/webrtc/p2p/base/port_unittest.cc
+++ b/webrtc/p2p/base/port_unittest.cc
@@ -207,7 +207,7 @@
   // Takes ownership of |p1| (but not |p2|).
   TestChannel(Port* p1, Port* p2)
       : ice_mode_(ICEMODE_FULL), src_(p1), dst_(p2), complete_count_(0),
-	conn_(NULL), remote_request_(), nominated_(false) {
+        conn_(NULL), remote_request_(), nominated_(false) {
     src_->SignalPortComplete.connect(
         this, &TestChannel::OnPortComplete);
     src_->SignalUnknownAddress.connect(this, &TestChannel::OnUnknownAddress);
@@ -413,7 +413,8 @@
   UDPPort* CreateUdpPort(const SocketAddress& addr,
                          PacketSocketFactory* socket_factory) {
     UDPPort* port = UDPPort::Create(main_, socket_factory, &network_,
-                                    addr.ipaddr(), 0, 0, username_, password_);
+                                    addr.ipaddr(), 0, 0, username_, password_,
+                                    std::string());
     port->SetIceProtocolType(ice_protocol_);
     return port;
   }
@@ -436,7 +437,8 @@
     stun_servers.insert(kStunAddr);
     StunPort* port = StunPort::Create(main_, factory, &network_,
                                       addr.ipaddr(), 0, 0,
-                                      username_, password_, stun_servers);
+                                      username_, password_, stun_servers,
+                                      std::string());
     port->SetIceProtocolType(ice_protocol_);
     return port;
   }
@@ -461,8 +463,9 @@
     TurnPort* port = TurnPort::Create(main_, socket_factory, &network_,
                                       addr.ipaddr(), 0, 0,
                                       username_, password_, ProtocolAddress(
-                                          server_addr, PROTO_UDP),
-                                      kRelayCredentials, 0);
+                                         server_addr, PROTO_UDP),
+                                      kRelayCredentials, 0,
+                                      std::string());
     port->SetIceProtocolType(ice_protocol_);
     return port;
   }
diff --git a/webrtc/p2p/base/portallocator.h b/webrtc/p2p/base/portallocator.h
index 65aab44..1a3735b 100644
--- a/webrtc/p2p/base/portallocator.h
+++ b/webrtc/p2p/base/portallocator.h
@@ -167,6 +167,10 @@
     return true;
   }
 
+  // Gets/Sets the Origin value used for WebRTC STUN requests.
+  const std::string& origin() const { return origin_; }
+  void set_origin(const std::string& origin) { origin_ = origin; }
+
  protected:
   virtual PortAllocatorSession* CreateSessionInternal(
       const std::string& content_name,
@@ -185,6 +189,7 @@
   SessionMuxerMap muxers_;
   bool allow_tcp_listen_;
   uint32 candidate_filter_;
+  std::string origin_;
 };
 
 }  // namespace cricket
diff --git a/webrtc/p2p/base/stun.cc b/webrtc/p2p/base/stun.cc
index 60367fa..866621f 100644
--- a/webrtc/p2p/base/stun.cc
+++ b/webrtc/p2p/base/stun.cc
@@ -387,6 +387,7 @@
     case STUN_ATTR_SOFTWARE:            return STUN_VALUE_BYTE_STRING;
     case STUN_ATTR_ALTERNATE_SERVER:    return STUN_VALUE_ADDRESS;
     case STUN_ATTR_FINGERPRINT:         return STUN_VALUE_UINT32;
+    case STUN_ATTR_ORIGIN:              return STUN_VALUE_BYTE_STRING;
     case STUN_ATTR_RETRANSMIT_COUNT:    return STUN_VALUE_UINT32;
     default:                            return STUN_VALUE_UNKNOWN;
   }
diff --git a/webrtc/p2p/base/stun.h b/webrtc/p2p/base/stun.h
index 0f600db..4bf6547 100644
--- a/webrtc/p2p/base/stun.h
+++ b/webrtc/p2p/base/stun.h
@@ -48,6 +48,7 @@
   STUN_ATTR_SOFTWARE                    = 0x8022,  // ByteString
   STUN_ATTR_ALTERNATE_SERVER            = 0x8023,  // Address
   STUN_ATTR_FINGERPRINT                 = 0x8028,  // UInt32
+  STUN_ATTR_ORIGIN                      = 0x802F,  // ByteString
   STUN_ATTR_RETRANSMIT_COUNT            = 0xFF00   // UInt32
 };
 
diff --git a/webrtc/p2p/base/stun_unittest.cc b/webrtc/p2p/base/stun_unittest.cc
index 396beb6..9d5779d7 100644
--- a/webrtc/p2p/base/stun_unittest.cc
+++ b/webrtc/p2p/base/stun_unittest.cc
@@ -191,6 +191,20 @@
   0x69, 0x7a, 0x65, 0x64
 };
 
+static const unsigned char kStunMessageWithOriginAttribute[] = {
+  0x00, 0x01, 0x00, 0x18,  // message header (binding request), length 24
+  0x21, 0x12, 0xA4, 0x42,  // magic cookie
+  0x29, 0x1f, 0xcd, 0x7c,  // transaction id
+  0xba, 0x58, 0xab, 0xd7,
+  0xf2, 0x41, 0x01, 0x00,
+  0x80, 0x2f, 0x00, 0x12,  // origin attribute (length 18)
+  0x68, 0x74, 0x74, 0x70,  // http://example.com
+  0x3A, 0x2F, 0x2F, 0x65,
+  0x78, 0x61, 0x6d, 0x70,
+  0x6c, 0x65, 0x2e, 0x63,
+  0x6f, 0x6d, 0x00, 0x00,
+};
+
 // Sample messages with an invalid length Field
 
 // The actual length in bytes of the invalid messages (including STUN header)
@@ -472,6 +486,7 @@
 const char kTestUserName1[] = "abcdefgh";
 const char kTestUserName2[] = "abc";
 const char kTestErrorReason[] = "Unauthorized";
+const char kTestOrigin[] = "http://example.com";
 const int kTestErrorClass = 4;
 const int kTestErrorNumber = 1;
 const int kTestErrorCode = 401;
@@ -1020,6 +1035,16 @@
   EXPECT_EQ(kTestUserName2, username->GetString());
 }
 
+TEST_F(StunTest, ReadMessageWithOriginAttribute) {
+  StunMessage msg;
+  size_t size = ReadStunMessage(&msg, kStunMessageWithOriginAttribute);
+  CheckStunHeader(msg, STUN_BINDING_REQUEST, size);
+  const StunByteStringAttribute* origin =
+      msg.GetByteString(STUN_ATTR_ORIGIN);
+  ASSERT_TRUE(origin != NULL);
+  EXPECT_EQ(kTestOrigin, origin->GetString());
+}
+
 TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) {
   StunMessage msg;
   size_t size = sizeof(kStunMessageWithErrorAttribute);
@@ -1066,6 +1091,25 @@
             memcmp(out.Data(), kStunMessageWithUInt16ListAttribute, size - 2));
 }
 
+TEST_F(StunTest, WriteMessageWithOriginAttribute) {
+  StunMessage msg;
+  size_t size = sizeof(kStunMessageWithOriginAttribute);
+
+  msg.SetType(STUN_BINDING_REQUEST);
+  msg.SetTransactionID(
+      std::string(reinterpret_cast<const char*>(kTestTransactionId1),
+                  kStunTransactionIdLength));
+  StunByteStringAttribute* origin =
+      new StunByteStringAttribute(STUN_ATTR_ORIGIN, kTestOrigin);
+  EXPECT_TRUE(msg.AddAttribute(origin));
+
+  rtc::ByteBuffer out;
+  EXPECT_TRUE(msg.Write(&out));
+  ASSERT_EQ(size, out.Length());
+  // Check everything up to the padding
+  ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithOriginAttribute, size - 2));
+}
+
 // Test that we fail to read messages with invalid lengths.
 void CheckFailureToRead(const unsigned char* testcase, size_t length) {
   StunMessage msg;
diff --git a/webrtc/p2p/base/stunport.cc b/webrtc/p2p/base/stunport.cc
index 5ef9e9e..fe125ec 100644
--- a/webrtc/p2p/base/stunport.cc
+++ b/webrtc/p2p/base/stunport.cc
@@ -163,7 +163,8 @@
                  rtc::Network* network,
                  rtc::AsyncPacketSocket* socket,
                  const std::string& username,
-                 const std::string& password)
+                 const std::string& password,
+                 const std::string& origin)
     : Port(thread, factory, network, socket->GetLocalAddress().ipaddr(),
            username, password),
       requests_(thread),
@@ -171,6 +172,7 @@
       error_(0),
       ready_(false),
       stun_keepalive_delay_(KEEPALIVE_DELAY) {
+  requests_.set_origin(origin);
 }
 
 UDPPort::UDPPort(rtc::Thread* thread,
@@ -180,7 +182,8 @@
                  uint16 min_port,
                  uint16 max_port,
                  const std::string& username,
-                 const std::string& password)
+                 const std::string& password,
+                 const std::string& origin)
     : Port(thread, LOCAL_PORT_TYPE, factory, network, ip, min_port, max_port,
            username, password),
       requests_(thread),
@@ -188,6 +191,7 @@
       error_(0),
       ready_(false),
       stun_keepalive_delay_(KEEPALIVE_DELAY) {
+  requests_.set_origin(origin);
 }
 
 bool UDPPort::Init() {
diff --git a/webrtc/p2p/base/stunport.h b/webrtc/p2p/base/stunport.h
index 9ca6046..d840a97 100644
--- a/webrtc/p2p/base/stunport.h
+++ b/webrtc/p2p/base/stunport.h
@@ -33,9 +33,10 @@
                          rtc::Network* network,
                          rtc::AsyncPacketSocket* socket,
                          const std::string& username,
-                         const std::string& password) {
-    UDPPort* port =
-        new UDPPort(thread, factory, network, socket, username, password);
+                         const std::string& password,
+                         const std::string& origin) {
+    UDPPort* port = new UDPPort(thread, factory, network, socket,
+                                username, password, origin);
     if (!port->Init()) {
       delete port;
       port = NULL;
@@ -50,15 +51,18 @@
                          uint16 min_port,
                          uint16 max_port,
                          const std::string& username,
-                         const std::string& password) {
-    UDPPort* port = new UDPPort(thread, factory, network, ip, min_port,
-                                max_port, username, password);
+                         const std::string& password,
+                         const std::string& origin) {
+    UDPPort* port = new UDPPort(thread, factory, network,
+                                ip, min_port, max_port,
+                                username, password, origin);
     if (!port->Init()) {
       delete port;
       port = NULL;
     }
     return port;
   }
+
   virtual ~UDPPort();
 
   rtc::SocketAddress GetLocalAddress() const {
@@ -105,14 +109,16 @@
           uint16 min_port,
           uint16 max_port,
           const std::string& username,
-          const std::string& password);
+          const std::string& password,
+          const std::string& origin);
 
   UDPPort(rtc::Thread* thread,
           rtc::PacketSocketFactory* factory,
           rtc::Network* network,
           rtc::AsyncPacketSocket* socket,
           const std::string& username,
-          const std::string& password);
+          const std::string& password,
+          const std::string& origin);
 
   bool Init();
 
@@ -208,9 +214,12 @@
                           uint16 min_port, uint16 max_port,
                           const std::string& username,
                           const std::string& password,
-                          const ServerAddresses& servers) {
-    StunPort* port = new StunPort(thread, factory, network, ip, min_port,
-                                  max_port, username, password, servers);
+                          const ServerAddresses& servers,
+                          const std::string& origin) {
+    StunPort* port = new StunPort(thread, factory, network,
+                                  ip, min_port, max_port,
+                                  username, password, servers,
+                                  origin);
     if (!port->Init()) {
       delete port;
       port = NULL;
@@ -233,9 +242,10 @@
            uint16 max_port,
            const std::string& username,
            const std::string& password,
-           const ServerAddresses& servers)
+           const ServerAddresses& servers,
+           const std::string& origin)
      : UDPPort(thread, factory, network, ip, min_port, max_port, username,
-               password) {
+               password, origin) {
     // UDPPort will set these to local udp, updating these to STUN.
     set_type(STUN_PORT_TYPE);
     set_server_addresses(servers);
diff --git a/webrtc/p2p/base/stunport_unittest.cc b/webrtc/p2p/base/stunport_unittest.cc
index 81b6808..8b6e81b 100644
--- a/webrtc/p2p/base/stunport_unittest.cc
+++ b/webrtc/p2p/base/stunport_unittest.cc
@@ -65,7 +65,7 @@
     stun_port_.reset(cricket::StunPort::Create(
         rtc::Thread::Current(), &socket_factory_, &network_,
         kLocalAddr.ipaddr(), 0, 0, rtc::CreateRandomString(16),
-        rtc::CreateRandomString(22), stun_servers));
+        rtc::CreateRandomString(22), stun_servers, std::string()));
     stun_port_->set_stun_keepalive_delay(stun_keepalive_delay_);
     stun_port_->SignalPortComplete.connect(this,
         &StunPortTest::OnPortComplete);
@@ -81,7 +81,8 @@
     stun_port_.reset(cricket::UDPPort::Create(
         rtc::Thread::Current(), &socket_factory_,
         &network_, socket_.get(),
-        rtc::CreateRandomString(16), rtc::CreateRandomString(22)));
+        rtc::CreateRandomString(16), rtc::CreateRandomString(22),
+        std::string()));
     ASSERT_TRUE(stun_port_ != NULL);
     ServerAddresses stun_servers;
     stun_servers.insert(server_addr);
diff --git a/webrtc/p2p/base/stunrequest.cc b/webrtc/p2p/base/stunrequest.cc
index 65eb027..a6f4c15 100644
--- a/webrtc/p2p/base/stunrequest.cc
+++ b/webrtc/p2p/base/stunrequest.cc
@@ -41,6 +41,7 @@
 void StunRequestManager::SendDelayed(StunRequest* request, int delay) {
   request->set_manager(this);
   ASSERT(requests_.find(request->id()) == requests_.end());
+  request->set_origin(origin_);
   request->Construct();
   requests_[request->id()] = request;
   thread_->PostDelayed(delay, request, MSG_STUN_SEND, NULL);
@@ -138,6 +139,10 @@
 
 void StunRequest::Construct() {
   if (msg_->type() == 0) {
+    if (!origin_.empty()) {
+      msg_->AddAttribute(new StunByteStringAttribute(STUN_ATTR_ORIGIN,
+          origin_));
+    }
     Prepare(msg_);
     ASSERT(msg_->type() != 0);
   }
diff --git a/webrtc/p2p/base/stunrequest.h b/webrtc/p2p/base/stunrequest.h
index 5fefc2f..6a4bdc0 100644
--- a/webrtc/p2p/base/stunrequest.h
+++ b/webrtc/p2p/base/stunrequest.h
@@ -24,7 +24,7 @@
 // Manages a set of STUN requests, sending and resending until we receive a
 // response or determine that the request has timed out.
 class StunRequestManager {
-public:
+ public:
   StunRequestManager(rtc::Thread* thread);
   ~StunRequestManager();
 
@@ -46,14 +46,18 @@
 
   bool empty() { return requests_.empty(); }
 
+  // Set the Origin header for outgoing stun messages.
+  void set_origin(const std::string& origin) { origin_ = origin; }
+
   // Raised when there are bytes to be sent.
   sigslot::signal3<const void*, size_t, StunRequest*> SignalSendPacket;
 
-private:
+ private:
   typedef std::map<std::string, StunRequest*> RequestMap;
 
   rtc::Thread* thread_;
   RequestMap requests_;
+  std::string origin_;
 
   friend class StunRequest;
 };
@@ -61,7 +65,7 @@
 // Represents an individual request to be sent.  The STUN message can either be
 // constructed beforehand or built on demand.
 class StunRequest : public rtc::MessageHandler {
-public:
+ public:
   StunRequest();
   StunRequest(StunMessage* request);
   virtual ~StunRequest();
@@ -75,6 +79,10 @@
   // Returns the transaction ID of this request.
   const std::string& id() { return msg_->transaction_id(); }
 
+  // the origin value
+  const std::string& origin() const { return origin_; }
+  void set_origin(const std::string& origin) { origin_ = origin; }
+
   // Returns the STUN type of the request message.
   int type();
 
@@ -84,9 +92,10 @@
   // Time elapsed since last send (in ms)
   uint32 Elapsed() const;
 
-protected:
+ protected:
   int count_;
   bool timeout_;
+  std::string origin_;
 
   // Fills in a request object to be sent.  Note that request's transaction ID
   // will already be set and cannot be changed.
@@ -98,7 +107,7 @@
   virtual void OnTimeout() {}
   virtual int GetNextDelay();
 
-private:
+ private:
   void set_manager(StunRequestManager* manager);
 
   // Handles messages for sending and timeout.
diff --git a/webrtc/p2p/base/testturnserver.h b/webrtc/p2p/base/testturnserver.h
index 19f73e7..7be35e5 100644
--- a/webrtc/p2p/base/testturnserver.h
+++ b/webrtc/p2p/base/testturnserver.h
@@ -87,6 +87,19 @@
     }
   }
 
+  // Finds the first allocation in the server allocation map with a source
+  // ip and port matching the socket address provided.
+  TurnServerAllocation* FindAllocation(const rtc::SocketAddress& src) {
+    const TurnServer::AllocationMap& map = server_.allocations();
+    for (TurnServer::AllocationMap::const_iterator it = map.begin();
+        it != map.end(); ++it) {
+      if (src == it->first.src()) {
+        return it->second;
+      }
+    }
+    return NULL;
+  }
+
  private:
   // For this test server, succeed if the password is the same as the username.
   // Obviously, do not use this in a production environment.
diff --git a/webrtc/p2p/base/turnport.cc b/webrtc/p2p/base/turnport.cc
index 8994aa8..2ea3ff4 100644
--- a/webrtc/p2p/base/turnport.cc
+++ b/webrtc/p2p/base/turnport.cc
@@ -164,7 +164,8 @@
                    const std::string& password,
                    const ProtocolAddress& server_address,
                    const RelayCredentials& credentials,
-                   int server_priority)
+                   int server_priority,
+                   const std::string& origin)
     : Port(thread, factory, network, socket->GetLocalAddress().ipaddr(),
            username, password),
       server_address_(server_address),
@@ -178,6 +179,7 @@
       server_priority_(server_priority),
       allocate_mismatch_retries_(0) {
   request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
+  request_manager_.set_origin(origin);
 }
 
 TurnPort::TurnPort(rtc::Thread* thread,
@@ -190,7 +192,8 @@
                    const std::string& password,
                    const ProtocolAddress& server_address,
                    const RelayCredentials& credentials,
-                   int server_priority)
+                   int server_priority,
+                   const std::string& origin)
     : Port(thread, RELAY_PORT_TYPE, factory, network, ip, min_port, max_port,
            username, password),
       server_address_(server_address),
@@ -204,6 +207,7 @@
       server_priority_(server_priority),
       allocate_mismatch_retries_(0) {
   request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
+  request_manager_.set_origin(origin);
 }
 
 TurnPort::~TurnPort() {
@@ -219,6 +223,10 @@
   }
 }
 
+rtc::SocketAddress TurnPort::GetLocalAddress() const {
+  return socket_ ? socket_->GetLocalAddress() : rtc::SocketAddress();
+}
+
 void TurnPort::PrepareAddress() {
   if (credentials_.username.empty() ||
       credentials_.password.empty()) {
diff --git a/webrtc/p2p/base/turnport.h b/webrtc/p2p/base/turnport.h
index 4ed77a0..3d3dad3 100644
--- a/webrtc/p2p/base/turnport.h
+++ b/webrtc/p2p/base/turnport.h
@@ -41,9 +41,10 @@
                           const std::string& password,  // ice password.
                           const ProtocolAddress& server_address,
                           const RelayCredentials& credentials,
-                          int server_priority) {
+                          int server_priority,
+                          const std::string& origin) {
     return new TurnPort(thread, factory, network, socket, username, password,
-                        server_address, credentials, server_priority);
+                        server_address, credentials, server_priority, origin);
   }
 
   static TurnPort* Create(rtc::Thread* thread,
@@ -56,15 +57,18 @@
                           const std::string& password,  // ice password.
                           const ProtocolAddress& server_address,
                           const RelayCredentials& credentials,
-                          int server_priority) {
+                          int server_priority,
+                          const std::string& origin) {
     return new TurnPort(thread, factory, network, ip, min_port, max_port,
                         username, password, server_address, credentials,
-                        server_priority);
+                        server_priority, origin);
   }
 
   virtual ~TurnPort();
 
   const ProtocolAddress& server_address() const { return server_address_; }
+  // Returns an empty address if the local address has not been assigned.
+  rtc::SocketAddress GetLocalAddress() const;
 
   bool connected() const { return connected_; }
   const RelayCredentials& credentials() const { return credentials_; }
@@ -129,7 +133,8 @@
            const std::string& password,
            const ProtocolAddress& server_address,
            const RelayCredentials& credentials,
-           int server_priority);
+           int server_priority,
+           const std::string& origin);
 
   TurnPort(rtc::Thread* thread,
            rtc::PacketSocketFactory* factory,
@@ -141,7 +146,8 @@
            const std::string& password,
            const ProtocolAddress& server_address,
            const RelayCredentials& credentials,
-           int server_priority);
+           int server_priority,
+           const std::string& origin);
 
  private:
   enum {
diff --git a/webrtc/p2p/base/turnport_unittest.cc b/webrtc/p2p/base/turnport_unittest.cc
index 748ed9d..e871aca 100644
--- a/webrtc/p2p/base/turnport_unittest.cc
+++ b/webrtc/p2p/base/turnport_unittest.cc
@@ -60,6 +60,7 @@
 static const char kIcePwd2[] = "TESTICEPWD00000000000002";
 static const char kTurnUsername[] = "test";
 static const char kTurnPassword[] = "test";
+static const char kTestOrigin[] = "http://example.com";
 static const unsigned int kTimeout = 1000;
 
 static const cricket::ProtocolAddress kTurnUdpProtoAddr(
@@ -193,7 +194,30 @@
     turn_port_.reset(TurnPort::Create(main_, &socket_factory_, &network_,
                                  local_address.ipaddr(), 0, 0,
                                  kIceUfrag1, kIcePwd1,
-                                 server_address, credentials, 0));
+                                 server_address, credentials, 0,
+                                 std::string()));
+    // Set ICE protocol type to ICEPROTO_RFC5245, as port by default will be
+    // in Hybrid mode. Protocol type is necessary to send correct type STUN ping
+    // messages.
+    // This TURN port will be the controlling.
+    turn_port_->SetIceProtocolType(cricket::ICEPROTO_RFC5245);
+    turn_port_->SetIceRole(cricket::ICEROLE_CONTROLLING);
+    ConnectSignals();
+  }
+
+  // Should be identical to CreateTurnPort but specifies an origin value
+  // when creating the instance of TurnPort.
+  void CreateTurnPortWithOrigin(const rtc::SocketAddress& local_address,
+                                const std::string& username,
+                                const std::string& password,
+                                const cricket::ProtocolAddress& server_address,
+                                const std::string& origin) {
+    cricket::RelayCredentials credentials(username, password);
+    turn_port_.reset(TurnPort::Create(main_, &socket_factory_, &network_,
+                                 local_address.ipaddr(), 0, 0,
+                                 kIceUfrag1, kIcePwd1,
+                                 server_address, credentials, 0,
+                                 origin));
     // Set ICE protocol type to ICEPROTO_RFC5245, as port by default will be
     // in Hybrid mode. Protocol type is necessary to send correct type STUN ping
     // messages.
@@ -219,7 +243,7 @@
     cricket::RelayCredentials credentials(username, password);
     turn_port_.reset(cricket::TurnPort::Create(
         main_, &socket_factory_, &network_, socket_.get(),
-        kIceUfrag1, kIcePwd1, server_address, credentials, 0));
+        kIceUfrag1, kIcePwd1, server_address, credentials, 0, std::string()));
     // Set ICE protocol type to ICEPROTO_RFC5245, as port by default will be
     // in Hybrid mode. Protocol type is necessary to send correct type STUN ping
     // messages.
@@ -242,7 +266,8 @@
   void CreateUdpPort() {
     udp_port_.reset(UDPPort::Create(main_, &socket_factory_, &network_,
                                     kLocalAddr2.ipaddr(), 0, 0,
-                                    kIceUfrag2, kIcePwd2));
+                                    kIceUfrag2, kIcePwd2,
+                                    std::string()));
     // Set protocol type to RFC5245, as turn port is also in same mode.
     // UDP port will be controlled.
     udp_port_->SetIceProtocolType(cricket::ICEPROTO_RFC5245);
@@ -685,6 +710,17 @@
   EXPECT_NE(0, turn_port_->Candidates()[0].address().port());
 }
 
+TEST_F(TurnPortTest, TestOriginHeader) {
+  CreateTurnPortWithOrigin(kLocalAddr1, kTurnUsername, kTurnPassword,
+                           kTurnUdpProtoAddr, kTestOrigin);
+  turn_port_->PrepareAddress();
+  EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+  ASSERT_GT(turn_server_.server()->allocations().size(), 0U);
+  SocketAddress local_address = turn_port_->GetLocalAddress();
+  ASSERT_TRUE(turn_server_.FindAllocation(local_address) != NULL);
+  EXPECT_EQ(kTestOrigin, turn_server_.FindAllocation(local_address)->origin());
+}
+
 // This test verifies any FD's are not leaked after TurnPort is destroyed.
 // https://code.google.com/p/webrtc/issues/detail?id=2651
 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
diff --git a/webrtc/p2p/base/turnserver.cc b/webrtc/p2p/base/turnserver.cc
index 8605e98..7d82d55 100644
--- a/webrtc/p2p/base/turnserver.cc
+++ b/webrtc/p2p/base/turnserver.cc
@@ -45,88 +45,15 @@
   return ((msg_type & 0xC000) == 0x4000);
 }
 
-// IDs used for posted messages for TurnServer::Allocation.
+// IDs used for posted messages for TurnServerAllocation.
 enum {
   MSG_ALLOCATION_TIMEOUT,
 };
 
-// Encapsulates a TURN allocation.
-// The object is created when an allocation request is received, and then
-// handles TURN messages (via HandleTurnMessage) and channel data messages
-// (via HandleChannelData) for this allocation when received by the server.
-// The object self-deletes and informs the server if its lifetime timer expires.
-class TurnServer::Allocation : public rtc::MessageHandler,
-                               public sigslot::has_slots<> {
- public:
-  Allocation(TurnServer* server_,
-             rtc::Thread* thread, const Connection& conn,
-             rtc::AsyncPacketSocket* server_socket,
-             const std::string& key);
-  virtual ~Allocation();
-
-  Connection* conn() { return &conn_; }
-  const std::string& key() const { return key_; }
-  const std::string& transaction_id() const { return transaction_id_; }
-  const std::string& username() const { return username_; }
-  const std::string& last_nonce() const { return last_nonce_; }
-  void set_last_nonce(const std::string& nonce) { last_nonce_ = nonce; }
-
-  std::string ToString() const;
-
-  void HandleTurnMessage(const TurnMessage* msg);
-  void HandleChannelData(const char* data, size_t size);
-
-  sigslot::signal1<Allocation*> SignalDestroyed;
-
- private:
-  typedef std::list<Permission*> PermissionList;
-  typedef std::list<Channel*> ChannelList;
-
-  void HandleAllocateRequest(const TurnMessage* msg);
-  void HandleRefreshRequest(const TurnMessage* msg);
-  void HandleSendIndication(const TurnMessage* msg);
-  void HandleCreatePermissionRequest(const TurnMessage* msg);
-  void HandleChannelBindRequest(const TurnMessage* msg);
-
-  void OnExternalPacket(rtc::AsyncPacketSocket* socket,
-                        const char* data, size_t size,
-                        const rtc::SocketAddress& addr,
-                        const rtc::PacketTime& packet_time);
-
-  static int ComputeLifetime(const TurnMessage* msg);
-  bool HasPermission(const rtc::IPAddress& addr);
-  void AddPermission(const rtc::IPAddress& addr);
-  Permission* FindPermission(const rtc::IPAddress& addr) const;
-  Channel* FindChannel(int channel_id) const;
-  Channel* FindChannel(const rtc::SocketAddress& addr) const;
-
-  void SendResponse(TurnMessage* msg);
-  void SendBadRequestResponse(const TurnMessage* req);
-  void SendErrorResponse(const TurnMessage* req, int code,
-                         const std::string& reason);
-  void SendExternal(const void* data, size_t size,
-                    const rtc::SocketAddress& peer);
-
-  void OnPermissionDestroyed(Permission* perm);
-  void OnChannelDestroyed(Channel* channel);
-  virtual void OnMessage(rtc::Message* msg);
-
-  TurnServer* server_;
-  rtc::Thread* thread_;
-  Connection conn_;
-  rtc::scoped_ptr<rtc::AsyncPacketSocket> external_socket_;
-  std::string key_;
-  std::string transaction_id_;
-  std::string username_;
-  std::string last_nonce_;
-  PermissionList perms_;
-  ChannelList channels_;
-};
-
 // Encapsulates a TURN permission.
 // The object is created when a create permission request is received by an
 // allocation, and self-deletes when its lifetime timer expires.
-class TurnServer::Permission : public rtc::MessageHandler {
+class TurnServerAllocation::Permission : public rtc::MessageHandler {
  public:
   Permission(rtc::Thread* thread, const rtc::IPAddress& peer);
   ~Permission();
@@ -146,7 +73,7 @@
 // Encapsulates a TURN channel binding.
 // The object is created when a channel bind request is received by an
 // allocation, and self-deletes when its lifetime timer expires.
-class TurnServer::Channel : public rtc::MessageHandler {
+class TurnServerAllocation::Channel : public rtc::MessageHandler {
  public:
   Channel(rtc::Thread* thread, int id,
                      const rtc::SocketAddress& peer);
@@ -187,6 +114,7 @@
   return true;
 }
 
+
 TurnServer::TurnServer(rtc::Thread* thread)
     : thread_(thread),
       nonce_key_(rtc::CreateRandomString(kNonceKeySize)),
@@ -271,21 +199,21 @@
   }
   InternalSocketMap::iterator iter = server_sockets_.find(socket);
   ASSERT(iter != server_sockets_.end());
-  Connection conn(addr, iter->second, socket);
+  TurnServerConnection conn(addr, iter->second, socket);
   uint16 msg_type = rtc::GetBE16(data);
   if (!IsTurnChannelData(msg_type)) {
     // This is a STUN message.
     HandleStunMessage(&conn, data, size);
   } else {
     // This is a channel message; let the allocation handle it.
-    Allocation* allocation = FindAllocation(&conn);
+    TurnServerAllocation* allocation = FindAllocation(&conn);
     if (allocation) {
       allocation->HandleChannelData(data, size);
     }
   }
 }
 
-void TurnServer::HandleStunMessage(Connection* conn, const char* data,
+void TurnServer::HandleStunMessage(TurnServerConnection* conn, const char* data,
                                    size_t size) {
   TurnMessage msg;
   rtc::ByteBuffer buf(data, size);
@@ -311,7 +239,7 @@
 
   // Look up the key that we'll use to validate the M-I. If we have an
   // existing allocation, the key will already be cached.
-  Allocation* allocation = FindAllocation(conn);
+  TurnServerAllocation* allocation = FindAllocation(conn);
   std::string key;
   if (!allocation) {
     GetKey(&msg, &key);
@@ -359,7 +287,7 @@
   return (auth_hook_ != NULL && auth_hook_->GetKey(username, realm_, key));
 }
 
-bool TurnServer::CheckAuthorization(Connection* conn,
+bool TurnServer::CheckAuthorization(TurnServerConnection* conn,
                                     const StunMessage* msg,
                                     const char* data, size_t size,
                                     const std::string& key) {
@@ -404,7 +332,7 @@
   }
 
   // Fail if one-time-use nonce feature is enabled.
-  Allocation* allocation = FindAllocation(conn);
+  TurnServerAllocation* allocation = FindAllocation(conn);
   if (enable_otu_nonce_ && allocation &&
       allocation->last_nonce() == nonce_attr->GetString()) {
     SendErrorResponseWithRealmAndNonce(conn, msg, STUN_ERROR_STALE_NONCE,
@@ -419,7 +347,7 @@
   return true;
 }
 
-void TurnServer::HandleBindingRequest(Connection* conn,
+void TurnServer::HandleBindingRequest(TurnServerConnection* conn,
                                       const StunMessage* req) {
   StunMessage response;
   InitResponse(req, &response);
@@ -433,7 +361,7 @@
   SendStun(conn, &response);
 }
 
-void TurnServer::HandleAllocateRequest(Connection* conn,
+void TurnServer::HandleAllocateRequest(TurnServerConnection* conn,
                                        const TurnMessage* msg,
                                        const std::string& key) {
   // Check the parameters in the request.
@@ -455,7 +383,7 @@
 
   // Create the allocation and let it send the success response.
   // If the actual socket allocation fails, send an internal error.
-  Allocation* alloc = CreateAllocation(conn, proto, key);
+  TurnServerAllocation* alloc = CreateAllocation(conn, proto, key);
   if (alloc) {
     alloc->HandleTurnMessage(msg);
   } else {
@@ -499,14 +427,14 @@
   return rtc::TimeSince(then) < kNonceTimeout;
 }
 
-TurnServer::Allocation* TurnServer::FindAllocation(Connection* conn) {
+TurnServerAllocation* TurnServer::FindAllocation(TurnServerConnection* conn) {
   AllocationMap::const_iterator it = allocations_.find(*conn);
   return (it != allocations_.end()) ? it->second : NULL;
 }
 
-TurnServer::Allocation* TurnServer::CreateAllocation(Connection* conn,
-                                                     int proto,
-                                                     const std::string& key) {
+TurnServerAllocation* TurnServer::CreateAllocation(TurnServerConnection* conn,
+                                                   int proto,
+                                                   const std::string& key) {
   rtc::AsyncPacketSocket* external_socket = (external_socket_factory_) ?
       external_socket_factory_->CreateUdpSocket(external_addr_, 0, 0) : NULL;
   if (!external_socket) {
@@ -514,14 +442,14 @@
   }
 
   // The Allocation takes ownership of the socket.
-  Allocation* allocation = new Allocation(this,
+  TurnServerAllocation* allocation = new TurnServerAllocation(this,
       thread_, *conn, external_socket, key);
   allocation->SignalDestroyed.connect(this, &TurnServer::OnAllocationDestroyed);
   allocations_[*conn] = allocation;
   return allocation;
 }
 
-void TurnServer::SendErrorResponse(Connection* conn,
+void TurnServer::SendErrorResponse(TurnServerConnection* conn,
                                    const StunMessage* req,
                                    int code, const std::string& reason) {
   TurnMessage resp;
@@ -532,7 +460,7 @@
 }
 
 void TurnServer::SendErrorResponseWithRealmAndNonce(
-    Connection* conn, const StunMessage* msg,
+    TurnServerConnection* conn, const StunMessage* msg,
     int code, const std::string& reason) {
   TurnMessage resp;
   InitErrorResponse(msg, code, reason, &resp);
@@ -544,7 +472,7 @@
 }
 
 void TurnServer::SendErrorResponseWithAlternateServer(
-    Connection* conn, const StunMessage* msg,
+    TurnServerConnection* conn, const StunMessage* msg,
     const rtc::SocketAddress& addr) {
   TurnMessage resp;
   InitErrorResponse(msg, STUN_ERROR_TRY_ALTERNATE,
@@ -554,7 +482,7 @@
   SendStun(conn, &resp);
 }
 
-void TurnServer::SendStun(Connection* conn, StunMessage* msg) {
+void TurnServer::SendStun(TurnServerConnection* conn, StunMessage* msg) {
   rtc::ByteBuffer buf;
   // Add a SOFTWARE attribute if one is set.
   if (!software_.empty()) {
@@ -565,13 +493,13 @@
   Send(conn, buf);
 }
 
-void TurnServer::Send(Connection* conn,
+void TurnServer::Send(TurnServerConnection* conn,
                       const rtc::ByteBuffer& buf) {
   rtc::PacketOptions options;
   conn->socket()->SendTo(buf.Data(), buf.Length(), conn->src(), options);
 }
 
-void TurnServer::OnAllocationDestroyed(Allocation* allocation) {
+void TurnServer::OnAllocationDestroyed(TurnServerAllocation* allocation) {
   // Removing the internal socket if the connection is not udp.
   rtc::AsyncPacketSocket* socket = allocation->conn()->socket();
   InternalSocketMap::iterator iter = server_sockets_.find(socket);
@@ -598,24 +526,24 @@
   }
 }
 
-TurnServer::Connection::Connection(const rtc::SocketAddress& src,
-                                   ProtocolType proto,
-                                   rtc::AsyncPacketSocket* socket)
+TurnServerConnection::TurnServerConnection(const rtc::SocketAddress& src,
+                                           ProtocolType proto,
+                                           rtc::AsyncPacketSocket* socket)
     : src_(src),
       dst_(socket->GetRemoteAddress()),
       proto_(proto),
       socket_(socket) {
 }
 
-bool TurnServer::Connection::operator==(const Connection& c) const {
+bool TurnServerConnection::operator==(const TurnServerConnection& c) const {
   return src_ == c.src_ && dst_ == c.dst_ && proto_ == c.proto_;
 }
 
-bool TurnServer::Connection::operator<(const Connection& c) const {
+bool TurnServerConnection::operator<(const TurnServerConnection& c) const {
   return src_ < c.src_ || dst_ < c.dst_ || proto_ < c.proto_;
 }
 
-std::string TurnServer::Connection::ToString() const {
+std::string TurnServerConnection::ToString() const {
   const char* const kProtos[] = {
       "unknown", "udp", "tcp", "ssltcp"
   };
@@ -624,21 +552,21 @@
   return ost.str();
 }
 
-TurnServer::Allocation::Allocation(TurnServer* server,
-                                   rtc::Thread* thread,
-                                   const Connection& conn,
-                                   rtc::AsyncPacketSocket* socket,
-                                   const std::string& key)
+TurnServerAllocation::TurnServerAllocation(TurnServer* server,
+                                           rtc::Thread* thread,
+                                           const TurnServerConnection& conn,
+                                           rtc::AsyncPacketSocket* socket,
+                                           const std::string& key)
     : server_(server),
       thread_(thread),
       conn_(conn),
       external_socket_(socket),
       key_(key) {
   external_socket_->SignalReadPacket.connect(
-      this, &TurnServer::Allocation::OnExternalPacket);
+      this, &TurnServerAllocation::OnExternalPacket);
 }
 
-TurnServer::Allocation::~Allocation() {
+TurnServerAllocation::~TurnServerAllocation() {
   for (ChannelList::iterator it = channels_.begin();
        it != channels_.end(); ++it) {
     delete *it;
@@ -651,13 +579,13 @@
   LOG_J(LS_INFO, this) << "Allocation destroyed";
 }
 
-std::string TurnServer::Allocation::ToString() const {
+std::string TurnServerAllocation::ToString() const {
   std::ostringstream ost;
   ost << "Alloc[" << conn_.ToString() << "]";
   return ost.str();
 }
 
-void TurnServer::Allocation::HandleTurnMessage(const TurnMessage* msg) {
+void TurnServerAllocation::HandleTurnMessage(const TurnMessage* msg) {
   ASSERT(msg != NULL);
   switch (msg->type()) {
     case STUN_ALLOCATE_REQUEST:
@@ -682,13 +610,18 @@
   }
 }
 
-void TurnServer::Allocation::HandleAllocateRequest(const TurnMessage* msg) {
+void TurnServerAllocation::HandleAllocateRequest(const TurnMessage* msg) {
   // Copy the important info from the allocate request.
   transaction_id_ = msg->transaction_id();
   const StunByteStringAttribute* username_attr =
       msg->GetByteString(STUN_ATTR_USERNAME);
   ASSERT(username_attr != NULL);
   username_ = username_attr->GetString();
+  const StunByteStringAttribute* origin_attr =
+      msg->GetByteString(STUN_ATTR_ORIGIN);
+  if (origin_attr) {
+    origin_ = origin_attr->GetString();
+  }
 
   // Figure out the lifetime and start the allocation timer.
   int lifetime_secs = ComputeLifetime(msg);
@@ -714,7 +647,7 @@
   SendResponse(&response);
 }
 
-void TurnServer::Allocation::HandleRefreshRequest(const TurnMessage* msg) {
+void TurnServerAllocation::HandleRefreshRequest(const TurnMessage* msg) {
   // Figure out the new lifetime.
   int lifetime_secs = ComputeLifetime(msg);
 
@@ -735,7 +668,7 @@
   SendResponse(&response);
 }
 
-void TurnServer::Allocation::HandleSendIndication(const TurnMessage* msg) {
+void TurnServerAllocation::HandleSendIndication(const TurnMessage* msg) {
   // Check mandatory attributes.
   const StunByteStringAttribute* data_attr = msg->GetByteString(STUN_ATTR_DATA);
   const StunAddressAttribute* peer_attr =
@@ -755,7 +688,7 @@
   }
 }
 
-void TurnServer::Allocation::HandleCreatePermissionRequest(
+void TurnServerAllocation::HandleCreatePermissionRequest(
     const TurnMessage* msg) {
   // Check mandatory attributes.
   const StunAddressAttribute* peer_attr =
@@ -777,7 +710,7 @@
   SendResponse(&response);
 }
 
-void TurnServer::Allocation::HandleChannelBindRequest(const TurnMessage* msg) {
+void TurnServerAllocation::HandleChannelBindRequest(const TurnMessage* msg) {
   // Check mandatory attributes.
   const StunUInt32Attribute* channel_attr =
       msg->GetUInt32(STUN_ATTR_CHANNEL_NUMBER);
@@ -808,7 +741,7 @@
   if (!channel1) {
     channel1 = new Channel(thread_, channel_id, peer_attr->GetAddress());
     channel1->SignalDestroyed.connect(this,
-        &TurnServer::Allocation::OnChannelDestroyed);
+        &TurnServerAllocation::OnChannelDestroyed);
     channels_.push_back(channel1);
   } else {
     channel1->Refresh();
@@ -826,7 +759,7 @@
   SendResponse(&response);
 }
 
-void TurnServer::Allocation::HandleChannelData(const char* data, size_t size) {
+void TurnServerAllocation::HandleChannelData(const char* data, size_t size) {
   // Extract the channel number from the data.
   uint16 channel_id = rtc::GetBE16(data);
   Channel* channel = FindChannel(channel_id);
@@ -840,7 +773,7 @@
   }
 }
 
-void TurnServer::Allocation::OnExternalPacket(
+void TurnServerAllocation::OnExternalPacket(
     rtc::AsyncPacketSocket* socket,
     const char* data, size_t size,
     const rtc::SocketAddress& addr,
@@ -871,7 +804,7 @@
   }
 }
 
-int TurnServer::Allocation::ComputeLifetime(const TurnMessage* msg) {
+int TurnServerAllocation::ComputeLifetime(const TurnMessage* msg) {
   // Return the smaller of our default lifetime and the requested lifetime.
   uint32 lifetime = kDefaultAllocationTimeout / 1000;  // convert to seconds
   const StunUInt32Attribute* lifetime_attr = msg->GetUInt32(STUN_ATTR_LIFETIME);
@@ -881,23 +814,23 @@
   return lifetime;
 }
 
-bool TurnServer::Allocation::HasPermission(const rtc::IPAddress& addr) {
+bool TurnServerAllocation::HasPermission(const rtc::IPAddress& addr) {
   return (FindPermission(addr) != NULL);
 }
 
-void TurnServer::Allocation::AddPermission(const rtc::IPAddress& addr) {
+void TurnServerAllocation::AddPermission(const rtc::IPAddress& addr) {
   Permission* perm = FindPermission(addr);
   if (!perm) {
     perm = new Permission(thread_, addr);
     perm->SignalDestroyed.connect(
-        this, &TurnServer::Allocation::OnPermissionDestroyed);
+        this, &TurnServerAllocation::OnPermissionDestroyed);
     perms_.push_back(perm);
   } else {
     perm->Refresh();
   }
 }
 
-TurnServer::Permission* TurnServer::Allocation::FindPermission(
+TurnServerAllocation::Permission* TurnServerAllocation::FindPermission(
     const rtc::IPAddress& addr) const {
   for (PermissionList::const_iterator it = perms_.begin();
        it != perms_.end(); ++it) {
@@ -907,7 +840,8 @@
   return NULL;
 }
 
-TurnServer::Channel* TurnServer::Allocation::FindChannel(int channel_id) const {
+TurnServerAllocation::Channel* TurnServerAllocation::FindChannel(
+    int channel_id) const {
   for (ChannelList::const_iterator it = channels_.begin();
        it != channels_.end(); ++it) {
     if ((*it)->id() == channel_id)
@@ -916,7 +850,7 @@
   return NULL;
 }
 
-TurnServer::Channel* TurnServer::Allocation::FindChannel(
+TurnServerAllocation::Channel* TurnServerAllocation::FindChannel(
     const rtc::SocketAddress& addr) const {
   for (ChannelList::const_iterator it = channels_.begin();
        it != channels_.end(); ++it) {
@@ -926,83 +860,83 @@
   return NULL;
 }
 
-void TurnServer::Allocation::SendResponse(TurnMessage* msg) {
+void TurnServerAllocation::SendResponse(TurnMessage* msg) {
   // Success responses always have M-I.
   msg->AddMessageIntegrity(key_);
   server_->SendStun(&conn_, msg);
 }
 
-void TurnServer::Allocation::SendBadRequestResponse(const TurnMessage* req) {
+void TurnServerAllocation::SendBadRequestResponse(const TurnMessage* req) {
   SendErrorResponse(req, STUN_ERROR_BAD_REQUEST, STUN_ERROR_REASON_BAD_REQUEST);
 }
 
-void TurnServer::Allocation::SendErrorResponse(const TurnMessage* req, int code,
+void TurnServerAllocation::SendErrorResponse(const TurnMessage* req, int code,
                                        const std::string& reason) {
   server_->SendErrorResponse(&conn_, req, code, reason);
 }
 
-void TurnServer::Allocation::SendExternal(const void* data, size_t size,
+void TurnServerAllocation::SendExternal(const void* data, size_t size,
                                   const rtc::SocketAddress& peer) {
   rtc::PacketOptions options;
   external_socket_->SendTo(data, size, peer, options);
 }
 
-void TurnServer::Allocation::OnMessage(rtc::Message* msg) {
+void TurnServerAllocation::OnMessage(rtc::Message* msg) {
   ASSERT(msg->message_id == MSG_ALLOCATION_TIMEOUT);
   SignalDestroyed(this);
   delete this;
 }
 
-void TurnServer::Allocation::OnPermissionDestroyed(Permission* perm) {
+void TurnServerAllocation::OnPermissionDestroyed(Permission* perm) {
   PermissionList::iterator it = std::find(perms_.begin(), perms_.end(), perm);
   ASSERT(it != perms_.end());
   perms_.erase(it);
 }
 
-void TurnServer::Allocation::OnChannelDestroyed(Channel* channel) {
+void TurnServerAllocation::OnChannelDestroyed(Channel* channel) {
   ChannelList::iterator it =
       std::find(channels_.begin(), channels_.end(), channel);
   ASSERT(it != channels_.end());
   channels_.erase(it);
 }
 
-TurnServer::Permission::Permission(rtc::Thread* thread,
+TurnServerAllocation::Permission::Permission(rtc::Thread* thread,
                                    const rtc::IPAddress& peer)
     : thread_(thread), peer_(peer) {
   Refresh();
 }
 
-TurnServer::Permission::~Permission() {
+TurnServerAllocation::Permission::~Permission() {
   thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
 }
 
-void TurnServer::Permission::Refresh() {
+void TurnServerAllocation::Permission::Refresh() {
   thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
   thread_->PostDelayed(kPermissionTimeout, this, MSG_ALLOCATION_TIMEOUT);
 }
 
-void TurnServer::Permission::OnMessage(rtc::Message* msg) {
+void TurnServerAllocation::Permission::OnMessage(rtc::Message* msg) {
   ASSERT(msg->message_id == MSG_ALLOCATION_TIMEOUT);
   SignalDestroyed(this);
   delete this;
 }
 
-TurnServer::Channel::Channel(rtc::Thread* thread, int id,
+TurnServerAllocation::Channel::Channel(rtc::Thread* thread, int id,
                              const rtc::SocketAddress& peer)
     : thread_(thread), id_(id), peer_(peer) {
   Refresh();
 }
 
-TurnServer::Channel::~Channel() {
+TurnServerAllocation::Channel::~Channel() {
   thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
 }
 
-void TurnServer::Channel::Refresh() {
+void TurnServerAllocation::Channel::Refresh() {
   thread_->Clear(this, MSG_ALLOCATION_TIMEOUT);
   thread_->PostDelayed(kChannelTimeout, this, MSG_ALLOCATION_TIMEOUT);
 }
 
-void TurnServer::Channel::OnMessage(rtc::Message* msg) {
+void TurnServerAllocation::Channel::OnMessage(rtc::Message* msg) {
   ASSERT(msg->message_id == MSG_ALLOCATION_TIMEOUT);
   SignalDestroyed(this);
   delete this;
diff --git a/webrtc/p2p/base/turnserver.h b/webrtc/p2p/base/turnserver.h
index 670b618..d3bd77a 100644
--- a/webrtc/p2p/base/turnserver.h
+++ b/webrtc/p2p/base/turnserver.h
@@ -32,10 +32,109 @@
 
 class StunMessage;
 class TurnMessage;
+class TurnServer;
 
 // The default server port for TURN, as specified in RFC5766.
 const int TURN_SERVER_PORT = 3478;
 
+// Encapsulates the client's connection to the server.
+class TurnServerConnection {
+ public:
+  TurnServerConnection() : proto_(PROTO_UDP), socket_(NULL) {}
+  TurnServerConnection(const rtc::SocketAddress& src,
+                       ProtocolType proto,
+                       rtc::AsyncPacketSocket* socket);
+  const rtc::SocketAddress& src() const { return src_; }
+  rtc::AsyncPacketSocket* socket() { return socket_; }
+  bool operator==(const TurnServerConnection& t) const;
+  bool operator<(const TurnServerConnection& t) const;
+  std::string ToString() const;
+
+ private:
+  rtc::SocketAddress src_;
+  rtc::SocketAddress dst_;
+  cricket::ProtocolType proto_;
+  rtc::AsyncPacketSocket* socket_;
+};
+
+// Encapsulates a TURN allocation.
+// The object is created when an allocation request is received, and then
+// handles TURN messages (via HandleTurnMessage) and channel data messages
+// (via HandleChannelData) for this allocation when received by the server.
+// The object self-deletes and informs the server if its lifetime timer expires.
+class TurnServerAllocation : public rtc::MessageHandler,
+                             public sigslot::has_slots<> {
+ public:
+  TurnServerAllocation(TurnServer* server_,
+                       rtc::Thread* thread,
+                       const TurnServerConnection& conn,
+                       rtc::AsyncPacketSocket* server_socket,
+                       const std::string& key);
+  virtual ~TurnServerAllocation();
+
+  TurnServerConnection* conn() { return &conn_; }
+  const std::string& key() const { return key_; }
+  const std::string& transaction_id() const { return transaction_id_; }
+  const std::string& username() const { return username_; }
+  const std::string& origin() const { return origin_; }
+  const std::string& last_nonce() const { return last_nonce_; }
+  void set_last_nonce(const std::string& nonce) { last_nonce_ = nonce; }
+
+  std::string ToString() const;
+
+  void HandleTurnMessage(const TurnMessage* msg);
+  void HandleChannelData(const char* data, size_t size);
+
+  sigslot::signal1<TurnServerAllocation*> SignalDestroyed;
+
+ private:
+  class Channel;
+  class Permission;
+  typedef std::list<Permission*> PermissionList;
+  typedef std::list<Channel*> ChannelList;
+
+  void HandleAllocateRequest(const TurnMessage* msg);
+  void HandleRefreshRequest(const TurnMessage* msg);
+  void HandleSendIndication(const TurnMessage* msg);
+  void HandleCreatePermissionRequest(const TurnMessage* msg);
+  void HandleChannelBindRequest(const TurnMessage* msg);
+
+  void OnExternalPacket(rtc::AsyncPacketSocket* socket,
+                        const char* data, size_t size,
+                        const rtc::SocketAddress& addr,
+                        const rtc::PacketTime& packet_time);
+
+  static int ComputeLifetime(const TurnMessage* msg);
+  bool HasPermission(const rtc::IPAddress& addr);
+  void AddPermission(const rtc::IPAddress& addr);
+  Permission* FindPermission(const rtc::IPAddress& addr) const;
+  Channel* FindChannel(int channel_id) const;
+  Channel* FindChannel(const rtc::SocketAddress& addr) const;
+
+  void SendResponse(TurnMessage* msg);
+  void SendBadRequestResponse(const TurnMessage* req);
+  void SendErrorResponse(const TurnMessage* req, int code,
+                         const std::string& reason);
+  void SendExternal(const void* data, size_t size,
+                    const rtc::SocketAddress& peer);
+
+  void OnPermissionDestroyed(Permission* perm);
+  void OnChannelDestroyed(Channel* channel);
+  virtual void OnMessage(rtc::Message* msg);
+
+  TurnServer* server_;
+  rtc::Thread* thread_;
+  TurnServerConnection conn_;
+  rtc::scoped_ptr<rtc::AsyncPacketSocket> external_socket_;
+  std::string key_;
+  std::string transaction_id_;
+  std::string username_;
+  std::string origin_;
+  std::string last_nonce_;
+  PermissionList perms_;
+  ChannelList channels_;
+};
+
 // An interface through which the MD5 credential hash can be retrieved.
 class TurnAuthInterface {
  public:
@@ -60,6 +159,8 @@
 // Not yet wired up: TCP support.
 class TurnServer : public sigslot::has_slots<> {
  public:
+  typedef std::map<TurnServerConnection, TurnServerAllocation*> AllocationMap;
+
   explicit TurnServer(rtc::Thread* thread);
   ~TurnServer();
 
@@ -71,6 +172,8 @@
   const std::string& software() const { return software_; }
   void set_software(const std::string& software) { software_ = software; }
 
+  const AllocationMap& allocations() const { return allocations_; }
+
   // Sets the authentication callback; does not take ownership.
   void set_auth_hook(TurnAuthInterface* auth_hook) { auth_hook_ = auth_hook; }
 
@@ -93,30 +196,6 @@
                                 const rtc::SocketAddress& address);
 
  private:
-  // Encapsulates the client's connection to the server.
-  class Connection {
-   public:
-    Connection() : proto_(PROTO_UDP), socket_(NULL) {}
-    Connection(const rtc::SocketAddress& src,
-               ProtocolType proto,
-               rtc::AsyncPacketSocket* socket);
-    const rtc::SocketAddress& src() const { return src_; }
-    rtc::AsyncPacketSocket* socket() { return socket_; }
-    bool operator==(const Connection& t) const;
-    bool operator<(const Connection& t) const;
-    std::string ToString() const;
-
-   private:
-    rtc::SocketAddress src_;
-    rtc::SocketAddress dst_;
-    cricket::ProtocolType proto_;
-    rtc::AsyncPacketSocket* socket_;
-  };
-  class Allocation;
-  class Permission;
-  class Channel;
-  typedef std::map<Connection, Allocation*> AllocationMap;
-
   void OnInternalPacket(rtc::AsyncPacketSocket* socket, const char* data,
                         size_t size, const rtc::SocketAddress& address,
                         const rtc::PacketTime& packet_time);
@@ -127,38 +206,39 @@
   void AcceptConnection(rtc::AsyncSocket* server_socket);
   void OnInternalSocketClose(rtc::AsyncPacketSocket* socket, int err);
 
-  void HandleStunMessage(Connection* conn, const char* data, size_t size);
-  void HandleBindingRequest(Connection* conn, const StunMessage* msg);
-  void HandleAllocateRequest(Connection* conn, const TurnMessage* msg,
+  void HandleStunMessage(
+      TurnServerConnection* conn, const char* data, size_t size);
+  void HandleBindingRequest(TurnServerConnection* conn, const StunMessage* msg);
+  void HandleAllocateRequest(TurnServerConnection* conn, const TurnMessage* msg,
                              const std::string& key);
 
   bool GetKey(const StunMessage* msg, std::string* key);
-  bool CheckAuthorization(Connection* conn, const StunMessage* msg,
+  bool CheckAuthorization(TurnServerConnection* conn, const StunMessage* msg,
                           const char* data, size_t size,
                           const std::string& key);
   std::string GenerateNonce() const;
   bool ValidateNonce(const std::string& nonce) const;
 
-  Allocation* FindAllocation(Connection* conn);
-  Allocation* CreateAllocation(Connection* conn, int proto,
-                               const std::string& key);
+  TurnServerAllocation* FindAllocation(TurnServerConnection* conn);
+  TurnServerAllocation* CreateAllocation(
+      TurnServerConnection* conn, int proto, const std::string& key);
 
-  void SendErrorResponse(Connection* conn, const StunMessage* req,
+  void SendErrorResponse(TurnServerConnection* conn, const StunMessage* req,
                          int code, const std::string& reason);
 
-  void SendErrorResponseWithRealmAndNonce(Connection* conn,
+  void SendErrorResponseWithRealmAndNonce(TurnServerConnection* conn,
                                           const StunMessage* req,
                                           int code,
                                           const std::string& reason);
 
-  void SendErrorResponseWithAlternateServer(Connection* conn,
+  void SendErrorResponseWithAlternateServer(TurnServerConnection* conn,
                                             const StunMessage* req,
                                             const rtc::SocketAddress& addr);
 
-  void SendStun(Connection* conn, StunMessage* msg);
-  void Send(Connection* conn, const rtc::ByteBuffer& buf);
+  void SendStun(TurnServerConnection* conn, StunMessage* msg);
+  void Send(TurnServerConnection* conn, const rtc::ByteBuffer& buf);
 
-  void OnAllocationDestroyed(Allocation* allocation);
+  void OnAllocationDestroyed(TurnServerAllocation* allocation);
   void DestroyInternalSocket(rtc::AsyncPacketSocket* socket);
 
   typedef std::map<rtc::AsyncPacketSocket*,
@@ -183,6 +263,8 @@
   rtc::SocketAddress external_addr_;
 
   AllocationMap allocations_;
+
+  friend class TurnServerAllocation;
 };
 
 }  // namespace cricket
diff --git a/webrtc/p2p/client/basicportallocator.cc b/webrtc/p2p/client/basicportallocator.cc
index 5013a57..a763791 100644
--- a/webrtc/p2p/client/basicportallocator.cc
+++ b/webrtc/p2p/client/basicportallocator.cc
@@ -889,14 +889,16 @@
     port = UDPPort::Create(session_->network_thread(),
                            session_->socket_factory(), network_,
                            udp_socket_.get(),
-                           session_->username(), session_->password());
+                           session_->username(), session_->password(),
+                           session_->allocator()->origin());
   } else {
     port = UDPPort::Create(session_->network_thread(),
                            session_->socket_factory(),
                            network_, ip_,
                            session_->allocator()->min_port(),
                            session_->allocator()->max_port(),
-                           session_->username(), session_->password());
+                           session_->username(), session_->password(),
+                           session_->allocator()->origin());
   }
 
   if (port) {
@@ -973,7 +975,8 @@
                                 session_->allocator()->min_port(),
                                 session_->allocator()->max_port(),
                                 session_->username(), session_->password(),
-                                config_->StunServers());
+                                config_->StunServers(),
+                                session_->allocator()->origin());
   if (port) {
     session_->AddAllocatedPort(port, this, true);
     // Since StunPort is not created using shared socket, |port| will not be
@@ -1055,8 +1058,8 @@
                               session_->socket_factory(),
                               network_, udp_socket_.get(),
                               session_->username(), session_->password(),
-                              *relay_port, config.credentials, config.priority);
-
+                              *relay_port, config.credentials, config.priority,
+                              session_->allocator()->origin());
       turn_ports_.push_back(port);
       // Listen to the port destroyed signal, to allow AllocationSequence to
       // remove entrt from it's map.
@@ -1069,7 +1072,8 @@
                               session_->allocator()->max_port(),
                               session_->username(),
                               session_->password(),
-                              *relay_port, config.credentials, config.priority);
+                              *relay_port, config.credentials, config.priority,
+                              session_->allocator()->origin());
     }
     ASSERT(port != NULL);
     session_->AddAllocatedPort(port, this, true);
diff --git a/webrtc/p2p/client/connectivitychecker.cc b/webrtc/p2p/client/connectivitychecker.cc
index 07c9d8b..1c3fc0e 100644
--- a/webrtc/p2p/client/connectivitychecker.cc
+++ b/webrtc/p2p/client/connectivitychecker.cc
@@ -371,7 +371,8 @@
                           0,
                           username,
                           password,
-                          config->stun_servers);
+                          config->stun_servers,
+                          std::string());
 }
 
 RelayPort* ConnectivityChecker::CreateRelayPort(
diff --git a/webrtc/p2p/client/connectivitychecker_unittest.cc b/webrtc/p2p/client/connectivitychecker_unittest.cc
index 838dc88..4b0566f 100644
--- a/webrtc/p2p/client/connectivitychecker_unittest.cc
+++ b/webrtc/p2p/client/connectivitychecker_unittest.cc
@@ -75,7 +75,7 @@
                const std::string& username, const std::string& password,
                const ServerAddresses& server_addr)
       : StunPort(thread, factory, network, ip, min_port, max_port,
-                 username, password, server_addr) {
+                 username, password, server_addr, std::string()) {
   }
 
   // Just set external address and signal that we are done.
diff --git a/webrtc/p2p/client/fakeportallocator.h b/webrtc/p2p/client/fakeportallocator.h
index 73dae3a..e265834 100644
--- a/webrtc/p2p/client/fakeportallocator.h
+++ b/webrtc/p2p/client/fakeportallocator.h
@@ -56,7 +56,8 @@
                                            0,
                                            0,
                                            username(),
-                                           password()));
+                                           password(),
+                                           std::string()));
       AddPort(port_.get());
     }
     ++port_config_count_;