summaryrefslogtreecommitdiff
path: root/vdagent.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2010-09-14 18:03:47 +0200
committerHans de Goede <hdegoede@redhat.com>2010-09-14 18:03:47 +0200
commit67f92ea676968f3ec6f6b8ab3fdc0a6bc33c987e (patch)
tree93b38e7ec6ed6b40b5381e63b8dab3e6c8d45f1b /vdagent.c
parente90aff7f90f7f58db242a57a2340b60960ce143c (diff)
Add unix domain client server support
To get a properly functioning agent we will need to split the functionality into a daemon (vdagentd, which has the rights to open the virtio device and to create fake input devices for the mouse) and into a client (vdagent) which runs under Xorg and thus can read / set things like the resolution and the clipboard and talks to the spice server / client through the daemon. Since we can have multiple xorg sessions active (through switch user for example), the daemon supports multiple agent connections. Security still needs to be filled in I'm afraid (see TODO). The protocol between the 2 is "described" in vdagentd-proto.h, currently there is only one vdagentd command, which allows vdagent to tell vdagentd the xorg screen resolution so that it knows what resolution to use for the fake absolute input device, and so that it can adjust that resolution if the xorg resolution changes. The client included in this commit is purely a test client, which just sends a hardcoded resolution once and then sits there and does nothing.
Diffstat (limited to 'vdagent.c')
-rw-r--r--vdagent.c79
1 files changed, 76 insertions, 3 deletions
diff --git a/vdagent.c b/vdagent.c
index e8e9128..1d140c0 100644
--- a/vdagent.c
+++ b/vdagent.c
@@ -5,6 +5,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
+#include <sys/select.h>
#include <linux/input.h>
#include <linux/uinput.h>
@@ -13,6 +14,9 @@
#include <spice/vd_agent.h>
+#include "udscs.h"
+#include "vdagentd-proto.h"
+
typedef struct VDAgentHeader {
uint32_t port;
uint32_t size;
@@ -26,6 +30,7 @@ static const char *uinput = "/dev/uinput";
static int vdagent, tablet;
static int debug = 0;
static int width = 1024, height = 768; /* FIXME: don't hardcode */
+static struct udscs_server *server = NULL;
/* uinput */
@@ -209,6 +214,66 @@ void daemonize(void)
}
}
+void client_read_complete(struct udscs_connection *conn,
+ struct udscs_message_header *header, const uint8_t *data)
+{
+ switch (header->type) {
+ case VDAGENTD_GUEST_XORG_RESOLUTION: {
+ struct vdagentd_guest_xorg_resolution *res =
+ (struct vdagentd_guest_xorg_resolution *)data;
+
+ if (header->size != sizeof(*res)) {
+ /* FIXME destroy connection, but this will cause a double
+ free of data */
+ break;
+ }
+
+ width = res->width;
+ height = res->height;
+ close(tablet);
+ tablet = open(uinput, O_RDWR);
+ if (-1 == tablet) {
+ fprintf(stderr, "open %s: %s\n", uinput, strerror(errno));
+ exit(1);
+ }
+ uinput_setup();
+ break;
+ }
+ default:
+ fprintf(stderr, "unknown message from vdagent client: %u, ignoring\n",
+ header->type);
+ }
+}
+
+void main_loop(void)
+{
+ fd_set readfds, writefds;
+ int n, nfds;
+
+ for (;;) {
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+
+ nfds = udscs_server_fill_fds(server, &readfds, &writefds);
+
+ FD_SET(vdagent, &readfds);
+ if (vdagent >= nfds)
+ nfds = vdagent + 1;
+
+ n = select(nfds, &readfds, &writefds, NULL, NULL);
+ if (n == -1) {
+ if (errno == EINTR)
+ continue;
+ perror("select");
+ exit(1);
+ }
+
+ udscs_server_handle_fds(server, &readfds, &writefds);
+ if (FD_ISSET(vdagent, &readfds))
+ vdagent_read();
+ }
+}
+
int main(int argc, char *argv[])
{
int c;
@@ -241,12 +306,18 @@ int main(int argc, char *argv[])
}
}
+ /* Open virtio port connection */
vdagent = open(portdev, O_RDWR);
if (-1 == vdagent) {
fprintf(stderr, "open %s: %s\n", portdev, strerror(errno));
exit(1);
}
+ /* Setup communication with vdagent process(es) */
+ server = udscs_create_server(VDAGENTD_SOCKET, client_read_complete, NULL);
+ if (!server)
+ exit(1);
+
tablet = open(uinput, O_RDWR);
if (-1 == tablet) {
fprintf(stderr, "open %s: %s\n", uinput, strerror(errno));
@@ -256,8 +327,10 @@ int main(int argc, char *argv[])
if (!debug)
daemonize();
- for (;;) {
- vdagent_read();
- }
+
+ main_loop();
+
+ udscs_destroy_server(server);
+
return 0;
}