static void tpm_emulator_inst_finalize(Object *obj) { TPMEmulator *tpm_emu = TPM_EMULATOR(obj); tpm_emulator_shutdown(tpm_emu); object_unref(OBJECT(tpm_emu->data_ioc)); qemu_chr_fe_deinit(&tpm_emu->ctrl_chr, false); qapi_free_TPMEmulatorOptions(tpm_emu->options); if (tpm_emu->migration_blocker) { migrate_del_blocker(tpm_emu->migration_blocker); error_free(tpm_emu->migration_blocker); } qemu_mutex_destroy(&tpm_emu->mutex); }
static void main_loop(void) { int sock = -1, devfd = -1, fh, res, npoll; int32_t in_len; uint32_t out_len; uint8_t in[TPM_CMD_BUF_SIZE], *out; struct sockaddr_un addr; socklen_t addr_len; struct pollfd poll_table[2]; info("staring main loop"); /* open UNIX socket */ if (opt_socket_name) { sock = init_socket(opt_socket_name); if (sock < 0) exit(EXIT_FAILURE); } if (opt_dev_name) { devfd = init_device(opt_dev_name); if (devfd < 0) exit(EXIT_FAILURE); } /* init tpm emulator */ debug("initializing TPM emulator"); if (tpm_emulator_init(tpm_startup, tpm_config) != 0) { error("tpm_emulator_init() failed"); close(sock); unlink(opt_socket_name); exit(EXIT_FAILURE); } /* start command processing */ while (!stopflag) { /* wait for incomming connections */ debug("waiting for connections..."); npoll = 0; if (sock != -1) { poll_table[npoll].fd = sock; poll_table[npoll].events = POLLIN; poll_table[npoll++].revents = 0; } if (devfd != -1) { poll_table[npoll].fd = devfd; poll_table[npoll].events = POLLIN | POLLERR; poll_table[npoll++].revents = 0; } res = poll(poll_table, npoll, -1); if (res < 0) { error("poll(sock,dev) failed: %s", strerror(errno)); break; } if (devfd != -1 && poll_table[npoll - 1].revents) { /* if POLLERR was set, let read() handle it */ if (handle_emuldev_command(devfd) < 0) break; } if (sock == -1 || !poll_table[0].revents) continue; /* Beyond this point, npoll will always be 1 if the emulator device is * not open and 2 if it is, so we can just fill in the second slot of * the poll table unconditionally and rely on passing npoll to poll(). */ addr_len = sizeof(addr); fh = accept(sock, (struct sockaddr*)&addr, &addr_len); if (fh < 0) { error("accept() failed: %s", strerror(errno)); continue; } /* receive and handle commands */ in_len = 0; do { debug("waiting for commands..."); poll_table[0].fd = fh; poll_table[0].events = POLLIN; poll_table[0].revents = 0; poll_table[1].fd = devfd; poll_table[1].events = POLLIN | POLLERR; poll_table[1].revents = 0; res = poll(poll_table, npoll, TPM_COMMAND_TIMEOUT); if (res < 0) { error("poll(fh) failed: %s", strerror(errno)); close(fh); break; } else if (res == 0) { #ifdef TPMD_DISCONNECT_IDLE_CLIENTS info("connection closed due to inactivity"); close(fh); break; #else continue; #endif } if (poll_table[1].revents) { /* if POLLERR was set, let read() handle it */ if (handle_emuldev_command(devfd) < 0) break; } if (!poll_table[0].revents) continue; in_len = read(fh, in, sizeof(in)); if (in_len > 0) { debug("received %d bytes", in_len); out = NULL; res = tpm_handle_command(in, in_len, &out, &out_len); if (res < 0) { error("tpm_handle_command() failed"); } else { debug("sending %d bytes", out_len); uint32_t len = 0; while (len < out_len) { res = write(fh, &out[len], out_len - len); if (res < 0) { error("write(%d) failed: %s", out_len - len, strerror(errno)); break; } len += res; } tpm_free(out); } } } while (in_len > 0); close(fh); } /* shutdown tpm emulator */ tpm_emulator_shutdown(); /* close socket */ close(sock); unlink(opt_socket_name); info("main loop stopped"); }