official_publish_example.cpp
Go to the documentation of this file.
00001 
00012 /*****************************************************************************
00013 ** Includes
00014 *****************************************************************************/
00015 
00016 #ifdef HAVE_CONFIG_H
00017 #include <config.h>
00018 #endif
00019 
00020 #include <iostream>
00021 #include <time.h>
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <assert.h>
00025 
00026 #include <avahi-client/client.h>
00027 #include <avahi-client/publish.h>
00028 
00029 #include <avahi-common/alternative.h>
00030 #include <avahi-common/simple-watch.h>
00031 #include <avahi-common/malloc.h>
00032 #include <avahi-common/error.h>
00033 #include <avahi-common/timeval.h>
00034 
00035 static AvahiEntryGroup *group = NULL;
00036 static AvahiSimplePoll *simple_poll = NULL;
00037 static char *name = NULL;
00038 
00039 static void create_services(AvahiClient *c);
00040 
00041 static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) {
00042     assert(g == group || group == NULL);
00043     group = g;
00044 
00045     /* Called whenever the entry group state changes */
00046 
00047     switch (state) {
00048         case AVAHI_ENTRY_GROUP_ESTABLISHED :
00049                 std::cout << "Entry group established" << std::endl;
00050             /* The entry group has been established successfully */
00051             fprintf(stderr, "Service '%s' successfully established.\n", name);
00052             break;
00053 
00054         case AVAHI_ENTRY_GROUP_COLLISION : {
00055             char *n;
00056                 std::cout << "Entry group collision" << std::endl;
00057 
00058             /* A service name collision with a remote service
00059              * happened. Let's pick a new name */
00060             n = avahi_alternative_service_name(name);
00061             avahi_free(name);
00062             name = n;
00063 
00064             fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
00065 
00066             /* And recreate the services */
00067             create_services(avahi_entry_group_get_client(g));
00068             break;
00069         }
00070 
00071         case AVAHI_ENTRY_GROUP_FAILURE :
00072 
00073                 std::cout << "Entry group failure" << std::endl;
00074             fprintf(stderr, "Entry group failure: %s\n", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
00075 
00076             /* Some kind of failure happened while we were registering our services */
00077             avahi_simple_poll_quit(simple_poll);
00078             break;
00079 
00080         case AVAHI_ENTRY_GROUP_UNCOMMITED:
00081                 std::cout << "Entry group uncommitted" << std::endl;
00082                 break;
00083         case AVAHI_ENTRY_GROUP_REGISTERING:
00084                 std::cout << "Entry group registering" << std::endl;
00085             break;
00086     }
00087 }
00088 
00089 static void create_services(AvahiClient *c) {
00090     char *n, r[128];
00091     int ret;
00092     assert(c);
00093 
00094     /* If this is the first time we're called, let's create a new
00095      * entry group if necessary */
00096 
00097     if (!group)
00098         if (!(group = avahi_entry_group_new(c, entry_group_callback, NULL))) {
00099             fprintf(stderr, "avahi_entry_group_new() failed: %s\n", avahi_strerror(avahi_client_errno(c)));
00100             goto fail;
00101         }
00102 
00103     /* If the group is empty (either because it was just created, or
00104      * because it was reset previously, add our entries.  */
00105 
00106     if (avahi_entry_group_is_empty(group)) {
00107         fprintf(stderr, "Adding service '%s'\n", name);
00108 
00109         /* Create some random TXT data */
00110         snprintf(r, sizeof(r), "random=%i", rand());
00111 
00112         /* We will now add two services and one subtype to the entry
00113          * group. The two services have the same name, but differ in
00114          * the service type (IPP vs. BSD LPR). Only services with the
00115          * same name should be put in the same entry group. */
00116 
00117         /* Add the service for IPP */
00118         if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, static_cast<AvahiPublishFlags>(0), name, "_ipp._tcp", NULL, NULL, 651, "test=blah", r, NULL)) < 0) {
00119 
00120             if (ret == AVAHI_ERR_COLLISION)
00121                 goto collision;
00122 
00123             fprintf(stderr, "Failed to add _ipp._tcp service: %s\n", avahi_strerror(ret));
00124             goto fail;
00125         }
00126 
00127         /* Add the same service for BSD LPR */
00128         if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, static_cast<AvahiPublishFlags>(0), name, "_printer._tcp", NULL, NULL, 515, NULL)) < 0) {
00129 
00130             if (ret == AVAHI_ERR_COLLISION)
00131                 goto collision;
00132 
00133             fprintf(stderr, "Failed to add _printer._tcp service: %s\n", avahi_strerror(ret));
00134             goto fail;
00135         }
00136 
00137         /* Add an additional (hypothetic) subtype */
00138         if ((ret = avahi_entry_group_add_service_subtype(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, static_cast<AvahiPublishFlags>(0), name, "_printer._tcp", NULL, "_magic._sub._printer._tcp") < 0)) {
00139             fprintf(stderr, "Failed to add subtype _magic._sub._printer._tcp: %s\n", avahi_strerror(ret));
00140             goto fail;
00141         }
00142 
00143         /* Tell the server to register the service */
00144         if ((ret = avahi_entry_group_commit(group)) < 0) {
00145             fprintf(stderr, "Failed to commit entry group: %s\n", avahi_strerror(ret));
00146             goto fail;
00147         }
00148     }
00149 
00150     return;
00151 
00152 collision:
00153 
00154     /* A service name collision with a local service happened. Let's
00155      * pick a new name */
00156     n = avahi_alternative_service_name(name);
00157     avahi_free(name);
00158     name = n;
00159 
00160     fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
00161 
00162     avahi_entry_group_reset(group);
00163 
00164     create_services(c);
00165     return;
00166 
00167 fail:
00168     avahi_simple_poll_quit(simple_poll);
00169 }
00170 
00171 static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
00172     assert(c);
00173 
00174     /* Called whenever the client or server state changes */
00175 
00176     switch (state) {
00177         case AVAHI_CLIENT_S_RUNNING:
00178 
00179             /* The server has startup successfully and registered its host
00180              * name on the network, so it's time to create our services */
00181             create_services(c);
00182             break;
00183 
00184         case AVAHI_CLIENT_FAILURE:
00185 
00186             fprintf(stderr, "Client failure: %s\n", avahi_strerror(avahi_client_errno(c)));
00187             avahi_simple_poll_quit(simple_poll);
00188 
00189             break;
00190 
00191         case AVAHI_CLIENT_S_COLLISION:
00192 
00193             /* Let's drop our registered services. When the server is back
00194              * in AVAHI_SERVER_RUNNING state we will register them
00195              * again with the new host name. */
00196 
00197         case AVAHI_CLIENT_S_REGISTERING:
00198             /* The server records are now being established. This
00199              * might be caused by a host name change. We need to wait
00200              * for our own records to register until the host name is
00201              * properly esatblished. */
00202 
00203             if (group)
00204                 avahi_entry_group_reset(group);
00205 
00206             break;
00207 
00208         case AVAHI_CLIENT_CONNECTING:
00209             ;
00210     }
00211 }
00212 
00213 static void modify_callback(AVAHI_GCC_UNUSED AvahiTimeout *e, void *userdata) {
00214     AvahiClient *client = static_cast<AvahiClient*>(userdata);
00215 
00216     fprintf(stderr, "Doing some weird modification\n");
00217 
00218     avahi_free(name);
00219     name = avahi_strdup("Modified MegaPrinter");
00220 
00221     /* If the server is currently running, we need to remove our
00222      * service and create it anew */
00223     if (avahi_client_get_state(client) == AVAHI_CLIENT_S_RUNNING) {
00224 
00225         /* Remove the old services */
00226         if (group)
00227             avahi_entry_group_reset(group);
00228 
00229         /* And create them again with the new name */
00230         create_services(client);
00231     }
00232 }
00233 
00234 /*****************************************************************************
00235 ** Main
00236 *****************************************************************************/
00237 
00238 int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char **argv) {
00239 
00240     AvahiClient *client = NULL;
00241     int error;
00242     int ret = 1;
00243     struct timeval tv;
00244 
00245     /* Allocate main loop object */
00246     if (!(simple_poll = avahi_simple_poll_new())) {
00247         fprintf(stderr, "Failed to create simple poll object.\n");
00248         goto fail;
00249     }
00250 
00251     name = avahi_strdup("MegaPrinter");
00252 
00253     /* Allocate a new client */
00254     client = avahi_client_new(avahi_simple_poll_get(simple_poll), static_cast<AvahiClientFlags>(0), client_callback, NULL, &error);
00255 
00256     /* Check wether creating the client object succeeded */
00257     if (!client) {
00258         fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
00259         goto fail;
00260     }
00261 
00262     /* After 10s do some weird modification to the service */
00263     avahi_simple_poll_get(simple_poll)->timeout_new(
00264         avahi_simple_poll_get(simple_poll),
00265         avahi_elapse_time(&tv, 1000*10, 0),
00266         modify_callback,
00267         client);
00268 
00269     /* Run the main loop */
00270     avahi_simple_poll_loop(simple_poll);
00271 
00272     ret = 0;
00273 
00274 fail:
00275 
00276     /* Cleanup things */
00277 
00278     if (client)
00279         avahi_client_free(client);
00280 
00281     if (simple_poll)
00282         avahi_simple_poll_free(simple_poll);
00283 
00284     avahi_free(name);
00285 
00286     return ret;
00287 }


zeroconf_avahi_demos
Author(s): Daniel Stonier
autogenerated on Mon Oct 6 2014 09:12:39