void virNetClientIncomingEvent(virNetSocketPtr sock, int events, void *opaque) { virNetClientPtr client = opaque; virNetClientLock(client); if (!client->sock) goto done; /* This should be impossible, but it doesn't hurt to check */ if (client->waitDispatch) goto done; VIR_DEBUG("Event fired %p %d", sock, events); if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) { VIR_DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__); virNetSocketRemoveIOCallback(sock); goto done; } if (virNetClientIOHandleInput(client) < 0) { VIR_WARN("Something went wrong during async message processing"); virNetSocketRemoveIOCallback(sock); } done: virNetClientUnlock(client); }
/* * * We don't free stuff here, merely disconnect the client's * network socket & resources. * * Full free of the client is done later in a safe point * where it can be guaranteed it is no longer in use */ void virNetServerClientCloseLocked(virNetServerClientPtr client) { virNetServerClientCloseFunc cf; virKeepAlivePtr ka; VIR_DEBUG("client=%p", client); if (!client->sock) return; if (client->keepalive) { virKeepAliveStop(client->keepalive); ka = client->keepalive; client->keepalive = NULL; virObjectRef(client); virObjectUnlock(client); virObjectUnref(ka); virObjectLock(client); virObjectUnref(client); } if (client->privateDataCloseFunc) { cf = client->privateDataCloseFunc; virObjectRef(client); virObjectUnlock(client); (cf)(client); virObjectLock(client); virObjectUnref(client); } /* Do now, even though we don't close the socket * until end, to ensure we don't get invoked * again due to tls shutdown */ if (client->sock) virNetSocketRemoveIOCallback(client->sock); if (client->tls) { virObjectUnref(client->tls); client->tls = NULL; } client->wantClose = true; while (client->rx) { virNetMessagePtr msg = virNetMessageQueueServe(&client->rx); virNetMessageFree(msg); } while (client->tx) { virNetMessagePtr msg = virNetMessageQueueServe(&client->tx); virNetMessageFree(msg); } if (client->sock) { virObjectUnref(client->sock); client->sock = NULL; } }
void qemuMonitorTestFree(qemuMonitorTestPtr test) { size_t i; int timer = -1; if (!test) return; virMutexLock(&test->lock); if (test->running) { test->quit = true; /* HACK: Add a dummy timeout to break event loop */ timer = virEventAddTimeout(0, qemuMonitorTestFreeTimer, NULL, NULL); } virMutexUnlock(&test->lock); if (test->client) { virNetSocketRemoveIOCallback(test->client); virNetSocketClose(test->client); virObjectUnref(test->client); } virObjectUnref(test->server); if (test->mon) { virObjectUnlock(test->mon); qemuMonitorClose(test->mon); } virObjectUnref(test->vm); virThreadJoin(&test->thread); if (timer != -1) virEventRemoveTimeout(timer); VIR_FREE(test->incoming); VIR_FREE(test->outgoing); for (i = 0 ; i < test->nitems ; i++) qemuMonitorTestItemFree(test->items[i]); VIR_FREE(test->items); if (test->tmpdir && rmdir(test->tmpdir) < 0) VIR_WARN("Failed to remove tempdir: %s", strerror(errno)); VIR_FREE(test->tmpdir); virMutexDestroy(&test->lock); VIR_FREE(test); }
void virNetClientClose(virNetClientPtr client) { if (!client) return; virNetClientLock(client); virNetSocketRemoveIOCallback(client->sock); virNetSocketFree(client->sock); client->sock = NULL; virNetTLSSessionFree(client->tls); client->tls = NULL; #if HAVE_SASL virNetSASLSessionFree(client->sasl); client->sasl = NULL; #endif virNetClientUnlock(client); }
static void libxlDoMigrateReceive(virNetSocketPtr sock, int events ATTRIBUTE_UNUSED, void *opaque) { libxlMigrationDstArgs *args = opaque; virConnectPtr conn = args->conn; virDomainObjPtr vm = args->vm; virNetSocketPtr *socks = args->socks; size_t nsocks = args->nsocks; bool paused = args->flags & VIR_MIGRATE_PAUSED; libxlDriverPrivatePtr driver = conn->privateData; virNetSocketPtr client_sock; int recvfd = -1; size_t i; int ret; if (virNetSocketAccept(sock, &client_sock) < 0) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Fail to accept migration connection")); goto cleanup; } VIR_DEBUG("Accepted migration connection\n"); recvfd = virNetSocketDupFD(client_sock, true); virObjectUnref(client_sock); virObjectLock(vm); ret = libxlDomainStart(driver, vm, paused, recvfd); virObjectUnlock(vm); if (ret < 0 && !vm->persistent) virDomainObjListRemove(driver->domains, vm); cleanup: /* Remove all listen socks from event handler, and close them. */ for (i = 0; i < nsocks; i++) { virNetSocketUpdateIOCallback(socks[i], 0); virNetSocketRemoveIOCallback(socks[i]); virNetSocketClose(socks[i]); virObjectUnref(socks[i]); socks[i] = NULL; } args->nsocks = 0; VIR_FORCE_CLOSE(recvfd); }
static void virNetServerClientDispatchEvent(virNetSocketPtr sock, int events, void *opaque) { virNetServerClientPtr client = opaque; virObjectLock(client); if (client->sock != sock) { virNetSocketRemoveIOCallback(sock); virObjectUnlock(client); return; } if (events & (VIR_EVENT_HANDLE_WRITABLE | VIR_EVENT_HANDLE_READABLE)) { #if WITH_GNUTLS if (client->tls && virNetTLSSessionGetHandshakeStatus(client->tls) != VIR_NET_TLS_HANDSHAKE_COMPLETE) { virNetServerClientDispatchHandshake(client); } else { #endif if (events & VIR_EVENT_HANDLE_WRITABLE) virNetServerClientDispatchWrite(client); if (events & VIR_EVENT_HANDLE_READABLE && client->rx) virNetServerClientDispatchRead(client); #if WITH_GNUTLS } #endif } /* NB, will get HANGUP + READABLE at same time upon * disconnect */ if (events & (VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP)) client->wantClose = true; virObjectUnlock(client); }
void virNetClientFree(virNetClientPtr client) { int i; if (!client) return; virNetClientLock(client); PROBE(RPC_CLIENT_FREE, "client=%p refs=%d", client, client->refs); client->refs--; if (client->refs > 0) { virNetClientUnlock(client); return; } for (i = 0 ; i < client->nprograms ; i++) virNetClientProgramFree(client->programs[i]); VIR_FREE(client->programs); VIR_FORCE_CLOSE(client->wakeupSendFD); VIR_FORCE_CLOSE(client->wakeupReadFD); VIR_FREE(client->hostname); if (client->sock) virNetSocketRemoveIOCallback(client->sock); virNetSocketFree(client->sock); virNetTLSSessionFree(client->tls); #if HAVE_SASL virNetSASLSessionFree(client->sasl); #endif virNetClientUnlock(client); virMutexDestroy(&client->lock); VIR_FREE(client); }
/* * Handles read/write of monitor data on the monitor server side */ static void qemuMonitorTestIO(virNetSocketPtr sock, int events, void *opaque) { qemuMonitorTestPtr test = opaque; bool err = false; virMutexLock(&test->lock); if (events & VIR_EVENT_HANDLE_WRITABLE) { ssize_t ret; if ((ret = virNetSocketWrite(sock, test->outgoing, test->outgoingLength)) < 0) { err = true; goto cleanup; } memmove(test->outgoing, test->outgoing + ret, test->outgoingLength - ret); test->outgoingLength -= ret; if ((test->outgoingCapacity - test->outgoingLength) > 1024) VIR_SHRINK_N(test->outgoing, test->outgoingCapacity, 1024); } if (events & VIR_EVENT_HANDLE_READABLE) { ssize_t ret, used; char *t1, *t2; if ((test->incomingCapacity - test->incomingLength) < 1024) { if (VIR_EXPAND_N(test->incoming, test->incomingCapacity, 1024) < 0) { err = true; goto cleanup; } } if ((ret = virNetSocketRead(sock, test->incoming + test->incomingLength, (test->incomingCapacity - test->incomingLength) - 1)) < 0) { err = true; goto cleanup; } test->incomingLength += ret; test->incoming[test->incomingLength] = '\0'; /* Look to see if we've got a complete line, and * if so, handle that command */ t1 = test->incoming; while ((t2 = strstr(t1, "\r\n"))) { *t2 = '\0'; if (qemuMonitorTestProcessCommand(test, t1) < 0) { err = true; goto cleanup; } t1 = t2 + 2; } used = t1 - test->incoming; memmove(test->incoming, t1, test->incomingLength - used); test->incomingLength -= used; if ((test->incomingCapacity - test->incomingLength) > 1024) { VIR_SHRINK_N(test->incoming, test->incomingCapacity, 1024); } } if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) err = true; cleanup: if (err) { virNetSocketRemoveIOCallback(sock); virNetSocketClose(sock); virObjectUnref(test->client); test->client = NULL; } else { events = VIR_EVENT_HANDLE_READABLE; if (test->outgoingLength) events |= VIR_EVENT_HANDLE_WRITABLE; virNetSocketUpdateIOCallback(sock, events); } virMutexUnlock(&test->lock); }