struct libxenvchan * vchan_maybe_client_init(xentoollog_logger * logger, int srvId){ int sourceId = getDomId(); int destId = srvId; struct libxenvchan *txCtrl=0; char serverRxXS [256]; // xenStore path for the server's receive. char p[256]; char *path = "data/serverVchan"; if (!path){ sprintf (p,"%s",SERV_REL_RX_XS_PATH); }else{ sprintf (p,"%s",path); } sprintf(p, "%s_%d",p,sourceId); sprintf(serverRxXS, "/local/domain/%d/%s", destId, p); // We act as a client so the servers Rx is our Tx. fprintf(stdout, "transmitChan: vchan init for xs=%s to domId=%d,\n", serverRxXS, sourceId ); txCtrl = libxenvchan_client_init((xentoollog_logger *)logger, destId, serverRxXS); if(txCtrl == NULL) { return NULL; } return txCtrl; }
struct libxenvchan * createTransmitChanP(xentoollog_logger * xc_logger, int destId, int sourceId, char * path){ struct libxenvchan *txCtrl=0; char serverRxXS [256]; // xenStore path for the server's receive. char p[256]; if (!path){ sprintf (p,"%s",SERV_REL_RX_XS_PATH); }else{ sprintf (p,"%s",path); } sprintf(p, "%s_%d",p,sourceId); sprintf(serverRxXS, "/local/domain/%d/%s", destId, p); // We act as a client so the servers Rx is our Tx. fprintf(stdout, "transmitChan: vchan init for xs=%s to domId=%d,\n", serverRxXS, sourceId ); txCtrl = libxenvchan_client_init((xentoollog_logger *)xc_logger, destId, serverRxXS); if(txCtrl == NULL) { // We had an error trying to initialise the client vchan. char * lclErrStr = strerror(errno); fprintf(stderr, "Error: %s: libxenvchan_client_init: domId=%d, xsPath=%s.\n", lclErrStr, destId, serverRxXS); if(errno == ENOENT) { fprintf(stderr, " kernel module xen_gntalloc (/dev/xen/gntalloc) or xen_evtchn (/dev/xen/evtchn) may not be running.\n"); } exit(1); } // txCtrl->blocking = 1; // Block for each vchan IO ? return txCtrl; }
libvchan_t *libvchan_client_init(int domain, int port) { char xs_path[255]; char xs_path_watch[255]; libvchan_t *ctrl; xc_interface *xc_handle; struct xs_handle *xs; char **vec; unsigned int count, len; char *dummy = NULL; char *own_domid = NULL; xc_handle = xc_interface_open(NULL, NULL, 0); if (!xc_handle) { /* error already logged by xc_interface_open */ goto err; } /* wait for server to appear */ xs = xs_open(0); if (!xs) { perror("xs_open"); goto err_xc; } len = 0; if (!xs_watch(xs, "domid", "domid")) { fprintf(stderr, "Cannot setup xenstore watch\n"); goto err_xs; } if (!xs_watch(xs, "@releaseDomain", "release")) { fprintf(stderr, "Cannot setup xenstore watch\n"); goto err_xs; } while (!dummy || !len) { vec = xs_read_watch(xs, &count); if (vec) { if (strcmp(vec[XS_WATCH_TOKEN], "domid") == 0) { /* domid have changed */ if (own_domid) { free(own_domid); own_domid = NULL; xs_unwatch(xs, xs_path_watch, xs_path_watch); } } free(vec); } if (!own_domid) { /* construct xenstore path on first iteration and on every domid * change detected (save+restore case) */ own_domid = xs_read(xs, 0, "domid", &len); if (!own_domid) { fprintf(stderr, "Cannot get own domid\n"); goto err_xs; } if (atoi(own_domid) == domain) { fprintf(stderr, "Loopback vchan connection not supported\n"); free(own_domid); goto err_xs; } snprintf(xs_path, sizeof(xs_path), "/local/domain/%d/data/vchan/%s/%d", domain, own_domid, port); /* watch on this key as we might not have access to the whole directory */ snprintf(xs_path_watch, sizeof(xs_path_watch), "%s/event-channel", xs_path); if (!xs_watch(xs, xs_path_watch, xs_path_watch)) { fprintf(stderr, "Cannot setup watch on %s\n", xs_path_watch); free(own_domid); goto err_xs; } } dummy = xs_read(xs, 0, xs_path_watch, &len); if (dummy) free(dummy); else { if (!libvchan__check_domain_alive(xc_handle, domain)) { fprintf(stderr, "domain dead\n"); goto err_xs; } } } if (own_domid) free(own_domid); xs_close(xs); ctrl = malloc(sizeof(*ctrl)); if (!ctrl) return NULL; ctrl->xs_path = NULL; ctrl->xenvchan = libxenvchan_client_init(NULL, domain, xs_path); if (!ctrl->xenvchan) { free(ctrl); return NULL; } ctrl->xenvchan->blocking = 1; /* notify server */ xc_evtchn_notify(ctrl->xenvchan->event, ctrl->xenvchan->event_port); ctrl->remote_domain = domain; ctrl->xc_handle = xc_handle; return ctrl; err_xs: xs_close(xs); err_xc: xc_interface_close(xc_handle); err: return NULL; }
libvchan_t *libvchan_client_init(int domain, int port) { char xs_path[255]; char xs_path_watch[255]; libvchan_t *ctrl = NULL; PXENCONTROL_CONTEXT xc_handle = NULL; char own_domid[16]; DWORD status; HANDLE path_watch_event = NULL; PVOID path_watch_handle = NULL; if (ERROR_SUCCESS != XcOpen(g_logger, &xc_handle)) { Log(XLL_ERROR, "opening xen device failed"); /* This error signifies that xeniface is not available. We need to return a well-defined code so the caller can potentially wait for xeniface to become active (this can happen after the first reboot after pvdrivers installation, it takes a while to load). */ SetLastError(ERROR_NOT_SUPPORTED); goto fail; } /* wait for server to appear */ status = XcStoreRead(xc_handle, "domid", sizeof(own_domid), own_domid); if (status != ERROR_SUCCESS) { Log(XLL_ERROR, "reading domid from xenstore failed: 0x%x", status); goto fail; } if (atoi(own_domid) == domain) { Log(XLL_ERROR, "Loopback vchan connection not supported"); goto fail; } path_watch_event = CreateEvent(NULL, FALSE, FALSE, NULL); if (!path_watch_event) { Log(XLL_ERROR, "CreateEvent(xs watch) failed: 0x%x", GetLastError()); goto fail; } snprintf(xs_path, sizeof(xs_path), "/local/domain/%d/data/vchan/%s/%d", domain, own_domid, port); /* watch on this key as we might not have access to the whole directory */ snprintf(xs_path_watch, sizeof(xs_path_watch), "%s/event-channel", xs_path); Log(XLL_DEBUG, "path: %S", xs_path); status = XcStoreAddWatch(xc_handle, xs_path_watch, path_watch_event, &path_watch_handle); if (status != ERROR_SUCCESS) { Log(XLL_ERROR, "adding xenstore watch (%S) failed: 0x%x", xs_path_watch, status); goto fail; } status = WaitForSingleObject(path_watch_event, 100); if (status != WAIT_OBJECT_0) { Log(XLL_ERROR, "Wait for xenstore (1) failed: 0x%x", GetLastError()); // don't fail completely yet, if we can read the store values we're ok } // wait two times because Xen always signals the watch immediately after creation status = WaitForSingleObject(path_watch_event, 100); if (status != WAIT_OBJECT_0) { Log(XLL_ERROR, "Wait for xenstore (2) failed: 0x%x", GetLastError()); } XcStoreRemoveWatch(xc_handle, path_watch_handle); path_watch_handle = 0; CloseHandle(path_watch_event); path_watch_event = NULL; ctrl = malloc(sizeof(*ctrl)); if (!ctrl) goto fail; ctrl->xs_path = NULL; ctrl->xenvchan = libxenvchan_client_init(g_logger, domain, xs_path); if (!ctrl->xenvchan) { Log(XLL_ERROR, "libxenvchan_client_init(%u, %S) failed", domain, xs_path); goto fail; } ctrl->xenvchan->blocking = 1; // notify server - xc handle must be the one that xenvchan opened since we use event channel that was allocated using that handle XcEvtchnNotify(ctrl->xenvchan->xc, ctrl->xenvchan->event_port); ctrl->remote_domain = domain; XcClose(xc_handle); Log(XLL_DEBUG, "ctrl %p, xenvchan %p", ctrl, ctrl->xenvchan); return ctrl; fail: if (path_watch_handle) XcStoreRemoveWatch(xc_handle, path_watch_handle); if (path_watch_event) CloseHandle(path_watch_event); if (xc_handle) XcClose(xc_handle); if (ctrl) free(ctrl); return NULL; }