Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avahi client #8

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ endif
openwrt: commotion-service-manager

ifeq ($(MAKECMDGOALS),linux)
CFLAGS+=-DUSE_UCI -DUSESYSLOG -DUCIPATH="\"/opt/luci-commotion/etc/config\""
CFLAGS+=-DUSE_UCI -DUSESYSLOG -DCLIENT -DUCIPATH="\"/opt/luci-commotion/etc/config\""
LDFLAGS+=-lavahi-client
OBJS+=uci-utils.o
endif
linux: commotion-service-manager
Expand Down
53 changes: 35 additions & 18 deletions commotion-service-manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
#include <avahi-common/simple-watch.h>
#include <avahi-core/core.h>
#include <avahi-core/lookup.h>
#ifdef CLIENT
#include <avahi-client/client.h>
#include <avahi-client/lookup.h>
#endif

#include "commotion.h"

Expand All @@ -64,7 +70,9 @@ extern int keyring_send_sas_request_client(const char *sid_str,
ServiceInfo *services = NULL;

AvahiSimplePoll *simple_poll = NULL;
#ifndef CLIENT
AvahiServer *server = NULL;
#endif

#define CO_APPEND_STR(R,S) CHECK(co_request_append_str(co_req,S,strlen(S)+1),"Failed to append to request")

Expand Down Expand Up @@ -92,14 +100,18 @@ ServiceInfo *find_service(const char *name) {
* @param domain domain service is advertised on (e.g. mesh.local)
* @return ServiceInfo struct representing the service that was added
*/
ServiceInfo *add_service(AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) {
ServiceInfo *add_service(BROWSER *b, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) {
ServiceInfo *i;

#ifdef CLIENT
AvahiClient *client = avahi_service_browser_get_client(b);
#endif

i = avahi_new0(ServiceInfo, 1);

if (!(i->resolver = avahi_s_service_resolver_new(server, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, i))) {
if (!(i->resolver = RESOLVER_NEW(interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, i))) {
avahi_free(i);
INFO("Failed to create resolver for service '%s' of type '%s' in domain '%s': %s", name, type, domain, avahi_strerror(avahi_server_errno(server)));
INFO("Failed to create resolver for service '%s' of type '%s' in domain '%s': %s", name, type, domain, AVAHI_ERROR);
return NULL;
}
i->interface = interface;
Expand Down Expand Up @@ -164,7 +176,7 @@ void remove_service(AvahiTimeout *t, void *userdata) {
AVAHI_LLIST_REMOVE(ServiceInfo, info, services, i);

if (i->resolver)
avahi_s_service_resolver_free(i->resolver);
RESOLVER_FREE(i->resolver);

avahi_free(i->name);
avahi_free(i->type);
Expand Down Expand Up @@ -349,7 +361,7 @@ int verify_announcement(ServiceInfo *i) {
* the local list
*/
void resolve_callback(
AvahiSServiceResolver *r,
RESOLVER *r,
AVAHI_GCC_UNUSED AvahiIfIndex interface,
AVAHI_GCC_UNUSED AvahiProtocol protocol,
AvahiResolverEvent event,
Expand All @@ -374,10 +386,14 @@ void resolve_callback(
long lifetime = 0, expiration;

assert(r);

#ifdef CLIENT
AvahiClient *client = avahi_service_resolver_get_client(r);
#endif

switch (event) {
case AVAHI_RESOLVER_FAILURE:
ERROR("(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s", name, type, domain, avahi_strerror(avahi_server_errno(server)));
ERROR("(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s", name, type, domain, AVAHI_ERROR);
break;

case AVAHI_RESOLVER_FOUND: {
Expand Down Expand Up @@ -484,7 +500,7 @@ void resolve_callback(
i->resolved = 1;
}
}
avahi_s_service_resolver_free(i->resolver);
RESOLVER_FREE(i->resolver);
i->resolver = NULL;
if (event == AVAHI_RESOLVER_FOUND && !i->resolved) {
remove_service(NULL, i);
Expand All @@ -496,7 +512,7 @@ void resolve_callback(
* services becomes available on the LAN or is removed from the LAN
*/
void browse_service_callback(
AvahiSServiceBrowser *b,
BROWSER *b,
AvahiIfIndex interface,
AvahiProtocol protocol,
AvahiBrowserEvent event,
Expand All @@ -512,7 +528,7 @@ void browse_service_callback(

case AVAHI_BROWSER_FAILURE:

ERROR("(Browser) %s", avahi_strerror(avahi_server_errno(server)));
ERROR("(Browser) %s", AVAHI_BROWSER_ERROR);
avahi_simple_poll_quit(simple_poll);
return;

Expand All @@ -525,7 +541,7 @@ void browse_service_callback(
found_service=find_service(name); // name is fingerprint, so should be unique
if (event == AVAHI_BROWSER_NEW && !found_service) {
/* add the service.*/
add_service(interface, protocol, name, type, domain);
add_service(b, interface, protocol, name, type, domain);
}
if (event == AVAHI_BROWSER_REMOVE && found_service) {
/* remove the service.*/
Expand All @@ -543,7 +559,7 @@ void browse_service_callback(
* Handler for creating Avahi service browser
*/
void browse_type_callback(
AvahiSServiceTypeBrowser *b,
TYPE_BROWSER *b,
AvahiIfIndex interface,
AvahiProtocol protocol,
AvahiBrowserEvent event,
Expand All @@ -552,25 +568,26 @@ void browse_type_callback(
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
void* userdata) {

AvahiServer *s = (AvahiServer*)userdata;
#ifdef CLIENT
AvahiClient *client = (AvahiClient*)userdata;
#else
AvahiServer *server = (AvahiServer*)userdata;
#endif
assert(b);

INFO("Type browser got an event: %d", event);
switch (event) {
case AVAHI_BROWSER_FAILURE:
ERROR("(Browser) %s",
avahi_strerror(avahi_server_errno(s)));
ERROR("(Browser) %s", AVAHI_ERROR);
avahi_simple_poll_quit(simple_poll);
return;
case AVAHI_BROWSER_NEW:
if (!avahi_s_service_browser_new(s,
AVAHI_IF_UNSPEC,
if (!BROWSER_NEW(AVAHI_IF_UNSPEC,
AVAHI_PROTO_UNSPEC,
type,
domain,
0,
browse_service_callback,
s)) {
browse_service_callback)) {
ERROR("Service Browser: Failed to create a service "
"browser for type (%s) in domain (%s)",
type,
Expand Down
43 changes: 37 additions & 6 deletions commotion-service-manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@

#include <stdlib.h>

#include <avahi-core/lookup.h>
#include <avahi-common/simple-watch.h>
#include <avahi-common/llist.h>
#include <avahi-core/core.h>
#include <avahi-core/lookup.h>
#ifdef CLIENT
#include <avahi-client/client.h>
#include <avahi-client/lookup.h>
#endif

/** Length (in hex chars) of Serval IDs */
#define FINGERPRINT_LEN 64
Expand All @@ -48,6 +53,32 @@

#define DEFAULT_CO_SOCK "/var/run/commotiond.sock"

#ifdef CLIENT
#define TYPE_BROWSER AvahiServiceTypeBrowser
#define TYPE_BROWSER_NEW(A,B,C,D,E) avahi_service_type_browser_new(client,A,B,C,D,E,client)
#define TYPE_BROWSER_FREE(J) avahi_service_type_browser_free(J)
#define BROWSER AvahiServiceBrowser
#define BROWSER_NEW(A,B,C,D,E,F) avahi_service_browser_new(client,A,B,C,D,E,F,client)
#define RESOLVER AvahiServiceResolver
#define RESOLVER_NEW(A,B,C,D,E,F,G,H,I) avahi_service_resolver_new(client,A,B,C,D,E,F,G,H,I)
#define RESOLVER_FREE(J) avahi_service_resolver_free(J)
#define AVAHI_ERROR avahi_strerror(avahi_client_errno(client))
#define AVAHI_BROWSER_ERROR avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b)))
#define FREE_AVAHI() if (client) avahi_client_free(client);
#else
#define TYPE_BROWSER AvahiSServiceTypeBrowser
#define TYPE_BROWSER_NEW(A,B,C,D,E) avahi_s_service_type_browser_new(server,A,B,C,D,E,server)
#define TYPE_BROWSER_FREE(J) avahi_s_service_type_browser_free(J)
#define BROWSER AvahiSServiceBrowser
#define BROWSER_NEW(A,B,C,D,E,F) avahi_s_service_browser_new(server,A,B,C,D,E,F,server)
#define RESOLVER AvahiSServiceResolver
#define RESOLVER_NEW(A,B,C,D,E,F,G,H,I) avahi_s_service_resolver_new(server,A,B,C,D,E,F,G,H,I)
#define RESOLVER_FREE(J) avahi_s_service_resolver_free(J)
#define AVAHI_ERROR avahi_strerror(avahi_server_errno(server))
#define AVAHI_BROWSER_ERROR AVAHI_ERROR
#define FREE_AVAHI() if (server) avahi_server_free(server);
#endif

struct arguments {
char *co_sock;
#ifdef USE_UCI
Expand All @@ -73,7 +104,7 @@ struct ServiceInfo {
AvahiStringList *txt_lst; /**< Collection of all the user-defined txt fields */
AvahiTimeout *timeout; /** Timer set for the service's expiration date */

AvahiSServiceResolver *resolver;
RESOLVER *resolver;
int resolved; /**< Flag indicating whether all the fields have been resolved */

AVAHI_LLIST_FIELDS(ServiceInfo, info);
Expand All @@ -86,7 +117,7 @@ extern AvahiServer *server;

// TODO document these
void browse_type_callback(
AvahiSServiceTypeBrowser *b,
TYPE_BROWSER *b,
AvahiIfIndex interface,
AvahiProtocol protocol,
AvahiBrowserEvent event,
Expand All @@ -95,7 +126,7 @@ void browse_type_callback(
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
void* userdata);
void browse_service_callback(
AvahiSServiceBrowser *b,
BROWSER *b,
AvahiIfIndex interface,
AvahiProtocol protocol,
AvahiBrowserEvent event,
Expand All @@ -105,11 +136,11 @@ void browse_service_callback(
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
void* userdata);
ServiceInfo *find_service(const char *name);
ServiceInfo *add_service(AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain);
ServiceInfo *add_service(BROWSER *b, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain);
void remove_service(AvahiTimeout *t, void *userdata);
int verify_announcement(ServiceInfo *i);
void resolve_callback(
AvahiSServiceResolver *r,
RESOLVER *r,
AVAHI_GCC_UNUSED AvahiIfIndex interface,
AVAHI_GCC_UNUSED AvahiProtocol protocol,
AvahiResolverEvent event,
Expand Down
42 changes: 36 additions & 6 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
#include <sys/stat.h>

#include <avahi-common/error.h>
#include <avahi-core/core.h>
#include <avahi-core/lookup.h>
#ifdef CLIENT
#include <avahi-client/client.h>
#include <avahi-client/lookup.h>
#endif

#include "commotion.h"

Expand All @@ -18,7 +24,9 @@ extern struct arguments arguments;
static int pid_filehandle;

extern AvahiSimplePoll *simple_poll;
#ifndef CLIENT
extern AvahiServer *server;
#endif

/** Parse commandline options */
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
Expand Down Expand Up @@ -139,9 +147,26 @@ static void daemon_start(char *pidfile) {

}

#ifdef CLIENT
static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
assert(c);

/* Called whenever the client or server state changes */

if (state == AVAHI_CLIENT_FAILURE) {
ERROR("Server connection failure: %s", avahi_strerror(avahi_client_errno(c)));
avahi_simple_poll_quit(simple_poll);
}
}
#endif

int main(int argc, char*argv[]) {
#ifdef CLIENT
AvahiClient *client = NULL;
#else
AvahiServerConfig config;
AvahiSServiceTypeBrowser *stb = NULL;
#endif
TYPE_BROWSER *stb = NULL;
int error;
int ret = 1;

Expand Down Expand Up @@ -190,6 +215,11 @@ int main(int argc, char*argv[]) {
/* Allocate main loop object */
CHECK((simple_poll = avahi_simple_poll_new()),"Failed to create simple poll object.");

#ifdef CLIENT
/* Allocate a new client */
client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, NULL, &error);
CHECK(client,"Failed to create client: %s", avahi_strerror(error));
#else
/* Do not publish any local records */
avahi_server_config_init(&config);
config.publish_hinfo = 0;
Expand All @@ -210,10 +240,11 @@ int main(int argc, char*argv[]) {

/* Check wether creating the server object succeeded */
CHECK(server,"Failed to create server: %s", avahi_strerror(error));
#endif

/* Create the service browser */
CHECK((stb = avahi_s_service_type_browser_new(server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "mesh.local", 0, browse_type_callback, server)),
"Failed to create service browser: %s", avahi_strerror(avahi_server_errno(server)));
CHECK((stb = TYPE_BROWSER_NEW(AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "mesh.local", 0, browse_type_callback)),
"Failed to create service browser: %s", AVAHI_ERROR);

/* Run the main loop */
avahi_simple_poll_loop(simple_poll);
Expand All @@ -226,10 +257,9 @@ int main(int argc, char*argv[]) {

/* Cleanup things */
if (stb)
avahi_s_service_type_browser_free(stb);
TYPE_BROWSER_FREE(stb);

if (server)
avahi_server_free(server);
FREE_AVAHI();

if (simple_poll)
avahi_simple_poll_free(simple_poll);
Expand Down