Adds a modified copy of talk/base to webrtc/base. It is the first step in
migrating talk/base to webrtc/base.

BUG=N/A
R=niklas.enbom@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@6129 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/base/socketstream.cc b/base/socketstream.cc
new file mode 100644
index 0000000..b0acf94
--- /dev/null
+++ b/base/socketstream.cc
@@ -0,0 +1,121 @@
+/*
+ *  Copyright 2010 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/base/socketstream.h"
+
+namespace rtc {
+
+SocketStream::SocketStream(AsyncSocket* socket) : socket_(NULL) {
+  Attach(socket);
+}
+
+SocketStream::~SocketStream() {
+  delete socket_;
+}
+
+void SocketStream::Attach(AsyncSocket* socket) {
+  if (socket_)
+    delete socket_;
+  socket_ = socket;
+  if (socket_) {
+    socket_->SignalConnectEvent.connect(this, &SocketStream::OnConnectEvent);
+    socket_->SignalReadEvent.connect(this,    &SocketStream::OnReadEvent);
+    socket_->SignalWriteEvent.connect(this,   &SocketStream::OnWriteEvent);
+    socket_->SignalCloseEvent.connect(this,   &SocketStream::OnCloseEvent);
+  }
+}
+
+AsyncSocket* SocketStream::Detach() {
+  AsyncSocket* socket = socket_;
+  if (socket_) {
+    socket_->SignalConnectEvent.disconnect(this);
+    socket_->SignalReadEvent.disconnect(this);
+    socket_->SignalWriteEvent.disconnect(this);
+    socket_->SignalCloseEvent.disconnect(this);
+    socket_ = NULL;
+  }
+  return socket;
+}
+
+StreamState SocketStream::GetState() const {
+  ASSERT(socket_ != NULL);
+  switch (socket_->GetState()) {
+    case Socket::CS_CONNECTED:
+      return SS_OPEN;
+    case Socket::CS_CONNECTING:
+      return SS_OPENING;
+    case Socket::CS_CLOSED:
+    default:
+      return SS_CLOSED;
+  }
+}
+
+StreamResult SocketStream::Read(void* buffer, size_t buffer_len,
+                                size_t* read, int* error) {
+  ASSERT(socket_ != NULL);
+  int result = socket_->Recv(buffer, buffer_len);
+  if (result < 0) {
+    if (socket_->IsBlocking())
+      return SR_BLOCK;
+    if (error)
+      *error = socket_->GetError();
+    return SR_ERROR;
+  }
+  if ((result > 0) || (buffer_len == 0)) {
+    if (read)
+      *read = result;
+    return SR_SUCCESS;
+  }
+  return SR_EOS;
+}
+
+StreamResult SocketStream::Write(const void* data, size_t data_len,
+                                 size_t* written, int* error) {
+  ASSERT(socket_ != NULL);
+  int result = socket_->Send(data, data_len);
+  if (result < 0) {
+    if (socket_->IsBlocking())
+      return SR_BLOCK;
+    if (error)
+      *error = socket_->GetError();
+    return SR_ERROR;
+  }
+  if (written)
+    *written = result;
+  return SR_SUCCESS;
+}
+
+void SocketStream::Close() {
+  ASSERT(socket_ != NULL);
+  socket_->Close();
+}
+
+void SocketStream::OnConnectEvent(AsyncSocket* socket) {
+  ASSERT(socket == socket_);
+  SignalEvent(this, SE_OPEN | SE_READ | SE_WRITE, 0);
+}
+
+void SocketStream::OnReadEvent(AsyncSocket* socket) {
+  ASSERT(socket == socket_);
+  SignalEvent(this, SE_READ, 0);
+}
+
+void SocketStream::OnWriteEvent(AsyncSocket* socket) {
+  ASSERT(socket == socket_);
+  SignalEvent(this, SE_WRITE, 0);
+}
+
+void SocketStream::OnCloseEvent(AsyncSocket* socket, int err) {
+  ASSERT(socket == socket_);
+  SignalEvent(this, SE_CLOSE, err);
+}
+
+
+}  // namespace rtc