*
* 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/osdep.h"
+#include "qemu-common.h"
#include "qapi/error.h"
+#include "qapi/qapi-visit-sockets.h"
+#include "qemu/module.h"
#include "io/channel-socket.h"
#include "io/channel-watch.h"
#include "trace.h"
SocketAddress *addr,
QIOTaskFunc callback,
gpointer opaque,
- GDestroyNotify destroy)
+ GDestroyNotify destroy,
+ GMainContext *context)
{
QIOTask *task = qio_task_new(
OBJECT(ioc), callback, opaque, destroy);
qio_task_run_in_thread(task,
qio_channel_socket_connect_worker,
addrCopy,
- (GDestroyNotify)qapi_free_SocketAddress);
+ (GDestroyNotify)qapi_free_SocketAddress,
+ context);
}
int qio_channel_socket_listen_sync(QIOChannelSocket *ioc,
SocketAddress *addr,
+ int num,
Error **errp)
{
int fd;
- trace_qio_channel_socket_listen_sync(ioc, addr);
- fd = socket_listen(addr, errp);
+ trace_qio_channel_socket_listen_sync(ioc, addr, num);
+ fd = socket_listen(addr, num, errp);
if (fd < 0) {
trace_qio_channel_socket_listen_fail(ioc);
return -1;
}
+struct QIOChannelListenWorkerData {
+ SocketAddress *addr;
+ int num; /* amount of expected connections */
+};
+
+static void qio_channel_listen_worker_free(gpointer opaque)
+{
+ struct QIOChannelListenWorkerData *data = opaque;
+
+ qapi_free_SocketAddress(data->addr);
+ g_free(data);
+}
+
static void qio_channel_socket_listen_worker(QIOTask *task,
gpointer opaque)
{
QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
- SocketAddress *addr = opaque;
+ struct QIOChannelListenWorkerData *data = opaque;
Error *err = NULL;
- qio_channel_socket_listen_sync(ioc, addr, &err);
+ qio_channel_socket_listen_sync(ioc, data->addr, data->num, &err);
qio_task_set_error(task, err);
}
void qio_channel_socket_listen_async(QIOChannelSocket *ioc,
SocketAddress *addr,
+ int num,
QIOTaskFunc callback,
gpointer opaque,
- GDestroyNotify destroy)
+ GDestroyNotify destroy,
+ GMainContext *context)
{
QIOTask *task = qio_task_new(
OBJECT(ioc), callback, opaque, destroy);
- SocketAddress *addrCopy;
+ struct QIOChannelListenWorkerData *data;
- addrCopy = QAPI_CLONE(SocketAddress, addr);
+ data = g_new0(struct QIOChannelListenWorkerData, 1);
+ data->addr = QAPI_CLONE(SocketAddress, addr);
+ data->num = num;
/* socket_listen() blocks in DNS lookups, so we must use a thread */
- trace_qio_channel_socket_listen_async(ioc, addr);
+ trace_qio_channel_socket_listen_async(ioc, addr, num);
qio_task_run_in_thread(task,
qio_channel_socket_listen_worker,
- addrCopy,
- (GDestroyNotify)qapi_free_SocketAddress);
+ data,
+ qio_channel_listen_worker_free,
+ context);
}
SocketAddress *remoteAddr,
QIOTaskFunc callback,
gpointer opaque,
- GDestroyNotify destroy)
+ GDestroyNotify destroy,
+ GMainContext *context)
{
QIOTask *task = qio_task_new(
OBJECT(ioc), callback, opaque, destroy);
qio_task_run_in_thread(task,
qio_channel_socket_dgram_worker,
data,
- qio_channel_socket_dgram_worker_free);
+ qio_channel_socket_dgram_worker_free,
+ context);
}
Error **errp)
{
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
+ int rc = 0;
+ Error *err = NULL;
if (sioc->fd != -1) {
#ifdef WIN32
WSAEventSelect(sioc->fd, NULL, 0);
#endif
+ if (qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_LISTEN)) {
+ socket_listen_cleanup(sioc->fd, errp);
+ }
+
if (closesocket(sioc->fd) < 0) {
sioc->fd = -1;
- error_setg_errno(errp, errno,
- "Unable to close socket");
+ error_setg_errno(&err, errno, "Unable to close socket");
+ error_propagate(errp, err);
return -1;
}
sioc->fd = -1;
}
- return 0;
+ return rc;
}
static int