Commit be059966 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1349 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0c7af397
...@@ -156,12 +156,12 @@ MKSNAPSHOT_EXTRA_FLAGS = { ...@@ -156,12 +156,12 @@ MKSNAPSHOT_EXTRA_FLAGS = {
'LIBS': ['pthread'], 'LIBS': ['pthread'],
}, },
'os:win32': { 'os:win32': {
'LIBS': ['winmm'], 'LIBS': ['winmm', 'ws2_32'],
}, },
}, },
'msvc': { 'msvc': {
'all': { 'all': {
'LIBS': ['winmm'] 'LIBS': ['winmm', 'ws2_32']
} }
} }
} }
...@@ -219,7 +219,7 @@ CCTEST_EXTRA_FLAGS = { ...@@ -219,7 +219,7 @@ CCTEST_EXTRA_FLAGS = {
'LIBS': ['execinfo', 'pthread'] 'LIBS': ['execinfo', 'pthread']
}, },
'os:win32': { 'os:win32': {
'LIBS': ['winmm'] 'LIBS': ['winmm', 'ws2_32']
}, },
'wordsize:64': { 'wordsize:64': {
'CCFLAGS': ['-m32'], 'CCFLAGS': ['-m32'],
...@@ -229,7 +229,7 @@ CCTEST_EXTRA_FLAGS = { ...@@ -229,7 +229,7 @@ CCTEST_EXTRA_FLAGS = {
'msvc': { 'msvc': {
'all': { 'all': {
'CPPDEFINES': ['_HAS_EXCEPTIONS=0'], 'CPPDEFINES': ['_HAS_EXCEPTIONS=0'],
'LIBS': ['winmm'] 'LIBS': ['winmm', 'ws2_32']
}, },
'library:shared': { 'library:shared': {
'CPPDEFINES': ['USING_V8_SHARED'] 'CPPDEFINES': ['USING_V8_SHARED']
...@@ -257,7 +257,7 @@ SAMPLE_FLAGS = { ...@@ -257,7 +257,7 @@ SAMPLE_FLAGS = {
'LIBS': ['execinfo', 'pthread'] 'LIBS': ['execinfo', 'pthread']
}, },
'os:win32': { 'os:win32': {
'LIBS': ['winmm'] 'LIBS': ['winmm', 'ws2_32']
}, },
'wordsize:64': { 'wordsize:64': {
'CCFLAGS': ['-m32'], 'CCFLAGS': ['-m32'],
...@@ -274,7 +274,7 @@ SAMPLE_FLAGS = { ...@@ -274,7 +274,7 @@ SAMPLE_FLAGS = {
'all': { 'all': {
'CCFLAGS': ['/nologo'], 'CCFLAGS': ['/nologo'],
'LINKFLAGS': ['/nologo'], 'LINKFLAGS': ['/nologo'],
'LIBS': ['winmm'] 'LIBS': ['winmm', 'ws2_32']
}, },
'library:shared': { 'library:shared': {
'CPPDEFINES': ['USING_V8_SHARED'] 'CPPDEFINES': ['USING_V8_SHARED']
...@@ -321,12 +321,12 @@ D8_FLAGS = { ...@@ -321,12 +321,12 @@ D8_FLAGS = {
'LIBS': ['pthread'], 'LIBS': ['pthread'],
}, },
'os:win32': { 'os:win32': {
'LIBS': ['winmm'], 'LIBS': ['winmm', 'ws2_32'],
}, },
}, },
'msvc': { 'msvc': {
'all': { 'all': {
'LIBS': ['winmm'] 'LIBS': ['winmm', 'ws2_32']
} }
} }
} }
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include <signal.h> #include <signal.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ucontext.h> #include <sys/ucontext.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -42,6 +44,9 @@ ...@@ -42,6 +44,9 @@
#include <unistd.h> // getpagesize #include <unistd.h> // getpagesize
#include <execinfo.h> // backtrace, backtrace_symbols #include <execinfo.h> // backtrace, backtrace_symbols
#include <strings.h> // index #include <strings.h> // index
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <limits.h> #include <limits.h>
...@@ -620,6 +625,172 @@ Semaphore* OS::CreateSemaphore(int count) { ...@@ -620,6 +625,172 @@ Semaphore* OS::CreateSemaphore(int count) {
return new FreeBSDSemaphore(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 #ifdef ENABLE_LOGGING_AND_PROFILING
static Sampler* active_sampler_ = NULL; static Sampler* active_sampler_ = NULL;
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include <signal.h> #include <signal.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
// Ubuntu Dapper requires memory pages to be marked as // Ubuntu Dapper requires memory pages to be marked as
...@@ -47,6 +49,10 @@ ...@@ -47,6 +49,10 @@
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#undef MAP_TYPE #undef MAP_TYPE
#include "v8.h" #include "v8.h"
...@@ -603,6 +609,172 @@ Semaphore* OS::CreateSemaphore(int count) { ...@@ -603,6 +609,172 @@ Semaphore* OS::CreateSemaphore(int count) {
return new LinuxSemaphore(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 #ifdef ENABLE_LOGGING_AND_PROFILING
static Sampler* active_sampler_ = NULL; static Sampler* active_sampler_ = NULL;
......
...@@ -45,9 +45,16 @@ ...@@ -45,9 +45,16 @@
#include <mach/task.h> #include <mach/task.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#undef MAP_TYPE #undef MAP_TYPE
#include "v8.h" #include "v8.h"
...@@ -569,6 +576,178 @@ Semaphore* OS::CreateSemaphore(int count) { ...@@ -569,6 +576,178 @@ Semaphore* OS::CreateSemaphore(int count) {
return new MacOSSemaphore(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 #ifdef ENABLE_LOGGING_AND_PROFILING
static Sampler* active_sampler_ = NULL; static Sampler* active_sampler_ = NULL;
......
...@@ -67,6 +67,7 @@ ...@@ -67,6 +67,7 @@
// These additional WIN32 includes have to be right here as the #undef's below // These additional WIN32 includes have to be right here as the #undef's below
// makes it impossible to have them elsewhere. // makes it impossible to have them elsewhere.
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h>
#include <process.h> // for _beginthreadex() #include <process.h> // for _beginthreadex()
#include <stdlib.h> #include <stdlib.h>
...@@ -1551,6 +1552,180 @@ Semaphore* OS::CreateSemaphore(int count) { ...@@ -1551,6 +1552,180 @@ Semaphore* OS::CreateSemaphore(int count) {
return new Win32Semaphore(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 #ifdef ENABLE_LOGGING_AND_PROFILING
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
......
...@@ -109,6 +109,9 @@ namespace v8 { namespace internal { ...@@ -109,6 +109,9 @@ namespace v8 { namespace internal {
double ceiling(double x); double ceiling(double x);
// Forward declarations.
class Socket;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// OS // OS
// //
...@@ -205,6 +208,10 @@ class OS { ...@@ -205,6 +208,10 @@ class OS {
// Please use delete to reclaim the storage for the returned Semaphore. // Please use delete to reclaim the storage for the returned Semaphore.
static Semaphore* CreateSemaphore(int count); 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 { class MemoryMappedFile {
public: public:
static MemoryMappedFile* create(const char* name, int size, void* initial); static MemoryMappedFile* create(const char* name, int size, void* initial);
...@@ -412,6 +419,38 @@ class Semaphore { ...@@ -412,6 +419,38 @@ class Semaphore {
}; };
// ----------------------------------------------------------------------------
// 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);
};
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Sampler // Sampler
......
...@@ -38,7 +38,8 @@ SOURCES = { ...@@ -38,7 +38,8 @@ SOURCES = {
'test-ast.cc', 'test-heap.cc', 'test-utils.cc', 'test-compiler.cc', 'test-ast.cc', 'test-heap.cc', 'test-utils.cc', 'test-compiler.cc',
'test-spaces.cc', 'test-mark-compact.cc', 'test-lock.cc', 'test-spaces.cc', 'test-mark-compact.cc', 'test-lock.cc',
'test-conversions.cc', 'test-strings.cc', 'test-serialize.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:arm': ['test-assembler-arm.cc', 'test-disasm-arm.cc'],
'arch:ia32': ['test-assembler-ia32.cc', 'test-disasm-ia32.cc'], 'arch:ia32': ['test-assembler-ia32.cc', 'test-disasm-ia32.cc'],
......
// 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)));
}
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="winmm.lib" AdditionalDependencies="winmm.lib Ws2_32.lib"
/> />
<Tool <Tool
Name="VCALinkTool" Name="VCALinkTool"
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="winmm.lib" AdditionalDependencies="winmm.lib Ws2_32.lib"
/> />
<Tool <Tool
Name="VCALinkTool" Name="VCALinkTool"
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="winmm.lib" AdditionalDependencies="winmm.lib Ws2_32.lib"
/> />
<Tool <Tool
Name="VCALinkTool" Name="VCALinkTool"
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="winmm.lib" AdditionalDependencies="winmm.lib Ws2_32.lib"
/> />
<Tool <Tool
Name="VCALinkTool" Name="VCALinkTool"
...@@ -209,6 +209,10 @@ ...@@ -209,6 +209,10 @@
RelativePath="..\..\test\cctest\test-serialize.cc" RelativePath="..\..\test\cctest\test-serialize.cc"
> >
</File> </File>
<File
RelativePath="..\..\test\cctest\test-sockets.cc"
>
</File>
<File <File
RelativePath="..\..\test\cctest\test-spaces.cc" RelativePath="..\..\test\cctest\test-spaces.cc"
> >
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="winmm.lib" AdditionalDependencies="winmm.lib Ws2_32.lib"
/> />
<Tool <Tool
Name="VCALinkTool" Name="VCALinkTool"
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="winmm.lib" AdditionalDependencies="winmm.lib Ws2_32.lib"
/> />
<Tool <Tool
Name="VCALinkTool" Name="VCALinkTool"
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="winmm.lib" AdditionalDependencies="winmm.lib Ws2_32.lib"
/> />
<Tool <Tool
Name="VCALinkTool" Name="VCALinkTool"
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="winmm.lib" AdditionalDependencies="winmm.lib Ws2_32.lib"
/> />
<Tool <Tool
Name="VCALinkTool" Name="VCALinkTool"
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="winmm.lib" AdditionalDependencies="winmm.lib Ws2_32.lib"
/> />
<Tool <Tool
Name="VCALinkTool" Name="VCALinkTool"
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="winmm.lib" AdditionalDependencies="winmm.lib Ws2_32.lib"
/> />
<Tool <Tool
Name="VCALinkTool" Name="VCALinkTool"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment