~serge-hallyn/ubuntu/raring/libvirt/libvirt-virbr0

« back to all changes in this revision

Viewing changes to .pc/Don-t-fail-if-we-can-t-setup-avahi.patch/src/rpc/virnetserver.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-05-13 15:44:12 UTC
  • mfrom: (1.2.13)
  • Revision ID: package-import@ubuntu.com-20120513154412-fgmn5sxqdzgnzlx3
Tags: 0.9.12-0ubuntu1
* New upstream version:
  * Synchronize with debian packaging:
    - debian/control: Update build depends.
    - debian/libvirt-bin.postrm: Cleanup /var/log/libvirt
      on purge.
    - Bump standards verson (no changes).
    - debian/patches/Don-t-fail-if-we-can-t-setup-avahi.patch: Added
  * Dropped patches:
    - debian/patches/Debianize-libvirt-guests.patch
    - debian/patches/rewrite-lxc-controller-eof-handling-yet-again
    - debian/patches/ubuntu/libnl13.patch
    - debian/patches/ubuntu/fix-lxc-startup-error.patch
    - debian/patches/ubuntu/fix-bridge-fd.patch
    - debian/patches/ubuntu/skip-labelling-network-disks.patch
    - debian/patches/ubuntu/xen-xend-shutdown-detection.patch
    - debian/patches/ubuntu/xen-config-no-vfb-for-hvm.patch
    - debian/patches/debian/Disable-daemon-start-test.patch
    - debian/patches/debian/Disable-gnulib-s-test-nonplocking-pipe.sh.patch
    - debian/patches/ubuntu/9006-default-config-test-case.patch
    - debian/patches/fix-block-migration.patch
    - debian/patches/ubuntu/9022-qemu-unescape-HMP-commands-before-converting-them-to.patch
    - debian/patches/ubuntu/9023-qemu-change-rbd-auth_supported-separation-character-.patch
    - debian/patches/ubuntu/9024-qemu-allow-snapshotting-of-sheepdog-and-rbd-disks.patch
    - debian/patches/9025-qemu-change-rbd-auth_supported-separation-character-.patch
    - debian/patches/ubuntu/arm-gcc-workaround.patch
  * Rediffed:
    - debian/patches/Allow-libvirt-group-to-access-the-socket.patch
    - debian/patches/Disable-failing-virnetsockettest.patch
    - debian/patches/dnsmasq-as-priv-user
    - debian/patches/9002-better_default_uri_virsh.patch
  * debian/control: Add libnl-route-3-dev ass a build depends.
  * debian/patches/libnl3-build-fix.patch: Fix build with libnl3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * virnetserver.c: generic network RPC server
 
3
 *
 
4
 * Copyright (C) 2006-2012 Red Hat, Inc.
 
5
 * Copyright (C) 2006 Daniel P. Berrange
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 
20
 *
 
21
 * Author: Daniel P. Berrange <berrange@redhat.com>
 
22
 */
 
23
 
 
24
#include <config.h>
 
25
 
 
26
#include <unistd.h>
 
27
#include <string.h>
 
28
#include <fcntl.h>
 
29
 
 
30
#include "virnetserver.h"
 
31
#include "logging.h"
 
32
#include "memory.h"
 
33
#include "virterror_internal.h"
 
34
#include "threads.h"
 
35
#include "threadpool.h"
 
36
#include "util.h"
 
37
#include "virfile.h"
 
38
#include "event.h"
 
39
#if HAVE_AVAHI
 
40
# include "virnetservermdns.h"
 
41
#endif
 
42
 
 
43
#ifndef SA_SIGINFO
 
44
# define SA_SIGINFO 0
 
45
#endif
 
46
 
 
47
#define VIR_FROM_THIS VIR_FROM_RPC
 
48
#define virNetError(code, ...)                                    \
 
49
    virReportErrorHelper(VIR_FROM_THIS, code, __FILE__,           \
 
50
                         __FUNCTION__, __LINE__, __VA_ARGS__)
 
51
 
 
52
typedef struct _virNetServerSignal virNetServerSignal;
 
53
typedef virNetServerSignal *virNetServerSignalPtr;
 
54
 
 
55
struct _virNetServerSignal {
 
56
    struct sigaction oldaction;
 
57
    int signum;
 
58
    virNetServerSignalFunc func;
 
59
    void *opaque;
 
60
};
 
61
 
 
62
typedef struct _virNetServerJob virNetServerJob;
 
63
typedef virNetServerJob *virNetServerJobPtr;
 
64
 
 
65
struct _virNetServerJob {
 
66
    virNetServerClientPtr client;
 
67
    virNetMessagePtr msg;
 
68
    virNetServerProgramPtr prog;
 
69
};
 
70
 
 
71
struct _virNetServer {
 
72
    int refs;
 
73
 
 
74
    virMutex lock;
 
75
 
 
76
    virThreadPoolPtr workers;
 
77
 
 
78
    bool privileged;
 
79
 
 
80
    size_t nsignals;
 
81
    virNetServerSignalPtr *signals;
 
82
    int sigread;
 
83
    int sigwrite;
 
84
    int sigwatch;
 
85
 
 
86
    char *mdnsGroupName;
 
87
#if HAVE_AVAHI
 
88
    virNetServerMDNSPtr mdns;
 
89
    virNetServerMDNSGroupPtr mdnsGroup;
 
90
#endif
 
91
 
 
92
    size_t nservices;
 
93
    virNetServerServicePtr *services;
 
94
 
 
95
    size_t nprograms;
 
96
    virNetServerProgramPtr *programs;
 
97
 
 
98
    size_t nclients;
 
99
    size_t nclients_max;
 
100
    virNetServerClientPtr *clients;
 
101
 
 
102
    int keepaliveInterval;
 
103
    unsigned int keepaliveCount;
 
104
    bool keepaliveRequired;
 
105
 
 
106
    unsigned int quit :1;
 
107
 
 
108
    virNetTLSContextPtr tls;
 
109
 
 
110
    unsigned int autoShutdownTimeout;
 
111
    virNetServerAutoShutdownFunc autoShutdownFunc;
 
112
    void *autoShutdownOpaque;
 
113
 
 
114
    virNetServerClientInitHook clientInitHook;
 
115
};
 
116
 
 
117
 
 
118
static void virNetServerLock(virNetServerPtr srv)
 
119
{
 
120
    virMutexLock(&srv->lock);
 
121
}
 
122
 
 
123
static void virNetServerUnlock(virNetServerPtr srv)
 
124
{
 
125
    virMutexUnlock(&srv->lock);
 
126
}
 
127
 
 
128
 
 
129
static void virNetServerHandleJob(void *jobOpaque, void *opaque)
 
130
{
 
131
    virNetServerPtr srv = opaque;
 
132
    virNetServerJobPtr job = jobOpaque;
 
133
 
 
134
    VIR_DEBUG("server=%p client=%p message=%p prog=%p",
 
135
              srv, job->client, job->msg, job->prog);
 
136
 
 
137
    if (!job->prog) {
 
138
        /* Only send back an error for type == CALL. Other
 
139
         * message types are not expecting replies, so we
 
140
         * must just log it & drop them
 
141
         */
 
142
        if (job->msg->header.type == VIR_NET_CALL ||
 
143
            job->msg->header.type == VIR_NET_CALL_WITH_FDS) {
 
144
            if (virNetServerProgramUnknownError(job->client,
 
145
                                                job->msg,
 
146
                                                &job->msg->header) < 0)
 
147
                goto error;
 
148
        } else {
 
149
            VIR_INFO("Dropping client mesage, unknown program %d version %d type %d proc %d",
 
150
                     job->msg->header.prog, job->msg->header.vers,
 
151
                     job->msg->header.type, job->msg->header.proc);
 
152
            /* Send a dummy reply to free up 'msg' & unblock client rx */
 
153
            virNetMessageClear(job->msg);
 
154
            job->msg->header.type = VIR_NET_REPLY;
 
155
            if (virNetServerClientSendMessage(job->client, job->msg) < 0)
 
156
                goto error;
 
157
        }
 
158
        goto cleanup;
 
159
    }
 
160
 
 
161
    if (virNetServerProgramDispatch(job->prog,
 
162
                                    srv,
 
163
                                    job->client,
 
164
                                    job->msg) < 0)
 
165
        goto error;
 
166
 
 
167
    virNetServerLock(srv);
 
168
    virNetServerProgramFree(job->prog);
 
169
    virNetServerUnlock(srv);
 
170
 
 
171
cleanup:
 
172
    virNetServerClientFree(job->client);
 
173
    VIR_FREE(job);
 
174
    return;
 
175
 
 
176
error:
 
177
    virNetServerProgramFree(job->prog);
 
178
    virNetMessageFree(job->msg);
 
179
    virNetServerClientClose(job->client);
 
180
    virNetServerClientFree(job->client);
 
181
    VIR_FREE(job);
 
182
}
 
183
 
 
184
static int virNetServerDispatchNewMessage(virNetServerClientPtr client,
 
185
                                          virNetMessagePtr msg,
 
186
                                          void *opaque)
 
187
{
 
188
    virNetServerPtr srv = opaque;
 
189
    virNetServerJobPtr job;
 
190
    virNetServerProgramPtr prog = NULL;
 
191
    unsigned int priority = 0;
 
192
    size_t i;
 
193
    int ret = -1;
 
194
 
 
195
    VIR_DEBUG("server=%p client=%p message=%p",
 
196
              srv, client, msg);
 
197
 
 
198
    if (VIR_ALLOC(job) < 0) {
 
199
        virReportOOMError();
 
200
        return -1;
 
201
    }
 
202
 
 
203
    job->client = client;
 
204
    job->msg = msg;
 
205
 
 
206
    virNetServerLock(srv);
 
207
    for (i = 0 ; i < srv->nprograms ; i++) {
 
208
        if (virNetServerProgramMatches(srv->programs[i], job->msg)) {
 
209
            prog = srv->programs[i];
 
210
            break;
 
211
        }
 
212
    }
 
213
 
 
214
    if (prog) {
 
215
        virNetServerProgramRef(prog);
 
216
        job->prog = prog;
 
217
        priority = virNetServerProgramGetPriority(prog, msg->header.proc);
 
218
    }
 
219
 
 
220
    ret = virThreadPoolSendJob(srv->workers, priority, job);
 
221
 
 
222
    if (ret < 0) {
 
223
        VIR_FREE(job);
 
224
        virNetServerProgramFree(prog);
 
225
    }
 
226
    virNetServerUnlock(srv);
 
227
 
 
228
    return ret;
 
229
}
 
230
 
 
231
 
 
232
static int virNetServerDispatchNewClient(virNetServerServicePtr svc ATTRIBUTE_UNUSED,
 
233
                                         virNetServerClientPtr client,
 
234
                                         void *opaque)
 
235
{
 
236
    virNetServerPtr srv = opaque;
 
237
 
 
238
    virNetServerLock(srv);
 
239
 
 
240
    if (srv->nclients >= srv->nclients_max) {
 
241
        virNetError(VIR_ERR_RPC,
 
242
                    _("Too many active clients (%zu), dropping connection from %s"),
 
243
                    srv->nclients_max, virNetServerClientRemoteAddrString(client));
 
244
        goto error;
 
245
    }
 
246
 
 
247
    if (virNetServerClientInit(client) < 0)
 
248
        goto error;
 
249
 
 
250
    if (srv->clientInitHook &&
 
251
        srv->clientInitHook(srv, client) < 0)
 
252
        goto error;
 
253
 
 
254
    if (VIR_EXPAND_N(srv->clients, srv->nclients, 1) < 0) {
 
255
        virReportOOMError();
 
256
        goto error;
 
257
    }
 
258
    srv->clients[srv->nclients-1] = client;
 
259
    virNetServerClientRef(client);
 
260
 
 
261
    virNetServerClientSetDispatcher(client,
 
262
                                    virNetServerDispatchNewMessage,
 
263
                                    srv);
 
264
 
 
265
    virNetServerClientInitKeepAlive(client, srv->keepaliveInterval,
 
266
                                    srv->keepaliveCount);
 
267
 
 
268
    virNetServerUnlock(srv);
 
269
    return 0;
 
270
 
 
271
error:
 
272
    virNetServerUnlock(srv);
 
273
    return -1;
 
274
}
 
275
 
 
276
 
 
277
static void
 
278
virNetServerFatalSignal(int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED,
 
279
                        void *context ATTRIBUTE_UNUSED)
 
280
{
 
281
    struct sigaction sig_action;
 
282
    int origerrno;
 
283
 
 
284
    origerrno = errno;
 
285
    virLogEmergencyDumpAll(sig);
 
286
 
 
287
    /*
 
288
     * If the signal is fatal, avoid looping over this handler
 
289
     * by deactivating it
 
290
     */
 
291
#ifdef SIGUSR2
 
292
    if (sig != SIGUSR2) {
 
293
#endif
 
294
        memset(&sig_action, 0, sizeof(sig_action));
 
295
        sig_action.sa_handler = SIG_DFL;
 
296
        sigaction(sig, &sig_action, NULL);
 
297
        raise(sig);
 
298
#ifdef SIGUSR2
 
299
    }
 
300
#endif
 
301
    errno = origerrno;
 
302
}
 
303
 
 
304
 
 
305
virNetServerPtr virNetServerNew(size_t min_workers,
 
306
                                size_t max_workers,
 
307
                                size_t priority_workers,
 
308
                                size_t max_clients,
 
309
                                int keepaliveInterval,
 
310
                                unsigned int keepaliveCount,
 
311
                                bool keepaliveRequired,
 
312
                                const char *mdnsGroupName,
 
313
                                virNetServerClientInitHook clientInitHook)
 
314
{
 
315
    virNetServerPtr srv;
 
316
    struct sigaction sig_action;
 
317
 
 
318
    if (VIR_ALLOC(srv) < 0) {
 
319
        virReportOOMError();
 
320
        return NULL;
 
321
    }
 
322
 
 
323
    srv->refs = 1;
 
324
 
 
325
    if (!(srv->workers = virThreadPoolNew(min_workers, max_workers,
 
326
                                          priority_workers,
 
327
                                          virNetServerHandleJob,
 
328
                                          srv)))
 
329
        goto error;
 
330
 
 
331
    srv->nclients_max = max_clients;
 
332
    srv->keepaliveInterval = keepaliveInterval;
 
333
    srv->keepaliveCount = keepaliveCount;
 
334
    srv->keepaliveRequired = keepaliveRequired;
 
335
    srv->sigwrite = srv->sigread = -1;
 
336
    srv->clientInitHook = clientInitHook;
 
337
    srv->privileged = geteuid() == 0 ? true : false;
 
338
 
 
339
    if (mdnsGroupName &&
 
340
        !(srv->mdnsGroupName = strdup(mdnsGroupName))) {
 
341
        virReportOOMError();
 
342
        goto error;
 
343
    }
 
344
#if HAVE_AVAHI
 
345
    if (srv->mdnsGroupName) {
 
346
        if (!(srv->mdns = virNetServerMDNSNew()))
 
347
            goto error;
 
348
        if (!(srv->mdnsGroup = virNetServerMDNSAddGroup(srv->mdns,
 
349
                                                        srv->mdnsGroupName)))
 
350
            goto error;
 
351
    }
 
352
#endif
 
353
 
 
354
    if (virMutexInit(&srv->lock) < 0) {
 
355
        virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
 
356
                    _("cannot initialize mutex"));
 
357
        goto error;
 
358
    }
 
359
 
 
360
    if (virEventRegisterDefaultImpl() < 0)
 
361
        goto error;
 
362
 
 
363
    memset(&sig_action, 0, sizeof(sig_action));
 
364
    sig_action.sa_handler = SIG_IGN;
 
365
    sigaction(SIGPIPE, &sig_action, NULL);
 
366
 
 
367
    /*
 
368
     * catch fatal errors to dump a log, also hook to USR2 for dynamic
 
369
     * debugging purposes or testing
 
370
     */
 
371
    sig_action.sa_sigaction = virNetServerFatalSignal;
 
372
    sig_action.sa_flags = SA_SIGINFO;
 
373
    sigaction(SIGFPE, &sig_action, NULL);
 
374
    sigaction(SIGSEGV, &sig_action, NULL);
 
375
    sigaction(SIGILL, &sig_action, NULL);
 
376
    sigaction(SIGABRT, &sig_action, NULL);
 
377
#ifdef SIGBUS
 
378
    sigaction(SIGBUS, &sig_action, NULL);
 
379
#endif
 
380
#ifdef SIGUSR2
 
381
    sigaction(SIGUSR2, &sig_action, NULL);
 
382
#endif
 
383
 
 
384
    VIR_DEBUG("srv=%p refs=%d", srv, srv->refs);
 
385
    return srv;
 
386
 
 
387
error:
 
388
    virNetServerFree(srv);
 
389
    return NULL;
 
390
}
 
391
 
 
392
 
 
393
void virNetServerRef(virNetServerPtr srv)
 
394
{
 
395
    virNetServerLock(srv);
 
396
    srv->refs++;
 
397
    VIR_DEBUG("srv=%p refs=%d", srv, srv->refs);
 
398
    virNetServerUnlock(srv);
 
399
}
 
400
 
 
401
 
 
402
bool virNetServerIsPrivileged(virNetServerPtr srv)
 
403
{
 
404
    bool priv;
 
405
    virNetServerLock(srv);
 
406
    priv = srv->privileged;
 
407
    virNetServerUnlock(srv);
 
408
    return priv;
 
409
}
 
410
 
 
411
 
 
412
void virNetServerAutoShutdown(virNetServerPtr srv,
 
413
                              unsigned int timeout,
 
414
                              virNetServerAutoShutdownFunc func,
 
415
                              void *opaque)
 
416
{
 
417
    virNetServerLock(srv);
 
418
 
 
419
    srv->autoShutdownTimeout = timeout;
 
420
    srv->autoShutdownFunc = func;
 
421
    srv->autoShutdownOpaque = opaque;
 
422
 
 
423
    virNetServerUnlock(srv);
 
424
}
 
425
 
 
426
static sig_atomic_t sigErrors = 0;
 
427
static int sigLastErrno = 0;
 
428
static int sigWrite = -1;
 
429
 
 
430
static void
 
431
virNetServerSignalHandler(int sig, siginfo_t * siginfo,
 
432
                          void* context ATTRIBUTE_UNUSED)
 
433
{
 
434
    int origerrno;
 
435
    int r;
 
436
    siginfo_t tmp;
 
437
 
 
438
    if (SA_SIGINFO)
 
439
        tmp = *siginfo;
 
440
    else
 
441
        memset(&tmp, 0, sizeof(tmp));
 
442
 
 
443
    /* set the sig num in the struct */
 
444
    tmp.si_signo = sig;
 
445
 
 
446
    origerrno = errno;
 
447
    r = safewrite(sigWrite, &tmp, sizeof(tmp));
 
448
    if (r == -1) {
 
449
        sigErrors++;
 
450
        sigLastErrno = errno;
 
451
    }
 
452
    errno = origerrno;
 
453
}
 
454
 
 
455
static void
 
456
virNetServerSignalEvent(int watch,
 
457
                        int fd ATTRIBUTE_UNUSED,
 
458
                        int events ATTRIBUTE_UNUSED,
 
459
                        void *opaque) {
 
460
    virNetServerPtr srv = opaque;
 
461
    siginfo_t siginfo;
 
462
    int i;
 
463
 
 
464
    virNetServerLock(srv);
 
465
 
 
466
    if (saferead(srv->sigread, &siginfo, sizeof(siginfo)) != sizeof(siginfo)) {
 
467
        virReportSystemError(errno, "%s",
 
468
                             _("Failed to read from signal pipe"));
 
469
        virEventRemoveHandle(watch);
 
470
        srv->sigwatch = -1;
 
471
        goto cleanup;
 
472
    }
 
473
 
 
474
    for (i = 0 ; i < srv->nsignals ; i++) {
 
475
        if (siginfo.si_signo == srv->signals[i]->signum) {
 
476
            virNetServerSignalFunc func = srv->signals[i]->func;
 
477
            void *funcopaque = srv->signals[i]->opaque;
 
478
            virNetServerUnlock(srv);
 
479
            func(srv, &siginfo, funcopaque);
 
480
            return;
 
481
        }
 
482
    }
 
483
 
 
484
    virNetError(VIR_ERR_INTERNAL_ERROR,
 
485
                _("Unexpected signal received: %d"), siginfo.si_signo);
 
486
 
 
487
cleanup:
 
488
    virNetServerUnlock(srv);
 
489
}
 
490
 
 
491
static int virNetServerSignalSetup(virNetServerPtr srv)
 
492
{
 
493
    int fds[2] = { -1, -1 };
 
494
 
 
495
    if (srv->sigwrite != -1)
 
496
        return 0;
 
497
 
 
498
    if (pipe2(fds, O_CLOEXEC|O_NONBLOCK) < 0) {
 
499
        virReportSystemError(errno, "%s",
 
500
                             _("Unable to create signal pipe"));
 
501
        return -1;
 
502
    }
 
503
 
 
504
    if ((srv->sigwatch = virEventAddHandle(fds[0],
 
505
                                           VIR_EVENT_HANDLE_READABLE,
 
506
                                           virNetServerSignalEvent,
 
507
                                           srv, NULL)) < 0) {
 
508
        virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
 
509
                    _("Failed to add signal handle watch"));
 
510
        goto error;
 
511
    }
 
512
 
 
513
    srv->sigread = fds[0];
 
514
    srv->sigwrite = fds[1];
 
515
    sigWrite = fds[1];
 
516
 
 
517
    return 0;
 
518
 
 
519
error:
 
520
    VIR_FORCE_CLOSE(fds[0]);
 
521
    VIR_FORCE_CLOSE(fds[1]);
 
522
    return -1;
 
523
}
 
524
 
 
525
int virNetServerAddSignalHandler(virNetServerPtr srv,
 
526
                                 int signum,
 
527
                                 virNetServerSignalFunc func,
 
528
                                 void *opaque)
 
529
{
 
530
    virNetServerSignalPtr sigdata;
 
531
    struct sigaction sig_action;
 
532
 
 
533
    virNetServerLock(srv);
 
534
 
 
535
    if (virNetServerSignalSetup(srv) < 0)
 
536
        goto error;
 
537
 
 
538
    if (VIR_EXPAND_N(srv->signals, srv->nsignals, 1) < 0)
 
539
        goto no_memory;
 
540
 
 
541
    if (VIR_ALLOC(sigdata) < 0)
 
542
        goto no_memory;
 
543
 
 
544
    sigdata->signum = signum;
 
545
    sigdata->func = func;
 
546
    sigdata->opaque = opaque;
 
547
 
 
548
    memset(&sig_action, 0, sizeof(sig_action));
 
549
    sig_action.sa_sigaction = virNetServerSignalHandler;
 
550
    sig_action.sa_flags = SA_SIGINFO;
 
551
    sigemptyset(&sig_action.sa_mask);
 
552
 
 
553
    sigaction(signum, &sig_action, &sigdata->oldaction);
 
554
 
 
555
    srv->signals[srv->nsignals-1] = sigdata;
 
556
 
 
557
    virNetServerUnlock(srv);
 
558
    return 0;
 
559
 
 
560
no_memory:
 
561
    virReportOOMError();
 
562
error:
 
563
    VIR_FREE(sigdata);
 
564
    virNetServerUnlock(srv);
 
565
    return -1;
 
566
}
 
567
 
 
568
 
 
569
 
 
570
int virNetServerAddService(virNetServerPtr srv,
 
571
                           virNetServerServicePtr svc,
 
572
                           const char *mdnsEntryName ATTRIBUTE_UNUSED)
 
573
{
 
574
    virNetServerLock(srv);
 
575
 
 
576
    if (VIR_EXPAND_N(srv->services, srv->nservices, 1) < 0)
 
577
        goto no_memory;
 
578
 
 
579
#if HAVE_AVAHI
 
580
    if (mdnsEntryName) {
 
581
        int port = virNetServerServiceGetPort(svc);
 
582
 
 
583
        if (!virNetServerMDNSAddEntry(srv->mdnsGroup,
 
584
                                      mdnsEntryName,
 
585
                                      port))
 
586
            goto error;
 
587
    }
 
588
#endif
 
589
 
 
590
    srv->services[srv->nservices-1] = svc;
 
591
    virNetServerServiceRef(svc);
 
592
 
 
593
    virNetServerServiceSetDispatcher(svc,
 
594
                                     virNetServerDispatchNewClient,
 
595
                                     srv);
 
596
 
 
597
    virNetServerUnlock(srv);
 
598
    return 0;
 
599
 
 
600
no_memory:
 
601
    virReportOOMError();
 
602
#if HAVE_AVAHI
 
603
error:
 
604
#endif
 
605
    virNetServerUnlock(srv);
 
606
    return -1;
 
607
}
 
608
 
 
609
int virNetServerAddProgram(virNetServerPtr srv,
 
610
                           virNetServerProgramPtr prog)
 
611
{
 
612
    virNetServerLock(srv);
 
613
 
 
614
    if (VIR_EXPAND_N(srv->programs, srv->nprograms, 1) < 0)
 
615
        goto no_memory;
 
616
 
 
617
    srv->programs[srv->nprograms-1] = prog;
 
618
    virNetServerProgramRef(prog);
 
619
 
 
620
    virNetServerUnlock(srv);
 
621
    return 0;
 
622
 
 
623
no_memory:
 
624
    virReportOOMError();
 
625
    virNetServerUnlock(srv);
 
626
    return -1;
 
627
}
 
628
 
 
629
int virNetServerSetTLSContext(virNetServerPtr srv,
 
630
                              virNetTLSContextPtr tls)
 
631
{
 
632
    srv->tls = tls;
 
633
    virNetTLSContextRef(tls);
 
634
    return 0;
 
635
}
 
636
 
 
637
 
 
638
static void virNetServerAutoShutdownTimer(int timerid ATTRIBUTE_UNUSED,
 
639
                                          void *opaque) {
 
640
    virNetServerPtr srv = opaque;
 
641
 
 
642
    virNetServerLock(srv);
 
643
 
 
644
    if (srv->autoShutdownFunc(srv, srv->autoShutdownOpaque)) {
 
645
        VIR_DEBUG("Automatic shutdown triggered");
 
646
        srv->quit = 1;
 
647
    }
 
648
 
 
649
    virNetServerUnlock(srv);
 
650
}
 
651
 
 
652
 
 
653
void virNetServerUpdateServices(virNetServerPtr srv,
 
654
                                bool enabled)
 
655
{
 
656
    int i;
 
657
 
 
658
    virNetServerLock(srv);
 
659
    for (i = 0 ; i < srv->nservices ; i++)
 
660
        virNetServerServiceToggle(srv->services[i], enabled);
 
661
 
 
662
    virNetServerUnlock(srv);
 
663
}
 
664
 
 
665
 
 
666
void virNetServerRun(virNetServerPtr srv)
 
667
{
 
668
    int timerid = -1;
 
669
    int timerActive = 0;
 
670
    int i;
 
671
 
 
672
    virNetServerLock(srv);
 
673
 
 
674
#if HAVE_AVAHI
 
675
    if (srv->mdns &&
 
676
        virNetServerMDNSStart(srv->mdns) < 0)
 
677
        goto cleanup;
 
678
#endif
 
679
 
 
680
    if (srv->autoShutdownTimeout &&
 
681
        (timerid = virEventAddTimeout(-1,
 
682
                                      virNetServerAutoShutdownTimer,
 
683
                                      srv, NULL)) < 0) {
 
684
        virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
 
685
                    _("Failed to register shutdown timeout"));
 
686
        goto cleanup;
 
687
    }
 
688
 
 
689
    VIR_DEBUG("srv=%p quit=%d", srv, srv->quit);
 
690
    while (!srv->quit) {
 
691
        /* A shutdown timeout is specified, so check
 
692
         * if any drivers have active state, if not
 
693
         * shutdown after timeout seconds
 
694
         */
 
695
        if (srv->autoShutdownTimeout) {
 
696
            if (timerActive) {
 
697
                if (srv->clients) {
 
698
                    VIR_DEBUG("Deactivating shutdown timer %d", timerid);
 
699
                    virEventUpdateTimeout(timerid, -1);
 
700
                    timerActive = 0;
 
701
                }
 
702
            } else {
 
703
                if (!srv->clients) {
 
704
                    VIR_DEBUG("Activating shutdown timer %d", timerid);
 
705
                    virEventUpdateTimeout(timerid,
 
706
                                          srv->autoShutdownTimeout * 1000);
 
707
                    timerActive = 1;
 
708
                }
 
709
            }
 
710
        }
 
711
 
 
712
        virNetServerUnlock(srv);
 
713
        if (virEventRunDefaultImpl() < 0) {
 
714
            virNetServerLock(srv);
 
715
            VIR_DEBUG("Loop iteration error, exiting");
 
716
            break;
 
717
        }
 
718
        virNetServerLock(srv);
 
719
 
 
720
    reprocess:
 
721
        for (i = 0 ; i < srv->nclients ; i++) {
 
722
            /* Coverity 5.3.0 couldn't see that srv->clients is non-NULL
 
723
             * if srv->nclients is non-zero.  */
 
724
            sa_assert(srv->clients);
 
725
            if (virNetServerClientWantClose(srv->clients[i]))
 
726
                virNetServerClientClose(srv->clients[i]);
 
727
            if (virNetServerClientIsClosed(srv->clients[i])) {
 
728
                virNetServerClientFree(srv->clients[i]);
 
729
                if (srv->nclients > 1) {
 
730
                    memmove(srv->clients + i,
 
731
                            srv->clients + i + 1,
 
732
                            sizeof(*srv->clients) * (srv->nclients - (i + 1)));
 
733
                    VIR_SHRINK_N(srv->clients, srv->nclients, 1);
 
734
                } else {
 
735
                    VIR_FREE(srv->clients);
 
736
                    srv->nclients = 0;
 
737
                }
 
738
 
 
739
                goto reprocess;
 
740
            }
 
741
        }
 
742
    }
 
743
 
 
744
cleanup:
 
745
    virNetServerUnlock(srv);
 
746
}
 
747
 
 
748
 
 
749
void virNetServerQuit(virNetServerPtr srv)
 
750
{
 
751
    virNetServerLock(srv);
 
752
 
 
753
    VIR_DEBUG("Quit requested %p", srv);
 
754
    srv->quit = 1;
 
755
 
 
756
    virNetServerUnlock(srv);
 
757
}
 
758
 
 
759
void virNetServerFree(virNetServerPtr srv)
 
760
{
 
761
    int i;
 
762
 
 
763
    if (!srv)
 
764
        return;
 
765
 
 
766
    virNetServerLock(srv);
 
767
    VIR_DEBUG("srv=%p refs=%d", srv, srv->refs);
 
768
    srv->refs--;
 
769
    if (srv->refs > 0) {
 
770
        virNetServerUnlock(srv);
 
771
        return;
 
772
    }
 
773
 
 
774
    for (i = 0 ; i < srv->nservices ; i++)
 
775
        virNetServerServiceToggle(srv->services[i], false);
 
776
 
 
777
    virThreadPoolFree(srv->workers);
 
778
 
 
779
    for (i = 0 ; i < srv->nsignals ; i++) {
 
780
        sigaction(srv->signals[i]->signum, &srv->signals[i]->oldaction, NULL);
 
781
        VIR_FREE(srv->signals[i]);
 
782
    }
 
783
    VIR_FREE(srv->signals);
 
784
    VIR_FORCE_CLOSE(srv->sigread);
 
785
    VIR_FORCE_CLOSE(srv->sigwrite);
 
786
    if (srv->sigwatch > 0)
 
787
        virEventRemoveHandle(srv->sigwatch);
 
788
 
 
789
    for (i = 0 ; i < srv->nservices ; i++)
 
790
        virNetServerServiceFree(srv->services[i]);
 
791
    VIR_FREE(srv->services);
 
792
 
 
793
    for (i = 0 ; i < srv->nprograms ; i++)
 
794
        virNetServerProgramFree(srv->programs[i]);
 
795
    VIR_FREE(srv->programs);
 
796
 
 
797
    for (i = 0 ; i < srv->nclients ; i++) {
 
798
        virNetServerClientClose(srv->clients[i]);
 
799
        virNetServerClientFree(srv->clients[i]);
 
800
    }
 
801
    VIR_FREE(srv->clients);
 
802
 
 
803
    VIR_FREE(srv->mdnsGroupName);
 
804
#if HAVE_AVAHI
 
805
    virNetServerMDNSFree(srv->mdns);
 
806
#endif
 
807
 
 
808
    virNetServerUnlock(srv);
 
809
    virMutexDestroy(&srv->lock);
 
810
    VIR_FREE(srv);
 
811
}
 
812
 
 
813
void virNetServerClose(virNetServerPtr srv)
 
814
{
 
815
    int i;
 
816
 
 
817
    if (!srv)
 
818
        return;
 
819
 
 
820
    virNetServerLock(srv);
 
821
 
 
822
    for (i = 0; i < srv->nservices; i++) {
 
823
        virNetServerServiceClose(srv->services[i]);
 
824
    }
 
825
 
 
826
    virNetServerUnlock(srv);
 
827
}
 
828
 
 
829
bool virNetServerKeepAliveRequired(virNetServerPtr srv)
 
830
{
 
831
    bool required;
 
832
    virNetServerLock(srv);
 
833
    required = srv->keepaliveRequired;
 
834
    virNetServerUnlock(srv);
 
835
    return required;
 
836
}