Skip to content

Commit

Permalink
c++: Add the new MDNS service callback handling
Browse files Browse the repository at this point in the history
Signed-off-by: Corey Minyard <[email protected]>
  • Loading branch information
cminyard committed Jul 19, 2023
1 parent 6263117 commit d17040a
Show file tree
Hide file tree
Showing 9 changed files with 378 additions and 35 deletions.
33 changes: 30 additions & 3 deletions c++/examples/mdns.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,32 @@ class Watch_Done: public MDNS_Watch_Free_Done {
Waiter *waiter;
};

class Service_Event: public MDNS_Service_Event {
public:
Service_Event(Waiter *w) { waiter = w; }

private:
void event(enum gensio_mdns_service_event ev,
const char *info) override
{
if (ev == GENSIO_MDNS_SERVICE_REMOVED) {
cout << "MDNS service removed" << endl;
waiter->wake();
return;
}

if (ev == GENSIO_MDNS_SERVICE_READY) {
cout << "MDNS service ready with name " << info << endl;
} else if (ev == GENSIO_MDNS_SERVICE_READY) {
cout << "MDNS service ready with new name " << info << endl;
} else if (ev == GENSIO_MDNS_SERVICE_ERROR) {
cout << "MDNS service error: " << info << endl;
}
}

Waiter *waiter;
};

class Done: public MDNS_Free_Done {
public:
Done(Waiter *w) { waiter = w; }
Expand Down Expand Up @@ -87,6 +113,7 @@ int main(int argc, char *argv[])
Os_Funcs o(0, new MDNS_Logger);
Waiter w(o);
Watch_Event e(&w);
Service_Event s(&w);
Watch_Done d(&w);
Done d2(&w);
MDNS *m;
Expand All @@ -97,15 +124,15 @@ int main(int argc, char *argv[])
o.proc_setup();
m = new MDNS(o);
serv = new MDNS_Service(m, -1, GENSIO_NETTYPE_UNSPEC, "gensio1",
"_gensio1._tcp", NULL, NULL, 5001, txt);
"_gensio1._tcp", NULL, NULL, 5001, txt, &s);
watch = new MDNS_Watch(m, -1, GENSIO_NETTYPE_UNSPEC, "gensio1", NULL,
NULL, NULL, &e);

w.wait(1, NULL);
delete serv;
serv->free();
watch->free(&d);
m->free(&d2);
w.wait(2, NULL);
w.wait(3, NULL);
err = 0;
} catch (gensio_error &e) {
cerr << "gensio error: " << e.what() << endl;
Expand Down
65 changes: 64 additions & 1 deletion c++/include/gensio/gensiomdns
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ namespace gensios {

class MDNS;
class MDNS_Service;
class MDNS_Service_Event;
class MDNS_Watch;
class MDNS_Watch_Event;

Expand Down Expand Up @@ -77,6 +78,16 @@ namespace gensios {
virtual void set_parent(Raw_MDNS_Event_Handler *parent) { }
};

class GENSIOMDNSCPP_DLL_PUBLIC Raw_MDNS_Service_Event_Handler {
public:
virtual ~Raw_MDNS_Service_Event_Handler() = default;

virtual void handle(MDNS_Service_Event *e,
enum gensio_mdns_service_event ev,
const char *info) = 0;
virtual void set_parent(Raw_MDNS_Service_Event_Handler *parent) { }
};

class GENSIOMDNSCPP_DLL_PUBLIC MDNS {
public:
MDNS(Os_Funcs &o);
Expand All @@ -88,6 +99,12 @@ namespace gensios {
const char *name, const char *mtype,
const char *domain, const char *host,
int port, const char * const *txt);
MDNS_Service *add_service(int interfacenum, int ipdomain,
const char *name, const char *mtype,
const char *domain, const char *host,
int port, const char * const *txt,
MDNS_Service_Event *event,
Raw_MDNS_Service_Event_Handler *evh = NULL);
MDNS_Watch *add_watch(int interfacenum, int ipdomain,
const char *name, const char *mtype,
const char *domain, const char *host,
Expand All @@ -108,6 +125,23 @@ namespace gensios {
friend void mdns_free_done(struct gensio_mdns *m, void *userdata);
};

// This handles events from an mdns service informing you that it
// has has finished registration, the name has changed, or that it
// is removed. Analogous to gensio_mdns_service_cb, see the
// gensio_mdns_add_service2() man page for details.
class GENSIOMDNSCPP_DLL_PUBLIC MDNS_Service_Event {
public:
virtual void event(enum gensio_mdns_service_event ev,
const char *info) = 0;
virtual ~MDNS_Service_Event() = default;
private:
MDNS_Service *s = NULL;
friend class MDNS_Service;
friend void mdns_service_event(struct gensio_mdns_service *s,
enum gensio_mdns_service_event ev,
const char *info, void *userdata);
};

// A class representing an MDNS service. A wrapper around
// gensio_mdns_add/remove_service(), see man pages on those
// functions for details.
Expand All @@ -117,9 +151,38 @@ namespace gensios {
const char *name, const char *mtype,
const char *domain, const char *host,
int port, const char * const *txt);
~MDNS_Service();
MDNS_Service(MDNS *m, int interfacenum, int ipdomain,
const char *name, const char *mtype,
const char *domain, const char *host,
int port, const char * const *txt,
MDNS_Service_Event *event,
Raw_MDNS_Service_Event_Handler *raw_event_handler = NULL);

inline Os_Funcs &get_os_funcs() { return m->get_os_funcs(); }

// Like a gensio, you cannot directly delete an MDNS_Watch object.
// It may be in callbacks. You have to go through a special
// free operation. See the Gensio free() method for details.
// Unlike a watch, the done callback goes through the event handler
// registered in MDNS_Service, if you registered one.
void free();

// This allows the user to intercept raw events, it is primarily
// used to help other language bindings tie in things they need.
Raw_MDNS_Service_Event_Handler *raw_event_handler = NULL;

protected:
virtual ~MDNS_Service() {
if (raw_event_handler)
delete raw_event_handler;
}
private:
MDNS *m;
struct gensio_mdns_service *s;
MDNS_Service_Event *event = NULL;
friend void mdns_service_event(struct gensio_mdns_service *s,
enum gensio_mdns_service_event ev,
const char *info, void *userdata);
};

// This class is used to know when an MDNS_Watch object has
Expand Down
94 changes: 90 additions & 4 deletions c++/lib/gensiomdns.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ namespace gensios {
domain, host, port, txt);
}

MDNS_Service *MDNS::add_service(int interfacenum, int ipdomain,
const char *name, const char *type,
const char *domain, const char *host,
int port, const char * const *txt,
MDNS_Service_Event *event,
Raw_MDNS_Service_Event_Handler *evh)
{
return new MDNS_Service(this, interfacenum, ipdomain, name, type,
domain, host, port, txt, event, evh);
}

MDNS_Watch *MDNS::add_watch(int interfacenum, int ipdomain,
const char *name, const char *type,
const char *domain, const char *host,
Expand All @@ -67,20 +78,95 @@ namespace gensios {
domain, host, event, evh);
}

class GENSIOMDNSCPP_DLL_PUBLIC Main_Raw_MDNS_Service_Event_Handler:
public Raw_MDNS_Service_Event_Handler {
public:
Main_Raw_MDNS_Service_Event_Handler(Os_Funcs io): o(io) { }

Os_Funcs o;

void handle(MDNS_Service_Event *event,
enum gensio_mdns_service_event ev,
const char *info) override
{
try {
if (event)
event->event(ev, info);
} catch (std::exception &e) {
gensio_log(o, GENSIO_LOG_ERR,
"Received C++ exception in mdns service event handler: %s",
e.what());
}
}
};

void mdns_service_event(struct gensio_mdns_service *se,
enum gensio_mdns_service_event ev,
const char *info, void *userdata)
{
MDNS_Service *s = static_cast<MDNS_Service *>(userdata);

try {
s->raw_event_handler->handle(s->event, ev, info);
} catch (std::exception &e) {
gensio_log(s->get_os_funcs(), GENSIO_LOG_ERR,
"Received C++ exception in mdns service event handler: %s",
e.what());
}
if (ev == GENSIO_MDNS_SERVICE_REMOVED)
delete s;
}

MDNS_Service::MDNS_Service(MDNS *m, int interfacenum, int ipdomain,
const char *name, const char *type,
const char *domain, const char *host,
int port, const char * const *txt)
{
int rv;

rv = gensio_mdns_add_service(m->m, interfacenum, ipdomain, name, type,
domain, host, port, txt, &this->s);
if (rv)
this->m = m;
this->event = NULL;
this->raw_event_handler =
new Main_Raw_MDNS_Service_Event_Handler(m->go);
rv = gensio_mdns_add_service2(m->m, interfacenum, ipdomain, name, type,
domain, host, port, txt,
mdns_service_event, this, &this->s);
if (rv) {
delete this->raw_event_handler;
throw gensio_error(rv);
}
}

MDNS_Service::MDNS_Service(MDNS *m, int interfacenum, int ipdomain,
const char *name, const char *type,
const char *domain, const char *host,
int port, const char * const *txt,
MDNS_Service_Event *event,
Raw_MDNS_Service_Event_Handler *raw_event_handler)
{
int rv;

this->m = m;
this->event = event;
if (event)
event->s = this;
this->raw_event_handler =
new Main_Raw_MDNS_Service_Event_Handler(m->go);
if (raw_event_handler) {
raw_event_handler->set_parent(this->raw_event_handler);
this->raw_event_handler = raw_event_handler;
}
rv = gensio_mdns_add_service2(m->m, interfacenum, ipdomain, name, type,
domain, host, port, txt,
mdns_service_event, this,
&this->s);
if (rv) {
delete this->raw_event_handler;
throw gensio_error(rv);
}
}

MDNS_Service::~MDNS_Service()
void MDNS_Service::free()
{
/* FIXME - no return code handling from this, C++ gives an error. */
gensio_mdns_remove_service(this->s);
Expand Down
6 changes: 4 additions & 2 deletions c++/swig/go/gensio/gensio.srcswigcxx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
%rename(rawgensio_acc_alloc) gensios::gensio_acc_alloc;
%rename(RawMDNS_Free_Done) gensios::MDNS_Free_Done;
%rename(RawMDNS) gensios::MDNS;
%rename(RawMDNS_Service_Event) gensios::MDNS_Service_Event;
%rename(RawMDNS_Service) gensios::MDNS_Service;
%rename(RawMDNS_Watch_Free_Done) gensios::MDNS_Watch_Free_Done;
%rename(RawMDNS_Watch_Event) gensios::MDNS_Watch_Event;
Expand Down Expand Up @@ -320,7 +321,8 @@ void *gensio_string_to_uintptr(char *in)
const std::string *mtype,
const std::string *domain,
const std::string *host,
int port, const char * const *txt) {
int port, const char * const *txt,
struct MDNS_Service_Event *ev = NULL) {
// string types from go are not nil terminated.
std::string nname, nmtype, ndomain, nhost;

Expand All @@ -345,7 +347,7 @@ void *gensio_string_to_uintptr(char *in)
mtype ? mtype->c_str() : NULL,
domain ? domain->c_str() : NULL,
host ? host->c_str() : NULL,
port, txt);
port, txt, ev);
}

MDNS_Watch *add_watch(int interfacenum, int ipdomain,
Expand Down
Loading

0 comments on commit d17040a

Please sign in to comment.