#include "qapi/qapi-visit-sockets.h"
#include "chardev/char-io.h"
+#include "qom/object.h"
/***********************************************************/
/* TCP Net console */
TCP_CHARDEV_STATE_CONNECTED,
} TCPChardevState;
-typedef struct {
+struct SocketChardev {
Chardev parent;
QIOChannel *ioc; /* Client I/O channel */
QIOChannelSocket *sioc; /* Client master channel */
bool connect_err_reported;
QIOTask *connect_task;
-} SocketChardev;
+};
+typedef struct SocketChardev SocketChardev;
#define SOCKET_CHARDEV(obj) \
OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET)
SocketChardev *s = SOCKET_CHARDEV(chr);
if (!s->connect_err_reported) {
- error_report("Unable to connect character device %s: %s",
- chr->label, error_get_pretty(err));
+ error_reportf_err(err,
+ "Unable to connect character device %s: ",
+ chr->label);
s->connect_err_reported = true;
+ } else {
+ error_free(err);
}
qemu_chr_socket_restart_timer(chr);
}
if (ret < 0 && errno != EAGAIN) {
if (tcp_chr_read_poll(chr) <= 0) {
+ /* Perform disconnect and return error. */
tcp_chr_disconnect_locked(chr);
- return len;
} /* else let the read handler finish it properly */
}
return ret;
} else {
- /* XXX: indicate an error ? */
- return len;
+ /* Indicate an error. */
+ errno = EIO;
+ return -1;
}
}
if (emit_close) {
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
- if (s->reconnect_time) {
+ if (s->reconnect_time && !s->reconnect_timer) {
qemu_chr_socket_restart_timer(chr);
}
}
qio_channel_set_blocking(s->ioc, true, NULL);
size = tcp_chr_recv(chr, (void *) buf, len);
- qio_channel_set_blocking(s->ioc, false, NULL);
+ if (s->state != TCP_CHARDEV_STATE_DISCONNECTED) {
+ qio_channel_set_blocking(s->ioc, false, NULL);
+ }
if (size == 0) {
/* connection closed */
tcp_chr_disconnect(chr);
{
SocketChardev *s = SOCKET_CHARDEV(chr);
QIOChannelTLS *tioc;
- Error *err = NULL;
gchar *name;
if (s->is_listen) {
tioc = qio_channel_tls_new_server(
s->ioc, s->tls_creds,
s->tls_authz,
- &err);
+ NULL);
} else {
tioc = qio_channel_tls_new_client(
s->ioc, s->tls_creds,
s->addr->u.inet.host,
- &err);
+ NULL);
}
if (tioc == NULL) {
- error_free(err);
tcp_chr_disconnect(chr);
return;
}
if (qio_task_propagate_error(task, &err)) {
tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
check_report_connect_error(chr, err);
- error_free(err);
goto cleanup;
}
*/
s->connect_task = qio_task_new(OBJECT(sioc),
qemu_chr_socket_connected,
- chr, NULL);
+ object_ref(OBJECT(chr)),
+ (GDestroyNotify)object_unref);
qio_task_run_in_thread(s->connect_task,
tcp_chr_connect_client_task,
s->addr,