Read recv timestamps from socket (posix only).

This helps a lot on Android devices where the user threads can be scheduled with low priority when the app is in the background, causing spurious significantly delayed before a packet can be read from the socket. With this patch the timestamp is taken by the kernel when the packet actually arrives.

R=juberti@chromium.org
TBR=juberti@webrtc.org

BUG=webrtc:5773

Review URL: https://codereview.webrtc.org/1944683002 .

Cr-Commit-Position: refs/heads/master@{#12850}
diff --git a/webrtc/base/asyncsocket.cc b/webrtc/base/asyncsocket.cc
index db451c6..089802e 100644
--- a/webrtc/base/asyncsocket.cc
+++ b/webrtc/base/asyncsocket.cc
@@ -64,12 +64,15 @@
   return socket_->SendTo(pv, cb, addr);
 }
 
-int AsyncSocketAdapter::Recv(void* pv, size_t cb) {
-  return socket_->Recv(pv, cb);
+int AsyncSocketAdapter::Recv(void* pv, size_t cb, int64_t* timestamp) {
+  return socket_->Recv(pv, cb, timestamp);
 }
 
-int AsyncSocketAdapter::RecvFrom(void* pv, size_t cb, SocketAddress* paddr) {
-  return socket_->RecvFrom(pv, cb, paddr);
+int AsyncSocketAdapter::RecvFrom(void* pv,
+                                 size_t cb,
+                                 SocketAddress* paddr,
+                                 int64_t* timestamp) {
+  return socket_->RecvFrom(pv, cb, paddr, timestamp);
 }
 
 int AsyncSocketAdapter::Listen(int backlog) {
diff --git a/webrtc/base/asyncsocket.h b/webrtc/base/asyncsocket.h
index 7a859be..5dbffb9 100644
--- a/webrtc/base/asyncsocket.h
+++ b/webrtc/base/asyncsocket.h
@@ -56,8 +56,11 @@
   int Connect(const SocketAddress& addr) override;
   int Send(const void* pv, size_t cb) override;
   int SendTo(const void* pv, size_t cb, const SocketAddress& addr) override;
-  int Recv(void* pv, size_t cb) override;
-  int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) override;
+  int Recv(void* pv, size_t cb, int64_t* timestamp) override;
+  int RecvFrom(void* pv,
+               size_t cb,
+               SocketAddress* paddr,
+               int64_t* timestamp) override;
   int Listen(int backlog) override;
   AsyncSocket* Accept(SocketAddress* paddr) override;
   int Close() override;
diff --git a/webrtc/base/asynctcpsocket.cc b/webrtc/base/asynctcpsocket.cc
index 9ba46d7..60ac7b3 100644
--- a/webrtc/base/asynctcpsocket.cc
+++ b/webrtc/base/asynctcpsocket.cc
@@ -208,7 +208,8 @@
         free_size = inbuf_.capacity() - inbuf_.size();
       }
 
-      int len = socket_->Recv(inbuf_.data() + inbuf_.size(), free_size);
+      int len =
+          socket_->Recv(inbuf_.data() + inbuf_.size(), free_size, nullptr);
       if (len < 0) {
         // TODO(stefan): Do something better like forwarding the error to the
         // user.
diff --git a/webrtc/base/asyncudpsocket.cc b/webrtc/base/asyncudpsocket.cc
index fc7d887..232d264 100644
--- a/webrtc/base/asyncudpsocket.cc
+++ b/webrtc/base/asyncudpsocket.cc
@@ -102,7 +102,8 @@
   ASSERT(socket_.get() == socket);
 
   SocketAddress remote_addr;
-  int len = socket_->RecvFrom(buf_, size_, &remote_addr);
+  int64_t timestamp;
+  int len = socket_->RecvFrom(buf_, size_, &remote_addr, &timestamp);
   if (len < 0) {
     // An error here typically means we got an ICMP error in response to our
     // send datagram, indicating the remote address was unreachable.
@@ -116,8 +117,9 @@
 
   // TODO: Make sure that we got all of the packet.
   // If we did not, then we should resize our buffer to be large enough.
-  SignalReadPacket(this, buf_, static_cast<size_t>(len), remote_addr,
-                   CreatePacketTime(0));
+  SignalReadPacket(
+      this, buf_, static_cast<size_t>(len), remote_addr,
+      (timestamp > -1 ? PacketTime(timestamp, 0) : CreatePacketTime(0)));
 }
 
 void AsyncUDPSocket::OnWriteEvent(AsyncSocket* socket) {
diff --git a/webrtc/base/autodetectproxy.cc b/webrtc/base/autodetectproxy.cc
index 22950fb..e6174ec 100644
--- a/webrtc/base/autodetectproxy.cc
+++ b/webrtc/base/autodetectproxy.cc
@@ -247,7 +247,7 @@
 
 void AutoDetectProxy::OnReadEvent(AsyncSocket * socket) {
   char data[257];
-  int len = socket_->Recv(data, 256);
+  int len = socket_->Recv(data, 256, nullptr);
   if (len > 0) {
     data[len] = 0;
     LOG(LS_VERBOSE) << "AutoDetectProxy read " << len << " bytes";
diff --git a/webrtc/base/firewallsocketserver.cc b/webrtc/base/firewallsocketserver.cc
index 6339017..bf3ec42 100644
--- a/webrtc/base/firewallsocketserver.cc
+++ b/webrtc/base/firewallsocketserver.cc
@@ -52,14 +52,17 @@
     }
     return AsyncSocketAdapter::SendTo(pv, cb, addr);
   }
-  int Recv(void* pv, size_t cb) override {
+  int Recv(void* pv, size_t cb, int64_t* timestamp) override {
     SocketAddress addr;
-    return RecvFrom(pv, cb, &addr);
+    return RecvFrom(pv, cb, &addr, timestamp);
   }
-  int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) override {
+  int RecvFrom(void* pv,
+               size_t cb,
+               SocketAddress* paddr,
+               int64_t* timestamp) override {
     if (type_ == SOCK_DGRAM) {
       while (true) {
-        int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
+        int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr, timestamp);
         if (res <= 0)
           return res;
         if (server_->Check(FP_UDP, *paddr, GetLocalAddress()))
@@ -69,7 +72,7 @@
                         << GetLocalAddress().ToSensitiveString() << " dropped";
       }
     }
-    return AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
+    return AsyncSocketAdapter::RecvFrom(pv, cb, paddr, timestamp);
   }
 
   int Listen(int backlog) override {
diff --git a/webrtc/base/macasyncsocket.cc b/webrtc/base/macasyncsocket.cc
index 8f811ea..9f38c29 100644
--- a/webrtc/base/macasyncsocket.cc
+++ b/webrtc/base/macasyncsocket.cc
@@ -188,7 +188,10 @@
 }
 
 // Read data received from the remote end we're connected to.
-int MacAsyncSocket::Recv(void* buffer, size_t length) {
+int MacAsyncSocket::Recv(void* buffer, size_t length, int64_t* timestamp) {
+  if (timestamp) {
+    *timestamp = -1;
+  }
   int received = ::recv(native_socket_, reinterpret_cast<char*>(buffer),
                         length, 0);
   if (received == SOCKET_ERROR) error_ = errno;
@@ -199,8 +202,13 @@
 }
 
 // Read data received from any remote party
-int MacAsyncSocket::RecvFrom(void* buffer, size_t length,
-                             SocketAddress* out_addr) {
+int MacAsyncSocket::RecvFrom(void* buffer,
+                             size_t length,
+                             SocketAddress* out_addr,
+                             int64_t* timestamp) {
+  if (timestamp) {
+    *timestamp = -1;
+  }
   sockaddr_storage saddr;
   socklen_t addr_len = sizeof(saddr);
   int received = ::recvfrom(native_socket_, reinterpret_cast<char*>(buffer),
diff --git a/webrtc/base/macasyncsocket.h b/webrtc/base/macasyncsocket.h
index c0f57b9..1996b35 100644
--- a/webrtc/base/macasyncsocket.h
+++ b/webrtc/base/macasyncsocket.h
@@ -42,8 +42,11 @@
   int SendTo(const void* buffer,
              size_t length,
              const SocketAddress& addr) override;
-  int Recv(void* buffer, size_t length) override;
-  int RecvFrom(void* buffer, size_t length, SocketAddress* out_addr) override;
+  int Recv(void* buffer, size_t length, int64_t* timestamp) override;
+  int RecvFrom(void* buffer,
+               size_t length,
+               SocketAddress* out_addr,
+               int64_t* timestamp) override;
   int Listen(int backlog) override;
   MacAsyncSocket* Accept(SocketAddress* out_addr) override;
   int Close() override;
diff --git a/webrtc/base/nat_unittest.cc b/webrtc/base/nat_unittest.cc
index ca72c93..bd630b3 100644
--- a/webrtc/base/nat_unittest.cc
+++ b/webrtc/base/nat_unittest.cc
@@ -195,7 +195,7 @@
   const size_t kRecvBufSize = 64;
   char recvbuf[kRecvBufSize];
   Thread::Current()->SleepMs(100);
-  int received = server->RecvFrom(recvbuf, kRecvBufSize, &addr);
+  int received = server->RecvFrom(recvbuf, kRecvBufSize, &addr, nullptr);
   return received == sent && ::memcmp(buf, recvbuf, len) == 0;
 }
 
diff --git a/webrtc/base/natsocketfactory.cc b/webrtc/base/natsocketfactory.cc
index 985748c..a924984 100644
--- a/webrtc/base/natsocketfactory.cc
+++ b/webrtc/base/natsocketfactory.cc
@@ -155,14 +155,17 @@
     return result;
   }
 
-  int Recv(void* data, size_t size) override {
+  int Recv(void* data, size_t size, int64_t* timestamp) override {
     SocketAddress addr;
-    return RecvFrom(data, size, &addr);
+    return RecvFrom(data, size, &addr, timestamp);
   }
 
-  int RecvFrom(void* data, size_t size, SocketAddress* out_addr) override {
+  int RecvFrom(void* data,
+               size_t size,
+               SocketAddress* out_addr,
+               int64_t* timestamp) override {
     if (server_addr_.IsNil() || type_ == SOCK_STREAM) {
-      return socket_->RecvFrom(data, size, out_addr);
+      return socket_->RecvFrom(data, size, out_addr, timestamp);
     }
     // Make sure we have enough room to read the requested amount plus the
     // largest possible header address.
@@ -170,7 +173,7 @@
     Grow(size + kNATEncodedIPv6AddressSize);
 
     // Read the packet from the socket.
-    int result = socket_->RecvFrom(buf_, size_, &remote_addr);
+    int result = socket_->RecvFrom(buf_, size_, &remote_addr, timestamp);
     if (result >= 0) {
       ASSERT(remote_addr == server_addr_);
 
@@ -278,7 +281,7 @@
   // Handles the byte sent back from the server and fires the appropriate event.
   void HandleConnectReply() {
     char code;
-    socket_->Recv(&code, sizeof(code));
+    socket_->Recv(&code, sizeof(code), nullptr);
     if (code == 0) {
       connected_ = true;
       SignalConnectEvent(this);
diff --git a/webrtc/base/openssladapter.cc b/webrtc/base/openssladapter.cc
index 40c352d..d1cbaa8 100644
--- a/webrtc/base/openssladapter.cc
+++ b/webrtc/base/openssladapter.cc
@@ -119,7 +119,7 @@
     return -1;
   rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(b->ptr);
   BIO_clear_retry_flags(b);
-  int result = socket->Recv(out, outl);
+  int result = socket->Recv(out, outl, nullptr);
   if (result > 0) {
     return result;
   } else if (result == 0) {
@@ -524,13 +524,12 @@
   return SOCKET_ERROR;
 }
 
-int
-OpenSSLAdapter::Recv(void* pv, size_t cb) {
+int OpenSSLAdapter::Recv(void* pv, size_t cb, int64_t* timestamp) {
   //LOG(LS_INFO) << "OpenSSLAdapter::Recv(" << cb << ")";
   switch (state_) {
 
   case SSL_NONE:
-    return AsyncSocketAdapter::Recv(pv, cb);
+    return AsyncSocketAdapter::Recv(pv, cb, timestamp);
 
   case SSL_WAIT:
   case SSL_CONNECTING:
@@ -579,10 +578,12 @@
   return SOCKET_ERROR;
 }
 
-int
-OpenSSLAdapter::RecvFrom(void* pv, size_t cb, SocketAddress* paddr) {
+int OpenSSLAdapter::RecvFrom(void* pv,
+                             size_t cb,
+                             SocketAddress* paddr,
+                             int64_t* timestamp) {
   if (socket_->GetState() == Socket::CS_CONNECTED) {
-    int ret = Recv(pv, cb);
+    int ret = Recv(pv, cb, timestamp);
 
     *paddr = GetRemoteAddress();
 
diff --git a/webrtc/base/openssladapter.h b/webrtc/base/openssladapter.h
index cdf45e6..554627f 100644
--- a/webrtc/base/openssladapter.h
+++ b/webrtc/base/openssladapter.h
@@ -37,8 +37,11 @@
   int StartSSL(const char* hostname, bool restartable) override;
   int Send(const void* pv, size_t cb) override;
   int SendTo(const void* pv, size_t cb, const SocketAddress& addr) override;
-  int Recv(void* pv, size_t cb) override;
-  int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) override;
+  int Recv(void* pv, size_t cb, int64_t* timestamp) override;
+  int RecvFrom(void* pv,
+               size_t cb,
+               SocketAddress* paddr,
+               int64_t* timestamp) override;
   int Close() override;
 
   // Note that the socket returns ST_CONNECTING while SSL is being negotiated.
diff --git a/webrtc/base/physicalsocketserver.cc b/webrtc/base/physicalsocketserver.cc
index 0230077..f28b1f5 100644
--- a/webrtc/base/physicalsocketserver.cc
+++ b/webrtc/base/physicalsocketserver.cc
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <sys/ioctl.h>
 #include <sys/time.h>
 #include <sys/select.h>
 #include <unistd.h>
@@ -55,8 +56,28 @@
 #include <netinet/tcp.h>  // for TCP_NODELAY
 #define IP_MTU 14 // Until this is integrated from linux/in.h to netinet/in.h
 typedef void* SockOptArg;
+
 #endif  // WEBRTC_POSIX
 
+#if defined(WEBRTC_POSIX) && !defined(WEBRTC_MAC)
+int64_t GetSocketRecvTimestamp(int socket) {
+  struct timeval tv_ioctl;
+  int ret = ioctl(socket, SIOCGSTAMP, &tv_ioctl);
+  if (ret != 0)
+    return -1;
+  int64_t timestamp =
+      rtc::kNumMicrosecsPerSec * static_cast<int64_t>(tv_ioctl.tv_sec) +
+      static_cast<int64_t>(tv_ioctl.tv_usec);
+  return timestamp;
+}
+
+#else
+
+int64_t GetSocketRecvTimestamp(int socket) {
+  return -1;
+}
+#endif
+
 #if defined(WEBRTC_WIN)
 typedef char* SockOptArg;
 #endif
@@ -324,7 +345,7 @@
   return sent;
 }
 
-int PhysicalSocket::Recv(void* buffer, size_t length) {
+int PhysicalSocket::Recv(void* buffer, size_t length, int64_t* timestamp) {
   int received = ::recv(s_, static_cast<char*>(buffer),
                         static_cast<int>(length), 0);
   if ((received == 0) && (length != 0)) {
@@ -338,6 +359,9 @@
     SetError(EWOULDBLOCK);
     return SOCKET_ERROR;
   }
+  if (timestamp) {
+    *timestamp = GetSocketRecvTimestamp(s_);
+  }
   UpdateLastError();
   int error = GetError();
   bool success = (received >= 0) || IsBlockingError(error);
@@ -352,12 +376,16 @@
 
 int PhysicalSocket::RecvFrom(void* buffer,
                              size_t length,
-                             SocketAddress* out_addr) {
+                             SocketAddress* out_addr,
+                             int64_t* timestamp) {
   sockaddr_storage addr_storage;
   socklen_t addr_len = sizeof(addr_storage);
   sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
   int received = ::recvfrom(s_, static_cast<char*>(buffer),
                             static_cast<int>(length), 0, addr, &addr_len);
+  if (timestamp) {
+    *timestamp = GetSocketRecvTimestamp(s_);
+  }
   UpdateLastError();
   if ((received >= 0) && (out_addr != nullptr))
     SocketAddressFromSockAddrStorage(addr_storage, out_addr);
diff --git a/webrtc/base/physicalsocketserver.h b/webrtc/base/physicalsocketserver.h
index f5867d2..3437eb8 100644
--- a/webrtc/base/physicalsocketserver.h
+++ b/webrtc/base/physicalsocketserver.h
@@ -143,8 +143,11 @@
              size_t length,
              const SocketAddress& addr) override;
 
-  int Recv(void* buffer, size_t length) override;
-  int RecvFrom(void* buffer, size_t length, SocketAddress* out_addr) override;
+  int Recv(void* buffer, size_t length, int64_t* timestamp) override;
+  int RecvFrom(void* buffer,
+               size_t length,
+               SocketAddress* out_addr,
+               int64_t* timestamp) override;
 
   int Listen(int backlog) override;
   AsyncSocket* Accept(SocketAddress* out_addr) override;
diff --git a/webrtc/base/physicalsocketserver_unittest.cc b/webrtc/base/physicalsocketserver_unittest.cc
index b069baa..bd1acfb 100644
--- a/webrtc/base/physicalsocketserver_unittest.cc
+++ b/webrtc/base/physicalsocketserver_unittest.cc
@@ -386,6 +386,21 @@
 
 #if defined(WEBRTC_POSIX)
 
+#if !defined(WEBRTC_MAC)
+TEST_F(PhysicalSocketTest, TestSocketRecvTimestampIPv4) {
+  SocketTest::TestSocketRecvTimestamp();
+}
+
+#if defined(WEBRTC_LINUX)
+#define MAYBE_TestSocketRecvTimestampIPv6 DISABLED_TestSocketRecvTimestampIPv6
+#else
+#define MAYBE_TestSocketRecvTimestampIPv6 TestSocketRecvTimestampIPv6
+#endif
+TEST_F(PhysicalSocketTest, MAYBE_TestSocketRecvTimestampIPv6) {
+  SocketTest::TestSocketRecvTimestamp();
+}
+#endif
+
 class PosixSignalDeliveryTest : public testing::Test {
  public:
   static void RecordSignal(int signum) {
diff --git a/webrtc/base/proxyserver.cc b/webrtc/base/proxyserver.cc
index d91a92f..6a1bdcd 100644
--- a/webrtc/base/proxyserver.cc
+++ b/webrtc/base/proxyserver.cc
@@ -129,7 +129,7 @@
   int read;
   if (buffer->GetBuffered(&size) && size == 0) {
     void* p = buffer->GetWriteBuffer(&size);
-    read = socket->Recv(p, size);
+    read = socket->Recv(p, size, nullptr);
     buffer->ConsumeWriteBuffer(std::max(read, 0));
   }
 }
diff --git a/webrtc/base/socket.h b/webrtc/base/socket.h
index 22326cb..7db9459 100644
--- a/webrtc/base/socket.h
+++ b/webrtc/base/socket.h
@@ -151,8 +151,11 @@
   virtual int Connect(const SocketAddress& addr) = 0;
   virtual int Send(const void *pv, size_t cb) = 0;
   virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr) = 0;
-  virtual int Recv(void *pv, size_t cb) = 0;
-  virtual int RecvFrom(void *pv, size_t cb, SocketAddress *paddr) = 0;
+  virtual int Recv(void* pv, size_t cb, int64_t* timestamp) = 0;
+  virtual int RecvFrom(void* pv,
+                       size_t cb,
+                       SocketAddress* paddr,
+                       int64_t* timestamp) = 0;
   virtual int Listen(int backlog) = 0;
   virtual Socket *Accept(SocketAddress *paddr) = 0;
   virtual int Close() = 0;
diff --git a/webrtc/base/socket_unittest.cc b/webrtc/base/socket_unittest.cc
index 718903d..ea37f23 100644
--- a/webrtc/base/socket_unittest.cc
+++ b/webrtc/base/socket_unittest.cc
@@ -184,6 +184,10 @@
   GetSetOptionsInternal(kIPv6Loopback);
 }
 
+void SocketTest::TestSocketRecvTimestamp() {
+  SocketRecvTimestamp(kIPv4Loopback);
+}
+
 // For unbound sockets, GetLocalAddress / GetRemoteAddress return AF_UNSPEC
 // values on Windows, but an empty address of the same family on Linux/MacOS X.
 bool IsUnspecOrEmptyIP(const IPAddress& address) {
@@ -541,7 +545,7 @@
 
   // Ensure the data can be read.
   char buffer[10];
-  EXPECT_EQ(1, client->Recv(buffer, sizeof(buffer)));
+  EXPECT_EQ(1, client->Recv(buffer, sizeof(buffer), nullptr));
   EXPECT_EQ('a', buffer[0]);
 
   // Now we should close, but the remote address will remain.
@@ -673,7 +677,7 @@
 
   // But should signal when process_io is true.
   EXPECT_TRUE_WAIT((sink.Check(accepted.get(), testing::SSE_READ)), kTimeout);
-  EXPECT_LT(0, accepted->Recv(buf, 1024));
+  EXPECT_LT(0, accepted->Recv(buf, 1024, nullptr));
 }
 
 void SocketTest::TcpInternal(const IPAddress& loopback, size_t data_size,
@@ -763,7 +767,7 @@
 
       // Receive as much as we can get in a single recv call.
       char recved_data[data_size];
-      int recved_size = receiver->Recv(recved_data, data_size);
+      int recved_size = receiver->Recv(recved_data, data_size, nullptr);
 
       if (!recv_called) {
         // The first Recv() after getting readability should succeed and receive
@@ -850,7 +854,7 @@
 
   // Pull data.
   for (int i = 0; i < sends; ++i) {
-    client->Recv(buf, arraysize(buf));
+    client->Recv(buf, arraysize(buf), nullptr);
   }
 
   // Expect at least one additional writable callback.
@@ -1023,4 +1027,25 @@
   }
 }
 
+void SocketTest::SocketRecvTimestamp(const IPAddress& loopback) {
+  std::unique_ptr<Socket> socket(
+      ss_->CreateSocket(loopback.family(), SOCK_DGRAM));
+  EXPECT_EQ(0, socket->Bind(SocketAddress(loopback, 0)));
+  SocketAddress address = socket->GetLocalAddress();
+
+  socket->SendTo("foo", 3, address);
+  int64_t timestamp;
+  char buffer[3];
+  socket->RecvFrom(buffer, 3, nullptr, &timestamp);
+  EXPECT_GT(timestamp, -1);
+  int64_t prev_timestamp = timestamp;
+
+  const int64_t kTimeBetweenPacketsMs = 10;
+  Thread::SleepMs(kTimeBetweenPacketsMs);
+
+  socket->SendTo("bar", 3, address);
+  socket->RecvFrom(buffer, 3, nullptr, &timestamp);
+  EXPECT_NEAR(timestamp, prev_timestamp + kTimeBetweenPacketsMs * 1000, 2000);
+}
+
 }  // namespace rtc
diff --git a/webrtc/base/socket_unittest.h b/webrtc/base/socket_unittest.h
index adc69f1..41f0a65 100644
--- a/webrtc/base/socket_unittest.h
+++ b/webrtc/base/socket_unittest.h
@@ -57,6 +57,7 @@
   void TestUdpReadyToSendIPv6();
   void TestGetSetOptionsIPv4();
   void TestGetSetOptionsIPv6();
+  void TestSocketRecvTimestamp();
 
   static const int kTimeout = 5000;  // ms
   const IPAddress kIPv4Loopback;
@@ -84,6 +85,7 @@
   void UdpInternal(const IPAddress& loopback);
   void UdpReadyToSend(const IPAddress& loopback);
   void GetSetOptionsInternal(const IPAddress& loopback);
+  void SocketRecvTimestamp(const IPAddress& loopback);
 
   SocketServer* ss_;
 };
diff --git a/webrtc/base/socketadapters.cc b/webrtc/base/socketadapters.cc
index 85c1267..e1c8a07 100644
--- a/webrtc/base/socketadapters.cc
+++ b/webrtc/base/socketadapters.cc
@@ -36,7 +36,7 @@
 
 #if defined(WEBRTC_WIN)
 #include "webrtc/base/sec_buffer.h"
-#endif  // WEBRTC_WIN 
+#endif  // WEBRTC_WIN
 
 namespace rtc {
 
@@ -59,7 +59,7 @@
   return AsyncSocketAdapter::Send(pv, cb);
 }
 
-int BufferedReadAdapter::Recv(void *pv, size_t cb) {
+int BufferedReadAdapter::Recv(void* pv, size_t cb, int64_t* timestamp) {
   if (buffering_) {
     socket_->SetError(EWOULDBLOCK);
     return -1;
@@ -80,7 +80,7 @@
 
   // FIX: If cb == 0, we won't generate another read event
 
-  int res = AsyncSocketAdapter::Recv(pv, cb);
+  int res = AsyncSocketAdapter::Recv(pv, cb, timestamp);
   if (res >= 0) {
     // Read from socket and possibly buffer; return combined length
     return res + static_cast<int>(read);
@@ -113,7 +113,8 @@
     data_len_ = 0;
   }
 
-  int len = socket_->Recv(buffer_ + data_len_, buffer_size_ - data_len_);
+  int len =
+      socket_->Recv(buffer_ + data_len_, buffer_size_ - data_len_, nullptr);
   if (len < 0) {
     // TODO: Do something better like forwarding the error to the user.
     LOG_ERR(INFO) << "Recv";
@@ -874,15 +875,18 @@
   return res;
 }
 
-int LoggingSocketAdapter::Recv(void *pv, size_t cb) {
-  int res = AsyncSocketAdapter::Recv(pv, cb);
+int LoggingSocketAdapter::Recv(void* pv, size_t cb, int64_t* timestamp) {
+  int res = AsyncSocketAdapter::Recv(pv, cb, timestamp);
   if (res > 0)
     LogMultiline(level_, label_.c_str(), true, pv, res, hex_mode_, &lms_);
   return res;
 }
 
-int LoggingSocketAdapter::RecvFrom(void *pv, size_t cb, SocketAddress *paddr) {
-  int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr);
+int LoggingSocketAdapter::RecvFrom(void* pv,
+                                   size_t cb,
+                                   SocketAddress* paddr,
+                                   int64_t* timestamp) {
+  int res = AsyncSocketAdapter::RecvFrom(pv, cb, paddr, timestamp);
   if (res > 0)
     LogMultiline(level_, label_.c_str(), true, pv, res, hex_mode_, &lms_);
   return res;
diff --git a/webrtc/base/socketadapters.h b/webrtc/base/socketadapters.h
index 970a3b5..02f6bca 100644
--- a/webrtc/base/socketadapters.h
+++ b/webrtc/base/socketadapters.h
@@ -36,7 +36,7 @@
   ~BufferedReadAdapter() override;
 
   int Send(const void* pv, size_t cb) override;
-  int Recv(void* pv, size_t cb) override;
+  int Recv(void* pv, size_t cb, int64_t* timestamp) override;
 
  protected:
   int DirectSend(const void* pv, size_t cb) {
@@ -224,8 +224,11 @@
 
   int Send(const void* pv, size_t cb) override;
   int SendTo(const void* pv, size_t cb, const SocketAddress& addr) override;
-  int Recv(void* pv, size_t cb) override;
-  int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) override;
+  int Recv(void* pv, size_t cb, int64_t* timestamp) override;
+  int RecvFrom(void* pv,
+               size_t cb,
+               SocketAddress* paddr,
+               int64_t* timestamp) override;
   int Close() override;
 
  protected:
diff --git a/webrtc/base/socketstream.cc b/webrtc/base/socketstream.cc
index b0acf94..9dc8794 100644
--- a/webrtc/base/socketstream.cc
+++ b/webrtc/base/socketstream.cc
@@ -60,7 +60,7 @@
 StreamResult SocketStream::Read(void* buffer, size_t buffer_len,
                                 size_t* read, int* error) {
   ASSERT(socket_ != NULL);
-  int result = socket_->Recv(buffer, buffer_len);
+  int result = socket_->Recv(buffer, buffer_len, nullptr);
   if (result < 0) {
     if (socket_->IsBlocking())
       return SR_BLOCK;
diff --git a/webrtc/base/ssladapter_unittest.cc b/webrtc/base/ssladapter_unittest.cc
index 16e5c2e..adce5f4 100644
--- a/webrtc/base/ssladapter_unittest.cc
+++ b/webrtc/base/ssladapter_unittest.cc
@@ -102,7 +102,7 @@
     char buffer[4096] = "";
 
     // Read data received from the server and store it in our internal buffer.
-    int read = socket->Recv(buffer, sizeof(buffer) - 1);
+    int read = socket->Recv(buffer, sizeof(buffer) - 1, nullptr);
     if (read != -1) {
       buffer[read] = '\0';
 
diff --git a/webrtc/base/testclient.cc b/webrtc/base/testclient.cc
index be4de82..fbb4f0c 100644
--- a/webrtc/base/testclient.cc
+++ b/webrtc/base/testclient.cc
@@ -19,7 +19,7 @@
 //         NextPacket.
 
 TestClient::TestClient(AsyncPacketSocket* socket)
-    : socket_(socket), ready_to_send_(false) {
+    : socket_(socket), ready_to_send_(false), prev_packet_timestamp_(-1) {
   packets_ = new std::vector<Packet*>();
   socket_->SignalReadPacket.connect(this, &TestClient::OnPacket);
   socket_->SignalReadyToSend.connect(this, &TestClient::OnReadyToSend);
@@ -91,7 +91,8 @@
   bool res = false;
   Packet* packet = NextPacket(kTimeoutMs);
   if (packet) {
-    res = (packet->size == size && memcmp(packet->buf, buf, size) == 0);
+    res = (packet->size == size && memcmp(packet->buf, buf, size) == 0 &&
+           CheckTimestamp(packet->packet_time.timestamp));
     if (addr)
       *addr = packet->addr;
     delete packet;
@@ -99,6 +100,29 @@
   return res;
 }
 
+bool TestClient::CheckTimestamp(int64_t packet_timestamp) {
+  bool res = true;
+  if (packet_timestamp == -1) {
+    res = false;
+  }
+  int64_t time_us = rtc::TimeMicros();
+  if (prev_packet_timestamp_ != -1) {
+    if (packet_timestamp < prev_packet_timestamp_) {
+      res = false;
+    }
+    const int64_t kErrorMarginUs = 20000;
+    if (packet_timestamp - prev_packet_timestamp_ <
+            time_us - prev_time_us_ - kErrorMarginUs ||
+        packet_timestamp - prev_packet_timestamp_ >
+            time_us - prev_time_us_ + kErrorMarginUs) {
+      res = false;
+    }
+  }
+  prev_packet_timestamp_ = packet_timestamp;
+  prev_time_us_ = time_us;
+  return res;
+}
+
 bool TestClient::CheckNoPacket() {
   bool res;
   Packet* packet = NextPacket(kNoPacketTimeoutMs);
@@ -123,21 +147,24 @@
                           size_t size, const SocketAddress& remote_addr,
                           const PacketTime& packet_time) {
   CritScope cs(&crit_);
-  packets_->push_back(new Packet(remote_addr, buf, size));
+  packets_->push_back(new Packet(remote_addr, buf, size, packet_time));
 }
 
 void TestClient::OnReadyToSend(AsyncPacketSocket* socket) {
   ready_to_send_ = true;
 }
 
-TestClient::Packet::Packet(const SocketAddress& a, const char* b, size_t s)
-    : addr(a), buf(0), size(s) {
+TestClient::Packet::Packet(const SocketAddress& a,
+                           const char* b,
+                           size_t s,
+                           const PacketTime& packet_time)
+    : addr(a), buf(0), size(s), packet_time(packet_time) {
   buf = new char[size];
   memcpy(buf, b, size);
 }
 
 TestClient::Packet::Packet(const Packet& p)
-    : addr(p.addr), buf(0), size(p.size) {
+    : addr(p.addr), buf(0), size(p.size), packet_time(p.packet_time) {
   buf = new char[size];
   memcpy(buf, p.buf, size);
 }
diff --git a/webrtc/base/testclient.h b/webrtc/base/testclient.h
index df831fe..d78e142 100644
--- a/webrtc/base/testclient.h
+++ b/webrtc/base/testclient.h
@@ -24,13 +24,17 @@
  public:
   // Records the contents of a packet that was received.
   struct Packet {
-    Packet(const SocketAddress& a, const char* b, size_t s);
+    Packet(const SocketAddress& a,
+           const char* b,
+           size_t s,
+           const PacketTime& packet_time);
     Packet(const Packet& p);
     virtual ~Packet();
 
     SocketAddress addr;
     char*  buf;
     size_t size;
+    PacketTime packet_time;
   };
 
   // Default timeout for NextPacket reads.
@@ -85,11 +89,14 @@
                 const SocketAddress& remote_addr,
                 const PacketTime& packet_time);
   void OnReadyToSend(AsyncPacketSocket* socket);
+  bool CheckTimestamp(int64_t packet_timestamp);
 
   CriticalSection crit_;
   AsyncPacketSocket* socket_;
   std::vector<Packet*>* packets_;
   bool ready_to_send_;
+  int64_t prev_packet_timestamp_;
+  int64_t prev_time_us_;
   RTC_DISALLOW_COPY_AND_ASSIGN(TestClient);
 };
 
diff --git a/webrtc/base/testutils.h b/webrtc/base/testutils.h
index e5e571b..c9d5a31 100644
--- a/webrtc/base/testutils.h
+++ b/webrtc/base/testutils.h
@@ -359,7 +359,7 @@
   }
   void OnReadEvent(AsyncSocket* socket) {
     char data[64 * 1024];
-    int result = socket_->Recv(data, arraysize(data));
+    int result = socket_->Recv(data, arraysize(data), nullptr);
     if (result > 0) {
       recv_buffer_.insert(recv_buffer_.end(), data, data + result);
     }
diff --git a/webrtc/base/virtualsocket_unittest.cc b/webrtc/base/virtualsocket_unittest.cc
index e633104..ce89b50 100644
--- a/webrtc/base/virtualsocket_unittest.cc
+++ b/webrtc/base/virtualsocket_unittest.cc
@@ -464,7 +464,7 @@
 
     char buffer[10];
     EXPECT_FALSE(sink.Check(b.get(), testing::SSE_READ));
-    EXPECT_EQ(-1, b->Recv(buffer, 10));
+    EXPECT_EQ(-1, b->Recv(buffer, 10, nullptr));
 
     EXPECT_TRUE(sink.Check(a, testing::SSE_CLOSE));
     EXPECT_EQ(a->GetState(), AsyncSocket::CS_CLOSED);
@@ -531,7 +531,7 @@
     EXPECT_TRUE(a->IsBlocking());
 
     // Read a subset of the data
-    result = b->Recv(recv_buffer + recv_pos, 500);
+    result = b->Recv(recv_buffer + recv_pos, 500, nullptr);
     EXPECT_EQ(500, result);
     recv_pos += result;
 
@@ -546,7 +546,7 @@
 
     // Empty the recv buffer
     while (true) {
-      result = b->Recv(recv_buffer + recv_pos, kDataSize - recv_pos);
+      result = b->Recv(recv_buffer + recv_pos, kDataSize - recv_pos, nullptr);
       if (result < 0) {
         EXPECT_EQ(-1, result);
         EXPECT_TRUE(b->IsBlocking());
@@ -560,7 +560,7 @@
 
     // Continue to empty the recv buffer
     while (true) {
-      result = b->Recv(recv_buffer + recv_pos, kDataSize - recv_pos);
+      result = b->Recv(recv_buffer + recv_pos, kDataSize - recv_pos, nullptr);
       if (result < 0) {
         EXPECT_EQ(-1, result);
         EXPECT_TRUE(b->IsBlocking());
@@ -579,7 +579,7 @@
 
     // Receive the last of the data
     while (true) {
-      result = b->Recv(recv_buffer + recv_pos, kDataSize - recv_pos);
+      result = b->Recv(recv_buffer + recv_pos, kDataSize - recv_pos, nullptr);
       if (result < 0) {
         EXPECT_EQ(-1, result);
         EXPECT_TRUE(b->IsBlocking());
@@ -626,7 +626,7 @@
     ss_->ProcessMessagesUntilIdle();
 
     for (char i = 0; i < cNumPackets; ++i) {
-      EXPECT_EQ(1, b->Recv(buffer, sizeof(buffer)));
+      EXPECT_EQ(1, b->Recv(buffer, sizeof(buffer), nullptr));
       EXPECT_EQ(static_cast<char>('0' + i), buffer[0]);
     }
 
@@ -646,7 +646,7 @@
     ss_->ProcessMessagesUntilIdle();
 
     for (char i = 0; i < cNumPackets; ++i) {
-      EXPECT_EQ(1, b->Recv(buffer, sizeof(buffer)));
+      EXPECT_EQ(1, b->Recv(buffer, sizeof(buffer), nullptr));
       EXPECT_EQ(static_cast<char>('A' + i), buffer[0]);
     }
   }
diff --git a/webrtc/base/virtualsocketserver.cc b/webrtc/base/virtualsocketserver.cc
index c76fe42..baeeb8e 100644
--- a/webrtc/base/virtualsocketserver.cc
+++ b/webrtc/base/virtualsocketserver.cc
@@ -264,12 +264,18 @@
   }
 }
 
-int VirtualSocket::Recv(void* pv, size_t cb) {
+int VirtualSocket::Recv(void* pv, size_t cb, int64_t* timestamp) {
   SocketAddress addr;
-  return RecvFrom(pv, cb, &addr);
+  return RecvFrom(pv, cb, &addr, timestamp);
 }
 
-int VirtualSocket::RecvFrom(void* pv, size_t cb, SocketAddress* paddr) {
+int VirtualSocket::RecvFrom(void* pv,
+                            size_t cb,
+                            SocketAddress* paddr,
+                            int64_t* timestamp) {
+  if (timestamp) {
+    *timestamp = -1;
+  }
   // If we don't have a packet, then either error or wait for one to arrive.
   if (recv_buffer_.empty()) {
     if (async_) {
diff --git a/webrtc/base/virtualsocketserver.h b/webrtc/base/virtualsocketserver.h
index 897ba9e..8673d40 100644
--- a/webrtc/base/virtualsocketserver.h
+++ b/webrtc/base/virtualsocketserver.h
@@ -274,8 +274,11 @@
   int Close() override;
   int Send(const void* pv, size_t cb) override;
   int SendTo(const void* pv, size_t cb, const SocketAddress& addr) override;
-  int Recv(void* pv, size_t cb) override;
-  int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) override;
+  int Recv(void* pv, size_t cb, int64_t* timestamp) override;
+  int RecvFrom(void* pv,
+               size_t cb,
+               SocketAddress* paddr,
+               int64_t* timestamp) override;
   int Listen(int backlog) override;
   VirtualSocket* Accept(SocketAddress* paddr) override;
 
diff --git a/webrtc/base/win32socketserver.cc b/webrtc/base/win32socketserver.cc
index 5423eed..ab25312 100644
--- a/webrtc/base/win32socketserver.cc
+++ b/webrtc/base/win32socketserver.cc
@@ -438,7 +438,10 @@
   return sent;
 }
 
-int Win32Socket::Recv(void* buffer, size_t length) {
+int Win32Socket::Recv(void* buffer, size_t length, int64_t* timestamp) {
+  if (timestamp) {
+    *timestamp = -1;
+  }
   int received = ::recv(socket_, static_cast<char*>(buffer),
                         static_cast<int>(length), 0);
   UpdateLastError();
@@ -447,8 +450,13 @@
   return received;
 }
 
-int Win32Socket::RecvFrom(void* buffer, size_t length,
-                          SocketAddress* out_addr) {
+int Win32Socket::RecvFrom(void* buffer,
+                          size_t length,
+                          SocketAddress* out_addr,
+                          int64_t* timestamp) {
+  if (timestamp) {
+    *timestamp = -1;
+  }
   sockaddr_storage saddr;
   socklen_t addr_len = sizeof(saddr);
   int received = ::recvfrom(socket_, static_cast<char*>(buffer),
diff --git a/webrtc/base/win32socketserver.h b/webrtc/base/win32socketserver.h
index f47ed75..28bee6a 100644
--- a/webrtc/base/win32socketserver.h
+++ b/webrtc/base/win32socketserver.h
@@ -44,8 +44,11 @@
   virtual int Connect(const SocketAddress& addr);
   virtual int Send(const void *buffer, size_t length);
   virtual int SendTo(const void *buffer, size_t length, const SocketAddress& addr);
-  virtual int Recv(void *buffer, size_t length);
-  virtual int RecvFrom(void *buffer, size_t length, SocketAddress *out_addr);
+  virtual int Recv(void* buffer, size_t length, int64_t* timestamp);
+  virtual int RecvFrom(void* buffer,
+                       size_t length,
+                       SocketAddress* out_addr,
+                       int64_t* timestamp);
   virtual int Listen(int backlog);
   virtual Win32Socket *Accept(SocketAddress *out_addr);
   virtual int Close();
diff --git a/webrtc/examples/peerconnection/client/peer_connection_client.cc b/webrtc/examples/peerconnection/client/peer_connection_client.cc
index 9875115..86d2119 100644
--- a/webrtc/examples/peerconnection/client/peer_connection_client.cc
+++ b/webrtc/examples/peerconnection/client/peer_connection_client.cc
@@ -296,7 +296,7 @@
                                           size_t* content_length) {
   char buffer[0xffff];
   do {
-    int bytes = socket->Recv(buffer, sizeof(buffer));
+    int bytes = socket->Recv(buffer, sizeof(buffer), nullptr);
     if (bytes <= 0)
       break;
     data->append(buffer, bytes);
diff --git a/webrtc/libjingle/xmpp/xmppsocket.cc b/webrtc/libjingle/xmpp/xmppsocket.cc
index 9c1bf8b..c42dcd1 100644
--- a/webrtc/libjingle/xmpp/xmppsocket.cc
+++ b/webrtc/libjingle/xmpp/xmppsocket.cc
@@ -179,7 +179,7 @@
 
 bool XmppSocket::Read(char * data, size_t len, size_t* len_read) {
 #ifndef USE_SSLSTREAM
-  int read = cricket_socket_->Recv(data, len);
+  int read = cricket_socket_->Recv(data, len, nullptr);
   if (read > 0) {
     *len_read = (size_t)read;
     return true;
diff --git a/webrtc/libjingle/xmpp/xmppsocket.h b/webrtc/libjingle/xmpp/xmppsocket.h
index d862afd..02d6453 100644
--- a/webrtc/libjingle/xmpp/xmppsocket.h
+++ b/webrtc/libjingle/xmpp/xmppsocket.h
@@ -19,7 +19,7 @@
 
 // The below define selects the SSLStreamAdapter implementation for
 // SSL, as opposed to the SSLAdapter socket adapter.
-// #define USE_SSLSTREAM 
+// #define USE_SSLSTREAM
 
 namespace rtc {
   class StreamInterface;