76 |
76 |
*
|
77 |
77 |
*/
|
78 |
78 |
|
|
79 |
typedef struct MonitorCompletionData MonitorCompletionData;
|
|
80 |
struct MonitorCompletionData {
|
|
81 |
Monitor *mon;
|
|
82 |
void (*user_print)(Monitor *mon, const QObject *data);
|
|
83 |
};
|
|
84 |
|
79 |
85 |
typedef struct mon_cmd_t {
|
80 |
86 |
const char *name;
|
81 |
87 |
const char *args_type;
|
... | ... | |
85 |
91 |
union {
|
86 |
92 |
void (*info)(Monitor *mon);
|
87 |
93 |
void (*info_new)(Monitor *mon, QObject **ret_data);
|
|
94 |
int (*info_async)(Monitor *mon, MonitorCompletion *cb, void *opaque);
|
88 |
95 |
void (*cmd)(Monitor *mon, const QDict *qdict);
|
89 |
96 |
void (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data);
|
|
97 |
int (*cmd_async)(Monitor *mon, const QDict *params,
|
|
98 |
MonitorCompletion *cb, void *opaque);
|
90 |
99 |
} mhandler;
|
|
100 |
int async;
|
91 |
101 |
} mon_cmd_t;
|
92 |
102 |
|
93 |
103 |
/* file descriptors passed via SCM_RIGHTS */
|
... | ... | |
255 |
265 |
return cmd->user_print != NULL;
|
256 |
266 |
}
|
257 |
267 |
|
|
268 |
static inline bool monitor_handler_is_async(const mon_cmd_t *cmd)
|
|
269 |
{
|
|
270 |
return cmd->async != 0;
|
|
271 |
}
|
|
272 |
|
258 |
273 |
static inline int monitor_has_error(const Monitor *mon)
|
259 |
274 |
{
|
260 |
275 |
return mon->error != NULL;
|
... | ... | |
453 |
468 |
}
|
454 |
469 |
}
|
455 |
470 |
|
|
471 |
static void user_monitor_complete(void *opaque, QObject *ret_data)
|
|
472 |
{
|
|
473 |
MonitorCompletionData *data = (MonitorCompletionData *)opaque;
|
|
474 |
|
|
475 |
if (ret_data) {
|
|
476 |
data->user_print(data->mon, ret_data);
|
|
477 |
}
|
|
478 |
monitor_resume(data->mon);
|
|
479 |
qemu_free(data);
|
|
480 |
}
|
|
481 |
|
|
482 |
static void qmp_monitor_complete(void *opaque, QObject *ret_data)
|
|
483 |
{
|
|
484 |
monitor_protocol_emitter(opaque, ret_data);
|
|
485 |
}
|
|
486 |
|
|
487 |
static void qmp_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd,
|
|
488 |
const QDict *params)
|
|
489 |
{
|
|
490 |
cmd->mhandler.cmd_async(mon, params, qmp_monitor_complete, mon);
|
|
491 |
}
|
|
492 |
|
|
493 |
static void qmp_async_info_handler(Monitor *mon, const mon_cmd_t *cmd)
|
|
494 |
{
|
|
495 |
cmd->mhandler.info_async(mon, qmp_monitor_complete, mon);
|
|
496 |
}
|
|
497 |
|
|
498 |
static void user_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd,
|
|
499 |
const QDict *params)
|
|
500 |
{
|
|
501 |
int ret;
|
|
502 |
|
|
503 |
MonitorCompletionData *cb_data = qemu_malloc(sizeof(*cb_data));
|
|
504 |
cb_data->mon = mon;
|
|
505 |
cb_data->user_print = cmd->user_print;
|
|
506 |
monitor_suspend(mon);
|
|
507 |
ret = cmd->mhandler.cmd_async(mon, params,
|
|
508 |
user_monitor_complete, cb_data);
|
|
509 |
if (ret < 0) {
|
|
510 |
monitor_resume(mon);
|
|
511 |
qemu_free(cb_data);
|
|
512 |
}
|
|
513 |
}
|
|
514 |
|
|
515 |
static void user_async_info_handler(Monitor *mon, const mon_cmd_t *cmd)
|
|
516 |
{
|
|
517 |
int ret;
|
|
518 |
|
|
519 |
MonitorCompletionData *cb_data = qemu_malloc(sizeof(*cb_data));
|
|
520 |
cb_data->mon = mon;
|
|
521 |
cb_data->user_print = cmd->user_print;
|
|
522 |
monitor_suspend(mon);
|
|
523 |
ret = cmd->mhandler.info_async(mon, user_monitor_complete, cb_data);
|
|
524 |
if (ret < 0) {
|
|
525 |
monitor_resume(mon);
|
|
526 |
qemu_free(cb_data);
|
|
527 |
}
|
|
528 |
}
|
|
529 |
|
456 |
530 |
static void do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
457 |
531 |
{
|
458 |
532 |
const mon_cmd_t *cmd;
|
... | ... | |
476 |
550 |
goto help;
|
477 |
551 |
}
|
478 |
552 |
|
479 |
|
if (monitor_handler_ported(cmd)) {
|
|
553 |
if (monitor_handler_is_async(cmd)) {
|
|
554 |
if (monitor_ctrl_mode(mon)) {
|
|
555 |
qmp_async_info_handler(mon, cmd);
|
|
556 |
} else {
|
|
557 |
user_async_info_handler(mon, cmd);
|
|
558 |
}
|
|
559 |
/*
|
|
560 |
* Indicate that this command is asynchronous and will not return any
|
|
561 |
* data (not even empty). Instead, the data will be returned via a
|
|
562 |
* completion callback.
|
|
563 |
*/
|
|
564 |
*ret_data = qobject_from_jsonf("{ '__mon_async': 'return' }");
|
|
565 |
} else if (monitor_handler_ported(cmd)) {
|
480 |
566 |
cmd->mhandler.info_new(mon, ret_data);
|
481 |
567 |
|
482 |
568 |
if (!monitor_ctrl_mode(mon)) {
|
... | ... | |
3588 |
3674 |
mon->error = NULL;
|
3589 |
3675 |
}
|
3590 |
3676 |
|
|
3677 |
static int is_async_return(const QObject *data)
|
|
3678 |
{
|
|
3679 |
return data && qdict_haskey(qobject_to_qdict(data), "__mon_async");
|
|
3680 |
}
|
|
3681 |
|
3591 |
3682 |
static void monitor_call_handler(Monitor *mon, const mon_cmd_t *cmd,
|
3592 |
3683 |
const QDict *params)
|
3593 |
3684 |
{
|
... | ... | |
3595 |
3686 |
|
3596 |
3687 |
cmd->mhandler.cmd_new(mon, params, &data);
|
3597 |
3688 |
|
3598 |
|
if (monitor_ctrl_mode(mon)) {
|
|
3689 |
if (is_async_return(data)) {
|
|
3690 |
/*
|
|
3691 |
* Asynchronous commands have no initial return data but they can
|
|
3692 |
* generate errors. Data is returned via the async completion handler.
|
|
3693 |
*/
|
|
3694 |
if (monitor_ctrl_mode(mon) && monitor_has_error(mon)) {
|
|
3695 |
monitor_protocol_emitter(mon, NULL);
|
|
3696 |
}
|
|
3697 |
} else if (monitor_ctrl_mode(mon)) {
|
3599 |
3698 |
/* Monitor Protocol */
|
3600 |
3699 |
monitor_protocol_emitter(mon, data);
|
3601 |
3700 |
} else {
|
... | ... | |
3620 |
3719 |
|
3621 |
3720 |
qemu_errors_to_mon(mon);
|
3622 |
3721 |
|
3623 |
|
if (monitor_handler_ported(cmd)) {
|
|
3722 |
if (monitor_handler_is_async(cmd)) {
|
|
3723 |
user_async_cmd_handler(mon, cmd, qdict);
|
|
3724 |
} else if (monitor_handler_ported(cmd)) {
|
3624 |
3725 |
monitor_call_handler(mon, cmd, qdict);
|
3625 |
3726 |
} else {
|
3626 |
3727 |
cmd->mhandler.cmd(mon, qdict);
|
... | ... | |
4082 |
4183 |
goto err_out;
|
4083 |
4184 |
}
|
4084 |
4185 |
|
4085 |
|
monitor_call_handler(mon, cmd, args);
|
|
4186 |
if (monitor_handler_is_async(cmd)) {
|
|
4187 |
qmp_async_cmd_handler(mon, cmd, args);
|
|
4188 |
} else {
|
|
4189 |
monitor_call_handler(mon, cmd, args);
|
|
4190 |
}
|
4086 |
4191 |
goto out;
|
4087 |
4192 |
|
4088 |
4193 |
err_input:
|