Commit ffd843bcdc46768f26507f0889c92f4bda287986
1 parent
1cb6c3fd
Run monitor over unix domain sockets, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2259 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
102 additions
and
19 deletions
qemu-doc.texi
... | ... | @@ -586,6 +586,11 @@ MAGIC_SYSRQ sequence if you use a telnet that supports sending the break |
586 | 586 | sequence. Typically in unix telnet you do it with Control-] and then |
587 | 587 | type "send break" followed by pressing the enter key. |
588 | 588 | |
589 | +@item unix:path[,server][,nowait] | |
590 | +A unix domain socket is used instead of a tcp socket. The option works the | |
591 | +same as if you had specified @code{-serial tcp} except the unix domain socket | |
592 | +@var{path} is used for connections. | |
593 | + | |
589 | 594 | @end table |
590 | 595 | |
591 | 596 | @item -parallel dev | ... | ... |
qemu_socket.h
vl.c
... | ... | @@ -2206,6 +2206,7 @@ static void udp_chr_add_read_handler(CharDriverState *chr, |
2206 | 2206 | } |
2207 | 2207 | |
2208 | 2208 | int parse_host_port(struct sockaddr_in *saddr, const char *str); |
2209 | +int parse_unix_path(struct sockaddr_un *uaddr, const char *str); | |
2209 | 2210 | int parse_host_src_port(struct sockaddr_in *haddr, |
2210 | 2211 | struct sockaddr_in *saddr, |
2211 | 2212 | const char *str); |
... | ... | @@ -2270,6 +2271,7 @@ typedef struct { |
2270 | 2271 | int connected; |
2271 | 2272 | int max_size; |
2272 | 2273 | int do_telnetopt; |
2274 | + int is_unix; | |
2273 | 2275 | } TCPCharDriver; |
2274 | 2276 | |
2275 | 2277 | static void tcp_chr_accept(void *opaque); |
... | ... | @@ -2291,6 +2293,8 @@ static int tcp_chr_read_poll(void *opaque) |
2291 | 2293 | TCPCharDriver *s = chr->opaque; |
2292 | 2294 | if (!s->connected) |
2293 | 2295 | return 0; |
2296 | + if (!s->fd_can_read) | |
2297 | + return 0; | |
2294 | 2298 | s->max_size = s->fd_can_read(s->fd_opaque); |
2295 | 2299 | return s->max_size; |
2296 | 2300 | } |
... | ... | @@ -2416,12 +2420,25 @@ static void tcp_chr_accept(void *opaque) |
2416 | 2420 | CharDriverState *chr = opaque; |
2417 | 2421 | TCPCharDriver *s = chr->opaque; |
2418 | 2422 | struct sockaddr_in saddr; |
2423 | +#ifndef _WIN32 | |
2424 | + struct sockaddr_un uaddr; | |
2425 | +#endif | |
2426 | + struct sockaddr *addr; | |
2419 | 2427 | socklen_t len; |
2420 | 2428 | int fd; |
2421 | 2429 | |
2422 | 2430 | for(;;) { |
2423 | - len = sizeof(saddr); | |
2424 | - fd = accept(s->listen_fd, (struct sockaddr *)&saddr, &len); | |
2431 | +#ifndef _WIN32 | |
2432 | + if (s->is_unix) { | |
2433 | + len = sizeof(uaddr); | |
2434 | + addr = (struct sockaddr *)&uaddr; | |
2435 | + } else | |
2436 | +#endif | |
2437 | + { | |
2438 | + len = sizeof(saddr); | |
2439 | + addr = (struct sockaddr *)&saddr; | |
2440 | + } | |
2441 | + fd = accept(s->listen_fd, addr, &len); | |
2425 | 2442 | if (fd < 0 && errno != EINTR) { |
2426 | 2443 | return; |
2427 | 2444 | } else if (fd >= 0) { |
... | ... | @@ -2447,7 +2464,8 @@ static void tcp_chr_close(CharDriverState *chr) |
2447 | 2464 | } |
2448 | 2465 | |
2449 | 2466 | static CharDriverState *qemu_chr_open_tcp(const char *host_str, |
2450 | - int is_telnet) | |
2467 | + int is_telnet, | |
2468 | + int is_unix) | |
2451 | 2469 | { |
2452 | 2470 | CharDriverState *chr = NULL; |
2453 | 2471 | TCPCharDriver *s = NULL; |
... | ... | @@ -2456,9 +2474,26 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, |
2456 | 2474 | int is_waitconnect = 1; |
2457 | 2475 | const char *ptr; |
2458 | 2476 | struct sockaddr_in saddr; |
2477 | +#ifndef _WIN32 | |
2478 | + struct sockaddr_un uaddr; | |
2479 | +#endif | |
2480 | + struct sockaddr *addr; | |
2481 | + socklen_t addrlen; | |
2459 | 2482 | |
2460 | - if (parse_host_port(&saddr, host_str) < 0) | |
2461 | - goto fail; | |
2483 | +#ifndef _WIN32 | |
2484 | + if (is_unix) { | |
2485 | + addr = (struct sockaddr *)&uaddr; | |
2486 | + addrlen = sizeof(uaddr); | |
2487 | + if (parse_unix_path(&uaddr, host_str) < 0) | |
2488 | + goto fail; | |
2489 | + } else | |
2490 | +#endif | |
2491 | + { | |
2492 | + addr = (struct sockaddr *)&saddr; | |
2493 | + addrlen = sizeof(saddr); | |
2494 | + if (parse_host_port(&saddr, host_str) < 0) | |
2495 | + goto fail; | |
2496 | + } | |
2462 | 2497 | |
2463 | 2498 | ptr = host_str; |
2464 | 2499 | while((ptr = strchr(ptr,','))) { |
... | ... | @@ -2481,8 +2516,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, |
2481 | 2516 | s = qemu_mallocz(sizeof(TCPCharDriver)); |
2482 | 2517 | if (!s) |
2483 | 2518 | goto fail; |
2484 | - | |
2485 | - fd = socket(PF_INET, SOCK_STREAM, 0); | |
2519 | + | |
2520 | +#ifndef _WIN32 | |
2521 | + if (is_unix) | |
2522 | + fd = socket(PF_UNIX, SOCK_STREAM, 0); | |
2523 | + else | |
2524 | +#endif | |
2525 | + fd = socket(PF_INET, SOCK_STREAM, 0); | |
2526 | + | |
2486 | 2527 | if (fd < 0) |
2487 | 2528 | goto fail; |
2488 | 2529 | |
... | ... | @@ -2492,24 +2533,43 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, |
2492 | 2533 | s->connected = 0; |
2493 | 2534 | s->fd = -1; |
2494 | 2535 | s->listen_fd = -1; |
2536 | + s->is_unix = is_unix; | |
2537 | + | |
2538 | + chr->opaque = s; | |
2539 | + chr->chr_write = tcp_chr_write; | |
2540 | + chr->chr_add_read_handler = tcp_chr_add_read_handler; | |
2541 | + chr->chr_close = tcp_chr_close; | |
2542 | + | |
2495 | 2543 | if (is_listen) { |
2496 | 2544 | /* allow fast reuse */ |
2497 | - val = 1; | |
2498 | - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); | |
2545 | +#ifndef _WIN32 | |
2546 | + if (is_unix) { | |
2547 | + char path[109]; | |
2548 | + strncpy(path, uaddr.sun_path, 108); | |
2549 | + path[108] = 0; | |
2550 | + unlink(path); | |
2551 | + } else | |
2552 | +#endif | |
2553 | + { | |
2554 | + val = 1; | |
2555 | + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); | |
2556 | + } | |
2499 | 2557 | |
2500 | - ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); | |
2501 | - if (ret < 0) | |
2558 | + ret = bind(fd, addr, addrlen); | |
2559 | + if (ret < 0) | |
2502 | 2560 | goto fail; |
2561 | + | |
2503 | 2562 | ret = listen(fd, 0); |
2504 | 2563 | if (ret < 0) |
2505 | 2564 | goto fail; |
2565 | + | |
2506 | 2566 | s->listen_fd = fd; |
2507 | 2567 | qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); |
2508 | 2568 | if (is_telnet) |
2509 | 2569 | s->do_telnetopt = 1; |
2510 | 2570 | } else { |
2511 | 2571 | for(;;) { |
2512 | - ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); | |
2572 | + ret = connect(fd, addr, addrlen); | |
2513 | 2573 | if (ret < 0) { |
2514 | 2574 | err = socket_error(); |
2515 | 2575 | if (err == EINTR || err == EWOULDBLOCK) { |
... | ... | @@ -2530,10 +2590,6 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, |
2530 | 2590 | qemu_set_fd_handler(s->fd, NULL, tcp_chr_connect, chr); |
2531 | 2591 | } |
2532 | 2592 | |
2533 | - chr->opaque = s; | |
2534 | - chr->chr_write = tcp_chr_write; | |
2535 | - chr->chr_add_read_handler = tcp_chr_add_read_handler; | |
2536 | - chr->chr_close = tcp_chr_close; | |
2537 | 2593 | if (is_listen && is_waitconnect) { |
2538 | 2594 | printf("QEMU waiting for connection on: %s\n", host_str); |
2539 | 2595 | tcp_chr_accept(chr); |
... | ... | @@ -2559,16 +2615,18 @@ CharDriverState *qemu_chr_open(const char *filename) |
2559 | 2615 | return qemu_chr_open_null(); |
2560 | 2616 | } else |
2561 | 2617 | if (strstart(filename, "tcp:", &p)) { |
2562 | - return qemu_chr_open_tcp(p, 0); | |
2618 | + return qemu_chr_open_tcp(p, 0, 0); | |
2563 | 2619 | } else |
2564 | 2620 | if (strstart(filename, "telnet:", &p)) { |
2565 | - return qemu_chr_open_tcp(p, 1); | |
2621 | + return qemu_chr_open_tcp(p, 1, 0); | |
2566 | 2622 | } else |
2567 | 2623 | if (strstart(filename, "udp:", &p)) { |
2568 | 2624 | return qemu_chr_open_udp(p); |
2569 | 2625 | } else |
2570 | 2626 | #ifndef _WIN32 |
2571 | - if (strstart(filename, "file:", &p)) { | |
2627 | + if (strstart(filename, "unix:", &p)) { | |
2628 | + return qemu_chr_open_tcp(p, 0, 1); | |
2629 | + } else if (strstart(filename, "file:", &p)) { | |
2572 | 2630 | return qemu_chr_open_file_out(p); |
2573 | 2631 | } else if (strstart(filename, "pipe:", &p)) { |
2574 | 2632 | return qemu_chr_open_pipe(p); |
... | ... | @@ -2743,6 +2801,24 @@ int parse_host_port(struct sockaddr_in *saddr, const char *str) |
2743 | 2801 | return 0; |
2744 | 2802 | } |
2745 | 2803 | |
2804 | +int parse_unix_path(struct sockaddr_un *uaddr, const char *str) | |
2805 | +{ | |
2806 | + const char *p; | |
2807 | + int len; | |
2808 | + | |
2809 | + len = MIN(108, strlen(str)); | |
2810 | + p = strchr(str, ','); | |
2811 | + if (p) | |
2812 | + len = MIN(len, p - str); | |
2813 | + | |
2814 | + memset(uaddr, 0, sizeof(*uaddr)); | |
2815 | + | |
2816 | + uaddr->sun_family = AF_UNIX; | |
2817 | + memcpy(uaddr->sun_path, str, len); | |
2818 | + | |
2819 | + return 0; | |
2820 | +} | |
2821 | + | |
2746 | 2822 | /* find or alloc a new VLAN */ |
2747 | 2823 | VLANState *qemu_find_vlan(int id) |
2748 | 2824 | { |
... | ... | @@ -6955,6 +7031,7 @@ int main(int argc, char **argv) |
6955 | 7031 | vm_start(); |
6956 | 7032 | } |
6957 | 7033 | } |
7034 | + | |
6958 | 7035 | main_loop(); |
6959 | 7036 | quit_timers(); |
6960 | 7037 | return 0; | ... | ... |