Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / gdp / gdp_zc_server.c @ master

History | View | Annotate | Download (6.84 KB)

1
/* vim: set ai sw=4 sts=4 ts=4 :*/
2

    
3
/*
4
**  ----- BEGIN LICENSE BLOCK -----
5
**        GDP: Global Data Plane Support Library
6
**        From the Ubiquitous Swarm Lab, 490 Cory Hall, U.C. Berkeley.
7
**
8
**        Copyright (c) 2015-2019, Regents of the University of California.
9
**        All rights reserved.
10
**
11
**        Permission is hereby granted, without written agreement and without
12
**        license or royalty fees, to use, copy, modify, and distribute this
13
**        software and its documentation for any purpose, provided that the above
14
**        copyright notice and the following two paragraphs appear in all copies
15
**        of this software.
16
**
17
**        IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
18
**        SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
19
**        PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
20
**        EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
**
22
**        REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
23
**        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24
**        FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
25
**        IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO
26
**        OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
27
**        OR MODIFICATIONS.
28
**  ----- END LICENSE BLOCK -----
29
*/
30

    
31
#include "gdp_zc_server.h"
32

    
33
#if GDP_OSCF_USE_ZEROCONF
34

    
35
#include <ep/ep_assert.h>
36

    
37
#include <time.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40

    
41

    
42
static AvahiEntryGroup *AGroup = NULL;
43
static AvahiSimplePoll *SimplePoll = NULL;
44
static char *SName = NULL;
45
static uint16_t SPort = 0;
46

    
47
static void create_services(AvahiClient *c);
48

    
49
static void
50
entry_group_callback(AvahiEntryGroup *g,
51
                AvahiEntryGroupState state,
52
                AVAHI_GCC_UNUSED void *userdata)
53
{
54
        assert(g == AGroup || AGroup == NULL);
55
        AGroup = g;
56

    
57
        /* Called whenever the entry group state changes */
58

    
59
        switch (state)
60
        {
61
                case AVAHI_ENTRY_GROUP_ESTABLISHED:
62
                        /* The entry group has been established successfully */
63
                        fprintf(stderr,
64
                                        "Service '%s' successfully established.\n",
65
                                        SName);
66
                        break;
67

    
68
                case AVAHI_ENTRY_GROUP_COLLISION:
69
                {
70
                        char *n;
71

    
72
                        /* A service name collision with a remote service
73
                         * happened. Let's pick a new name */
74
                        n = avahi_alternative_service_name(SName);
75
                        avahi_free(SName);
76
                        SName = n;
77

    
78
                        fprintf(stderr,
79
                                        "Service name collision, renaming service to '%s'\n",
80
                                        SName);
81

    
82
                        /* And recreate the services */
83
                        create_services(avahi_entry_group_get_client(g));
84
                        break;
85
                }
86

    
87
                case AVAHI_ENTRY_GROUP_FAILURE:
88
                        fprintf(stderr,
89
                                        "Entry group failure: %s\n",
90
                                        avahi_strerror
91
                                        (
92
                                         avahi_client_errno( avahi_entry_group_get_client(g))
93
                                        ));
94

    
95
                        /* Some kind of failure happened while we were registering our services */
96
                        avahi_simple_poll_quit(SimplePoll);
97
                        break;
98

    
99
                case AVAHI_ENTRY_GROUP_UNCOMMITED:
100
                case AVAHI_ENTRY_GROUP_REGISTERING:
101
                        break;
102

    
103
                default:
104
                        EP_ASSERT_FAILURE("Unknown state %d", state);
105
        }
106
}
107

    
108
static void
109
create_services(AvahiClient *c)
110
{
111
        char *n, r[128];
112
        int ret;
113
        assert(c);
114

    
115
        /* If this is the first time we're called, let's create a new
116
         * entry group if necessary */
117

    
118
        if (!AGroup)
119
        {
120
                if (!(AGroup = avahi_entry_group_new(c, entry_group_callback, NULL)))
121
                {
122
                        fprintf(stderr,
123
                                        "avahi_entry_group_new() failed: %s\n",
124
                                        avahi_strerror(avahi_client_errno(c)));
125
                        goto fail;
126
                }
127
        }
128

    
129
        /* If the group is empty (either because it was just created, or
130
         * because it was reset previously, add our entries.  */
131

    
132
        if (avahi_entry_group_is_empty(AGroup))
133
        {
134
                fprintf(stderr, "Adding service '%s'\n", SName);
135

    
136
                /* Create some random TXT data */
137
                snprintf(r, sizeof(r), "random=%i", rand());
138

    
139
                if ((ret = avahi_entry_group_add_service(
140
                                                AGroup,                                        // group
141
                                                AVAHI_IF_UNSPEC,                // interface
142
                                                AVAHI_PROTO_UNSPEC,                // protocol
143
                                                (AvahiPublishFlags) 0,        // flags
144
                                                SName,                                        // service name
145
                                                "_gdp._tcp",                        // service type
146
                                                NULL,                                        // domain
147
                                                NULL,                                        // host
148
                                                SPort,                                        // port number
149
                                                r,                                                // TXT entry
150
                                                NULL)                                        // end of vararg TXT list
151
                                        ) < 0)
152
                {
153
                        if (ret == AVAHI_ERR_COLLISION)
154
                                goto collision;
155

    
156
                        fprintf(stderr,
157
                                        "Failed to add _gdp._tcp service: %s\n",
158
                                        avahi_strerror(ret));
159
                        goto fail;
160
                }
161

    
162
                /* Tell the server to register the service */
163
                if ((ret = avahi_entry_group_commit(AGroup)) < 0)
164
                {
165
                        fprintf(stderr,
166
                                        "Failed to commit entry group: %s\n",
167
                                        avahi_strerror(ret));
168
                        goto fail;
169
                }
170
        }
171

    
172
        return;
173

    
174
collision:
175

    
176
        /* A service name collision with a local service happened. Let's
177
         * pick a new name */
178
        n = avahi_alternative_service_name(SName);
179
        avahi_free(SName);
180
        SName = n;
181

    
182
        fprintf(stderr,
183
                        "Service name collision, renaming service to '%s'\n",
184
                        SName);
185

    
186
        avahi_entry_group_reset(AGroup);
187

    
188
        create_services(c);
189
        return;
190

    
191
fail:
192
        avahi_simple_poll_quit(SimplePoll);
193
}
194

    
195
static void
196
client_callback(AvahiClient *c,
197
                AvahiClientState state,
198
                AVAHI_GCC_UNUSED void * userdata)
199
{
200
        assert(c);
201

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

    
204
        switch (state)
205
        {
206
                case AVAHI_CLIENT_S_RUNNING:
207
                        /* The server has startup successfully and registered its host
208
                         * name on the network, so it's time to create our services */
209
                        create_services(c);
210
                        break;
211

    
212
                case AVAHI_CLIENT_FAILURE:
213
                        fprintf(stderr,
214
                                        "Client failure: %s\n",
215
                                        avahi_strerror(avahi_client_errno(c)));
216
                        avahi_simple_poll_quit(SimplePoll);
217
                        break;
218

    
219
                case AVAHI_CLIENT_S_COLLISION:
220
                        /* Let's drop our registered services. When the server is back
221
                         * in AVAHI_SERVER_RUNNING state we will register them
222
                         * again with the new host name. */
223

    
224
                case AVAHI_CLIENT_S_REGISTERING:
225
                        /* The server records are now being established. This
226
                         * might be caused by a host name change. We need to wait
227
                         * for our own records to register until the host name is
228
                         * properly esatblished. */
229
                        if (AGroup)
230
                                avahi_entry_group_reset(AGroup);
231
                        break;
232

    
233
                case AVAHI_CLIENT_CONNECTING:
234
                        break;
235

    
236
                default:
237
                        EP_ASSERT_FAILURE("Unknown state %d", state);
238
        }
239
}
240

    
241
int
242
gdp_zc_publish(const char *instance, uint16_t port_no)
243
{
244
        AvahiClient *client = NULL;
245
        int error;
246
        int ret = 1;
247

    
248
        /* Allocate main loop object */
249
        if (!(SimplePoll = avahi_simple_poll_new()))
250
        {
251
                fprintf(stderr, "Failed to create simple poll object.\n");
252
                goto fail;
253
        }
254

    
255
        SName = avahi_strdup(instance);
256
        SPort = port_no;
257

    
258
        /* Allocate a new client */
259
        client = avahi_client_new(avahi_simple_poll_get(SimplePoll),
260
                        (AvahiClientFlags) 0, client_callback, NULL, &error);
261

    
262
        /* Check whether creating the client object succeeded */
263
        if (!client)
264
        {
265
                fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
266
                goto fail;
267
        }
268

    
269
        /* Run the main loop */
270
        avahi_simple_poll_loop(SimplePoll);
271

    
272
        ret = 0;
273

    
274
fail:
275

    
276
        /* Cleanup things */
277

    
278
        if (client)
279
                avahi_client_free(client);
280

    
281
        if (SimplePoll)
282
                avahi_simple_poll_free(SimplePoll);
283

    
284
        avahi_free(SName);
285

    
286
        return ret;
287
}
288

    
289
int gdp_zc_shutdown()
290
{
291
        return 0;
292
}
293

    
294
#endif // GDP_OSCF_USE_ZEROCONF
295

    
296
/* vim: set noexpandtab : */