virNetServerServicePtr virNetServerServiceNewUNIX(const char *path, mode_t mask, gid_t grp, int auth, bool readonly, size_t nrequests_client_max, virNetTLSContextPtr tls) { virNetServerServicePtr svc; int i; if (VIR_ALLOC(svc) < 0) goto no_memory; svc->refs = 1; svc->auth = auth; svc->readonly = readonly; svc->nrequests_client_max = nrequests_client_max; svc->tls = tls; if (tls) virNetTLSContextRef(tls); svc->nsocks = 1; if (VIR_ALLOC_N(svc->socks, svc->nsocks) < 0) goto no_memory; if (virNetSocketNewListenUNIX(path, mask, -1, grp, &svc->socks[0]) < 0) goto error; for (i = 0 ; i < svc->nsocks ; i++) { if (virNetSocketListen(svc->socks[i], 0) < 0) goto error; /* IO callback is initially disabled, until we're ready * to deal with incoming clients */ virNetServerServiceRef(svc); if (virNetSocketAddIOCallback(svc->socks[i], 0, virNetServerServiceAccept, svc, virNetServerServiceEventFree) < 0) { virNetServerServiceFree(svc); goto error; } } return svc; no_memory: virReportOOMError(); error: virNetServerServiceFree(svc); return NULL; }
static virNetClientPtr virNetClientNew(virNetSocketPtr sock, const char *hostname) { virNetClientPtr client = NULL; int wakeupFD[2] = { -1, -1 }; if (pipe2(wakeupFD, O_CLOEXEC) < 0) { virReportSystemError(errno, "%s", _("unable to make pipe")); goto error; } if (VIR_ALLOC(client) < 0) goto no_memory; client->refs = 1; if (virMutexInit(&client->lock) < 0) goto error; client->sock = sock; client->wakeupReadFD = wakeupFD[0]; client->wakeupSendFD = wakeupFD[1]; wakeupFD[0] = wakeupFD[1] = -1; if (hostname && !(client->hostname = strdup(hostname))) goto no_memory; /* Set up a callback to listen on the socket data */ client->refs++; if (virNetSocketAddIOCallback(client->sock, VIR_EVENT_HANDLE_READABLE, virNetClientIncomingEvent, client, virNetClientEventFree) < 0) { client->refs--; VIR_DEBUG("Failed to add event watch, disabling events"); } PROBE(RPC_CLIENT_NEW, "client=%p refs=%d sock=%p", client, client->refs, client->sock); return client; no_memory: virReportOOMError(); error: VIR_FORCE_CLOSE(wakeupFD[0]); VIR_FORCE_CLOSE(wakeupFD[1]); virNetClientFree(client); return NULL; }
virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename, const char *service, int auth, bool readonly, size_t nrequests_client_max, virNetTLSContextPtr tls) { virNetServerServicePtr svc; size_t i; if (virNetServerServiceInitialize() < 0) return NULL; if (!(svc = virObjectNew(virNetServerServiceClass))) return NULL; svc->auth = auth; svc->readonly = readonly; svc->nrequests_client_max = nrequests_client_max; svc->tls = virObjectRef(tls); if (virNetSocketNewListenTCP(nodename, service, &svc->socks, &svc->nsocks) < 0) goto error; for (i = 0 ; i < svc->nsocks ; i++) { if (virNetSocketListen(svc->socks[i], 0) < 0) goto error; /* IO callback is initially disabled, until we're ready * to deal with incoming clients */ virObjectRef(svc); if (virNetSocketAddIOCallback(svc->socks[i], 0, virNetServerServiceAccept, svc, virObjectFreeCallback) < 0) { virObjectUnref(svc); goto error; } } return svc; error: virObjectUnref(svc); return NULL; }
virNetServerServicePtr virNetServerServiceNewFD(int fd, int auth, bool readonly, size_t nrequests_client_max, virNetTLSContextPtr tls) { virNetServerServicePtr svc; int i; if (virNetServerServiceInitialize() < 0) return NULL; if (!(svc = virObjectNew(virNetServerServiceClass))) return NULL; svc->auth = auth; svc->readonly = readonly; svc->nrequests_client_max = nrequests_client_max; svc->tls = virObjectRef(tls); svc->nsocks = 1; if (VIR_ALLOC_N(svc->socks, svc->nsocks) < 0) goto no_memory; if (virNetSocketNewListenFD(fd, &svc->socks[0]) < 0) goto error; for (i = 0 ; i < svc->nsocks ; i++) { /* IO callback is initially disabled, until we're ready * to deal with incoming clients */ if (virNetSocketAddIOCallback(svc->socks[i], 0, virNetServerServiceAccept, svc, virObjectFreeCallback) < 0) goto error; } return svc; no_memory: virReportOOMError(); error: virObjectUnref(svc); return NULL; }
/* * @server: a locked or unlocked server object * @client: a locked client object */ static int virNetServerClientRegisterEvent(virNetServerClientPtr client) { int mode = virNetServerClientCalculateHandleMode(client); if (!client->sock) return -1; virObjectRef(client); VIR_DEBUG("Registering client event callback %d", mode); if (virNetSocketAddIOCallback(client->sock, mode, virNetServerClientDispatchEvent, client, virObjectFreeCallback) < 0) { virObjectUnref(client); return -1; } return 0; }
int libxlDomainMigrationPrepare(virConnectPtr dconn, virDomainDefPtr def, const char *uri_in, char **uri_out, unsigned int flags) { libxlDriverPrivatePtr driver = dconn->privateData; virDomainObjPtr vm = NULL; char *hostname = NULL; unsigned short port; char portstr[100]; virURIPtr uri = NULL; virNetSocketPtr *socks = NULL; size_t nsocks = 0; int nsocks_listen = 0; libxlMigrationDstArgs *args; size_t i; int ret = -1; if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, VIR_DOMAIN_OBJ_LIST_ADD_LIVE | VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE, NULL))) goto cleanup; /* Create socket connection to receive migration data */ if (!uri_in) { if ((hostname = virGetHostname()) == NULL) goto cleanup; if (STRPREFIX(hostname, "localhost")) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("hostname on destination resolved to localhost," " but migration requires an FQDN")); goto cleanup; } if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0) goto cleanup; if (virAsprintf(uri_out, "tcp://%s:%d", hostname, port) < 0) goto cleanup; } else { if (!(STRPREFIX(uri_in, "tcp://"))) { /* not full URI, add prefix tcp:// */ char *tmp; if (virAsprintf(&tmp, "tcp://%s", uri_in) < 0) goto cleanup; uri = virURIParse(tmp); VIR_FREE(tmp); } else { uri = virURIParse(uri_in); } if (uri == NULL) { virReportError(VIR_ERR_INVALID_ARG, _("unable to parse URI: %s"), uri_in); goto cleanup; } if (uri->server == NULL) { virReportError(VIR_ERR_INVALID_ARG, _("missing host in migration URI: %s"), uri_in); goto cleanup; } else { hostname = uri->server; } if (uri->port == 0) { if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0) goto cleanup; } else { port = uri->port; } if (virAsprintf(uri_out, "tcp://%s:%d", hostname, port) < 0) goto cleanup; } snprintf(portstr, sizeof(portstr), "%d", port); if (virNetSocketNewListenTCP(hostname, portstr, &socks, &nsocks) < 0) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Fail to create socket for incoming migration")); goto cleanup; } if (libxlMigrationDstArgsInitialize() < 0) goto cleanup; if (!(args = virObjectNew(libxlMigrationDstArgsClass))) goto cleanup; args->conn = dconn; args->vm = vm; args->flags = flags; args->socks = socks; args->nsocks = nsocks; for (i = 0; i < nsocks; i++) { if (virNetSocketSetBlocking(socks[i], true) < 0) continue; if (virNetSocketListen(socks[i], 1) < 0) continue; if (virNetSocketAddIOCallback(socks[i], VIR_EVENT_HANDLE_READABLE, libxlDoMigrateReceive, args, virObjectFreeCallback) < 0) continue; /* * Successfully added sock to event loop. Take a ref on args to * ensure it is not freed until sock is removed from the event loop. * Ref is dropped in virObjectFreeCallback after being removed * from the event loop. */ virObjectRef(args); nsocks_listen++; } /* Done with args in this function, drop reference */ virObjectUnref(args); if (!nsocks_listen) goto cleanup; ret = 0; goto done; cleanup: for (i = 0; i < nsocks; i++) { virNetSocketClose(socks[i]); virObjectUnref(socks[i]); } done: virURIFree(uri); if (vm) virObjectUnlock(vm); return ret; }
qemuMonitorTestPtr qemuMonitorTestNew(bool json, virCapsPtr caps) { qemuMonitorTestPtr test = NULL; virDomainChrSourceDef src; char *path = NULL; char *tmpdir_template = NULL; if (VIR_ALLOC(test) < 0) goto no_memory; if (virMutexInit(&test->lock) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", "Cannot initialize mutex"); VIR_FREE(test); return NULL; } if (!(tmpdir_template = strdup("/tmp/libvirt_XXXXXX"))) goto no_memory; if (!(test->tmpdir = mkdtemp(tmpdir_template))) { virReportSystemError(errno, "%s", "Failed to create temporary directory"); goto error; } tmpdir_template = NULL; if (virAsprintf(&path, "%s/qemumonitorjsontest.sock", test->tmpdir) < 0) goto no_memory; test->json = json; if (!(test->vm = virDomainObjNew(caps))) goto error; if (virNetSocketNewListenUNIX(path, 0700, getuid(), getgid(), &test->server) < 0) goto error; memset(&src, 0, sizeof(src)); src.type = VIR_DOMAIN_CHR_TYPE_UNIX; src.data.nix.path = (char *)path; src.data.nix.listen = false; if (virNetSocketListen(test->server, 1) < 0) goto error; if (!(test->mon = qemuMonitorOpen(test->vm, &src, json ? 1 : 0, &qemuCallbacks))) goto error; qemuMonitorLock(test->mon); if (virNetSocketAccept(test->server, &test->client) < 0) goto error; if (!test->client) goto error; if (qemuMonitorTestAddReponse(test, json ? QEMU_JSON_GREETING : QEMU_TEXT_GREETING) < 0) goto error; if (virNetSocketAddIOCallback(test->client, VIR_EVENT_HANDLE_WRITABLE, qemuMonitorTestIO, test, NULL) < 0) goto error; virMutexLock(&test->lock); if (virThreadCreate(&test->thread, true, qemuMonitorTestWorker, test) < 0) { virMutexUnlock(&test->lock); goto error; } test->running = true; virMutexUnlock(&test->lock); cleanup: VIR_FREE(path); return test; no_memory: virReportOOMError(); error: VIR_FREE(tmpdir_template); qemuMonitorTestFree(test); goto cleanup; }