Skip to content

Instantly share code, notes, and snippets.

@croteb
Created November 15, 2012 23:30
Show Gist options
  • Save croteb/4082355 to your computer and use it in GitHub Desktop.
Save croteb/4082355 to your computer and use it in GitHub Desktop.
winsockwatcher
#include "mdns.hpp"
#include "winsock_watcher.hpp"
#include <node.h>
#include <node_version.h>
using namespace v8;
#if NODE_VERSION_AT_LEAST(0, 7, 8)
// Nothing
#else
namespace node {
Handle<Value>
MakeCallback(const Handle<Object> object,
const Handle<Function> callback,
int argc,
Handle<Value> argv[]) {
HandleScope scope;
// TODO Hook for long stack traces to be made here.
TryCatch try_catch;
Local<Value> ret = callback->Call(object, argc, argv);
if (try_catch.HasCaught()) {
FatalException(try_catch);
return Undefined();
}
return scope.Close(ret);
}
} // namespace node
#endif
namespace node_mdns {
Persistent<String> callback_symbol;
Handle<Value> Calleback(const Arguments& args) {
return Undefined();
};
void WinsockWatcher::Initialize(Handle<Object> target) {
printf("top of initialize\n");
Local<FunctionTemplate> t = FunctionTemplate::New(New);
Local<String> symbol = String::NewSymbol("WinsockWatcher");
t->SetClassName(symbol);
t->InstanceTemplate()->SetInternalFieldCount(1);
NODE_SET_PROTOTYPE_METHOD(t, "set", WinsockWatcher::Set);
NODE_SET_PROTOTYPE_METHOD(t, "start", WinsockWatcher::Start);
NODE_SET_PROTOTYPE_METHOD(t, "stop", WinsockWatcher::Stop);
target->Set(symbol, t->GetFunction());
callback_symbol = NODE_PSYMBOL("callback");
//target->Set(String::NewSymbol("callback"), FunctionTemplate::New(Calleback)->GetFunction());
printf("bottom of initialize\n");
}
Handle<Value> WinsockWatcher::Start(const Arguments& args) {
HandleScope scope;
WinsockWatcher *io = ObjectWrap::Unwrap<WinsockWatcher>(args.Holder());
io->Start();
printf("returned from local start in cpp\n");
return Undefined();
}
void WinsockWatcher::Start() {
printf("starting watcher from cpp\n");
if (!ev_is_active(&watcher_)) {
printf("is not active from cpp\n");
ev_io_start(EV_DEFAULT_UC_ &watcher_);
//uv_poll_init(uv_default_loop(), &watcher_.handle, 0);
//uv_poll_start(&watcher_.handle,UV_READABLE,io_event);
printf("ev_io_start called from cpp\n");
Ref();
}
}
void WinsockWatcher::Callback(EV_P_ ev_io *w, int revents) {
HandleScope scope;
printf("top of callback");
/*
WinsockWatcher *io = static_cast<WinsockWatcher*>(w->data);
assert(w == &io->watcher_);
HandleScope scope;
Local<Value> callback_v = io->handle_->Get(callback_symbol);
if (!callback_v->IsFunction()) {
io->Stop();
return;
}
Local<Function> callback = Local<Function>::Cast(callback_v);
TryCatch try_catch;
Local<Value> argv[2];
argv[0] = Local<Value>::New(revents & UV_READ ? True() : False());
argv[1] = Local<Value>::New(revents & UV_WRITE ? True() : False());
printf("calling callback\n");
callback->Call(io->handle_, 2, argv);
printf("returned from callback\n");
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
*/
WinsockWatcher *io = static_cast<WinsockWatcher*>(w->data);
assert(w == &io->watcher_);
Local<Value> callback_v = io->handle_->Get(callback_symbol);
if (!callback_v->IsFunction()) {
io->Stop();
return;
}
Local<Function> callback = Local<Function>::Cast(callback_v);
Local<Value> argv[2];
argv[0] = Local<Value>::New(revents & UV_READABLE ? True() : False());
argv[1] = Local<Value>::New(revents & UV_WRITABLE ? True() : False());
node::MakeCallback(io->handle_, callback, ARRAY_SIZE(argv), argv);
}
Handle<Value> WinsockWatcher::Stop(const Arguments& args) {
HandleScope scope;
WinsockWatcher *io = ObjectWrap::Unwrap<WinsockWatcher>(args.Holder());
io->Stop();
return Undefined();
}
void WinsockWatcher::Stop() {
printf("stopping from cpp.\n");
if (ev_is_active(&watcher_)) {
printf("watcher is active from cpp\n");
ev_io_stop(EV_DEFAULT_UC_ &watcher_);
Unref();
}
}
v8::Handle<v8::Value>
WinsockWatcher::New(const v8::Arguments & args) {
HandleScope scope;
WinsockWatcher *s = new WinsockWatcher();
s->Wrap(args.This());
return args.This();
}
Handle<Value> WinsockWatcher::Set(const Arguments& args) {
HandleScope scope;
printf("top of set function\n");
WinsockWatcher *io = ObjectWrap::Unwrap<WinsockWatcher>(args.Holder());
if (!args[0]->IsInt32()) {
return ThrowException(Exception::TypeError(
String::New("First arg should be a file descriptor.")));
}
int fd = args[0]->Int32Value();
if (!args[1]->IsBoolean()) {
return ThrowException(Exception::TypeError(
String::New("Second arg should boolean (readable).")));
}
int events = 0;
if (args[1]->IsTrue()) events |= UV_READABLE;
if (!args[2]->IsBoolean()) {
return ThrowException(Exception::TypeError(
String::New("Third arg should boolean (writable).")));
}
if (args[2]->IsTrue()) events |= UV_WRITABLE;
printf("middle of function: %i, %i\n",fd,events);
//assert(!io->watcher_.active);
assert(!ev_is_active(&io->watcher_));
ev_io_set(&io->watcher_, fd, events);
printf("bottom of set function\n");
return Undefined();
}
/*
void InitAll(Handle<Object> target) {
WinsockWatcher::Initialize(target);
}
NODE_MODULE(dns_sd_bindings, WinsockWatcher::Initialize);
*/
} // end of namespace node_mdns
#ifndef NODE_MDNS_WINSOCK_WATCHER_INCLUDED
#define NODE_MDNS_WINSOCK_WATCHER_INCLUDED
#define BUILDING_NODE_EXTENSION
#include "uv.h"
#undef ev_init
#undef ev_set_cb
#undef ev_set_priority
#undef ev_is_active
#undef ev_timer_init
#undef ev_timer_set
#undef ev_io_init
#undef ev_io_set
#undef EV_P
#undef EV_P_
#undef EV_A
#undef EV_A_
#undef EV_DEFAULT
#undef EV_DEFAULT_
#undef EV_DEFAULT_UC
#undef EV_DEFAULT_UC_
#define EV_P void
#define EV_P_
#define EV_A
#define EV_A_
#define EV_DEFAULT
#define EV_DEFAULT_
#define EV_DEFAULT_UC
#define EV_DEFAULT_UC_
#define ev_io __ev_io
#define ev_io_init __ev_io_init
#define ev_io_set __ev_io_set
#define ev_io_start __ev_io_start
#define ev_io_stop __ev_io_stop
#define ev_init(w, cb_) \
do { \
void* data = (w)->data; \
memset((w), 0, sizeof(*(w))); \
(w)->data = data; \
(w)->cb = (cb_); \
} \
while (0)
#define ev_set_cb(w, cb_) \
do \
(w)->cb = (cb_); \
while (0)
#define ev_is_active(w) \
(uv_is_active((uv_handle_t*) &(w)->handle))
#define __uv_container_of(ptr, type, field) \
((type*) ((char*) (ptr) - offsetof(type, field)))
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
struct __ev_io;
typedef struct __ev_io __ev_io;
typedef void (*__ev_io_cb)(__ev_io*, int);
struct __ev_io {
__ev_io_cb cb;
void* data;
int flags; /* bit 1 == initialized, yes or no? */
uv_poll_t handle;
int fd;
int events;
};
inline static void __uv_poll_cb(uv_poll_t* handle, int status, int events) {
printf("__uv_poll_cb\n");
__ev_io* w = __uv_container_of(handle, __ev_io, handle);
w->cb(w, events);
(void) status;
}
inline static void __ev_io_stop(__ev_io* w) {
printf("ev_io_stop\n");
uv_poll_stop(&w->handle);
}
inline static void __ev_io_set(__ev_io* w, int fd, int events) {
printf("ev_io_set,%x,%i,%x\n",w,fd,events);
w->fd = fd;
w->events = events;
printf("ev_io_set from struct,%x,%i,%x\n",w,w->fd,w->events);
}
static void io_event(uv_poll_t* w, int status, int revents){
printf("handling io_event\n");
}
namespace node_mdns {
class WinsockWatcher : public node::ObjectWrap {
public:
static void Initialize(v8::Handle<v8::Object> target);
__ev_io watcher_;
static void Callback(EV_P_ ev_io *watcher, int revents);
protected:
static v8::Handle<v8::Value> New(const v8::Arguments & args);
static v8::Handle<v8::Value> Set(const v8::Arguments & args);
static v8::Handle<v8::Value> Start(const v8::Arguments& args);
static v8::Handle<v8::Value> Stop(const v8::Arguments& args);
WinsockWatcher() : ObjectWrap() {
printf("WinsockWatcher constructor: %x\n",WinsockWatcher::Callback);
ev_init(&watcher_, WinsockWatcher::Callback);
watcher_.data = this;
}
~WinsockWatcher() {
printf("WinsockWatcher destructor\n");
ev_io_stop(EV_DEFAULT_UC_ &watcher_);
assert(!ev_is_active(&watcher_));
//assert(!ev_is_pending(&watcher_));
}
private:
void Start();
void Stop();
};
} // end of namespace node_mdns
inline static void __ev_io_start(__ev_io* w) {
printf("ev_io_start\n");
printf("starting ev_poll_start, %x,%i,%x,%x,%x\n",w,w->fd,&w->handle,w->events,&__uv_poll_cb);
if (!(w->flags & 1)) {
printf("calling uv_poll_init\n");
uv_poll_init(uv_default_loop(), &w->handle, w->fd);
w->flags |= 1;
}
printf("starting uv_poll_start, %x,%i,%x,%x,%x,%x\n",w,w->fd,&w->handle,w->events,&__uv_poll_cb, io_event);
//uv_poll_start(&w->handle,UV_READABLE,io_event);
//printf("after starting uv_poll_start, %x,%i,%x,%x,%x,%x\n",w,w->fd,&w->handle,w->events,&__uv_poll_cb, io_event);
uv_poll_start(&w->handle, w->events, __uv_poll_cb);
}
#endif // NODE_MDNS_WINSOCK_WATCHER_INCLUDED
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment