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 (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); 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 */ 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 int testSocketTCPAccept(const void *opaque) { virNetSocketPtr *lsock = NULL; /* Listen socket */ size_t nlsock = 0, i; virNetSocketPtr ssock = NULL; /* Server socket */ virNetSocketPtr csock = NULL; /* Client socket */ const struct testTCPData *data = opaque; int ret = -1; char portstr[100]; snprintf(portstr, sizeof(portstr), "%d", data->port); if (virNetSocketNewListenTCP(data->lnode, portstr, AF_UNSPEC, &lsock, &nlsock) < 0) goto cleanup; for (i = 0; i < nlsock; i++) { if (virNetSocketListen(lsock[i], 0) < 0) goto cleanup; } if (virNetSocketNewConnectTCP(data->cnode, portstr, AF_UNSPEC, &csock) < 0) goto cleanup; virObjectUnref(csock); for (i = 0; i < nlsock; i++) { if (virNetSocketAccept(lsock[i], &ssock) != -1 && ssock) { char c = 'a'; if (virNetSocketWrite(ssock, &c, 1) != -1 && virNetSocketRead(ssock, &c, 1) != -1) { VIR_DEBUG("Unexpected client socket present"); goto cleanup; } } virObjectUnref(ssock); ssock = NULL; } ret = 0; cleanup: virObjectUnref(ssock); for (i = 0; i < nlsock; i++) virObjectUnref(lsock[i]); VIR_FREE(lsock); return ret; }
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; }
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; }