Author: [email protected]
Date: Tue Feb 24 05:32:01 2009
New Revision: 1349
Added:
branches/bleeding_edge/test/cctest/test-sockets.cc (contents, props
changed)
Modified:
branches/bleeding_edge/SConstruct
branches/bleeding_edge/src/platform-freebsd.cc
branches/bleeding_edge/src/platform-linux.cc
branches/bleeding_edge/src/platform-macos.cc
branches/bleeding_edge/src/platform-win32.cc
branches/bleeding_edge/src/platform.h
branches/bleeding_edge/test/cctest/SConscript
branches/bleeding_edge/tools/visual_studio/d8.vcproj
branches/bleeding_edge/tools/visual_studio/v8_cctest.vcproj
branches/bleeding_edge/tools/visual_studio/v8_mksnapshot.vcproj
branches/bleeding_edge/tools/visual_studio/v8_process_sample.vcproj
branches/bleeding_edge/tools/visual_studio/v8_shell_sample.vcproj
Log:
Add socket support to platform code.
The new Socket class is an encapsulation of the standard BSD socket API. As
it depends on platform specific include files and have some slight platform
variations it is part of the platform code.
On Mac OS only the option SO_REUSEADDR is set to true for server sockets.
Running the test required it as the bound listener socket would sometimes
end up in TIME_WAIT. On Windows and Linux this has never been observed
(given the client end of the socket is closed before the server end).
The code has been tested on Windows, Linux and Mac OS. The FreeBSD version
is a copy of the Linux version but has not been compiled nor tested.
Missing Xcode project updates.
Review URL: http://codereview.chromium.org/27085
Modified: branches/bleeding_edge/SConstruct
==============================================================================
--- branches/bleeding_edge/SConstruct (original)
+++ branches/bleeding_edge/SConstruct Tue Feb 24 05:32:01 2009
@@ -156,12 +156,12 @@
'LIBS': ['pthread'],
},
'os:win32': {
- 'LIBS': ['winmm'],
+ 'LIBS': ['winmm', 'ws2_32'],
},
},
'msvc': {
'all': {
- 'LIBS': ['winmm']
+ 'LIBS': ['winmm', 'ws2_32']
}
}
}
@@ -219,7 +219,7 @@
'LIBS': ['execinfo', 'pthread']
},
'os:win32': {
- 'LIBS': ['winmm']
+ 'LIBS': ['winmm', 'ws2_32']
},
'wordsize:64': {
'CCFLAGS': ['-m32'],
@@ -229,7 +229,7 @@
'msvc': {
'all': {
'CPPDEFINES': ['_HAS_EXCEPTIONS=0'],
- 'LIBS': ['winmm']
+ 'LIBS': ['winmm', 'ws2_32']
},
'library:shared': {
'CPPDEFINES': ['USING_V8_SHARED']
@@ -257,7 +257,7 @@
'LIBS': ['execinfo', 'pthread']
},
'os:win32': {
- 'LIBS': ['winmm']
+ 'LIBS': ['winmm', 'ws2_32']
},
'wordsize:64': {
'CCFLAGS': ['-m32'],
@@ -274,7 +274,7 @@
'all': {
'CCFLAGS': ['/nologo'],
'LINKFLAGS': ['/nologo'],
- 'LIBS': ['winmm']
+ 'LIBS': ['winmm', 'ws2_32']
},
'library:shared': {
'CPPDEFINES': ['USING_V8_SHARED']
@@ -321,12 +321,12 @@
'LIBS': ['pthread'],
},
'os:win32': {
- 'LIBS': ['winmm'],
+ 'LIBS': ['winmm', 'ws2_32'],
},
},
'msvc': {
'all': {
- 'LIBS': ['winmm']
+ 'LIBS': ['winmm', 'ws2_32']
}
}
}
Modified: branches/bleeding_edge/src/platform-freebsd.cc
==============================================================================
--- branches/bleeding_edge/src/platform-freebsd.cc (original)
+++ branches/bleeding_edge/src/platform-freebsd.cc Tue Feb 24 05:32:01 2009
@@ -32,6 +32,8 @@
#include <signal.h>
#include <sys/time.h>
#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#include <sys/ucontext.h>
#include <stdlib.h>
@@ -42,6 +44,9 @@
#include <unistd.h> // getpagesize
#include <execinfo.h> // backtrace, backtrace_symbols
#include <strings.h> // index
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <errno.h>
#include <stdarg.h>
#include <limits.h>
@@ -619,6 +624,172 @@
Semaphore* OS::CreateSemaphore(int count) {
return new FreeBSDSemaphore(count);
}
+
+
+//
----------------------------------------------------------------------------
+// FreeBSD socket support.
+//
+
+class FreeBSDSocket : public Socket {
+ public:
+ explicit FreeBSDSocket() {
+ // Create the socket.
+ socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ }
+ explicit FreeBSDSocket(int socket): socket_(socket) { }
+
+
+ virtual ~FreeBSDSocket() {
+ if (IsValid()) {
+ // Close socket.
+ close(socket_);
+ }
+ }
+
+ // 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);
+
+ // Data Transimission
+ int Send(const char* data, int len) const;
+ bool SendAll(const char* data, int len) const;
+ int Receive(char* data, int len) const;
+
+ bool IsValid() const { return socket_ != -1; }
+
+ private:
+ int socket_;
+};
+
+
+bool FreeBSDSocket::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 FreeBSDSocket::Listen(int backlog) const {
+ if (!IsValid()) {
+ return false;
+ }
+
+ int status = listen(socket_, backlog);
+ return status == 0;
+}
+
+
+Socket* FreeBSDSocket::Accept() const {
+ if (!IsValid()) {
+ return NULL;
+ }
+
+ int socket = accept(socket_, NULL, NULL);
+ if (socket == -1) {
+ return NULL;
+ } else {
+ return new FreeBSDSocket(socket);
+ }
+}
+
+
+bool FreeBSDSocket::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, result->ai_addrlen);
+ return status == 0;
+}
+
+
+int FreeBSDSocket::Send(const char* data, int len) const {
+ int status = send(socket_, data, len, 0);
+ return status;
+}
+
+
+bool FreeBSDSocket::SendAll(const char* data, int len) const {
+ int sent_len = 0;
+ while (sent_len < len) {
+ int status = Send(data, len);
+ if (status <= 0) {
+ return false;
+ }
+ sent_len += status;
+ }
+ return true;
+}
+
+
+int FreeBSDSocket::Receive(char* data, int len) const {
+ int status = recv(socket_, data, len, 0);
+ return status;
+}
+
+
+bool Socket::Setup() {
+ // Nothing to do on FreeBSD.
+ 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 FreeBSDSocket();
+}
+
#ifdef ENABLE_LOGGING_AND_PROFILING
Modified: branches/bleeding_edge/src/platform-linux.cc
==============================================================================
--- branches/bleeding_edge/src/platform-linux.cc (original)
+++ branches/bleeding_edge/src/platform-linux.cc Tue Feb 24 05:32:01 2009
@@ -32,6 +32,8 @@
#include <signal.h>
#include <sys/time.h>
#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#include <stdlib.h>
// Ubuntu Dapper requires memory pages to be marked as
@@ -47,6 +49,10 @@
#include <errno.h>
#include <stdarg.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
#undef MAP_TYPE
#include "v8.h"
@@ -602,6 +608,172 @@
Semaphore* OS::CreateSemaphore(int count) {
return new LinuxSemaphore(count);
}
+
+
+//
----------------------------------------------------------------------------
+// Linux socket support.
+//
+
+class LinuxSocket : public Socket {
+ public:
+ explicit LinuxSocket() {
+ // Create the socket.
+ socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ }
+ explicit LinuxSocket(int socket): socket_(socket) { }
+
+
+ virtual ~LinuxSocket() {
+ if (IsValid()) {
+ // Close socket.
+ close(socket_);
+ }
+ }
+
+ // 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);
+
+ // Data Transimission
+ int Send(const char* data, int len) const;
+ bool SendAll(const char* data, int len) const;
+ int Receive(char* data, int len) const;
+
+ bool IsValid() const { return socket_ != -1; }
+
+ private:
+ int socket_;
+};
+
+
+bool LinuxSocket::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 LinuxSocket::Listen(int backlog) const {
+ if (!IsValid()) {
+ return false;
+ }
+
+ int status = listen(socket_, backlog);
+ return status == 0;
+}
+
+
+Socket* LinuxSocket::Accept() const {
+ if (!IsValid()) {
+ return NULL;
+ }
+
+ int socket = accept(socket_, NULL, NULL);
+ if (socket == -1) {
+ return NULL;
+ } else {
+ return new LinuxSocket(socket);
+ }
+}
+
+
+bool LinuxSocket::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, result->ai_addrlen);
+ return status == 0;
+}
+
+
+int LinuxSocket::Send(const char* data, int len) const {
+ int status = send(socket_, data, len, 0);
+ return status;
+}
+
+
+bool LinuxSocket::SendAll(const char* data, int len) const {
+ int sent_len = 0;
+ while (sent_len < len) {
+ int status = Send(data, len);
+ if (status <= 0) {
+ return false;
+ }
+ sent_len += status;
+ }
+ return true;
+}
+
+
+int LinuxSocket::Receive(char* data, int len) const {
+ int status = recv(socket_, data, len, 0);
+ return status;
+}
+
+
+bool Socket::Setup() {
+ // Nothing to do on Linux.
+ 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 LinuxSocket();
+}
+
#ifdef ENABLE_LOGGING_AND_PROFILING
Modified: branches/bleeding_edge/src/platform-macos.cc
==============================================================================
--- branches/bleeding_edge/src/platform-macos.cc (original)
+++ branches/bleeding_edge/src/platform-macos.cc Tue Feb 24 05:32:01 2009
@@ -45,9 +45,16 @@
#include <mach/task.h>
#include <sys/time.h>
#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#include <stdarg.h>
#include <stdlib.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+
#undef MAP_TYPE
#include "v8.h"
@@ -568,6 +575,178 @@
Semaphore* OS::CreateSemaphore(int count) {
return new MacOSSemaphore(count);
}
+
+
+//
----------------------------------------------------------------------------
+// MacOS socket support.
+//
+
+class MacOSSocket : public Socket {
+ public:
+ explicit MacOSSocket() {
+ // Create the socket.
+ socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ }
+ explicit MacOSSocket(int socket): socket_(socket) { }
+
+
+ virtual ~MacOSSocket() {
+ if (IsValid()) {
+ // Close socket.
+ close(socket_);
+ }
+ }
+
+ // 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);
+
+ // Data Transimission
+ int Send(const char* data, int len) const;
+ bool SendAll(const char* data, int len) const;
+ int Receive(char* data, int len) const;
+
+ bool IsValid() const { return socket_ != -1; }
+
+ private:
+ int socket_;
+};
+
+
+bool MacOSSocket::Bind(const int port) {
+ if (!IsValid()) {
+ return false;
+ }
+
+ int on = 1;
+ int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on));
+ if (status != 0) {
+ 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);
+ status = bind(socket_,
+ reinterpret_cast<struct sockaddr *>(&addr),
+ sizeof (addr));
+ return status == 0;
+}
+
+
+bool MacOSSocket::Listen(int backlog) const {
+ if (!IsValid()) {
+ return false;
+ }
+
+ int status = listen(socket_, backlog);
+ return status == 0;
+}
+
+
+Socket* MacOSSocket::Accept() const {
+ if (!IsValid()) {
+ return NULL;
+ }
+
+ int socket = accept(socket_, NULL, NULL);
+ if (socket == -1) {
+ return NULL;
+ } else {
+ return new MacOSSocket(socket);
+ }
+}
+
+
+bool MacOSSocket::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, result->ai_addrlen);
+ return status == 0;
+}
+
+
+int MacOSSocket::Send(const char* data, int len) const {
+ int status = send(socket_, data, len, 0);
+ return status;
+}
+
+
+bool MacOSSocket::SendAll(const char* data, int len) const {
+ int sent_len = 0;
+ while (sent_len < len) {
+ int status = Send(data, len);
+ if (status <= 0) {
+ return false;
+ }
+ sent_len += status;
+ }
+ return true;
+}
+
+
+int MacOSSocket::Receive(char* data, int len) const {
+ int status = recv(socket_, data, len, 0);
+ return status;
+}
+
+
+bool Socket::Setup() {
+ // Nothing to do on MacOS.
+ 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 MacOSSocket();
+}
+
#ifdef ENABLE_LOGGING_AND_PROFILING
Modified: branches/bleeding_edge/src/platform-win32.cc
==============================================================================
--- branches/bleeding_edge/src/platform-win32.cc (original)
+++ branches/bleeding_edge/src/platform-win32.cc Tue Feb 24 05:32:01 2009
@@ -67,6 +67,7 @@
// These additional WIN32 includes have to be right here as the #undef's
below
// makes it impossible to have them elsewhere.
#include <winsock2.h>
+#include <ws2tcpip.h>
#include <process.h> // for _beginthreadex()
#include <stdlib.h>
@@ -1550,6 +1551,180 @@
Semaphore* OS::CreateSemaphore(int count) {
return new Win32Semaphore(count);
}
+
+
+//
----------------------------------------------------------------------------
+// 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() {
+ if (IsValid()) {
+ // Close socket.
+ closesocket(socket_);
+ }
+ }
+
+ // 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);
+
+ // Data Transimission
+ int Send(const char* data, int len) const;
+ bool SendAll(const char* data, int len) const;
+ int Receive(char* data, int len) const;
+
+ 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, result->ai_addrlen);
+ return status == 0;
+}
+
+
+int Win32Socket::Send(const char* data, int len) const {
+ int status = send(socket_, data, len, 0);
+ return status;
+}
+
+
+bool Win32Socket::SendAll(const char* data, int len) const {
+ int sent_len = 0;
+ while (sent_len < len) {
+ int status = Send(data, len);
+ if (status <= 0) {
+ return false;
+ }
+ sent_len += status;
+ }
+ return true;
+}
+
+
+int Win32Socket::Receive(char* data, int len) const {
+ int status = recv(socket_, data, len, 0);
+ return status;
+}
+
+
+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();
+}
+
#ifdef ENABLE_LOGGING_AND_PROFILING
Modified: branches/bleeding_edge/src/platform.h
==============================================================================
--- branches/bleeding_edge/src/platform.h (original)
+++ branches/bleeding_edge/src/platform.h Tue Feb 24 05:32:01 2009
@@ -109,6 +109,9 @@
double ceiling(double x);
+// Forward declarations.
+class Socket;
+
//
----------------------------------------------------------------------------
// OS
//
@@ -205,6 +208,10 @@
// Please use delete to reclaim the storage for the returned Semaphore.
static Semaphore* CreateSemaphore(int count);
+ // 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* create(const char* name, int size, void*
initial);
@@ -409,6 +416,38 @@
// Increments the semaphore counter.
virtual void Signal() = 0;
+};
+
+
+//
----------------------------------------------------------------------------
+// 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;
+
+ // Data Transimission
+ virtual int Send(const char* data, int len) const = 0;
+ virtual bool SendAll(const char* data, int len) const = 0;
+ virtual int Receive(char* data, int len) const = 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);
};
Modified: branches/bleeding_edge/test/cctest/SConscript
==============================================================================
--- branches/bleeding_edge/test/cctest/SConscript (original)
+++ branches/bleeding_edge/test/cctest/SConscript Tue Feb 24 05:32:01 2009
@@ -38,7 +38,8 @@
'test-ast.cc', 'test-heap.cc', 'test-utils.cc', 'test-compiler.cc',
'test-spaces.cc', 'test-mark-compact.cc', 'test-lock.cc',
'test-conversions.cc', 'test-strings.cc', 'test-serialize.cc',
- 'test-decls.cc', 'test-alloc.cc', 'test-regexp.cc', 'test-threads.cc'
+ 'test-decls.cc', 'test-alloc.cc', 'test-regexp.cc', 'test-threads.cc',
+ 'test-sockets.cc'
],
'arch:arm': ['test-assembler-arm.cc', 'test-disasm-arm.cc'],
'arch:ia32': ['test-assembler-ia32.cc', 'test-disasm-ia32.cc'],
Added: branches/bleeding_edge/test/cctest/test-sockets.cc
==============================================================================
--- (empty file)
+++ branches/bleeding_edge/test/cctest/test-sockets.cc Tue Feb 24 05:32:01
2009
@@ -0,0 +1,134 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+
+#include "v8.h"
+#include "platform.h"
+#include "cctest.h"
+
+
+using namespace ::v8::internal;
+
+
+static const char* kPort = "5858";
+static const char* kLocalhost = "localhost";
+
+class SocketListenerThread : public Thread {
+ public:
+ SocketListenerThread(int data_size) : data_size_(data_size),
+ server_(NULL), client_(NULL),
+ listening_(OS::CreateSemaphore(0))
{
+ data_ = new char[data_size_];
+ }
+ ~SocketListenerThread() {
+ // Close both sockets.
+ delete client_;
+ delete server_;
+ }
+
+ void Run();
+ void WaitForListening() { listening_->Wait(); }
+ char* data() { return data_; }
+
+ private:
+ char* data_;
+ int data_size_;
+ Socket* server_; // Server socket used for bind/accept.
+ Socket* client_; // Single client connection used by the test.
+ Semaphore* listening_; // Signalled when the server socket is in listen
mode.
+};
+
+
+void SocketListenerThread::Run() {
+ bool ok;
+
+ // Create the server socket and bind it to the requested port.
+ server_ = OS::CreateSocket();
+ CHECK(server_ != NULL);
+ ok = server_->Bind(5858);
+ CHECK(ok);
+
+ // Listen for new connections.
+ ok = server_->Listen(1);
+ CHECK(ok);
+ listening_->Signal();
+
+ // Accept a connection.
+ client_ = server_->Accept();
+ CHECK(client_ != NULL);
+
+ // Read the expected niumber of bytes of data.
+ int bytes_read = 0;
+ while (bytes_read < data_size_) {
+ bytes_read += client_->Receive(data_ + bytes_read, data_size_ -
bytes_read);
+ }
+}
+
+
+static void SendAndReceive(char *data, int len) {
+ bool ok;
+
+ // Create a socket listener.
+ SocketListenerThread* listener = new SocketListenerThread(len);
+ listener->Start();
+ listener->WaitForListening();
+
+ // Connect and write some data.
+ Socket* client = OS::CreateSocket();
+ CHECK(client != NULL);
+ ok = client->Connect(kLocalhost, kPort);
+ CHECK(ok);
+
+ // Send all the data.
+ ok = client->SendAll(data, len);
+ CHECK(ok);
+
+ // Wait until data is received.
+ listener->Join();
+
+ // Check that data received is the same as data send.
+ for (int i = 0; i < len; i++) {
+ CHECK(data[i] == listener->data()[i]);
+ }
+
+ // Close the client before the listener to avoid TIME_WAIT issues.
+ delete client;
+ delete listener;
+}
+
+
+TEST(Socket) {
+ 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";
+ SendAndReceive(small_data, kBufferSizeSmall);
+
+ // Send and receive some more data.
+ static const int kBufferSizeMedium = 10000;
+ char* medium_data = new char[kBufferSizeMedium];
+ for (int i = 0; i < kBufferSizeMedium; i++) {
+ medium_data[i] = i % 256;
+ }
+ SendAndReceive(medium_data, kBufferSizeMedium);
+
+ // Send and receive even more data.
+ static const int kBufferSizeLarge = 1000000;
+ char* large_data = new char[kBufferSizeLarge];
+ for (int i = 0; i < kBufferSizeLarge; i++) {
+ large_data[i] = i % 256;
+ }
+ SendAndReceive(large_data, kBufferSizeLarge);
+}
+
+
+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)));
+}
Modified: branches/bleeding_edge/tools/visual_studio/d8.vcproj
==============================================================================
--- branches/bleeding_edge/tools/visual_studio/d8.vcproj (original)
+++ branches/bleeding_edge/tools/visual_studio/d8.vcproj Tue Feb 24
05:32:01 2009
@@ -49,7 +49,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib"
+ AdditionalDependencies="winmm.lib Ws2_32.lib"
/>
<Tool
Name="VCALinkTool"
@@ -110,7 +110,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib"
+ AdditionalDependencies="winmm.lib Ws2_32.lib"
/>
<Tool
Name="VCALinkTool"
Modified: branches/bleeding_edge/tools/visual_studio/v8_cctest.vcproj
==============================================================================
--- branches/bleeding_edge/tools/visual_studio/v8_cctest.vcproj (original)
+++ branches/bleeding_edge/tools/visual_studio/v8_cctest.vcproj Tue Feb 24
05:32:01 2009
@@ -49,7 +49,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib"
+ AdditionalDependencies="winmm.lib Ws2_32.lib"
/>
<Tool
Name="VCALinkTool"
@@ -110,7 +110,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib"
+ AdditionalDependencies="winmm.lib Ws2_32.lib"
/>
<Tool
Name="VCALinkTool"
@@ -207,6 +207,10 @@
</File>
<File
RelativePath="..\..\test\cctest\test-serialize.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\test\cctest\test-sockets.cc"
>
</File>
<File
Modified: branches/bleeding_edge/tools/visual_studio/v8_mksnapshot.vcproj
==============================================================================
--- branches/bleeding_edge/tools/visual_studio/v8_mksnapshot.vcproj
(original)
+++ branches/bleeding_edge/tools/visual_studio/v8_mksnapshot.vcproj Tue Feb
24 05:32:01 2009
@@ -49,7 +49,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib"
+ AdditionalDependencies="winmm.lib Ws2_32.lib"
/>
<Tool
Name="VCALinkTool"
@@ -110,7 +110,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib"
+ AdditionalDependencies="winmm.lib Ws2_32.lib"
/>
<Tool
Name="VCALinkTool"
Modified:
branches/bleeding_edge/tools/visual_studio/v8_process_sample.vcproj
==============================================================================
--- branches/bleeding_edge/tools/visual_studio/v8_process_sample.vcproj
(original)
+++ branches/bleeding_edge/tools/visual_studio/v8_process_sample.vcproj Tue
Feb 24 05:32:01 2009
@@ -49,7 +49,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib"
+ AdditionalDependencies="winmm.lib Ws2_32.lib"
/>
<Tool
Name="VCALinkTool"
@@ -110,7 +110,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib"
+ AdditionalDependencies="winmm.lib Ws2_32.lib"
/>
<Tool
Name="VCALinkTool"
Modified: branches/bleeding_edge/tools/visual_studio/v8_shell_sample.vcproj
==============================================================================
--- branches/bleeding_edge/tools/visual_studio/v8_shell_sample.vcproj
(original)
+++ branches/bleeding_edge/tools/visual_studio/v8_shell_sample.vcproj Tue
Feb 24 05:32:01 2009
@@ -49,7 +49,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib"
+ AdditionalDependencies="winmm.lib Ws2_32.lib"
/>
<Tool
Name="VCALinkTool"
@@ -110,7 +110,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="winmm.lib"
+ AdditionalDependencies="winmm.lib Ws2_32.lib"
/>
<Tool
Name="VCALinkTool"
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---