Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
15
gaia/tests/jsmarionette/client/sockit-to-me/src/addon.cc
Executable file
15
gaia/tests/jsmarionette/client/sockit-to-me/src/addon.cc
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
// Global includes
|
||||
#include <node.h>
|
||||
|
||||
// Local includes
|
||||
#include "sockit.h"
|
||||
|
||||
// So we don't spend half the time typing 'v8::'
|
||||
using namespace v8;
|
||||
|
||||
// Initialize
|
||||
void InitAll(Handle<Object> aExports) {
|
||||
Sockit::Init(aExports);
|
||||
}
|
||||
|
||||
NODE_MODULE(sockit, InitAll)
|
||||
629
gaia/tests/jsmarionette/client/sockit-to-me/src/sockit.cc
Executable file
629
gaia/tests/jsmarionette/client/sockit-to-me/src/sockit.cc
Executable file
|
|
@ -0,0 +1,629 @@
|
|||
// Global includes
|
||||
#include <node.h>
|
||||
#include <node_buffer.h>
|
||||
|
||||
// Platform dependent includes.
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
// Local includes
|
||||
#include "sockit.h"
|
||||
|
||||
// So we don't spend half the time typing 'v8::'
|
||||
using namespace v8;
|
||||
|
||||
// Error Messages
|
||||
#define E_ALREADY_CONNECTING \
|
||||
"ALREADY CONNECTING! You must call close before calling connect again."
|
||||
#define E_ALREADY_CONNECTED \
|
||||
"ALREADY CONNECTED! You must call close before calling connect again."
|
||||
|
||||
// Clever constants
|
||||
static const int MAX_LOOKUP_RETRIES = 3;
|
||||
static const int POLL_TIMEOUT_MS = 60000;
|
||||
|
||||
// Global for debug log enable/disable at runtime.
|
||||
static bool gDebugLog = false;
|
||||
|
||||
Persistent<Function> Sockit::constructor;
|
||||
|
||||
static void _debug_log(const char *aMsg) {
|
||||
if(gDebugLog) {
|
||||
fprintf(stderr, "[sockit-to-me] %s\n", aMsg);
|
||||
}
|
||||
}
|
||||
|
||||
Sockit::Sockit() : mSocket(0),
|
||||
mPollTimeout(POLL_TIMEOUT_MS),
|
||||
mIsConnecting(false),
|
||||
mIsConnected(false) {
|
||||
|
||||
}
|
||||
|
||||
Sockit::~Sockit() {
|
||||
// Close our socket if it's still open.
|
||||
if(mSocket != 0) {
|
||||
// XXXAus: We should probably report error on close.
|
||||
close(mSocket);
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
Sockit::Init(Handle<Object> aExports) {
|
||||
Isolate* isolate = Isolate::GetCurrent();
|
||||
|
||||
Local<FunctionTemplate> object = FunctionTemplate::New(isolate, New);
|
||||
// Set the classname our object will have in JavaScript land.
|
||||
object->SetClassName(String::NewFromUtf8(isolate, "Sockit"));
|
||||
|
||||
// Reserve space for our object instance.
|
||||
object->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
// Add the 'Connect' function.
|
||||
NODE_SET_PROTOTYPE_METHOD(object, "connect", Connect);
|
||||
// Add the 'Read' function.
|
||||
NODE_SET_PROTOTYPE_METHOD(object, "read", Read);
|
||||
// Add the 'Write' function.
|
||||
NODE_SET_PROTOTYPE_METHOD(object, "write", Write);
|
||||
// Add the 'Close' function.
|
||||
NODE_SET_PROTOTYPE_METHOD(object, "close", Close);
|
||||
// Add the 'SetPollTimeout' function.
|
||||
NODE_SET_PROTOTYPE_METHOD(object, "setPollTimeout", SetPollTimeout);
|
||||
// Add the 'SetDebugLog' function.
|
||||
NODE_SET_PROTOTYPE_METHOD(object, "setDebugLog", SetDebugLog);
|
||||
|
||||
// Add the constructor.
|
||||
constructor.Reset(isolate, object->GetFunction());
|
||||
aExports->Set(String::NewFromUtf8(isolate, "Sockit"),
|
||||
object->GetFunction());
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
Sockit::New(const FunctionCallbackInfo<Value>& aArgs) {
|
||||
Isolate* isolate = Isolate::GetCurrent();
|
||||
HandleScope scope(isolate);
|
||||
|
||||
if (aArgs.IsConstructCall()) {
|
||||
Sockit* sockit = new Sockit();
|
||||
sockit->Wrap(aArgs.This());
|
||||
aArgs.GetReturnValue().Set(aArgs.This());
|
||||
}
|
||||
else {
|
||||
const int argc = 0;
|
||||
Local<Value> argv[argc] = { };
|
||||
Local<Function> cons = Local<Function>::New(isolate, constructor);
|
||||
aArgs.GetReturnValue().Set(cons->NewInstance(argc, argv));
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
Sockit::Connect(const FunctionCallbackInfo<Value>& aArgs) {
|
||||
Isolate* isolate = Isolate::GetCurrent();
|
||||
HandleScope scope(isolate);
|
||||
|
||||
// Always return self.
|
||||
aArgs.GetReturnValue().Set(aArgs.This());
|
||||
|
||||
if(aArgs.Length() < 1) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(String::NewFromUtf8(isolate,
|
||||
"Not enough arguments.")));
|
||||
return;
|
||||
}
|
||||
|
||||
if(aArgs.Length() > 1) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(String::NewFromUtf8(isolate,
|
||||
"Too many arguments.")));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!aArgs[0]->IsObject()) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(
|
||||
String::NewFromUtf8(isolate,
|
||||
"Invalid argument. Must be an Object.")));
|
||||
return;
|
||||
}
|
||||
|
||||
Local<Object> options = aArgs[0]->ToObject();
|
||||
|
||||
Local<String> hostKey = String::NewFromUtf8(isolate, "host");
|
||||
Local<String> portKey = String::NewFromUtf8(isolate, "port");
|
||||
|
||||
if(!options->Has(hostKey) ||
|
||||
!options->Get(hostKey)->IsString()) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(
|
||||
String::NewFromUtf8(
|
||||
isolate,
|
||||
"Object must have 'host' field and it must be a string.")));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!options->Has(portKey) ||
|
||||
!options->Get(portKey)->IsNumber()) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(
|
||||
String::NewFromUtf8(
|
||||
isolate,
|
||||
"Object must have 'port' field and it must be a number.")));
|
||||
return;
|
||||
}
|
||||
|
||||
Sockit *sockit = ObjectWrap::Unwrap<Sockit>(aArgs.Holder());
|
||||
|
||||
// Ensure we're not already attempting to connect.
|
||||
if(sockit->mIsConnecting) {
|
||||
_debug_log(E_ALREADY_CONNECTING);
|
||||
isolate->ThrowException(
|
||||
Exception::Error(String::NewFromUtf8(isolate, E_ALREADY_CONNECTING)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure we're not already connected.
|
||||
if(sockit->mIsConnected) {
|
||||
_debug_log(E_ALREADY_CONNECTED);
|
||||
isolate->ThrowException(
|
||||
Exception::Error(String::NewFromUtf8(isolate, E_ALREADY_CONNECTED)));
|
||||
return;
|
||||
}
|
||||
|
||||
// We can consider ourselves in an attempt to connect at this point.
|
||||
sockit->mIsConnecting = true;
|
||||
|
||||
// XXXAus: Move the DNS piece into it's own method.
|
||||
|
||||
String::Utf8Value optionsHost(options->Get(hostKey)->ToString());
|
||||
|
||||
bool shouldRetry = false;
|
||||
int retryCount = 0;
|
||||
struct hostent *hostEntry;
|
||||
|
||||
do {
|
||||
hostEntry = gethostbyname(*optionsHost);
|
||||
|
||||
// Getting the host address failed. Let's see why.
|
||||
if(hostEntry == NULL) {
|
||||
// Check h_errno, we might retry if the error indicates we should.
|
||||
switch(h_errno) {
|
||||
case HOST_NOT_FOUND:
|
||||
isolate->ThrowException(
|
||||
Exception::Error(String::NewFromUtf8(isolate,
|
||||
"Couldn't resolve host.")));
|
||||
return;
|
||||
break;
|
||||
|
||||
case NO_RECOVERY:
|
||||
isolate->ThrowException(
|
||||
Exception::Error(
|
||||
String::NewFromUtf8(isolate,
|
||||
"Unexpected failure during host lookup.")));
|
||||
return;
|
||||
break;
|
||||
|
||||
case NO_DATA:
|
||||
isolate->ThrowException(
|
||||
Exception::Error(String::NewFromUtf8(isolate,
|
||||
"Host exists but has no address.")));
|
||||
return;
|
||||
break;
|
||||
|
||||
case TRY_AGAIN:
|
||||
shouldRetry = true;
|
||||
retryCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(shouldRetry && retryCount <= MAX_LOOKUP_RETRIES);
|
||||
|
||||
if(hostEntry == NULL) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(String::NewFromUtf8(isolate,
|
||||
"Couldn't resolve host even after retries.")));
|
||||
return;
|
||||
}
|
||||
|
||||
int socketHandle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if(socketHandle < 0) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(String::NewFromUtf8(isolate, "Failed to create socket.")));
|
||||
return;
|
||||
}
|
||||
|
||||
sockit->mSocket = socketHandle;
|
||||
|
||||
// Set socket non-blocking prior to connect. We'll poll for connect success.
|
||||
int flags = fcntl(socketHandle, F_GETFL, 0);
|
||||
if(flags == -1) {
|
||||
flags = 0;
|
||||
}
|
||||
int result = fcntl(socketHandle, F_SETFL, flags | O_NONBLOCK);
|
||||
if(result < 0) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(
|
||||
String::NewFromUtf8(isolate, "Failed to set non blocking to socket.")));
|
||||
return;
|
||||
}
|
||||
|
||||
// Magic socket incantation.
|
||||
struct sockaddr_in address;
|
||||
memset(&address, 0, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
// Always use first address returned, it's good enough for our purposes.
|
||||
address.sin_addr.s_addr =
|
||||
inet_addr(inet_ntoa(*(struct in_addr *)hostEntry->h_addr_list[0]));
|
||||
// Using static cast here to enforce short as required by IPv4 functions.
|
||||
address.sin_port =
|
||||
htons(static_cast<short>(options->Get(portKey)->ToNumber()->Uint32Value()));
|
||||
|
||||
result = connect(
|
||||
sockit->mSocket, (sockaddr *) &address, sizeof(struct sockaddr)
|
||||
);
|
||||
|
||||
if(result == -1 && errno != EINPROGRESS) {
|
||||
// We failed to connect. Close to socket we created.
|
||||
close(sockit->mSocket);
|
||||
// In case there's another connect attempt, clean up the socket data.
|
||||
sockit->mSocket = 0;
|
||||
sockit->mIsConnecting = false;
|
||||
// Report failure to connect.
|
||||
isolate->ThrowException(
|
||||
Exception::Error(String::NewFromUtf8(isolate, "Failed to connect.")));
|
||||
return;
|
||||
}
|
||||
|
||||
struct pollfd fds;
|
||||
fds.fd = sockit->mSocket;
|
||||
fds.events = POLLWRBAND | POLLWRNORM | POLLNVAL;
|
||||
fds.revents = 0;
|
||||
|
||||
result = poll(&fds, 1, sockit->mPollTimeout);
|
||||
|
||||
// If we've failed, we'll clean-up and try and send an exception.
|
||||
if(result != 1) {
|
||||
// Close and clean-up.
|
||||
close(sockit->mSocket);
|
||||
sockit->mSocket = 0;
|
||||
sockit->mIsConnecting = false;
|
||||
sockit->mIsConnected = false;
|
||||
|
||||
if(result == 0) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(
|
||||
String::NewFromUtf8(isolate, "Polling socket connect() timeout!")));
|
||||
}
|
||||
else if(result < 0 || (fds.revents & POLLERR)) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(
|
||||
String::NewFromUtf8(isolate, "Error polling connect() socket!")));
|
||||
}
|
||||
else if(!((fds.revents & POLLWRBAND) || (fds.revents & POLLWRNORM)) ) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(
|
||||
String::NewFromUtf8(isolate, "Unhandled poll event connect() socket!")));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we're really connected.
|
||||
sockit->mIsConnected = true;
|
||||
// And we're no longer attempting to connect.
|
||||
sockit->mIsConnecting = false;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
Sockit::Read(const FunctionCallbackInfo<Value>& aArgs) {
|
||||
Isolate* isolate = Isolate::GetCurrent();
|
||||
HandleScope scope(isolate);
|
||||
|
||||
// Default to returning undefined
|
||||
aArgs.GetReturnValue().Set(Undefined(isolate));
|
||||
|
||||
if(aArgs.Length() != 1) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(
|
||||
String::NewFromUtf8(
|
||||
isolate,
|
||||
"Not enough arguments, read takes the number of bytes to be read from the socket.")));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!aArgs[0]->IsNumber()) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(String::NewFromUtf8(isolate,
|
||||
"Argument must be a Number.")));
|
||||
return;
|
||||
}
|
||||
|
||||
Sockit *sockit = ObjectWrap::Unwrap<Sockit>(aArgs.Holder());
|
||||
|
||||
// Make sure we're connected to something.
|
||||
if(sockit->mSocket == 0) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(
|
||||
String::NewFromUtf8(
|
||||
isolate,
|
||||
"Not connected. To read data you must call connect first.")));
|
||||
return;
|
||||
}
|
||||
|
||||
// Figure out how many bytes the user wants us to read from the socket.
|
||||
unsigned int bytesToRead = aArgs[0]->ToNumber()->Uint32Value();
|
||||
// Allocate a shiny buffer.
|
||||
char *buffer = new char[bytesToRead];
|
||||
// Track how many bytes we've read and total bytes read.
|
||||
int totalBytesRead = 0;
|
||||
int bytesRead = 0;
|
||||
// Read me some tasty bytes!
|
||||
struct pollfd fds;
|
||||
fds.fd = sockit->mSocket;
|
||||
fds.events = POLLIN;
|
||||
|
||||
do {
|
||||
fds.revents = 0;
|
||||
|
||||
int result = poll(&fds, 1, sockit->mPollTimeout);
|
||||
if(result == 0) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(String::NewFromUtf8(isolate,
|
||||
"Polling socket recv() timeout!")));
|
||||
break;
|
||||
}
|
||||
else if(result < 0 || (fds.revents & POLLERR)) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(String::NewFromUtf8(isolate,
|
||||
"Error polling recv() socket!")));
|
||||
break;
|
||||
}
|
||||
else if(!(fds.revents & POLLIN)) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(String::NewFromUtf8(isolate,
|
||||
"Unhandled poll event recv() socket!")));
|
||||
break;
|
||||
}
|
||||
bytesRead = recv(sockit->mSocket, &buffer[totalBytesRead], bytesToRead, 0);
|
||||
|
||||
if(bytesRead < 0) {
|
||||
|
||||
if(errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
isolate->ThrowException(
|
||||
Exception::Error(
|
||||
String::NewFromUtf8(isolate,
|
||||
"Error while reading from socket!")));
|
||||
break;
|
||||
}
|
||||
if(bytesRead == 0) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(String::NewFromUtf8(isolate,
|
||||
"Connection reset by peer!")));
|
||||
break;
|
||||
}
|
||||
|
||||
bytesToRead -= bytesRead;
|
||||
totalBytesRead += bytesRead;
|
||||
|
||||
bytesRead = 0;
|
||||
}
|
||||
while(bytesToRead > 0);
|
||||
|
||||
if(totalBytesRead) {
|
||||
// Create a node heap allocated buffer first.
|
||||
Local<Object> heapBuffer = node::Buffer::New(isolate, totalBytesRead).ToLocalChecked();
|
||||
|
||||
// Copy our temporary buffer data into the heap buffer.
|
||||
memcpy(node::Buffer::Data(heapBuffer), buffer, totalBytesRead);
|
||||
// Done with our temporary buffer.
|
||||
delete [] buffer;
|
||||
// Return those tasty bytes!
|
||||
aArgs.GetReturnValue().Set(heapBuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
// Done with our temporary buffer.
|
||||
delete [] buffer;
|
||||
|
||||
// Return NULL!
|
||||
aArgs.GetReturnValue().Set(Null(isolate));
|
||||
return;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
Sockit::Write(const FunctionCallbackInfo<Value>& aArgs) {
|
||||
Isolate* isolate = Isolate::GetCurrent();
|
||||
HandleScope scope(isolate);
|
||||
|
||||
if(aArgs.Length() < 1) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(String::NewFromUtf8(isolate,
|
||||
"Not enough arguments.")));
|
||||
return;
|
||||
}
|
||||
|
||||
if(aArgs.Length() > 1) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(
|
||||
String::NewFromUtf8(isolate,
|
||||
"Too many arguments.")));
|
||||
return;
|
||||
}
|
||||
|
||||
Sockit *sockit = ObjectWrap::Unwrap<Sockit>(aArgs.Holder());
|
||||
|
||||
// Always return self even when we throw.
|
||||
aArgs.GetReturnValue().Set(aArgs.This());
|
||||
|
||||
// Make sure we're connected to something.
|
||||
if(sockit->mSocket == 0) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(
|
||||
String::NewFromUtf8(
|
||||
isolate,
|
||||
"Not connected. To write data you must call connect first.")));
|
||||
return;
|
||||
}
|
||||
|
||||
int success = 0;
|
||||
|
||||
if(aArgs[0]->IsString()) {
|
||||
// Convert to utf8 value before sending.
|
||||
Local<String> dataString = aArgs[0]->ToString();
|
||||
String::Utf8Value data(dataString);
|
||||
// Write the data to the socket.
|
||||
success = sockit->Write(*data, dataString->Utf8Length());
|
||||
}
|
||||
else if(aArgs[0]->IsObject() &&
|
||||
aArgs[0]->ToObject()->GetConstructorName()->Equals(String::NewFromUtf8(isolate, "Buffer"))) {
|
||||
Local<Object> buffer = aArgs[0]->ToObject();
|
||||
success =
|
||||
sockit->Write(node::Buffer::Data(buffer), node::Buffer::Length(buffer));
|
||||
}
|
||||
else {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(
|
||||
String::NewFromUtf8(isolate,
|
||||
"Invalid argument, must be a 'String' or 'Buffer' object.")));
|
||||
return;
|
||||
}
|
||||
|
||||
if(success < 0) {
|
||||
isolate->ThrowException(
|
||||
Exception::Error(String::NewFromUtf8(isolate,
|
||||
"Unable to write data to socket.")));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
Sockit::Write(const char *aBuffer, const int aLength) {
|
||||
|
||||
int bytesToWrite = aLength;
|
||||
int totalBytesWritten = 0;
|
||||
int bytesWritten = 0;
|
||||
|
||||
do {
|
||||
bytesWritten =
|
||||
send(mSocket,
|
||||
aBuffer + (totalBytesWritten * sizeof(char)),
|
||||
bytesToWrite,
|
||||
0
|
||||
);
|
||||
|
||||
if(bytesWritten < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
totalBytesWritten += bytesWritten;
|
||||
bytesToWrite -= bytesWritten;
|
||||
|
||||
bytesWritten = 0;
|
||||
}
|
||||
while(bytesToWrite > 0);
|
||||
|
||||
return totalBytesWritten;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
Sockit::Close(const FunctionCallbackInfo<Value>& aArgs) {
|
||||
Isolate* isolate = Isolate::GetCurrent();
|
||||
HandleScope scope(isolate);
|
||||
|
||||
Sockit *sockit = ObjectWrap::Unwrap<Sockit>(aArgs.Holder());
|
||||
if(sockit->mSocket != 0) {
|
||||
// If close fails we have bigger problems on our hands than a stale
|
||||
// socket that isn't closed.
|
||||
close(sockit->mSocket);
|
||||
}
|
||||
|
||||
sockit->mSocket = 0;
|
||||
sockit->mIsConnecting = false;
|
||||
sockit->mIsConnected = false;
|
||||
|
||||
aArgs.GetReturnValue().Set(aArgs.This());
|
||||
return;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
Sockit::SetPollTimeout(const FunctionCallbackInfo<Value>& aArgs) {
|
||||
Isolate* isolate = Isolate::GetCurrent();
|
||||
HandleScope scope(isolate);
|
||||
|
||||
if(aArgs.Length() < 1) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(String::NewFromUtf8(isolate,
|
||||
"Not enough arguments.")));
|
||||
return;
|
||||
}
|
||||
|
||||
if(aArgs.Length() > 1) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(String::NewFromUtf8(isolate,
|
||||
"Too many arguments.")));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!aArgs[0]->IsNumber()) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(String::NewFromUtf8(isolate,
|
||||
"Argument is not a number.")));
|
||||
return;
|
||||
}
|
||||
|
||||
Sockit *sockit = ObjectWrap::Unwrap<Sockit>(aArgs.Holder());
|
||||
sockit->mPollTimeout = aArgs[0]->Int32Value();
|
||||
|
||||
aArgs.GetReturnValue().Set(aArgs.This());
|
||||
return;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
Sockit::SetDebugLog(const FunctionCallbackInfo<Value>& aArgs) {
|
||||
Isolate* isolate = Isolate::GetCurrent();
|
||||
HandleScope scope(isolate);
|
||||
|
||||
if(aArgs.Length() < 1) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(String::NewFromUtf8(isolate,
|
||||
"Not enough arguments.")));
|
||||
return;
|
||||
}
|
||||
|
||||
if(aArgs.Length() > 1) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(String::NewFromUtf8(isolate,
|
||||
"Too many arguments.")));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!aArgs[0]->IsBoolean()) {
|
||||
isolate->ThrowException(
|
||||
Exception::TypeError(String::NewFromUtf8(isolate,
|
||||
"Argument is not a boolean.")));
|
||||
return;
|
||||
}
|
||||
|
||||
gDebugLog = aArgs[0]->BooleanValue();
|
||||
|
||||
if(gDebugLog) {
|
||||
_debug_log("debug log enabled");
|
||||
}
|
||||
|
||||
aArgs.GetReturnValue().Set(aArgs.This());
|
||||
return;
|
||||
}
|
||||
39
gaia/tests/jsmarionette/client/sockit-to-me/src/sockit.h
Executable file
39
gaia/tests/jsmarionette/client/sockit-to-me/src/sockit.h
Executable file
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef __SOCKIT_H__
|
||||
#define __SOCKIT_H__
|
||||
|
||||
#include <node.h>
|
||||
#include <node_object_wrap.h>
|
||||
|
||||
class Sockit : public node::ObjectWrap {
|
||||
public:
|
||||
static void Init(v8::Handle<v8::Object>);
|
||||
|
||||
private:
|
||||
Sockit();
|
||||
~Sockit();
|
||||
|
||||
static v8::Persistent<v8::Function> constructor;
|
||||
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>&);
|
||||
|
||||
static void Connect(const v8::FunctionCallbackInfo<v8::Value>&);
|
||||
|
||||
static void Read(const v8::FunctionCallbackInfo<v8::Value>&);
|
||||
|
||||
static void Write(const v8::FunctionCallbackInfo<v8::Value>&);
|
||||
|
||||
int Write(const char *, const int);
|
||||
|
||||
static void Close(const v8::FunctionCallbackInfo<v8::Value>&);
|
||||
|
||||
static void SetPollTimeout(const v8::FunctionCallbackInfo<v8::Value>&);
|
||||
static void SetDebugLog(const v8::FunctionCallbackInfo<v8::Value>&);
|
||||
|
||||
int mSocket;
|
||||
int mPollTimeout;
|
||||
|
||||
bool mIsConnecting;
|
||||
bool mIsConnected;
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Reference in a new issue