Skip to content

Instantly share code, notes, and snippets.

@eduardoaugustojulio
Last active April 14, 2021 20:46
Show Gist options
  • Save eduardoaugustojulio/eba88a6a1ef6555f9b076942f9c2fce7 to your computer and use it in GitHub Desktop.
Save eduardoaugustojulio/eba88a6a1ef6555f9b076942f9c2fce7 to your computer and use it in GitHub Desktop.
C++ class that publish a service with message in the network using avahi msdn library.
#include <iostream>
#include <vector>
#include "publisher.h"
int main(const int argc, const char **argv)
{
std::vector<std::string> message;
for(auto i = 0; i < 10; i++)
message.push_back("test message " + std::to_string(i));
libpublisher::publisher new_publish("test service", 8080, "_http._tcp", message);
}
#include <iostream>
#include <iostream>
#include <string>
#include <cstring>
#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 "publisher.h"
static AvahiEntryGroup *group;
static AvahiSimplePoll *poll;
static const char *name;
std::string service_type, message;
AvahiStringList *dns_message;
int port_number;
void publisher::entry_group_callback(AvahiEntryGroup * _group, AvahiEntryGroupState _state, void * userdata)
{
group = _group;
switch(_state){
case AVAHI_ENTRY_GROUP_FAILURE:
std::cerr << "ENTRY GROUP FAILURE: " << avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(_group))) << std::endl;
avahi_simple_poll_quit(poll);
break;
case AVAHI_ENTRY_GROUP_COLLISION :
case AVAHI_ENTRY_GROUP_ESTABLISHED :
case AVAHI_ENTRY_GROUP_UNCOMMITED:
case AVAHI_ENTRY_GROUP_REGISTERING:
;
break;
}
}
void publisher::create_services(AvahiClient * _client)
{
if ((!group)&&(!(group = avahi_entry_group_new(_client, entry_group_callback, NULL))))
{
std::cout << "avahi_entry_group_new() failed: " << avahi_strerror(avahi_client_errno(_client)) << std::endl;
avahi_simple_poll_quit(poll);
}
if (avahi_entry_group_is_empty(group))
{
auto ret = avahi_entry_group_add_service_strlst(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, static_cast<AvahiPublishFlags>(0), name, service_type.c_str() , NULL, NULL, port_number, dns_message);
if (ret < 0)
{
if (ret == AVAHI_ERR_COLLISION){
create_services(_client);
}
std::cerr << "Failed to add _ipp._tcp service:" << avahi_strerror(ret) << std::endl;
avahi_simple_poll_quit(poll);
}
if ((ret = avahi_entry_group_commit(group)) < 0) {
std::cerr << "Failed to commit entry group: " << avahi_strerror(ret) << std::endl;
avahi_simple_poll_quit(poll);
}
}
return;
}
void publisher::client_callback(AvahiClient *_client, AvahiClientState _state, void *userdata)
{
switch (_state)
{
case AVAHI_CLIENT_S_RUNNING:
create_services(_client);
break;
case AVAHI_CLIENT_FAILURE:
std::cerr << "Client failure: " << avahi_strerror(avahi_client_errno(_client)) << std::endl;
avahi_simple_poll_quit(poll);
break;
case AVAHI_CLIENT_S_COLLISION:
case AVAHI_CLIENT_S_REGISTERING:
if (group) avahi_entry_group_reset(group);
break;
case AVAHI_CLIENT_CONNECTING:
;
break;
}
}
void publisher::treat_collision(AvahiClient * _client)
{
char *n;
n = avahi_alternative_service_name(name);
avahi_free((void *)name);
name = n;
fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
avahi_entry_group_reset(group);
create_services(_client);
return;
}
void publisher::publish_avahi_service(const char *_service_name, const int _port_number, const char *_service_type)
{
name = _service_name;
port_number = _port_number;
service_type = _service_type;
poll = avahi_simple_poll_new();
if(poll){
int error;
AvahiClient *client = avahi_client_new(avahi_simple_poll_get(poll), static_cast<AvahiClientFlags>(0), client_callback, NULL, &error);
if(client){
avahi_simple_poll_loop(poll);
avahi_client_free(client);
} else {
std::cout << "FAILED TO CREATE AVAHI CLIENT OBJECT: " << avahi_strerror(error) << std::endl;
avahi_simple_poll_free(poll);
}
} else {
std::cout << "FAILED TO CREATE AVAHI SIMPLE POLL OBJECT: " << std::endl;
}
}
publisher::publisher(const std::string &service_name, const int &port_number, const std::string &service_type, std::vector<std::string> &message)
{
dns_message = avahi_string_list_new("version = V1.13", NULL);
for(auto i = 0; i < message.size(); i++)
dns_message = avahi_string_list_add(dns_message,std::string("message"+std::to_string(i)+"="+message.at(i)).c_str());
publish_avahi_service(service_name.c_str(), port_number, service_type.c_str());
}
publisher::~publisher()
{
avahi_simple_poll_free(poll);
}
#ifndef _PUBLISHER_H
#define _PUBLISHER_H
#include <iostream>
#include <string>
#include <vector>
#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>
namespace libpublisher
{
class publisher
{
private:
static void entry_group_callback(AvahiEntryGroup *_group, AvahiEntryGroupState _state, void *userdata);
static void create_services(AvahiClient *_client);
static void client_callback(AvahiClient *_client, AvahiClientState _state, void *userdata);
void treat_collision(AvahiClient *_client);
public:
void publish_avahi_service(const char *_service_name, const int _port_number, const char *_service_type);
publisher(const std::string &service_name, const int &port_number, const std::string &service_type, std::vector<std::string> & message);
~publisher();
};
}
#endif //_PUBLISHER_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment