Cleanup Socket class and remove it from the platform files.
authorbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 4 Sep 2013 10:41:51 +0000 (10:41 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 4 Sep 2013 10:41:51 +0000 (10:41 +0000)
Move the Socket class to dedicated platform/socket.{cc,h} files.
Cleaned up the implementation to allow for more code sharing.

R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/23484014

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16521 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

14 files changed:
src/d8-debug.cc
src/debug-agent.cc
src/debug-agent.h
src/debug.cc
src/platform-posix.cc
src/platform-win32.cc
src/platform.h
src/platform/socket.cc [new file with mode: 0644]
src/platform/socket.h [new file with mode: 0644]
test/cctest/cctest.gyp
test/cctest/cctest.status
test/cctest/test-debug.cc
test/cctest/test-socket.cc [moved from test/cctest/test-sockets.cc with 94% similarity]
tools/gyp/v8.gyp

index 2905500..602ae16 100644 (file)
@@ -29,8 +29,9 @@
 
 #include "d8.h"
 #include "d8-debug.h"
-#include "platform.h"
 #include "debug-agent.h"
+#include "platform.h"
+#include "platform/socket.h"
 
 
 namespace v8 {
@@ -171,21 +172,14 @@ void RunRemoteDebugger(Isolate* isolate, int port) {
 void RemoteDebugger::Run() {
   bool ok;
 
-  // Make sure that socket support is initialized.
-  ok = i::Socket::SetUp();
-  if (!ok) {
-    printf("Unable to initialize socket support %d\n", i::Socket::LastError());
-    return;
-  }
-
   // Connect to the debugger agent.
-  conn_ = i::OS::CreateSocket();
+  conn_ = new i::Socket;
   static const int kPortStrSize = 6;
   char port_str[kPortStrSize];
   i::OS::SNPrintF(i::Vector<char>(port_str, kPortStrSize), "%d", port_);
   ok = conn_->Connect("localhost", port_str);
   if (!ok) {
-    printf("Unable to connect to debug agent %d\n", i::Socket::LastError());
+    printf("Unable to connect to debug agent %d\n", i::Socket::GetLastError());
     return;
   }
 
index 51bd4b1..aad3608 100644 (file)
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 
 #include "v8.h"
 #include "debug.h"
 #include "debug-agent.h"
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
+#include "platform/socket.h"
 
 namespace v8 {
 namespace internal {
@@ -44,6 +44,27 @@ void DebuggerAgentMessageHandler(const v8::Debug::Message& message) {
 }
 
 
+DebuggerAgent::DebuggerAgent(Isolate* isolate, const char* name, int port)
+  : Thread(name),
+    isolate_(isolate),
+    name_(StrDup(name)),
+    port_(port),
+    server_(new Socket),
+    terminate_(false),
+    session_(NULL),
+    terminate_now_(0),
+    listening_(0) {
+  ASSERT(isolate_->debugger_agent_instance() == NULL);
+  isolate_->set_debugger_agent_instance(this);
+}
+
+
+DebuggerAgent::~DebuggerAgent() {
+  isolate_->set_debugger_agent_instance(NULL);
+  delete server_;
+}
+
+
 // Debugger agent main thread.
 void DebuggerAgent::Run() {
   // Allow this socket to reuse port even if still in TIME_WAIT.
@@ -112,8 +133,10 @@ void DebuggerAgent::CreateSession(Socket* client) {
 
   // If another session is already established terminate this one.
   if (session_ != NULL) {
-    client->Send(kCreateSessionMessage, StrLength(kCreateSessionMessage));
+    int len = StrLength(kCreateSessionMessage);
+    int res = client->Send(kCreateSessionMessage, len);
     delete client;
+    USE(res);
     return;
   }
 
@@ -228,7 +251,7 @@ void DebuggerAgentSession::Shutdown() {
 const char* const DebuggerAgentUtil::kContentLength = "Content-Length";
 
 
-SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(const Socket* conn) {
+SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(Socket* conn) {
   int received;
 
   // Read header.
@@ -245,7 +268,7 @@ SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(const Socket* conn) {
       prev_c = c;
       received = conn->Receive(&c, 1);
       if (received == 0) {
-        PrintF("Error %d\n", Socket::LastError());
+        PrintF("Error %d\n", Socket::GetLastError());
         return SmartArrayPointer<char>();
       }
 
@@ -307,7 +330,7 @@ SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(const Socket* conn) {
   char* buffer = NewArray<char>(content_length + 1);
   received = ReceiveAll(conn, buffer, content_length);
   if (received < content_length) {
-    PrintF("Error %d\n", Socket::LastError());
+    PrintF("Error %d\n", Socket::GetLastError());
     return SmartArrayPointer<char>();
   }
   buffer[content_length] = '\0';
@@ -316,7 +339,7 @@ SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(const Socket* conn) {
 }
 
 
-bool DebuggerAgentUtil::SendConnectMessage(const Socket* conn,
+bool DebuggerAgentUtil::SendConnectMessage(Socket* conn,
                                            const char* embedding_host) {
   static const int kBufferSize = 80;
   char buffer[kBufferSize];  // Sending buffer.
@@ -362,7 +385,7 @@ bool DebuggerAgentUtil::SendConnectMessage(const Socket* conn,
 }
 
 
-bool DebuggerAgentUtil::SendMessage(const Socket* conn,
+bool DebuggerAgentUtil::SendMessage(Socket* conn,
                                     const Vector<uint16_t> message) {
   static const int kBufferSize = 80;
   char buffer[kBufferSize];  // Sending buffer both for header and body.
@@ -377,14 +400,17 @@ bool DebuggerAgentUtil::SendMessage(const Socket* conn,
   }
 
   // Send the header.
-  int len;
-  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
-                     "%s: %d\r\n", kContentLength, utf8_len);
-  conn->Send(buffer, len);
+  int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
+                         "%s: %d\r\n", kContentLength, utf8_len);
+  if (conn->Send(buffer, len) < len) {
+    return false;
+  }
 
   // Terminate header with empty line.
   len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
-  conn->Send(buffer, len);
+  if (conn->Send(buffer, len) < len) {
+    return false;
+  }
 
   // Send message body as UTF-8.
   int buffer_position = 0;  // Current buffer position.
@@ -404,13 +430,19 @@ bool DebuggerAgentUtil::SendMessage(const Socket* conn,
         const int kEncodedSurrogateLength =
             unibrow::Utf16::kUtf8BytesToCodeASurrogate;
         ASSERT(buffer_position >= kEncodedSurrogateLength);
-        conn->Send(buffer, buffer_position - kEncodedSurrogateLength);
+        len = buffer_position - kEncodedSurrogateLength;
+        if (conn->Send(buffer, len) < len) {
+          return false;
+        }
         for (int i = 0; i < kEncodedSurrogateLength; i++) {
           buffer[i] = buffer[buffer_position + i];
         }
         buffer_position = kEncodedSurrogateLength;
       } else {
-        conn->Send(buffer, buffer_position);
+        len = buffer_position;
+        if (conn->Send(buffer, len) < len) {
+          return false;
+        }
         buffer_position = 0;
       }
     }
@@ -421,7 +453,7 @@ bool DebuggerAgentUtil::SendMessage(const Socket* conn,
 }
 
 
-bool DebuggerAgentUtil::SendMessage(const Socket* conn,
+bool DebuggerAgentUtil::SendMessage(Socket* conn,
                                     const v8::Handle<v8::String> request) {
   static const int kBufferSize = 80;
   char buffer[kBufferSize];  // Sending buffer both for header and body.
@@ -430,24 +462,30 @@ bool DebuggerAgentUtil::SendMessage(const Socket* conn,
   v8::String::Utf8Value utf8_request(request);
 
   // Send the header.
-  int len;
-  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
-                     "Content-Length: %d\r\n", utf8_request.length());
-  conn->Send(buffer, len);
+  int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
+                         "Content-Length: %d\r\n", utf8_request.length());
+  if (conn->Send(buffer, len) < len) {
+    return false;
+  }
 
   // Terminate header with empty line.
   len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
-  conn->Send(buffer, len);
+  if (conn->Send(buffer, len) < len) {
+    return false;
+  }
 
   // Send message body as UTF-8.
-  conn->Send(*utf8_request, utf8_request.length());
+  len = utf8_request.length();
+  if (conn->Send(*utf8_request, len) < len) {
+    return false;
+  }
 
   return true;
 }
 
 
 // Receive the full buffer before returning unless an error occours.
-int DebuggerAgentUtil::ReceiveAll(const Socket* conn, char* data, int len) {
+int DebuggerAgentUtil::ReceiveAll(Socket* conn, char* data, int len) {
   int total_received = 0;
   while (total_received < len) {
     int received = conn->Receive(data + total_received, len - total_received);
index 9d7c62b..138e51a 100644 (file)
@@ -37,27 +37,15 @@ namespace internal {
 
 // Forward decelrations.
 class DebuggerAgentSession;
+class Socket;
 
 
 // Debugger agent which starts a socket listener on the debugger port and
 // handles connection from a remote debugger.
 class DebuggerAgent: public Thread {
  public:
-  DebuggerAgent(Isolate* isolate, const char* name, int port)
-      : Thread(name),
-        isolate_(isolate),
-        name_(StrDup(name)), port_(port),
-        server_(OS::CreateSocket()), terminate_(false),
-        session_(NULL),
-        terminate_now_(0),
-        listening_(0) {
-    ASSERT(isolate_->debugger_agent_instance() == NULL);
-    isolate_->set_debugger_agent_instance(this);
-  }
-  ~DebuggerAgent() {
-     isolate_->set_debugger_agent_instance(NULL);
-     delete server_;
-  }
+  DebuggerAgent(Isolate* isolate, const char* name, int port);
+  ~DebuggerAgent();
 
   void Shutdown();
   void WaitUntilListening();
@@ -116,13 +104,11 @@ class DebuggerAgentUtil {
  public:
   static const char* const kContentLength;
 
-  static SmartArrayPointer<char> ReceiveMessage(const Socket* conn);
-  static bool SendConnectMessage(const Socket* conn,
-                                 const char* embedding_host);
-  static bool SendMessage(const Socket* conn, const Vector<uint16_t> message);
-  static bool SendMessage(const Socket* conn,
-                          const v8::Handle<v8::String> message);
-  static int ReceiveAll(const Socket* conn, char* data, int len);
+  static SmartArrayPointer<char> ReceiveMessage(Socket* conn);
+  static bool SendConnectMessage(Socket* conn, const char* embedding_host);
+  static bool SendMessage(Socket* conn, const Vector<uint16_t> message);
+  static bool SendMessage(Socket* conn, const v8::Handle<v8::String> message);
+  static int ReceiveAll(Socket* conn, char* data, int len);
 };
 
 } }  // namespace v8::internal
index 9f38601..c3d737e 100644 (file)
@@ -3433,15 +3433,11 @@ bool Debugger::StartAgent(const char* name, int port,
     v8::Debug::DebugBreak();
   }
 
-  if (Socket::SetUp()) {
-    if (agent_ == NULL) {
-      agent_ = new DebuggerAgent(isolate_, name, port);
-      agent_->Start();
-    }
-    return true;
+  if (agent_ == NULL) {
+    agent_ = new DebuggerAgent(isolate_, name, port);
+    agent_->Start();
   }
-
-  return false;
+  return true;
 }
 
 
index aaf0ca7..504d140 100644 (file)
@@ -739,202 +739,4 @@ void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
 }
 
 
-// ----------------------------------------------------------------------------
-// POSIX socket support.
-//
-
-class POSIXSocket : public Socket {
- public:
-  explicit POSIXSocket() {
-    // Create the socket.
-    socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-    if (IsValid()) {
-      // Allow rapid reuse.
-      static const int kOn = 1;
-      int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
-                           &kOn, sizeof(kOn));
-      ASSERT(ret == 0);
-      USE(ret);
-    }
-  }
-  explicit POSIXSocket(int socket): socket_(socket) { }
-  virtual ~POSIXSocket() { Shutdown(); }
-
-  // Server initialization.
-  bool Bind(const int port);
-  bool Listen(int backlog) const;
-  Socket* Accept() const;
-
-  // Client initialization.
-  bool Connect(const char* host, const char* port);
-
-  // Shutdown socket for both read and write.
-  bool Shutdown();
-
-  // Data Transimission
-  int Send(const char* data, int len) const;
-  int Receive(char* data, int len) const;
-
-  bool SetReuseAddress(bool reuse_address);
-
-  bool IsValid() const { return socket_ != -1; }
-
- private:
-  int socket_;
-};
-
-
-bool POSIXSocket::Bind(const int port) {
-  if (!IsValid())  {
-    return false;
-  }
-
-  sockaddr_in addr;
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
-  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-  addr.sin_port = htons(port);
-  int status = bind(socket_,
-                    BitCast<struct sockaddr *>(&addr),
-                    sizeof(addr));
-  return status == 0;
-}
-
-
-bool POSIXSocket::Listen(int backlog) const {
-  if (!IsValid()) {
-    return false;
-  }
-
-  int status = listen(socket_, backlog);
-  return status == 0;
-}
-
-
-Socket* POSIXSocket::Accept() const {
-  if (!IsValid()) {
-    return NULL;
-  }
-
-  int socket;
-  do {
-    socket = accept(socket_, NULL, NULL);
-  } while (socket == -1 && errno == EINTR);
-
-  if (socket == -1) {
-    return NULL;
-  } else {
-    return new POSIXSocket(socket);
-  }
-}
-
-
-bool POSIXSocket::Connect(const char* host, const char* port) {
-  if (!IsValid()) {
-    return false;
-  }
-
-  // Lookup host and port.
-  struct addrinfo *result = NULL;
-  struct addrinfo hints;
-  memset(&hints, 0, sizeof(addrinfo));
-  hints.ai_family = AF_INET;
-  hints.ai_socktype = SOCK_STREAM;
-  hints.ai_protocol = IPPROTO_TCP;
-  int status = getaddrinfo(host, port, &hints, &result);
-  if (status != 0) {
-    return false;
-  }
-
-  // Connect.
-  do {
-    status = connect(socket_, result->ai_addr, result->ai_addrlen);
-  } while (status == -1 && errno == EINTR);
-  freeaddrinfo(result);
-  return status == 0;
-}
-
-
-bool POSIXSocket::Shutdown() {
-  if (IsValid()) {
-    // Shutdown socket for both read and write.
-    int status = shutdown(socket_, SHUT_RDWR);
-    close(socket_);
-    socket_ = -1;
-    return status == 0;
-  }
-  return true;
-}
-
-
-int POSIXSocket::Send(const char* data, int len) const {
-  if (len <= 0) return 0;
-  int written = 0;
-  while (written < len) {
-    int status = send(socket_, data + written, len - written, 0);
-    if (status == 0) {
-      break;
-    } else if (status > 0) {
-      written += status;
-    } else if (errno != EINTR) {
-      return 0;
-    }
-  }
-  return written;
-}
-
-
-int POSIXSocket::Receive(char* data, int len) const {
-  if (len <= 0) return 0;
-  int status;
-  do {
-    status = recv(socket_, data, len, 0);
-  } while (status == -1 && errno == EINTR);
-  return (status < 0) ? 0 : status;
-}
-
-
-bool POSIXSocket::SetReuseAddress(bool reuse_address) {
-  int on = reuse_address ? 1 : 0;
-  int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-  return status == 0;
-}
-
-
-bool Socket::SetUp() {
-  // Nothing to do on POSIX.
-  return true;
-}
-
-
-int Socket::LastError() {
-  return errno;
-}
-
-
-uint16_t Socket::HToN(uint16_t value) {
-  return htons(value);
-}
-
-
-uint16_t Socket::NToH(uint16_t value) {
-  return ntohs(value);
-}
-
-
-uint32_t Socket::HToN(uint32_t value) {
-  return htonl(value);
-}
-
-
-uint32_t Socket::NToH(uint32_t value) {
-  return ntohl(value);
-}
-
-
-Socket* OS::CreateSocket() {
-  return new POSIXSocket();
-}
-
-
 } }  // namespace v8::internal
index 199ed2d..87387e7 100644 (file)
@@ -1615,198 +1615,6 @@ void Thread::YieldCPU() {
 }
 
 
-// ----------------------------------------------------------------------------
-// Win32 socket support.
-//
-
-class Win32Socket : public Socket {
- public:
-  explicit Win32Socket() {
-    // Create the socket.
-    socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-  }
-  explicit Win32Socket(SOCKET socket): socket_(socket) { }
-  virtual ~Win32Socket() { Shutdown(); }
-
-  // Server initialization.
-  bool Bind(const int port);
-  bool Listen(int backlog) const;
-  Socket* Accept() const;
-
-  // Client initialization.
-  bool Connect(const char* host, const char* port);
-
-  // Shutdown socket for both read and write.
-  bool Shutdown();
-
-  // Data Transimission
-  int Send(const char* data, int len) const;
-  int Receive(char* data, int len) const;
-
-  bool SetReuseAddress(bool reuse_address);
-
-  bool IsValid() const { return socket_ != INVALID_SOCKET; }
-
- private:
-  SOCKET socket_;
-};
-
-
-bool Win32Socket::Bind(const int port) {
-  if (!IsValid())  {
-    return false;
-  }
-
-  sockaddr_in addr;
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
-  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-  addr.sin_port = htons(port);
-  int status = bind(socket_,
-                    reinterpret_cast<struct sockaddr *>(&addr),
-                    sizeof(addr));
-  return status == 0;
-}
-
-
-bool Win32Socket::Listen(int backlog) const {
-  if (!IsValid()) {
-    return false;
-  }
-
-  int status = listen(socket_, backlog);
-  return status == 0;
-}
-
-
-Socket* Win32Socket::Accept() const {
-  if (!IsValid()) {
-    return NULL;
-  }
-
-  SOCKET socket = accept(socket_, NULL, NULL);
-  if (socket == INVALID_SOCKET) {
-    return NULL;
-  } else {
-    return new Win32Socket(socket);
-  }
-}
-
-
-bool Win32Socket::Connect(const char* host, const char* port) {
-  if (!IsValid()) {
-    return false;
-  }
-
-  // Lookup host and port.
-  struct addrinfo *result = NULL;
-  struct addrinfo hints;
-  memset(&hints, 0, sizeof(addrinfo));
-  hints.ai_family = AF_INET;
-  hints.ai_socktype = SOCK_STREAM;
-  hints.ai_protocol = IPPROTO_TCP;
-  int status = getaddrinfo(host, port, &hints, &result);
-  if (status != 0) {
-    return false;
-  }
-
-  // Connect.
-  status = connect(socket_,
-                   result->ai_addr,
-                   static_cast<int>(result->ai_addrlen));
-  freeaddrinfo(result);
-  return status == 0;
-}
-
-
-bool Win32Socket::Shutdown() {
-  if (IsValid()) {
-    // Shutdown socket for both read and write.
-    int status = shutdown(socket_, SD_BOTH);
-    closesocket(socket_);
-    socket_ = INVALID_SOCKET;
-    return status == SOCKET_ERROR;
-  }
-  return true;
-}
-
-
-int Win32Socket::Send(const char* data, int len) const {
-  if (len <= 0) return 0;
-  int written = 0;
-  while (written < len) {
-    int status = send(socket_, data + written, len - written, 0);
-    if (status == 0) {
-      break;
-    } else if (status > 0) {
-      written += status;
-    } else {
-      return 0;
-    }
-  }
-  return written;
-}
-
-
-int Win32Socket::Receive(char* data, int len) const {
-  if (len <= 0) return 0;
-  int status = recv(socket_, data, len, 0);
-  return (status == SOCKET_ERROR) ? 0 : status;
-}
-
-
-bool Win32Socket::SetReuseAddress(bool reuse_address) {
-  BOOL on = reuse_address ? true : false;
-  int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
-                          reinterpret_cast<char*>(&on), sizeof(on));
-  return status == SOCKET_ERROR;
-}
-
-
-bool Socket::SetUp() {
-  // Initialize Winsock32
-  int err;
-  WSADATA winsock_data;
-  WORD version_requested = MAKEWORD(1, 0);
-  err = WSAStartup(version_requested, &winsock_data);
-  if (err != 0) {
-    PrintF("Unable to initialize Winsock, err = %d\n", Socket::LastError());
-  }
-
-  return err == 0;
-}
-
-
-int Socket::LastError() {
-  return WSAGetLastError();
-}
-
-
-uint16_t Socket::HToN(uint16_t value) {
-  return htons(value);
-}
-
-
-uint16_t Socket::NToH(uint16_t value) {
-  return ntohs(value);
-}
-
-
-uint32_t Socket::HToN(uint32_t value) {
-  return htonl(value);
-}
-
-
-uint32_t Socket::NToH(uint32_t value) {
-  return ntohl(value);
-}
-
-
-Socket* OS::CreateSocket() {
-  return new Win32Socket();
-}
-
-
 void OS::SetUp() {
   // Seed the random number generator.
   // Convert the current time to a 64-bit integer first, before converting it
index 8565775..18bf6b0 100644 (file)
@@ -108,9 +108,6 @@ double fast_sqrt(double input);
 // on demand.
 void lazily_initialize_fast_exp();
 
-// Forward declarations.
-class Socket;
-
 // ----------------------------------------------------------------------------
 // Fast TLS support
 
@@ -287,10 +284,6 @@ class OS {
 
   static int StackWalk(Vector<StackFrame> frames);
 
-  // Factory method for creating platform dependent Socket.
-  // Please use delete to reclaim the storage for the returned Socket.
-  static Socket* CreateSocket();
-
   class MemoryMappedFile {
    public:
     static MemoryMappedFile* open(const char* name);
@@ -619,47 +612,6 @@ class Thread {
   DISALLOW_COPY_AND_ASSIGN(Thread);
 };
 
-
-// ----------------------------------------------------------------------------
-// Socket
-//
-
-class Socket {
- public:
-  virtual ~Socket() {}
-
-  // Server initialization.
-  virtual bool Bind(const int port) = 0;
-  virtual bool Listen(int backlog) const = 0;
-  virtual Socket* Accept() const = 0;
-
-  // Client initialization.
-  virtual bool Connect(const char* host, const char* port) = 0;
-
-  // Shutdown socket for both read and write. This causes blocking Send and
-  // Receive calls to exit. After Shutdown the Socket object cannot be used for
-  // any communication.
-  virtual bool Shutdown() = 0;
-
-  // Data Transimission
-  // Return 0 on failure.
-  virtual int Send(const char* data, int len) const = 0;
-  virtual int Receive(char* data, int len) const = 0;
-
-  // Set the value of the SO_REUSEADDR socket option.
-  virtual bool SetReuseAddress(bool reuse_address) = 0;
-
-  virtual bool IsValid() const = 0;
-
-  static bool SetUp();
-  static int LastError();
-  static uint16_t HToN(uint16_t value);
-  static uint16_t NToH(uint16_t value);
-  static uint32_t HToN(uint32_t value);
-  static uint32_t NToH(uint32_t value);
-};
-
-
 } }  // namespace v8::internal
 
 #endif  // V8_PLATFORM_H_
diff --git a/src/platform/socket.cc b/src/platform/socket.cc
new file mode 100644 (file)
index 0000000..e82c38c
--- /dev/null
@@ -0,0 +1,223 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "platform/socket.h"
+
+#if V8_OS_POSIX
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <unistd.h>
+#endif
+
+#include <cerrno>
+
+#include "checks.h"
+#include "once.h"
+
+namespace v8 {
+namespace internal {
+
+#if V8_OS_WIN
+
+static V8_DECLARE_ONCE(initialize_winsock) = V8_ONCE_INIT;
+
+
+static void InitializeWinsock() {
+  WSADATA wsa_data;
+  int result = WSAStartup(MAKEWORD(1, 0), &wsa_data);
+  CHECK_EQ(0, result);
+}
+
+#endif  // V8_OS_WIN
+
+
+Socket::Socket() {
+#if V8_OS_WIN
+  // Be sure to initialize the WinSock DLL first.
+  CallOnce(&initialize_winsock, &InitializeWinsock);
+#endif  // V8_OS_WIN
+
+  // Create the native socket handle.
+  native_handle_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+}
+
+
+bool Socket::Bind(int port) {
+  ASSERT_GE(port, 0);
+  ASSERT_LT(port, 65536);
+  if (!IsValid()) return false;
+  struct sockaddr_in sin;
+  memset(&sin, 0, sizeof(sin));
+  sin.sin_family = AF_INET;
+  sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+  sin.sin_port = htons(static_cast<uint16_t>(port));
+  int result = ::bind(
+      native_handle_, reinterpret_cast<struct sockaddr*>(&sin), sizeof(sin));
+  return result == 0;
+}
+
+
+bool Socket::Listen(int backlog) {
+  if (!IsValid()) return false;
+  int result = ::listen(native_handle_, backlog);
+  return result == 0;
+}
+
+
+Socket* Socket::Accept() {
+  if (!IsValid()) return NULL;
+  while (true) {
+    NativeHandle native_handle = ::accept(native_handle_, NULL, NULL);
+    if (native_handle == kInvalidNativeHandle) {
+#if V8_OS_POSIX
+      if (errno == EINTR) continue;  // Retry after signal.
+#endif
+      return NULL;
+    }
+    return new Socket(native_handle);
+  }
+}
+
+
+bool Socket::Connect(const char* host, const char* port) {
+  ASSERT_NE(NULL, host);
+  ASSERT_NE(NULL, port);
+  if (!IsValid()) return false;
+
+  // Lookup host and port.
+  struct addrinfo* info = NULL;
+  struct addrinfo hint;
+  memset(&hint, 0, sizeof(hint));
+  hint.ai_family = AF_INET;
+  hint.ai_socktype = SOCK_STREAM;
+  hint.ai_protocol = IPPROTO_TCP;
+  int result = ::getaddrinfo(host, port, &hint, &info);
+  if (result != 0) {
+    return false;
+  }
+
+  // Connect to the host on the given port.
+  for (struct addrinfo* ai = info; ai != NULL; ai = ai->ai_next) {
+    // Try to connect using this addr info.
+    while (true) {
+      result = ::connect(native_handle_, ai->ai_addr, ai->ai_addrlen);
+      if (result == 0) {
+        freeaddrinfo(info);
+        return true;
+      }
+#if V8_OS_POSIX
+      if (errno == EINTR) continue;  // Retry after signal.
+#endif
+      break;
+    }
+  }
+  freeaddrinfo(info);
+  return false;
+}
+
+
+bool Socket::Shutdown() {
+  if (!IsValid()) return false;
+  // Shutdown socket for both read and write.
+#if V8_OS_POSIX
+  int result = ::shutdown(native_handle_, SHUT_RDWR);
+  ::close(native_handle_);
+#elif V8_OS_WIN
+  int result = ::shutdown(native_handle_, SD_BOTH);
+  ::closesocket(native_handle_);
+#endif
+  native_handle_ = kInvalidNativeHandle;
+  return result == 0;
+}
+
+
+int Socket::Send(const char* buffer, int length) {
+  ASSERT(length <= 0 || buffer != NULL);
+  if (!IsValid()) return 0;
+  int offset = 0;
+  while (offset < length) {
+    int result = ::send(native_handle_, buffer + offset, length - offset, 0);
+    if (result == 0) {
+      break;
+    } else if (result > 0) {
+      ASSERT(result <= length - offset);
+      offset += result;
+    } else {
+#if V8_OS_POSIX
+      if (errno == EINTR) continue;  // Retry after signal.
+#endif
+      return 0;
+    }
+  }
+  return offset;
+}
+
+
+int Socket::Receive(char* buffer, int length) {
+  if (!IsValid()) return 0;
+  if (length <= 0) return 0;
+  ASSERT_NE(NULL, buffer);
+  while (true) {
+    int result = ::recv(native_handle_, buffer, length, 0);
+    if (result < 0) {
+#if V8_OS_POSIX
+      if (errno == EINTR) continue;  // Retry after signal.
+#endif
+      return 0;
+    }
+    return result;
+  }
+}
+
+
+bool Socket::SetReuseAddress(bool reuse_address) {
+  if (!IsValid()) return 0;
+  int v = reuse_address ? 1 : 0;
+  int result = ::setsockopt(native_handle_, SOL_SOCKET, SO_REUSEADDR,
+                            reinterpret_cast<char*>(&v), sizeof(v));
+  return result == 0;
+}
+
+
+// static
+int Socket::GetLastError() {
+#if V8_OS_POSIX
+  return errno;
+#elif V8_OS_WIN
+  // Be sure to initialize the WinSock DLL first.
+  CallOnce(&initialize_winsock, &InitializeWinsock);
+
+  // Now we can safely perform WSA calls.
+  return ::WSAGetLastError();
+#endif
+}
+
+} }  // namespace v8::internal
diff --git a/src/platform/socket.h b/src/platform/socket.h
new file mode 100644 (file)
index 0000000..6710692
--- /dev/null
@@ -0,0 +1,101 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PLATFORM_SOCKET_H_
+#define V8_PLATFORM_SOCKET_H_
+
+#include "globals.h"
+#if V8_OS_WIN
+#include "win32-headers.h"
+#endif
+
+namespace v8 {
+namespace internal {
+
+// ----------------------------------------------------------------------------
+// Socket
+//
+
+class Socket V8_FINAL {
+ public:
+  Socket();
+  ~Socket() { Shutdown(); }
+
+  // Server initialization.
+  bool Bind(int port) V8_WARN_UNUSED_RESULT;
+  bool Listen(int backlog) V8_WARN_UNUSED_RESULT;
+  Socket* Accept() V8_WARN_UNUSED_RESULT;
+
+  // Client initialization.
+  bool Connect(const char* host, const char* port) V8_WARN_UNUSED_RESULT;
+
+  // Shutdown socket for both read and write. This causes blocking Send and
+  // Receive calls to exit. After |Shutdown()| the Socket object cannot be
+  // used for any communication.
+  bool Shutdown();
+
+  // Data Transimission
+  // Return 0 on failure.
+  int Send(const char* buffer, int length) V8_WARN_UNUSED_RESULT;
+  int Receive(char* buffer, int length) V8_WARN_UNUSED_RESULT;
+
+  // Set the value of the SO_REUSEADDR socket option.
+  bool SetReuseAddress(bool reuse_address);
+
+  V8_INLINE(bool IsValid()) const V8_WARN_UNUSED_RESULT {
+    return native_handle_ != kInvalidNativeHandle;
+  }
+
+  static int GetLastError() V8_WARN_UNUSED_RESULT;
+
+  // The implementation-defined native handle type.
+#if V8_OS_POSIX
+  typedef int NativeHandle;
+  static const NativeHandle kInvalidNativeHandle = -1;
+#elif V8_OS_WIN
+  typedef SOCKET NativeHandle;
+  static const NativeHandle kInvalidNativeHandle = INVALID_SOCKET;
+#endif
+
+  NativeHandle& native_handle() V8_WARN_UNUSED_RESULT {
+    return native_handle_;
+  }
+  const NativeHandle& native_handle() const V8_WARN_UNUSED_RESULT {
+    return native_handle_;
+  }
+
+ private:
+  explicit Socket(NativeHandle native_handle) : native_handle_(native_handle) {}
+
+  NativeHandle native_handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(Socket);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_PLATFORM_SOCKET_H_
index ce01e3d..75d26b6 100644 (file)
@@ -95,7 +95,7 @@
         'test-reloc-info.cc',
         'test-semaphore.cc',
         'test-serialize.cc',
-        'test-sockets.cc',
+        'test-socket.cc',
         'test-spaces.cc',
         'test-strings.cc',
         'test-symbols.cc',
index c034e48..e09de7d 100644 (file)
@@ -116,7 +116,7 @@ test-log/ProfLazyMode: SKIP
 # Native Client doesn't support sockets.
 test-debug/DebuggerAgent: SKIP
 test-debug/DebuggerAgentProtocolOverflowHeader: SKIP
-test-sockets/Socket: SKIP
+test-socket/Socket: SKIP
 
 # Profiling doesn't work on Native Client.
 test-cpu-profiler/*: SKIP
index b41a77a..012face 100644 (file)
@@ -37,7 +37,7 @@
 #include "compilation-cache.h"
 #include "debug.h"
 #include "deoptimizer.h"
-#include "platform.h"
+#include "platform/socket.h"
 #include "stub-cache.h"
 #include "utils.h"
 #undef V8_DISABLE_DEPRECATIONS
@@ -5947,9 +5947,6 @@ TEST(DebuggerAgent) {
 
   bool ok;
 
-  // Initialize the socket library.
-  i::Socket::SetUp();
-
   // Test starting and stopping the agent without any client connection.
   debugger->StartAgent("test", kPort1);
   debugger->StopAgent();
@@ -5958,7 +5955,7 @@ TEST(DebuggerAgent) {
   ok = debugger->StartAgent("test", kPort2);
   CHECK(ok);
   debugger->WaitForAgent();
-  i::Socket* client = i::OS::CreateSocket();
+  i::Socket* client = new i::Socket;
   ok = client->Connect("localhost", port2_str);
   CHECK(ok);
   // It is important to wait for a message from the agent. Otherwise,
@@ -5972,8 +5969,9 @@ TEST(DebuggerAgent) {
 
   // Test starting and stopping the agent with the required port already
   // occoupied.
-  i::Socket* server = i::OS::CreateSocket();
-  server->Bind(kPort3);
+  i::Socket* server = new i::Socket;
+  ok = server->Bind(kPort3);
+  CHECK(ok);
 
   debugger->StartAgent("test", kPort3);
   debugger->StopAgent();
@@ -6014,7 +6012,7 @@ void DebuggerAgentProtocolServerThread::Run() {
   bool ok;
 
   // Create the server socket and bind it to the requested port.
-  server_ = i::OS::CreateSocket();
+  server_ = new i::Socket;
   CHECK(server_ != NULL);
   ok = server_->Bind(port_);
   CHECK(ok);
@@ -6044,9 +6042,6 @@ TEST(DebuggerAgentProtocolOverflowHeader) {
   char port_str[kPortBufferLen];
   OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort);
 
-  // Initialize the socket library.
-  i::Socket::SetUp();
-
   // Create a socket server to receive a debugger agent message.
   DebuggerAgentProtocolServerThread* server =
       new DebuggerAgentProtocolServerThread(kPort);
@@ -6054,7 +6049,7 @@ TEST(DebuggerAgentProtocolOverflowHeader) {
   server->WaitForListening();
 
   // Connect.
-  i::Socket* client = i::OS::CreateSocket();
+  i::Socket* client = new i::Socket;
   CHECK(client != NULL);
   bool ok = client->Connect(kLocalhost, port_str);
   CHECK(ok);
@@ -6071,7 +6066,8 @@ TEST(DebuggerAgentProtocolOverflowHeader) {
   buffer[kBufferSize - 3] = '0';
   buffer[kBufferSize - 2] = '\r';
   buffer[kBufferSize - 1] = '\n';
-  client->Send(buffer, kBufferSize);
+  int result = client->Send(buffer, kBufferSize);
+  CHECK_EQ(kBufferSize, result);
 
   // Short key and long value: X:XXXX....XXXX\r\n.
   buffer[0] = 'X';
@@ -6081,13 +6077,16 @@ TEST(DebuggerAgentProtocolOverflowHeader) {
   }
   buffer[kBufferSize - 2] = '\r';
   buffer[kBufferSize - 1] = '\n';
-  client->Send(buffer, kBufferSize);
+  result = client->Send(buffer, kBufferSize);
+  CHECK_EQ(kBufferSize, result);
 
   // Add empty body to request.
   const char* content_length_zero_header = "Content-Length:0\r\n";
-  client->Send(content_length_zero_header,
-               StrLength(content_length_zero_header));
-  client->Send("\r\n", 2);
+  int length = StrLength(content_length_zero_header);
+  result = client->Send(content_length_zero_header, length);
+  CHECK_EQ(length, result);
+  result = client->Send("\r\n", 2);
+  CHECK_EQ(2, result);
 
   // Wait until data is received.
   server->Join();
similarity index 94%
rename from test/cctest/test-sockets.cc
rename to test/cctest/test-socket.cc
index 87a62ce..47d8b17 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "v8.h"
 #include "platform.h"
+#include "platform/socket.h"
 #include "cctest.h"
 
 
@@ -69,7 +70,7 @@ void SocketListenerThread::Run() {
   bool ok;
 
   // Create the server socket and bind it to the requested port.
-  server_ = OS::CreateSocket();
+  server_ = new Socket;
   server_->SetReuseAddress(true);
   CHECK(server_ != NULL);
   ok = server_->Bind(port_);
@@ -121,7 +122,7 @@ static void SendAndReceive(int port, char *data, int len) {
   listener->WaitForListening();
 
   // Connect and write some data.
-  Socket* client = OS::CreateSocket();
+  Socket* client = new Socket;
   CHECK(client != NULL);
   ok = client->Connect(kLocalhost, port_str);
   CHECK(ok);
@@ -150,12 +151,6 @@ TEST(Socket) {
   // parallel.
   static const int kPort = 5859 + FlagDependentPortOffset();
 
-  bool ok;
-
-  // Initialize socket support.
-  ok = Socket::SetUp();
-  CHECK(ok);
-
   // Send and receive some data.
   static const int kBufferSizeSmall = 20;
   char small_data[kBufferSizeSmall + 1] = "1234567890abcdefghij";
@@ -179,12 +174,3 @@ TEST(Socket) {
   SendAndReceive(kPort, large_data, kBufferSizeLarge);
   delete[] large_data;
 }
-
-
-TEST(HToNNToH) {
-  uint16_t x = 1234;
-  CHECK_EQ(x, Socket::NToH(Socket::HToN(x)));
-
-  uint32_t y = 12345678;
-  CHECK(y == Socket::NToH(Socket::HToN(y)));
-}
index 8548efe..5a5a2ae 100644 (file)
         '../../src/platform/mutex.h',
         '../../src/platform/semaphore.cc',
         '../../src/platform/semaphore.h',
+        '../../src/platform/socket.cc',
+        '../../src/platform/socket.h',
         '../../src/preparse-data-format.h',
         '../../src/preparse-data.cc',
         '../../src/preparse-data.h',