mirror of https://github.com/xqemu/xqemu.git
Merge io-channels-3 partial branch
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJWJl9qAAoJEL6G67QVEE/fn+gQAI4Y+0CLmds9bb0q3yWUmhwx QUjnae8Ji11av6i9chSh3Qg1ZLdYl/SbpS/yi+YOfGHo3k8cAU6JqWvCfZW5wSck 541X89b6s6kF2HsknRm1tJchQHsp8kxe4nlNgzJN8lraOcamBNzWH4GngXV6km6t V15JIOKCW1zW9w13O+Td8buN0MTDFxioe1sbZsdhyNWGoKSGXSlOcWNzr18zE/Ji SryhHt45hanV7Aiq/jW+rDHgddOjpspA7vSW/f2SCimAtbrVx6+2ZTEvIVnylfj0 VgE4XiH385RZN0wHMT8Gs4wEaB8BM4coRJBDVoRqk0fy6FtEvgK3Z/48KHYiAhkr rWLQiat/o20cbgRCVRWju5/DPoFwQEM0GStEI+NVMBMUW8sxnQ2ob16Ks60u/FaU PT8WKApQz1258FxWURjJzs6dObp62CJdNqUjvwJ6kQkSrdxDsqDz07BcMqbQ3D/H VNP/L5b24eLZQKo9KSAxtfIgUeQuvceN0csZ++Sb1ABnu+tTp8S2P8Y//lugghsq PvgmZNt2oCySVLMCEenu5a2y+NlavzzPVl64CJRDXdv65uoPUDo7YJjt6z3iwmEu UUJTr178r3lKZH4bzlwq6bLz/XbM4RMk7KI1HzFP/MPL1AMggdB8zPZZ2J0N7t7X Xl4kofpluFBmBILt4PKl =XIOA -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/berrange/tags/io-channel-3-for-upstream' into staging Merge io-channels-3 partial branch # gpg: Signature made Tue 20 Oct 2015 16:36:10 BST using RSA key ID 15104FDF # gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" # gpg: aka "Daniel P. Berrange <berrange@redhat.com>" * remotes/berrange/tags/io-channel-3-for-upstream: util: pull Buffer code out of VNC module coroutine: move into libqemuutil.a library osdep: add qemu_fork() wrapper for safely handling signals ui: convert VNC startup code to use SocketAddress sockets: allow port to be NULL when listening on IP address sockets: move qapi_copy_SocketAddress into qemu-sockets.c sockets: add helpers for creating SocketAddress from a socket Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
426c0df9e3
13
MAINTAINERS
13
MAINTAINERS
|
@ -1193,6 +1193,19 @@ F: crypto/
|
|||
F: include/crypto/
|
||||
F: tests/test-crypto-*
|
||||
|
||||
Coroutines
|
||||
M: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
M: Kevin Wolf <kwolf@redhat.com>
|
||||
F: util/*coroutine*
|
||||
F: include/qemu/coroutine*
|
||||
F: tests/test-coroutine.c
|
||||
|
||||
Buffers
|
||||
M: Daniel P. Berrange <berrange@redhat.com>
|
||||
S: Odd fixes
|
||||
F: util/buffer.c
|
||||
F: include/qemu/buffer.h
|
||||
|
||||
Usermode Emulation
|
||||
------------------
|
||||
Overall
|
||||
|
|
|
@ -15,10 +15,6 @@ block-obj-$(CONFIG_WIN32) += aio-win32.o
|
|||
block-obj-y += block/
|
||||
block-obj-y += qemu-io-cmds.o
|
||||
|
||||
block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
|
||||
block-obj-y += qemu-coroutine-sleep.o
|
||||
block-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
|
||||
|
||||
block-obj-m = block/
|
||||
|
||||
#######################################################################
|
||||
|
|
2
block.c
2
block.c
|
@ -33,7 +33,7 @@
|
|||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "block/qapi.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "qemu/timer.h"
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#define BLOCK_QCOW2_H
|
||||
|
||||
#include "crypto/cipher.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
|
||||
//#define DEBUG_ALLOC
|
||||
//#define DEBUG_ALLOC2
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
#include "migration/migration.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
|
||||
#if defined(CONFIG_UUID)
|
||||
#include <uuid/uuid.h>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
|
||||
#include "block/block_int.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "block/write-threshold.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "qapi-event.h"
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include "block/block_int.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qapi-event.h"
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "fsdev/qemu-fsdev.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "virtio-9p-coth.h"
|
||||
|
||||
int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent,
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "fsdev/qemu-fsdev.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "virtio-9p-coth.h"
|
||||
|
||||
int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode,
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "fsdev/qemu-fsdev.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "virtio-9p-coth.h"
|
||||
|
||||
static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf)
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "fsdev/qemu-fsdev.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "virtio-9p-coth.h"
|
||||
|
||||
int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, size_t size)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "fsdev/qemu-fsdev.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/event_notifier.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "virtio-9p-coth.h"
|
||||
|
||||
/* v9fs glib thread pool */
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#define _QEMU_VIRTIO_9P_COTH_H
|
||||
|
||||
#include "qemu/thread.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "virtio-9p.h"
|
||||
#include <glib.h>
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "fsdev/file-op-9p.h"
|
||||
#include "fsdev/virtio-9p-marshal.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
|
||||
enum {
|
||||
P9_TLERROR = 6,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "block/aio.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/option.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "block/accounting.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi-types.h"
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include "block/block.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qapi-types.h"
|
||||
#include "qemu/hbitmap.h"
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* QEMU generic buffers
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_BUFFER_H__
|
||||
#define QEMU_BUFFER_H__
|
||||
|
||||
#include "qemu-common.h"
|
||||
|
||||
typedef struct Buffer Buffer;
|
||||
|
||||
/**
|
||||
* Buffer:
|
||||
*
|
||||
* The Buffer object provides a simple dynamically resizing
|
||||
* array, with separate tracking of capacity and usage. This
|
||||
* is typically useful when buffering I/O or processing data.
|
||||
*/
|
||||
|
||||
struct Buffer {
|
||||
size_t capacity;
|
||||
size_t offset;
|
||||
uint8_t *buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* buffer_reserve:
|
||||
* @buffer: the buffer object
|
||||
* @len: the minimum required free space
|
||||
*
|
||||
* Ensure that the buffer has space allocated for at least
|
||||
* @len bytes. If the current buffer is too small, it will
|
||||
* be reallocated, possibly to a larger size than requested.
|
||||
*/
|
||||
void buffer_reserve(Buffer *buffer, size_t len);
|
||||
|
||||
/**
|
||||
* buffer_reset:
|
||||
* @buffer: the buffer object
|
||||
*
|
||||
* Reset the length of the stored data to zero, but do
|
||||
* not free / reallocate the memory buffer
|
||||
*/
|
||||
void buffer_reset(Buffer *buffer);
|
||||
|
||||
/**
|
||||
* buffer_free:
|
||||
* @buffer: the buffer object
|
||||
*
|
||||
* Reset the length of the stored data to zero and also
|
||||
* free the internal memory buffer
|
||||
*/
|
||||
void buffer_free(Buffer *buffer);
|
||||
|
||||
/**
|
||||
* buffer_append:
|
||||
* @buffer: the buffer object
|
||||
* @data: the data block to append
|
||||
* @len: the length of @data in bytes
|
||||
*
|
||||
* Append the contents of @data to the end of the buffer.
|
||||
* The caller must ensure that the buffer has sufficient
|
||||
* free space for @len bytes, typically by calling the
|
||||
* buffer_reserve() method prior to appending.
|
||||
*/
|
||||
void buffer_append(Buffer *buffer, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* buffer_advance:
|
||||
* @buffer: the buffer object
|
||||
* @len: the number of bytes to skip
|
||||
*
|
||||
* Remove @len bytes of data from the head of the buffer.
|
||||
* The internal buffer will not be reallocated, so will
|
||||
* have at least @len bytes of free space after this
|
||||
* call completes
|
||||
*/
|
||||
void buffer_advance(Buffer *buffer, size_t len);
|
||||
|
||||
/**
|
||||
* buffer_end:
|
||||
* @buffer: the buffer object
|
||||
*
|
||||
* Get a pointer to the tail end of the internal buffer
|
||||
* The returned pointer is only valid until the next
|
||||
* call to buffer_reserve().
|
||||
*
|
||||
* Returns: the tail of the buffer
|
||||
*/
|
||||
uint8_t *buffer_end(Buffer *buffer);
|
||||
|
||||
/**
|
||||
* buffer_empty:
|
||||
* @buffer: the buffer object
|
||||
*
|
||||
* Determine if the buffer contains any current data
|
||||
*
|
||||
* Returns: true if the buffer holds data, false otherwise
|
||||
*/
|
||||
gboolean buffer_empty(Buffer *buffer);
|
||||
|
||||
#endif /* QEMU_BUFFER_H__ */
|
|
@ -26,7 +26,7 @@
|
|||
#define QEMU_COROUTINE_INT_H
|
||||
|
||||
#include "qemu/queue.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
|
||||
typedef enum {
|
||||
COROUTINE_YIELD = 1,
|
|
@ -69,6 +69,8 @@
|
|||
#include "sysemu/os-posix.h"
|
||||
#endif
|
||||
|
||||
#include "qapi/error.h"
|
||||
|
||||
#if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10
|
||||
/* [u]int_fast*_t not in <sys/int_types.h> */
|
||||
typedef unsigned char uint_fast8_t;
|
||||
|
@ -286,4 +288,18 @@ void os_mem_prealloc(int fd, char *area, size_t sz);
|
|||
|
||||
int qemu_read_password(char *buf, int buf_size);
|
||||
|
||||
/**
|
||||
* qemu_fork:
|
||||
*
|
||||
* A version of fork that avoids signal handler race
|
||||
* conditions that can lead to child process getting
|
||||
* signals that are otherwise only expected by the
|
||||
* parent. It also resets all signal handlers to the
|
||||
* default settings.
|
||||
*
|
||||
* Returns 0 to child process, pid number to parent
|
||||
* or -1 on failure.
|
||||
*/
|
||||
pid_t qemu_fork(Error **errp);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -88,4 +88,38 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
|
|||
int parse_host_port(struct sockaddr_in *saddr, const char *str);
|
||||
int socket_init(void);
|
||||
|
||||
/**
|
||||
* socket_local_address:
|
||||
* @fd: the socket file handle
|
||||
* @errp: pointer to uninitialized error object
|
||||
*
|
||||
* Get the string representation of the local socket
|
||||
* address. A pointer to the allocated address information
|
||||
* struct will be returned, which the caller is required to
|
||||
* release with a call qapi_free_SocketAddress when no
|
||||
* longer required.
|
||||
*
|
||||
* Returns: the socket address struct, or NULL on error
|
||||
*/
|
||||
SocketAddress *socket_local_address(int fd, Error **errp);
|
||||
|
||||
/**
|
||||
* socket_remote_address:
|
||||
* @fd: the socket file handle
|
||||
* @errp: pointer to uninitialized error object
|
||||
*
|
||||
* Get the string representation of the remote socket
|
||||
* address. A pointer to the allocated address information
|
||||
* struct will be returned, which the caller is required to
|
||||
* release with a call qapi_free_SocketAddress when no
|
||||
* longer required.
|
||||
*
|
||||
* Returns: the socket address struct, or NULL on error
|
||||
*/
|
||||
SocketAddress *socket_remote_address(int fd, Error **errp);
|
||||
|
||||
|
||||
void qapi_copy_SocketAddress(SocketAddress **p_dest,
|
||||
SocketAddress *src);
|
||||
|
||||
#endif /* QEMU_SOCKET_H */
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "qemu/error-report.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "migration/migration.h"
|
||||
#include "migration/qemu-file.h"
|
||||
#include "migration/qemu-file-internal.h"
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu-common.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "migration/qemu-file.h"
|
||||
|
||||
typedef struct QEMUFileStdio {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "qemu-common.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "migration/qemu-file.h"
|
||||
#include "migration/qemu-file-internal.h"
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "qemu/error-report.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "migration/migration.h"
|
||||
#include "migration/qemu-file.h"
|
||||
#include "migration/qemu-file-internal.h"
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "qemu/main-loop.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
|
2
nbd.c
2
nbd.c
|
@ -19,7 +19,7 @@
|
|||
#include "block/nbd.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -2614,7 +2614,9 @@
|
|||
#
|
||||
# @host: host part of the address
|
||||
#
|
||||
# @port: port part of the address, or lowest port if @to is present
|
||||
# @port: port part of the address, or lowest port if @to is present.
|
||||
# Kernel selects a free port if omitted for listener addresses.
|
||||
# #optional
|
||||
#
|
||||
# @to: highest port to try
|
||||
#
|
||||
|
@ -2629,7 +2631,7 @@
|
|||
{ 'struct': 'InetSocketAddress',
|
||||
'data': {
|
||||
'host': 'str',
|
||||
'port': 'str',
|
||||
'*port': 'str',
|
||||
'*to': 'uint16',
|
||||
'*ipv4': 'bool',
|
||||
'*ipv6': 'bool' } }
|
||||
|
|
25
qemu-char.c
25
qemu-char.c
|
@ -92,31 +92,6 @@
|
|||
|
||||
/***********************************************************/
|
||||
/* Socket address helpers */
|
||||
static void qapi_copy_SocketAddress(SocketAddress **p_dest,
|
||||
SocketAddress *src)
|
||||
{
|
||||
QmpOutputVisitor *qov;
|
||||
QmpInputVisitor *qiv;
|
||||
Visitor *ov, *iv;
|
||||
QObject *obj;
|
||||
|
||||
*p_dest = NULL;
|
||||
|
||||
qov = qmp_output_visitor_new();
|
||||
ov = qmp_output_get_visitor(qov);
|
||||
visit_type_SocketAddress(ov, &src, NULL, &error_abort);
|
||||
obj = qmp_output_get_qobject(qov);
|
||||
qmp_output_visitor_cleanup(qov);
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
qiv = qmp_input_visitor_new(obj);
|
||||
iv = qmp_input_get_visitor(qiv);
|
||||
visit_type_SocketAddress(iv, p_dest, NULL, &error_abort);
|
||||
qmp_input_visitor_cleanup(qiv);
|
||||
qobject_decref(obj);
|
||||
}
|
||||
|
||||
static int SocketAddress_to_str(char *dest, int max_len,
|
||||
const char *prefix, SocketAddress *addr,
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include "block/coroutine.h"
|
||||
#include "block/coroutine_int.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/coroutine_int.h"
|
||||
|
||||
/*
|
||||
* Check that qemu_in_coroutine() works
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "qemu-common.h"
|
||||
#include "migration/migration.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
|
||||
static char temp_file[] = "/tmp/vmst.test.XXXXXX";
|
||||
static int temp_fd;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "qemu/queue.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "trace.h"
|
||||
#include "block/thread-pool.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
|
205
ui/vnc.c
205
ui/vnc.c
|
@ -647,49 +647,6 @@ void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
|
|||
vnc_write_s32(vs, encoding);
|
||||
}
|
||||
|
||||
void buffer_reserve(Buffer *buffer, size_t len)
|
||||
{
|
||||
if ((buffer->capacity - buffer->offset) < len) {
|
||||
buffer->capacity += (len + 1024);
|
||||
buffer->buffer = g_realloc(buffer->buffer, buffer->capacity);
|
||||
}
|
||||
}
|
||||
|
||||
static int buffer_empty(Buffer *buffer)
|
||||
{
|
||||
return buffer->offset == 0;
|
||||
}
|
||||
|
||||
uint8_t *buffer_end(Buffer *buffer)
|
||||
{
|
||||
return buffer->buffer + buffer->offset;
|
||||
}
|
||||
|
||||
void buffer_reset(Buffer *buffer)
|
||||
{
|
||||
buffer->offset = 0;
|
||||
}
|
||||
|
||||
void buffer_free(Buffer *buffer)
|
||||
{
|
||||
g_free(buffer->buffer);
|
||||
buffer->offset = 0;
|
||||
buffer->capacity = 0;
|
||||
buffer->buffer = NULL;
|
||||
}
|
||||
|
||||
void buffer_append(Buffer *buffer, const void *data, size_t len)
|
||||
{
|
||||
memcpy(buffer->buffer + buffer->offset, data, len);
|
||||
buffer->offset += len;
|
||||
}
|
||||
|
||||
void buffer_advance(Buffer *buf, size_t len)
|
||||
{
|
||||
memmove(buf->buffer, buf->buffer + len,
|
||||
(buf->offset - len));
|
||||
buf->offset -= len;
|
||||
}
|
||||
|
||||
static void vnc_desktop_resize(VncState *vs)
|
||||
{
|
||||
|
@ -3506,18 +3463,14 @@ void vnc_display_open(const char *id, Error **errp)
|
|||
{
|
||||
VncDisplay *vs = vnc_display_find(id);
|
||||
QemuOpts *opts = qemu_opts_find(&qemu_vnc_opts, id);
|
||||
QemuOpts *sopts, *wsopts;
|
||||
SocketAddress *saddr = NULL, *wsaddr = NULL;
|
||||
const char *share, *device_id;
|
||||
QemuConsole *con;
|
||||
bool password = false;
|
||||
bool reverse = false;
|
||||
const char *vnc;
|
||||
const char *has_to;
|
||||
char *h;
|
||||
bool has_ipv4 = false;
|
||||
bool has_ipv6 = false;
|
||||
const char *credid;
|
||||
const char *websocket;
|
||||
bool sasl = false;
|
||||
#ifdef CONFIG_VNC_SASL
|
||||
int saslErr;
|
||||
|
@ -3539,44 +3492,83 @@ void vnc_display_open(const char *id, Error **errp)
|
|||
return;
|
||||
}
|
||||
|
||||
sopts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
|
||||
wsopts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort);
|
||||
|
||||
h = strrchr(vnc, ':');
|
||||
if (h) {
|
||||
char *host;
|
||||
size_t hlen = h - vnc;
|
||||
|
||||
if (vnc[0] == '[' && vnc[hlen - 1] == ']') {
|
||||
host = g_strndup(vnc + 1, hlen - 2);
|
||||
} else {
|
||||
host = g_strndup(vnc, hlen);
|
||||
const char *websocket = qemu_opt_get(opts, "websocket");
|
||||
int to = qemu_opt_get_number(opts, "to", 0);
|
||||
bool has_ipv4 = qemu_opt_get_bool(opts, "ipv4", false);
|
||||
bool has_ipv6 = qemu_opt_get_bool(opts, "ipv6", false);
|
||||
|
||||
saddr = g_new0(SocketAddress, 1);
|
||||
if (websocket) {
|
||||
if (!qcrypto_hash_supports(QCRYPTO_HASH_ALG_SHA1)) {
|
||||
error_setg(errp,
|
||||
"SHA1 hash support is required for websockets");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
wsaddr = g_new0(SocketAddress, 1);
|
||||
vs->ws_enabled = true;
|
||||
}
|
||||
|
||||
if (strncmp(vnc, "unix:", 5) == 0) {
|
||||
saddr->kind = SOCKET_ADDRESS_KIND_UNIX;
|
||||
saddr->q_unix = g_new0(UnixSocketAddress, 1);
|
||||
saddr->q_unix->path = g_strdup(vnc + 5);
|
||||
|
||||
if (vs->ws_enabled) {
|
||||
error_setg(errp, "UNIX sockets not supported with websock");
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
unsigned long long baseport;
|
||||
saddr->kind = SOCKET_ADDRESS_KIND_INET;
|
||||
saddr->inet = g_new0(InetSocketAddress, 1);
|
||||
if (vnc[0] == '[' && vnc[hlen - 1] == ']') {
|
||||
saddr->inet->host = g_strndup(vnc + 1, hlen - 2);
|
||||
} else {
|
||||
saddr->inet->host = g_strndup(vnc, hlen);
|
||||
}
|
||||
if (parse_uint_full(h + 1, &baseport, 10) < 0) {
|
||||
error_setg(errp, "can't convert to a number: %s", h + 1);
|
||||
goto fail;
|
||||
}
|
||||
if (baseport > 65535 ||
|
||||
baseport + 5900 > 65535) {
|
||||
error_setg(errp, "port %s out of range", h + 1);
|
||||
goto fail;
|
||||
}
|
||||
saddr->inet->port = g_strdup_printf(
|
||||
"%d", (int)baseport + 5900);
|
||||
|
||||
if (to) {
|
||||
saddr->inet->has_to = true;
|
||||
saddr->inet->to = to;
|
||||
}
|
||||
saddr->inet->ipv4 = saddr->inet->has_ipv4 = has_ipv4;
|
||||
saddr->inet->ipv6 = saddr->inet->has_ipv6 = has_ipv6;
|
||||
|
||||
if (vs->ws_enabled) {
|
||||
wsaddr->kind = SOCKET_ADDRESS_KIND_INET;
|
||||
wsaddr->inet = g_new0(InetSocketAddress, 1);
|
||||
wsaddr->inet->host = g_strdup(saddr->inet->host);
|
||||
wsaddr->inet->port = g_strdup(websocket);
|
||||
|
||||
if (to) {
|
||||
wsaddr->inet->has_to = true;
|
||||
wsaddr->inet->to = to;
|
||||
}
|
||||
wsaddr->inet->ipv4 = wsaddr->inet->has_ipv4 = has_ipv4;
|
||||
wsaddr->inet->ipv6 = wsaddr->inet->has_ipv6 = has_ipv6;
|
||||
}
|
||||
}
|
||||
qemu_opt_set(sopts, "host", host, &error_abort);
|
||||
qemu_opt_set(wsopts, "host", host, &error_abort);
|
||||
qemu_opt_set(sopts, "port", h+1, &error_abort);
|
||||
g_free(host);
|
||||
} else {
|
||||
error_setg(errp, "no vnc port specified");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
has_to = qemu_opt_get(opts, "to");
|
||||
has_ipv4 = qemu_opt_get_bool(opts, "ipv4", false);
|
||||
has_ipv6 = qemu_opt_get_bool(opts, "ipv6", false);
|
||||
if (has_to) {
|
||||
qemu_opt_set(sopts, "to", has_to, &error_abort);
|
||||
qemu_opt_set(wsopts, "to", has_to, &error_abort);
|
||||
}
|
||||
if (has_ipv4) {
|
||||
qemu_opt_set(sopts, "ipv4", "on", &error_abort);
|
||||
qemu_opt_set(wsopts, "ipv4", "on", &error_abort);
|
||||
}
|
||||
if (has_ipv6) {
|
||||
qemu_opt_set(sopts, "ipv6", "on", &error_abort);
|
||||
qemu_opt_set(wsopts, "ipv6", "on", &error_abort);
|
||||
}
|
||||
|
||||
password = qemu_opt_get_bool(opts, "password", false);
|
||||
if (password) {
|
||||
if (fips_get_state()) {
|
||||
|
@ -3682,16 +3674,6 @@ void vnc_display_open(const char *id, Error **errp)
|
|||
}
|
||||
vs->connections_limit = qemu_opt_get_number(opts, "connections", 32);
|
||||
|
||||
websocket = qemu_opt_get(opts, "websocket");
|
||||
if (websocket) {
|
||||
vs->ws_enabled = true;
|
||||
qemu_opt_set(wsopts, "port", websocket, &error_abort);
|
||||
if (!qcrypto_hash_supports(QCRYPTO_HASH_ALG_SHA1)) {
|
||||
error_setg(errp, "SHA1 hash support is required for websockets");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VNC_JPEG
|
||||
vs->lossy = qemu_opt_get_bool(opts, "lossy", false);
|
||||
#endif
|
||||
|
@ -3725,7 +3707,7 @@ void vnc_display_open(const char *id, Error **errp)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (vnc_display_setup_auth(vs, password, sasl, websocket, errp) < 0) {
|
||||
if (vnc_display_setup_auth(vs, password, sasl, vs->ws_enabled, errp) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -3770,37 +3752,31 @@ void vnc_display_open(const char *id, Error **errp)
|
|||
int csock;
|
||||
vs->lsock = -1;
|
||||
vs->lwebsock = -1;
|
||||
if (strncmp(vnc, "unix:", 5) == 0) {
|
||||
csock = unix_connect(vnc+5, errp);
|
||||
} else {
|
||||
csock = inet_connect(vnc, errp);
|
||||
if (vs->ws_enabled) {
|
||||
error_setg(errp, "Cannot use websockets in reverse mode");
|
||||
goto fail;
|
||||
}
|
||||
csock = socket_connect(saddr, errp, NULL, NULL);
|
||||
if (csock < 0) {
|
||||
goto fail;
|
||||
}
|
||||
vs->is_unix = saddr->kind == SOCKET_ADDRESS_KIND_UNIX;
|
||||
vnc_connect(vs, csock, false, false);
|
||||
} else {
|
||||
/* listen for connects */
|
||||
if (strncmp(vnc, "unix:", 5) == 0) {
|
||||
vs->lsock = unix_listen(vnc+5, NULL, 0, errp);
|
||||
if (vs->lsock < 0) {
|
||||
goto fail;
|
||||
}
|
||||
vs->is_unix = true;
|
||||
} else {
|
||||
vs->lsock = inet_listen_opts(sopts, 5900, errp);
|
||||
if (vs->lsock < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if (vs->ws_enabled) {
|
||||
vs->lwebsock = inet_listen_opts(wsopts, 0, errp);
|
||||
if (vs->lwebsock < 0) {
|
||||
if (vs->lsock != -1) {
|
||||
close(vs->lsock);
|
||||
vs->lsock = -1;
|
||||
}
|
||||
goto fail;
|
||||
vs->lsock = socket_listen(saddr, errp);
|
||||
if (vs->lsock < 0) {
|
||||
goto fail;
|
||||
}
|
||||
vs->is_unix = saddr->kind == SOCKET_ADDRESS_KIND_UNIX;
|
||||
if (vs->ws_enabled) {
|
||||
vs->lwebsock = socket_listen(wsaddr, errp);
|
||||
if (vs->lwebsock < 0) {
|
||||
if (vs->lsock != -1) {
|
||||
close(vs->lsock);
|
||||
vs->lsock = -1;
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
vs->enabled = true;
|
||||
|
@ -3810,13 +3786,14 @@ void vnc_display_open(const char *id, Error **errp)
|
|||
NULL, vs);
|
||||
}
|
||||
}
|
||||
qemu_opts_del(sopts);
|
||||
qemu_opts_del(wsopts);
|
||||
|
||||
qapi_free_SocketAddress(saddr);
|
||||
qapi_free_SocketAddress(wsaddr);
|
||||
return;
|
||||
|
||||
fail:
|
||||
qemu_opts_del(sopts);
|
||||
qemu_opts_del(wsopts);
|
||||
qapi_free_SocketAddress(saddr);
|
||||
qapi_free_SocketAddress(wsaddr);
|
||||
vs->enabled = false;
|
||||
vs->ws_enabled = false;
|
||||
}
|
||||
|
|
16
ui/vnc.h
16
ui/vnc.h
|
@ -34,6 +34,7 @@
|
|||
#include "audio/audio.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "crypto/tlssession.h"
|
||||
#include "qemu/buffer.h"
|
||||
#include <zlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
@ -56,13 +57,6 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct Buffer
|
||||
{
|
||||
size_t capacity;
|
||||
size_t offset;
|
||||
uint8_t *buffer;
|
||||
} Buffer;
|
||||
|
||||
typedef struct VncState VncState;
|
||||
typedef struct VncJob VncJob;
|
||||
typedef struct VncRect VncRect;
|
||||
|
@ -535,14 +529,6 @@ ssize_t vnc_client_io_error(VncState *vs, ssize_t ret, int last_errno);
|
|||
void start_client_init(VncState *vs);
|
||||
void start_auth_vnc(VncState *vs);
|
||||
|
||||
/* Buffer management */
|
||||
void buffer_reserve(Buffer *buffer, size_t len);
|
||||
void buffer_reset(Buffer *buffer);
|
||||
void buffer_free(Buffer *buffer);
|
||||
void buffer_append(Buffer *buffer, const void *data, size_t len);
|
||||
void buffer_advance(Buffer *buf, size_t len);
|
||||
uint8_t *buffer_end(Buffer *buffer);
|
||||
|
||||
|
||||
/* Misc helpers */
|
||||
|
||||
|
|
|
@ -18,3 +18,7 @@ util-obj-y += getauxval.o
|
|||
util-obj-y += readline.o
|
||||
util-obj-y += rfifolock.o
|
||||
util-obj-y += rcu.o
|
||||
util-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
|
||||
util-obj-y += qemu-coroutine-sleep.o
|
||||
util-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
|
||||
util-obj-y += buffer.o
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* QEMU generic buffers
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/buffer.h"
|
||||
|
||||
void buffer_reserve(Buffer *buffer, size_t len)
|
||||
{
|
||||
if ((buffer->capacity - buffer->offset) < len) {
|
||||
buffer->capacity += (len + 1024);
|
||||
buffer->buffer = g_realloc(buffer->buffer, buffer->capacity);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean buffer_empty(Buffer *buffer)
|
||||
{
|
||||
return buffer->offset == 0;
|
||||
}
|
||||
|
||||
uint8_t *buffer_end(Buffer *buffer)
|
||||
{
|
||||
return buffer->buffer + buffer->offset;
|
||||
}
|
||||
|
||||
void buffer_reset(Buffer *buffer)
|
||||
{
|
||||
buffer->offset = 0;
|
||||
}
|
||||
|
||||
void buffer_free(Buffer *buffer)
|
||||
{
|
||||
g_free(buffer->buffer);
|
||||
buffer->offset = 0;
|
||||
buffer->capacity = 0;
|
||||
buffer->buffer = NULL;
|
||||
}
|
||||
|
||||
void buffer_append(Buffer *buffer, const void *data, size_t len)
|
||||
{
|
||||
memcpy(buffer->buffer + buffer->offset, data, len);
|
||||
buffer->offset += len;
|
||||
}
|
||||
|
||||
void buffer_advance(Buffer *buffer, size_t len)
|
||||
{
|
||||
memmove(buffer->buffer, buffer->buffer + len,
|
||||
(buffer->offset - len));
|
||||
buffer->offset -= len;
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include <glib.h>
|
||||
#include "qemu-common.h"
|
||||
#include "block/coroutine_int.h"
|
||||
#include "qemu/coroutine_int.h"
|
||||
|
||||
typedef struct {
|
||||
Coroutine base;
|
|
@ -31,7 +31,7 @@
|
|||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include "qemu-common.h"
|
||||
#include "block/coroutine_int.h"
|
||||
#include "qemu/coroutine_int.h"
|
||||
|
||||
typedef struct {
|
||||
Coroutine base;
|
|
@ -27,7 +27,7 @@
|
|||
#include <stdint.h>
|
||||
#include <ucontext.h>
|
||||
#include "qemu-common.h"
|
||||
#include "block/coroutine_int.h"
|
||||
#include "qemu/coroutine_int.h"
|
||||
|
||||
#ifdef CONFIG_VALGRIND_H
|
||||
#include <valgrind/valgrind.h>
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "block/coroutine_int.h"
|
||||
#include "qemu/coroutine_int.h"
|
||||
|
||||
typedef struct
|
||||
{
|
|
@ -490,3 +490,74 @@ int qemu_read_password(char *buf, int buf_size)
|
|||
printf("\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
pid_t qemu_fork(Error **errp)
|
||||
{
|
||||
sigset_t oldmask, newmask;
|
||||
struct sigaction sig_action;
|
||||
int saved_errno;
|
||||
pid_t pid;
|
||||
|
||||
/*
|
||||
* Need to block signals now, so that child process can safely
|
||||
* kill off caller's signal handlers without a race.
|
||||
*/
|
||||
sigfillset(&newmask);
|
||||
if (pthread_sigmask(SIG_SETMASK, &newmask, &oldmask) != 0) {
|
||||
error_setg_errno(errp, errno,
|
||||
"cannot block signals");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
saved_errno = errno;
|
||||
|
||||
if (pid < 0) {
|
||||
/* attempt to restore signal mask, but ignore failure, to
|
||||
* avoid obscuring the fork failure */
|
||||
(void)pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
|
||||
error_setg_errno(errp, saved_errno,
|
||||
"cannot fork child process");
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
} else if (pid) {
|
||||
/* parent process */
|
||||
|
||||
/* Restore our original signal mask now that the child is
|
||||
* safely running. Only documented failures are EFAULT (not
|
||||
* possible, since we are using just-grabbed mask) or EINVAL
|
||||
* (not possible, since we are using correct arguments). */
|
||||
(void)pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
|
||||
} else {
|
||||
/* child process */
|
||||
size_t i;
|
||||
|
||||
/* Clear out all signal handlers from parent so nothing
|
||||
* unexpected can happen in our child once we unblock
|
||||
* signals */
|
||||
sig_action.sa_handler = SIG_DFL;
|
||||
sig_action.sa_flags = 0;
|
||||
sigemptyset(&sig_action.sa_mask);
|
||||
|
||||
for (i = 1; i < NSIG; i++) {
|
||||
/* Only possible errors are EFAULT or EINVAL The former
|
||||
* won't happen, the latter we expect, so no need to check
|
||||
* return value */
|
||||
(void)sigaction(i, &sig_action, NULL);
|
||||
}
|
||||
|
||||
/* Unmask all signals in child, since we've no idea what the
|
||||
* caller's done with their signal mask and don't want to
|
||||
* propagate that to children */
|
||||
sigemptyset(&newmask);
|
||||
if (pthread_sigmask(SIG_SETMASK, &newmask, NULL) != 0) {
|
||||
Error *local_err = NULL;
|
||||
error_setg_errno(&local_err, errno,
|
||||
"cannot unblock signals");
|
||||
error_report_err(local_err);
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
|
|
@ -496,3 +496,12 @@ int qemu_read_password(char *buf, int buf_size)
|
|||
buf[i] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
pid_t qemu_fork(Error **errp)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
error_setg_errno(errp, errno,
|
||||
"cannot fork child process");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*/
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
|
@ -23,8 +23,8 @@
|
|||
*/
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "block/coroutine_int.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/coroutine_int.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "trace.h"
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "block/coroutine.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "block/aio.h"
|
||||
|
|
@ -16,8 +16,8 @@
|
|||
#include "qemu-common.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/atomic.h"
|
||||
#include "block/coroutine.h"
|
||||
#include "block/coroutine_int.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/coroutine_int.h"
|
||||
|
||||
enum {
|
||||
POOL_BATCH_SIZE = 64,
|
|
@ -25,6 +25,9 @@
|
|||
#include "monitor/monitor.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qapi/qmp-input-visitor.h"
|
||||
#include "qapi/qmp-output-visitor.h"
|
||||
#include "qapi-visit.h"
|
||||
|
||||
#ifndef AI_ADDRCONFIG
|
||||
# define AI_ADDRCONFIG 0
|
||||
|
@ -125,12 +128,15 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
|
|||
ai.ai_family = PF_UNSPEC;
|
||||
ai.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if ((qemu_opt_get(opts, "host") == NULL) ||
|
||||
(qemu_opt_get(opts, "port") == NULL)) {
|
||||
error_setg(errp, "host and/or port not specified");
|
||||
if ((qemu_opt_get(opts, "host") == NULL)) {
|
||||
error_setg(errp, "host not specified");
|
||||
return -1;
|
||||
}
|
||||
pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
|
||||
if (qemu_opt_get(opts, "port") != NULL) {
|
||||
pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
|
||||
} else {
|
||||
port[0] = '\0';
|
||||
}
|
||||
addr = qemu_opt_get(opts, "host");
|
||||
|
||||
to = qemu_opt_get_number(opts, "to", 0);
|
||||
|
@ -142,6 +148,10 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
|
|||
/* lookup */
|
||||
if (port_offset) {
|
||||
unsigned long long baseport;
|
||||
if (strlen(port) == 0) {
|
||||
error_setg(errp, "port not specified");
|
||||
return -1;
|
||||
}
|
||||
if (parse_uint_full(port, &baseport, 10) < 0) {
|
||||
error_setg(errp, "can't convert to a number: %s", port);
|
||||
return -1;
|
||||
|
@ -153,7 +163,8 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
|
|||
}
|
||||
snprintf(port, sizeof(port), "%d", (int)baseport + port_offset);
|
||||
}
|
||||
rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
|
||||
rc = getaddrinfo(strlen(addr) ? addr : NULL,
|
||||
strlen(port) ? port : NULL, &ai, &res);
|
||||
if (rc != 0) {
|
||||
error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
|
||||
gai_strerror(rc));
|
||||
|
@ -1018,3 +1029,140 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
|
|||
qemu_opts_del(opts);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
static SocketAddress *
|
||||
socket_sockaddr_to_address_inet(struct sockaddr_storage *sa,
|
||||
socklen_t salen,
|
||||
Error **errp)
|
||||
{
|
||||
char host[NI_MAXHOST];
|
||||
char serv[NI_MAXSERV];
|
||||
SocketAddress *addr;
|
||||
int ret;
|
||||
|
||||
ret = getnameinfo((struct sockaddr *)sa, salen,
|
||||
host, sizeof(host),
|
||||
serv, sizeof(serv),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV);
|
||||
if (ret != 0) {
|
||||
error_setg(errp, "Cannot format numeric socket address: %s",
|
||||
gai_strerror(ret));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
addr = g_new0(SocketAddress, 1);
|
||||
addr->kind = SOCKET_ADDRESS_KIND_INET;
|
||||
addr->inet = g_new0(InetSocketAddress, 1);
|
||||
addr->inet->host = g_strdup(host);
|
||||
addr->inet->port = g_strdup(serv);
|
||||
if (sa->ss_family == AF_INET) {
|
||||
addr->inet->has_ipv4 = addr->inet->ipv4 = true;
|
||||
} else {
|
||||
addr->inet->has_ipv6 = addr->inet->ipv6 = true;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
static SocketAddress *
|
||||
socket_sockaddr_to_address_unix(struct sockaddr_storage *sa,
|
||||
socklen_t salen,
|
||||
Error **errp)
|
||||
{
|
||||
SocketAddress *addr;
|
||||
struct sockaddr_un *su = (struct sockaddr_un *)sa;
|
||||
|
||||
addr = g_new0(SocketAddress, 1);
|
||||
addr->kind = SOCKET_ADDRESS_KIND_UNIX;
|
||||
addr->q_unix = g_new0(UnixSocketAddress, 1);
|
||||
if (su->sun_path[0]) {
|
||||
addr->q_unix->path = g_strndup(su->sun_path,
|
||||
sizeof(su->sun_path));
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
||||
static SocketAddress *
|
||||
socket_sockaddr_to_address(struct sockaddr_storage *sa,
|
||||
socklen_t salen,
|
||||
Error **errp)
|
||||
{
|
||||
switch (sa->ss_family) {
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
return socket_sockaddr_to_address_inet(sa, salen, errp);
|
||||
|
||||
#ifndef WIN32
|
||||
case AF_UNIX:
|
||||
return socket_sockaddr_to_address_unix(sa, salen, errp);
|
||||
#endif /* WIN32 */
|
||||
|
||||
default:
|
||||
error_setg(errp, "socket family %d unsupported",
|
||||
sa->ss_family);
|
||||
return NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SocketAddress *socket_local_address(int fd, Error **errp)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t sslen = sizeof(ss);
|
||||
|
||||
if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) {
|
||||
error_setg_errno(errp, socket_error(), "%s",
|
||||
"Unable to query local socket address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return socket_sockaddr_to_address(&ss, sslen, errp);
|
||||
}
|
||||
|
||||
|
||||
SocketAddress *socket_remote_address(int fd, Error **errp)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t sslen = sizeof(ss);
|
||||
|
||||
if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) {
|
||||
error_setg_errno(errp, socket_error(), "%s",
|
||||
"Unable to query remote socket address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return socket_sockaddr_to_address(&ss, sslen, errp);
|
||||
}
|
||||
|
||||
|
||||
void qapi_copy_SocketAddress(SocketAddress **p_dest,
|
||||
SocketAddress *src)
|
||||
{
|
||||
QmpOutputVisitor *qov;
|
||||
QmpInputVisitor *qiv;
|
||||
Visitor *ov, *iv;
|
||||
QObject *obj;
|
||||
|
||||
*p_dest = NULL;
|
||||
|
||||
qov = qmp_output_visitor_new();
|
||||
ov = qmp_output_get_visitor(qov);
|
||||
visit_type_SocketAddress(ov, &src, NULL, &error_abort);
|
||||
obj = qmp_output_get_qobject(qov);
|
||||
qmp_output_visitor_cleanup(qov);
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
qiv = qmp_input_visitor_new(obj);
|
||||
iv = qmp_input_get_visitor(qiv);
|
||||
visit_type_SocketAddress(iv, p_dest, NULL, &error_abort);
|
||||
qmp_input_visitor_cleanup(qiv);
|
||||
qobject_decref(obj);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue