1 /*** 2 This file is part of avahi. 3 4 avahi is free software; you can redistribute it and/or modify it 5 under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 2.1 of the 7 License, or (at your option) any later version. 8 9 avahi is distributed in the hope that it will be useful, but WITHOUT 10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General 12 Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with avahi; if not, write to the Free Software 16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 17 USA. 18 ***/ 19 20 #ifdef HAVE_CONFIG_H 21 #include <config.h> 22 #endif 23 24 #include <time.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <assert.h> 28 29 #include <avahi-core/core.h> 30 #include <avahi-core/publish.h> 31 #include <avahi-common/simple-watch.h> 32 #include "avahi-common/avahi-malloc.h" 33 #include <avahi-common/alternative.h> 34 #include <avahi-common/error.h> 35 36 static AvahiSEntryGroup *group = NULL; 37 static AvahiSimplePoll *simple_poll = NULL; 38 static char *name = NULL; 39 40 static void create_services(AvahiServer *s); 41 42 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) { 43 assert(s); 44 assert(g == group); 45 46 /* Called whenever the entry group state changes */ 47 48 switch (state) { 49 50 case AVAHI_ENTRY_GROUP_ESTABLISHED: 51 52 /* The entry group has been established successfully */ 53 fprintf(stderr, "Service '%s' successfully established.\n", name); 54 break; 55 56 case AVAHI_ENTRY_GROUP_COLLISION: { 57 char *n; 58 59 /* A service name collision happened. Let's pick a new name */ 60 n = avahi_alternative_service_name(name); 61 avahi_free(name); 62 name = n; 63 64 fprintf(stderr, "Service name collision, renaming service to '%s'\n", name); 65 66 /* And recreate the services */ 67 create_services(s); 68 break; 69 } 70 71 case AVAHI_ENTRY_GROUP_FAILURE : 72 73 fprintf(stderr, "Entry group failure: %s\n", avahi_strerror(avahi_server_errno(s))); 74 75 /* Some kind of failure happened while we were registering our services */ 76 avahi_simple_poll_quit(simple_poll); 77 break; 78 79 case AVAHI_ENTRY_GROUP_UNCOMMITED: 80 case AVAHI_ENTRY_GROUP_REGISTERING: 81 ; 82 } 83 } 84 85 static void create_services(AvahiServer *s) { 86 char r[128]; 87 int ret; 88 assert(s); 89 90 /* If this is the first time we're called, let's create a new entry group */ 91 if (!group) 92 if (!(group = avahi_s_entry_group_new(s, entry_group_callback, NULL))) { 93 fprintf(stderr, "avahi_entry_group_new() failed: %s\n", avahi_strerror(avahi_server_errno(s))); 94 goto fail; 95 } 96 97 fprintf(stderr, "Adding service '%s'\n", name); 98 99 /* Create some random TXT data */ 100 snprintf(r, sizeof(r), "random=%i", rand()); 101 102 /* Add the service for IPP */ 103 if ((ret = avahi_server_add_service(s, group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, "_ipp._tcp", NULL, NULL, 651, "test=blah", r, NULL)) < 0) { 104 fprintf(stderr, "Failed to add _ipp._tcp service: %s\n", avahi_strerror(ret)); 105 goto fail; 106 } 107 108 /* Add the same service for BSD LPR */ 109 if ((ret = avahi_server_add_service(s, group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, "_printer._tcp", NULL, NULL, 515, NULL)) < 0) { 110 fprintf(stderr, "Failed to add _printer._tcp service: %s\n", avahi_strerror(ret)); 111 goto fail; 112 } 113 114 /* Add an additional (hypothetic) subtype */ 115 if ((ret = avahi_server_add_service_subtype(s, group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, "_printer._tcp", NULL, "_magic._sub._printer._tcp") < 0)) { 116 fprintf(stderr, "Failed to add subtype _magic._sub._printer._tcp: %s\n", avahi_strerror(ret)); 117 goto fail; 118 } 119 120 /* Tell the server to register the service */ 121 if ((ret = avahi_s_entry_group_commit(group)) < 0) { 122 fprintf(stderr, "Failed to commit entry_group: %s\n", avahi_strerror(ret)); 123 goto fail; 124 } 125 126 return; 127 128 fail: 129 avahi_simple_poll_quit(simple_poll); 130 } 131 132 static void server_callback(AvahiServer *s, AvahiServerState state, AVAHI_GCC_UNUSED void * userdata) { 133 assert(s); 134 135 /* Called whenever the server state changes */ 136 137 switch (state) { 138 139 case AVAHI_SERVER_RUNNING: 140 /* The serve has startup successfully and registered its host 141 * name on the network, so it's time to create our services */ 142 143 if (!group) 144 create_services(s); 145 146 break; 147 148 case AVAHI_SERVER_COLLISION: { 149 char *n; 150 int r; 151 152 /* A host name collision happened. Let's pick a new name for the server */ 153 n = avahi_alternative_host_name(avahi_server_get_host_name(s)); 154 fprintf(stderr, "Host name collision, retrying with '%s'\n", n); 155 r = avahi_server_set_host_name(s, n); 156 avahi_free(n); 157 158 if (r < 0) { 159 fprintf(stderr, "Failed to set new host name: %s\n", avahi_strerror(r)); 160 161 avahi_simple_poll_quit(simple_poll); 162 return; 163 } 164 165 } 166 167 /* Fall through */ 168 169 case AVAHI_SERVER_REGISTERING: 170 171 /* Let's drop our registered services. When the server is back 172 * in AVAHI_SERVER_RUNNING state we will register them 173 * again with the new host name. */ 174 if (group) 175 avahi_s_entry_group_reset(group); 176 177 break; 178 179 case AVAHI_SERVER_FAILURE: 180 181 /* Terminate on failure */ 182 183 fprintf(stderr, "Server failure: %s\n", avahi_strerror(avahi_server_errno(s))); 184 avahi_simple_poll_quit(simple_poll); 185 break; 186 187 case AVAHI_SERVER_INVALID: 188 ; 189 } 190 } 191 192 int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) { 193 AvahiServerConfig config; 194 AvahiServer *server = NULL; 195 int error; 196 int ret = 1; 197 198 /* Initialize the pseudo-RNG */ 199 srand(time(NULL)); 200 201 /* Allocate main loop object */ 202 if (!(simple_poll = avahi_simple_poll_new())) { 203 fprintf(stderr, "Failed to create simple poll object.\n"); 204 goto fail; 205 } 206 207 name = avahi_strdup("MegaPrinter"); 208 209 /* Let's set the host name for this server. */ 210 avahi_server_config_init(&config); 211 config.host_name = avahi_strdup("gurkiman"); 212 config.publish_workstation = 0; 213 214 /* Allocate a new server */ 215 server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, server_callback, NULL, &error); 216 217 /* Free the configuration data */ 218 avahi_server_config_free(&config); 219 220 /* Check wether creating the server object succeeded */ 221 if (!server) { 222 fprintf(stderr, "Failed to create server: %s\n", avahi_strerror(error)); 223 goto fail; 224 } 225 226 /* Run the main loop */ 227 avahi_simple_poll_loop(simple_poll); 228 229 ret = 0; 230 231 fail: 232 233 /* Cleanup things */ 234 235 if (server) 236 avahi_server_free(server); 237 238 if (simple_poll) 239 avahi_simple_poll_free(simple_poll); 240 241 avahi_free(name); 242 243 return ret; 244 } 245