[feat] add avahi publish service

This commit is contained in:
Julian Sparber
2017-06-19 11:13:23 +02:00
parent 88bb7a8ac4
commit caffff26aa
5 changed files with 274 additions and 5 deletions

View File

@@ -4,7 +4,7 @@ CFLAGS = $(shell $(PKGCONFIG) --cflags gtk+-3.0 avahi-client)
LIBS = $(shell $(PKGCONFIG) --libs gtk+-3.0 avahi-client) LIBS = $(shell $(PKGCONFIG) --libs gtk+-3.0 avahi-client)
GLIB_COMPILE_RESOURCES = $(shell $(PKGCONFIG) --variable=glib_compile_resources gio-2.0) GLIB_COMPILE_RESOURCES = $(shell $(PKGCONFIG) --variable=glib_compile_resources gio-2.0)
SRC = teleportapp.c teleportappwin.c teleportpeer.c main.c browser.c SRC = teleportapp.c teleportappwin.c teleportpeer.c main.c browser.c publish.c
BUILT_SRC = resources.c BUILT_SRC = resources.c
OBJS = $(BUILT_SRC:.c=.o) $(SRC:.c=.o) OBJS = $(BUILT_SRC:.c=.o) $(SRC:.c=.o)

View File

@@ -16,7 +16,7 @@
#include "teleportpeer.h" #include "teleportpeer.h"
#include "browser.h" #include "browser.h"
static AvahiSimplePoll *simple_poll = NULL; //static AvahiSimplePoll *simple_poll = NULL;
static AvahiThreadedPoll *threaded_poll = NULL; static AvahiThreadedPoll *threaded_poll = NULL;
static AvahiClient *client = NULL; static AvahiClient *client = NULL;
static TeleportPeer *peerList = NULL; static TeleportPeer *peerList = NULL;
@@ -96,8 +96,8 @@ static void browse_callback(
function we free it. If the server is terminated before function we free it. If the server is terminated before
the callback function is called the server will free the callback function is called the server will free
the resolver for us. */ the resolver for us. */
//if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, c))) if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, c)))
if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_INET, 0, resolve_callback, c))) //if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_INET, 0, resolve_callback, c)))
fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c))); fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c)));
break; break;
case AVAHI_BROWSER_REMOVE: case AVAHI_BROWSER_REMOVE:
@@ -182,7 +182,8 @@ int run_avahi_service(TeleportPeer* peers) {
} }
/* create some browsers on the client object here, if you wish */ /* create some browsers on the client object here, if you wish */
if (!(avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_http._tcp", NULL, 0, browse_callback, client))) { //if (!(avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_http._tcp", NULL, 0, browse_callback, client))) {
if (!(avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, "_http._tcp", NULL, 0, browse_callback, client))) {
/* so something bad */ /* so something bad */
return 1; return 1;
} }

258
src/publish.c Normal file
View File

@@ -0,0 +1,258 @@
/***
This file is part of avahi.
avahi is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
avahi is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with avahi; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
***/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <avahi-client/client.h>
#include <avahi-client/publish.h>
#include <avahi-common/alternative.h>
#include <avahi-common/simple-watch.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
#include <avahi-common/timeval.h>
#include <avahi-common/thread-watch.h>
#include "teleportapp.h"
#include "teleportpeer.h"
#include "browser.h"
static AvahiThreadedPoll *threaded_poll = NULL;
static AvahiEntryGroup *group = NULL;
static AvahiClient *client = NULL;
//static AvahiSimplePoll *simple_poll = NULL;
static char *name = NULL;
static void create_services(AvahiClient *c);
static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) {
assert(g == group || group == NULL);
group = g;
/* Called whenever the entry group state changes */
switch (state) {
case AVAHI_ENTRY_GROUP_ESTABLISHED :
/* The entry group has been established successfully */
fprintf(stderr, "Service '%s' successfully established.\n", name);
break;
case AVAHI_ENTRY_GROUP_COLLISION : {
char *n;
/* A service name collision with a remote service
* happened. Let's pick a new name */
n = avahi_alternative_service_name(name);
avahi_free(name);
name = n;
fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
/* And recreate the services */
create_services(avahi_entry_group_get_client(g));
break;
}
case AVAHI_ENTRY_GROUP_FAILURE :
fprintf(stderr, "Entry group failure: %s\n", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
/* Some kind of failure happened while we were registering our services */
//avahi_simple_poll_quit(simple_poll);
avahi_shutdown();
break;
case AVAHI_ENTRY_GROUP_UNCOMMITED:
case AVAHI_ENTRY_GROUP_REGISTERING:
;
}
}
static void create_services(AvahiClient *c) {
char *n, r[128];
int ret;
assert(c);
/* If this is the first time we're called, let's create a new
* entry group if necessary */
if (!group)
if (!(group = avahi_entry_group_new(c, entry_group_callback, NULL))) {
fprintf(stderr, "avahi_entry_group_new() failed: %s\n", avahi_strerror(avahi_client_errno(c)));
goto fail;
}
/* If the group is empty (either because it was just created, or
* because it was reset previously, add our entries. */
if (avahi_entry_group_is_empty(group)) {
fprintf(stderr, "Adding service '%s'\n", name);
/* Create some random TXT data */
snprintf(r, sizeof(r), "random=%i", rand());
/* We will now add two services and one subtype to the entry
* group. The two services have the same name, but differ in
* the service type (IPP vs. BSD LPR). Only services with the
* same name should be put in the same entry group. */
/* Add the service for Teleport */
if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, "_http._tcp", NULL, NULL, 3000, "test=blah", r, NULL)) < 0) {
if (ret == AVAHI_ERR_COLLISION)
goto collision;
fprintf(stderr, "Failed to add _http._tcp service: %s\n", avahi_strerror(ret));
goto fail;
}
/* Tell the server to register the service */
if ((ret = avahi_entry_group_commit(group)) < 0) {
fprintf(stderr, "Failed to commit entry group: %s\n", avahi_strerror(ret));
goto fail;
}
}
return;
collision:
/* A service name collision with a local service happened. Let's
* pick a new name */
n = avahi_alternative_service_name(name);
avahi_free(name);
name = n;
fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
avahi_entry_group_reset(group);
create_services(c);
return;
fail:
//avahi_simple_poll_quit(simple_poll);
avahi_shutdown();
}
static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
assert(c);
/* Called whenever the client or server state changes */
switch (state) {
case AVAHI_CLIENT_S_RUNNING:
/* The server has startup successfully and registered its host
* name on the network, so it's time to create our services */
create_services(c);
break;
case AVAHI_CLIENT_FAILURE:
fprintf(stderr, "Client failure: %s\n", avahi_strerror(avahi_client_errno(c)));
//avahi_simple_poll_quit(simple_poll);
avahi_shutdown();
break;
case AVAHI_CLIENT_S_COLLISION:
/* Let's drop our registered services. When the server is back
* in AVAHI_SERVER_RUNNING state we will register them
* again with the new host name. */
case AVAHI_CLIENT_S_REGISTERING:
/* The server records are now being established. This
* might be caused by a host name change. We need to wait
* for our own records to register until the host name is
* properly esatblished. */
if (group)
avahi_entry_group_reset(group);
break;
case AVAHI_CLIENT_CONNECTING:
;
}
}
static void update_service(char * service_name) {
avahi_free(name);
name = avahi_strdup(service_name);
/* If the server is currently running, we need to remove our
* service and create it anew */
if (avahi_client_get_state(client) == AVAHI_CLIENT_S_RUNNING) {
/* Remove the old services */
if (group)
avahi_entry_group_reset(group);
/* And create them again with the new name */
create_services(client);
}
}
int run_avahi_publish_service(char * service_name) {
int error;
int ret = 1;
struct timeval tv;
if (!(threaded_poll = avahi_threaded_poll_new())) {
fprintf(stderr, "Failed to create threaded poll object.\n");
return 1;
}
name = avahi_strdup(service_name);
/* Allocate a new client */
if (!(client = avahi_client_new(avahi_threaded_poll_get(threaded_poll), 0, client_callback, NULL, &error))) {
fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
return 1;
}
if (avahi_threaded_poll_start(threaded_poll) < 0) {
return 1;
}
return 0;
}
void shutdown_avahi_publish_service(void) {
/* Call this when the app shuts down */
//fprintf(stderr, "Some error\n");
avahi_threaded_poll_stop(threaded_poll);
avahi_client_free(client);
avahi_threaded_poll_free(threaded_poll);
avahi_free(name);
}

8
src/publish.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef __PUBLISH_H
#define __PUBLISH_H
extern int run_avahi_publish_service(char *);
extern void shutdown_avahi_publish_service();
#endif /* __PUBLISH_H */

View File

@@ -4,6 +4,7 @@
#include "teleportpeer.h" #include "teleportpeer.h"
#include "teleportappwin.h" #include "teleportappwin.h"
#include "browser.h" #include "browser.h"
#include "publish.h"
static TeleportAppWindow *win; static TeleportAppWindow *win;
@@ -55,6 +56,7 @@ teleport_app_activate (GApplication *app)
g_print("Data: %s\n", teleport_peer_get_ip(peerList, 0, NULL)); g_print("Data: %s\n", teleport_peer_get_ip(peerList, 0, NULL));
g_print("Data: %d\n", teleport_peer_get_port(peerList, 0, NULL)); g_print("Data: %d\n", teleport_peer_get_port(peerList, 0, NULL));
*/ */
run_avahi_publish_service("Angela's (self)");
run_avahi_service(peerList); run_avahi_service(peerList);
} }