Skip to content
Browse files

ServiceBrowser first steps

  • Loading branch information...
1 parent c0282bd commit 7410b7c2b68ceff3ea64dcdaa49f52e51906a4b6 @agnat committed May 2, 2010
Showing with 211 additions and 55 deletions.
  1. +198 −41 binding.cc
  2. +7 −0 mDNS.js
  3. +6 −14 test.js
View
239 binding.cc
@@ -11,10 +11,120 @@ using namespace node;
namespace {
-static Persistent<String> ready_symbol;
-static Persistent<String> shutdown_symbol;
-#define READY_STATE_SYMBOL String::NewSymbol("readyState")
+template <typename T>
+void
+io_event(EV_P_ ev_io *w, int revents) {
+ T * sink = static_cast<T*>(w->data);
+ sink->Event(revents);
+}
+
+inline
+const char *
+errorString(DNSServiceErrorType error) {
+ switch (error) {
+ case kDNSServiceErr_NoError:
+ return "NoError";
+ case kDNSServiceErr_Unknown:
+ return "Unknown";
+ case kDNSServiceErr_NoSuchName:
+ return "NoSuchName";
+ case kDNSServiceErr_NoMemory:
+ return "NoMemory";
+ case kDNSServiceErr_BadParam:
+ return "BadParam";
+ case kDNSServiceErr_BadReference:
+ return "BadReference";
+ case kDNSServiceErr_BadState:
+ return "BadState";
+ case kDNSServiceErr_BadFlags:
+ return "BadFlags";
+ case kDNSServiceErr_Unsupported:
+ return "Unsupported";
+ case kDNSServiceErr_NotInitialized:
+ return "NotInitialized";
+ case kDNSServiceErr_AlreadyRegistered:
+ return "AlreadyRegistered";
+ case kDNSServiceErr_NameConflict:
+ return "NameConflict";
+ case kDNSServiceErr_Invalid:
+ return "Invalid";
+ case kDNSServiceErr_Firewall:
+ return "Firewall";
+ case kDNSServiceErr_Incompatible:
+ return "Incompatible";
+ case kDNSServiceErr_BadInterfaceIndex:
+ return "BadInterfaceIndex";
+ case kDNSServiceErr_Refused:
+ return "Refused";
+ case kDNSServiceErr_NoSuchRecord:
+ return "NoSuchRecord";
+ case kDNSServiceErr_NoAuth:
+ return "NoAuth";
+ case kDNSServiceErr_NoSuchKey:
+ return "NoSuchKey";
+ case kDNSServiceErr_NATTraversal:
+ return "NATTraversal";
+ case kDNSServiceErr_DoubleNAT:
+ return "DoubleNAT";
+ case kDNSServiceErr_BadTime:
+ return "BadTime";
+ case kDNSServiceErr_BadSig:
+ return "BadSig";
+ case kDNSServiceErr_BadKey:
+ return "BadKey";
+ case kDNSServiceErr_Transient:
+ return "Transient";
+ case kDNSServiceErr_ServiceNotRunning:
+ return "ServiceNotRunning";
+ case kDNSServiceErr_NATPortMappingUnsupported:
+ return "NATPortMappingUnsupported";
+ case kDNSServiceErr_NATPortMappingDisabled:
+ return "NATPortMappingDisabled";
+#ifdef kDNSServiceErr_NoRouter
+ case kDNSServiceErr_NoRouter:
+ return "NoRouter";
+#endif
+#ifdef kDNSServiceErr_PollingMode
+ case kDNSServiceErr_PollingMode:
+ return "PollingMode";
+#endif
+ };
+ return "Unknown DNSServiceError";
+}
+
+inline
+Local<Value>
+buildException(DNSServiceErrorType error_code) {
+ HandleScope scope;
+
+ const char * error_str = errorString(error_code);
+ Local<String> error_msg = String::New(error_str);
+ Local<Value> error_v = Exception::Error(error_msg);
+ Local<Object> error = Local<Object>::Cast(error_v);
+ return scope.Close(error);
+}
+
+void
+prepareSocket(DNSServiceRef ref, ev_io * read_watcher) {
+ int fd = DNSServiceRefSockFD(ref);
+ if (-1 == fd) {
+ // XXX deal with error
+ return;
+ }
+
+ if (-1 == fcntl(fd, F_SETFL, O_NONBLOCK) ||
+ -1 == fcntl(fd, F_SETFD, FD_CLOEXEC))
+ {
+ // XXX deal with error
+ return;
+ }
+
+ ev_io_set(read_watcher, fd, EV_READ);
+ ev_io_start(EV_DEFAULT_ read_watcher);
+}
+
+//=== Service ==================================================================
class Service : public EventEmitter {
public:
static
@@ -27,15 +137,10 @@ class Service : public EventEmitter {
t->InstanceTemplate()->SetInternalFieldCount(1);
ready_symbol = NODE_PSYMBOL("ready");
- shutdown_symbol = NODE_PSYMBOL("shutdown");
+ discontinue_symbol = NODE_PSYMBOL("discontinue");
NODE_SET_PROTOTYPE_METHOD(t, "doAnnounce", DoAnnounce);
- NODE_SET_PROTOTYPE_METHOD(t, "shutdown", Shutdown);
-
- /*
- t->PrototypeTemplate()->SetAccessor(READY_STATE_SYMBOL,
- ReadyStateGetter);
- */
+ NODE_SET_PROTOTYPE_METHOD(t, "discontinue", Discontinue);
target->Set(String::NewSymbol("Service"), t->GetFunction());
}
@@ -55,35 +160,24 @@ class Service : public EventEmitter {
// XXX deal with error
return false;
}
- int fd = DNSServiceRefSockFD(ref_);
- if (-1 == fd) {
- // XXX deal with error
- return false;
- }
- if (-1 == fcntl(fd, F_SETFL, O_NONBLOCK) ||
- -1 == fcntl(fd, F_SETFD, FD_CLOEXEC))
- {
- return false;
- }
+ prepareSocket(ref_, &read_watcher_);
- ev_io_set(&read_watcher_, fd, EV_READ);
- ev_io_start(EV_DEFAULT_ &read_watcher_);
Ref();
return true;
}
bool
- Shutdown(Local<Value> exception = Local<Value>()) {
+ Discontinue(Local<Value> exception = Local<Value>()) {
HandleScope scope;
ev_io_stop(EV_DEFAULT_ &read_watcher_);
DNSServiceRefDeallocate(ref_);
ref_ = NULL;
if (exception.IsEmpty()) {
- Emit(shutdown_symbol, 0, NULL);
+ Emit(discontinue_symbol, 0, NULL);
} else {
- Emit(shutdown_symbol, 1, &exception);
+ Emit(discontinue_symbol, 1, &exception);
}
Unref();
@@ -111,15 +205,32 @@ class Service : public EventEmitter {
Service() : EventEmitter() {
ref_ = NULL;
- ev_init(&read_watcher_, io_event);
+ ev_init(&read_watcher_, io_event<Service>);
read_watcher_.data = this;
}
- void on_ready(int flags, DNSServiceErrorType errorCode,
- const char * name, const char * regtype, const char * domain)
- {
- Emit(ready_symbol, 0, NULL);
- }
+ ~Service() {
+ assert(NULL == ref_);
+ }
+
+ void
+ on_service_registered(int flags, DNSServiceErrorType errorCode,
+ const char * name, const char * regtype, const char * domain)
+ {
+ const size_t argc = 5;
+ Local<Value> args[argc];
+ if (kDNSServiceErr_NoError == errorCode) {
+ args[0] = Local<Value>::New(Null());
+ args[1] = Integer::New(flags);
+ args[2] = String::New(name);
+ args[3] = String::New(regtype);
+ args[4] = String::New(domain);
+ Emit(ready_symbol, argc, args);
+ } else {
+ args[0] = buildException(errorCode);
+ Emit(ready_symbol, 1, args);
+ }
+ }
static
Handle<Value>
@@ -166,11 +277,11 @@ class Service : public EventEmitter {
}
static
Handle<Value>
- Shutdown(const Arguments & args) {
+ Discontinue(const Arguments & args) {
HandleScope scope;
Service * service = ObjectWrap::Unwrap<Service>(args.This());
- bool r = service->Shutdown();
+ bool r = service->Discontinue();
if ( ! r) {
// XXX
@@ -185,30 +296,76 @@ class Service : public EventEmitter {
private:
static
void
- io_event(EV_P_ ev_io *w, int revents) {
- Service * service = static_cast<Service*>(w->data);
- service->Event(revents);
- }
-
- static
- void
on_service_registered(DNSServiceRef sdRef, DNSServiceFlags flags,
DNSServiceErrorType errorCode, const char *name,
const char *regtype, const char *domain, void *context )
{
Service * service = static_cast<Service*>( context );
- service->on_ready(flags, errorCode, name, regtype, domain);
+ service->on_service_registered(flags, errorCode, name, regtype, domain);
}
ev_io read_watcher_;
DNSServiceRef ref_;
+
+ static Persistent<String> ready_symbol;
+ static Persistent<String> discontinue_symbol;
};
+Persistent<String> Service::ready_symbol;
+Persistent<String> Service::discontinue_symbol;
+
+//=== Service Browser ==========================================================
+
+class ServiceBrowser : public EventEmitter {
+ public:
+ static
+ void
+ Initialize(Handle<Object> target) {
+ HandleScope scope;
+ Local<FunctionTemplate> t = FunctionTemplate::New(New);
+
+ t->Inherit(EventEmitter::constructor_template);
+ t->InstanceTemplate()->SetInternalFieldCount(1);
+
+ target->Set(String::NewSymbol("ServiceBrowser"), t->GetFunction());
+ }
+
+ void
+ Event(int revents) {
+ if (EV_READ & revents) {
+ }
+ }
+ protected:
+
+ static Handle<Value>
+ New(const Arguments & args) {
+ HandleScope scope;
+
+ ServiceBrowser * browser = new ServiceBrowser();
+ browser->Wrap(args.This());
+ return args.This();
+ }
+
+ ServiceBrowser() : EventEmitter() {
+ ref_ = NULL;
+
+ ev_init(&read_watcher_, io_event<ServiceBrowser>);
+ read_watcher_.data = this;
+ }
+
+ ~ServiceBrowser() {
+ assert(NULL == ref_);
+ }
+ private:
+ DNSServiceRef ref_;
+ ev_io read_watcher_;
+};
} // end of anonymous namespace
extern "C"
void
init (Handle<Object> target) {
HandleScope scope;
Service::Initialize( target );
+ ServiceBrowser::Initialize( target );
}
View
7 mDNS.js
@@ -1,5 +1,6 @@
binding = require('./binding');
+//=== Service ==================================================================
var Service = binding.Service;
Service.prototype.announce = function() {
return this.doAnnounce("_" + this.name + "._" + this.protocol, this.port);
@@ -16,8 +17,14 @@ exports.createService = function(name, port, protocol, ready_callback) {
return service;
};
+//=== Service Browser ==========================================================
+
exports.createServiceBrowser = function() {
+ var browser = new ServiceBrowser();
+ return browser;
};
+//=== Constants ================================================================
+
exports.TCP = "tcp";
exports.UDP = "udp";
View
20 test.js
@@ -1,17 +1,9 @@
-var mDNS = require('./mDNS'),
- sys = require('sys'),
- puts = sys.puts;
-
-s = mDNS.createService( "node_js_mdns_test", 4321, mDNS.TCP, function() {
- puts('=== service announced');
-});
-
-puts(s);
+var mDNS = require('./mDNS'),
+ sys = require('sys'),
+ assert = require('assert');
+var puts = sys.puts;
+s = mDNS.createService("node_js_mdns_test", 4321, mDNS.TCP);
s.announce();
-s.addListener('shutdown', function() { puts('=== announcement is down') });
-
-setTimeout(function() { puts('shutdown'); s.shutdown();}, 10000);
-
-puts('setup done');
+setTimeout(function() { s.discontinue(); }, 10000);

0 comments on commit 7410b7c

Please sign in to comment.
Something went wrong with that request. Please try again.