[Spice-commits] 5 commits - vdagent/pci_vdi_port.cpp vdagent/pci_vdi_port.h vdagent/vdagent.cpp vdagent/vdagent.vcproj vdagent/vdi_port.cpp vdagent/vdi_port.h vdagent/virtio_vdi_port.cpp vdagent/virtio_vdi_port.h vdservice/vdservice.cpp

Arnon Gilboa agilboa at kemper.freedesktop.org
Sun Dec 9 01:26:35 PST 2012


 vdagent/pci_vdi_port.cpp    |  132 ---------------------
 vdagent/pci_vdi_port.h      |   59 ---------
 vdagent/vdagent.cpp         |  269 ++++++++++++++++++++------------------------
 vdagent/vdagent.vcproj      |   24 ---
 vdagent/vdi_port.cpp        |   90 --------------
 vdagent/vdi_port.h          |   75 ------------
 vdagent/virtio_vdi_port.cpp |  187 ------------------------------
 vdagent/virtio_vdi_port.h   |   33 -----
 vdservice/vdservice.cpp     |    7 +
 9 files changed, 132 insertions(+), 744 deletions(-)

New commits:
commit cd4baafb03446ab316c27f44a2af431676b6bf2c
Author: Arnon Gilboa <agilboa at redhat.com>
Date:   Tue Nov 27 16:41:42 2012 +0200

    vdagent: git rm *vdi_port*

diff --git a/vdagent/pci_vdi_port.cpp b/vdagent/pci_vdi_port.cpp
deleted file mode 100644
index 7466fbc..0000000
--- a/vdagent/pci_vdi_port.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdio.h"
-#include "pci_vdi_port.h"
-#include "vdlog.h"
-
-#define VDI_PORT_DEV_NAME   TEXT("\\\\.\\VDIPort")
-#define FILE_DEVICE_UNKNOWN 0x00000022
-#define METHOD_BUFFERED     0
-#define FILE_ANY_ACCESS     0
-
-#ifndef CTL_CODE
-//With mingw, this is defined in winioctl.h
-#define CTL_CODE(DeviceType, Function, Method, Access) (                   \
-    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
-)
-#endif
-
-#define FIRST_AVAIL_IO_FUNC 0x800
-#define RED_TUNNEL_CTL_FUNC FIRST_AVAIL_IO_FUNC
-
-#define IOCTL_RED_TUNNEL_SET_EVENT \
-    CTL_CODE(FILE_DEVICE_UNKNOWN, RED_TUNNEL_CTL_FUNC, METHOD_BUFFERED, FILE_ANY_ACCESS)
-
-#define MIN(a, b) ((a) > (b) ? (b) : (a))
-
-PCIVDIPort::PCIVDIPort()
-    : _handle (INVALID_HANDLE_VALUE)
-    , _event (NULL)
-{
-}
-
-PCIVDIPort::~PCIVDIPort()
-{
-    if (_handle != INVALID_HANDLE_VALUE) {
-        CloseHandle(_handle);
-    }
-    if (_event) {
-        CloseHandle(_event);
-    }
-}
-
-void PCIVDIPort::fill_events(HANDLE* handles) {
-    handles[PCI_VDI_PORT_EVENT] = _event;
-}
-
-bool PCIVDIPort::init()
-{
-    DWORD io_ret_len;
-    _handle = CreateFile(VDI_PORT_DEV_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
-                         OPEN_EXISTING, 0, NULL);
-    if (_handle == INVALID_HANDLE_VALUE) {
-        vd_printf("CreateFile() failed: %lu", GetLastError());
-        return false;
-    }
-    _event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (_event == NULL) {
-        vd_printf("CreateEvent() failed: %lu", GetLastError());
-        return false;
-    }
-    if (!DeviceIoControl(_handle, IOCTL_RED_TUNNEL_SET_EVENT, &_event, sizeof(_event),
-                         NULL, 0, &io_ret_len, NULL)) {
-        vd_printf("DeviceIoControl() failed: %lu", GetLastError());
-        return false;
-    }
-    return true;
-}
-
-int PCIVDIPort::write()
-{
-    int size;
-    int n;
-
-    if (_write.start == _write.end) {
-        return 0;
-    }
-    if (_write.start < _write.end) {
-        size = (int)(_write.end - _write.start);
-    } else {
-        size = (int)(&_write.ring[BUF_SIZE] - _write.start);
-    }
-    if (!WriteFile(_handle, _write.start, size, (LPDWORD)&n, NULL)) {
-        return handle_error();
-    }
-    _write.start = _write.ring + (_write.start - _write.ring + n) % BUF_SIZE;
-    return n;
-}
-
-int PCIVDIPort::read()
-{
-    int size;
-    int n;
-
-    if ((_read.end - _read.ring + 1) % BUF_SIZE == _read.start - _read.ring) {
-        return 0;
-    }
-    if (_read.start == _read.end) {
-        _read.start = _read.end = _read.ring;
-    }
-    if (_read.start <= _read.end) {
-        size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
-    } else {
-        size = (int)(_read.start - _read.end - 1);
-    }
-    if (!ReadFile(_handle, _read.end, size, (LPDWORD)&n, NULL)) {
-        return handle_error();
-    }
-    _read.end = _read.ring + (_read.end - _read.ring + n) % BUF_SIZE;
-    return n;
-}
-
-bool PCIVDIPort::handle_event(int event)
-{
-    // do nothing - the event merely serves to wake us up, then we call read/write
-    // at VDService::execute start of while(_running) loop.
-    return true;
-}
diff --git a/vdagent/pci_vdi_port.h b/vdagent/pci_vdi_port.h
deleted file mode 100644
index fcc76dc..0000000
--- a/vdagent/pci_vdi_port.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_PCI_VDI_PORT
-#define _H_PCI_VDI_PORT
-
-#include "vdi_port.h"
-
-#define BUF_READ    (1 << 0)
-#define BUF_WRITE   (1 << 1)
-#define BUF_ALL     (BUF_READ | BUF_WRITE)
-
-enum {
-    PCI_VDI_PORT_EVENT = 0,
-    PCI_VDI_PORT_EVENT_COUNT
-};
-
-class PCIVDIPort : public VDIPort {
-public:
-    PCIVDIPort();
-    ~PCIVDIPort();
-    virtual bool init();
-    virtual const char *name() {
-        return "PCIVDIPort";
-    }
-    virtual int write();
-    virtual int read();
-    virtual unsigned get_num_events() { return PCI_VDI_PORT_EVENT_COUNT; }
-    virtual void fill_events(HANDLE* handles);
-    virtual bool handle_event(int event);
-
-private:
-    HANDLE _handle;
-    HANDLE _event;
-};
-
-// Ring notes:
-// _end is one after the end of data
-// _start==_end means empty ring
-// _start-1==_end (modulo) means full ring
-// _start-1 is never used
-// ring_write & read on right side of the ring (update _end)
-// ring_read & write from left (update _start)
-
-#endif
diff --git a/vdagent/vdi_port.cpp b/vdagent/vdi_port.cpp
deleted file mode 100644
index bd5ea05..0000000
--- a/vdagent/vdi_port.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "vdlog.h"
-#include "vdi_port.h"
-
-VDIPort::VDIPort()
-{
-    ZeroMemory(&_write, offsetof(VDIPortBuffer, ring));
-    _write.start = _write.end = _write.ring;
-    ZeroMemory(&_read, offsetof(VDIPortBuffer, ring));
-    _read.start = _read.end = _read.ring;
-}
-
-size_t VDIPort::read_ring_size()
-{
-    return (BUF_SIZE + _read.end - _read.start) % BUF_SIZE;
-}
-
-size_t VDIPort::write_ring_free_space()
-{
-    return (BUF_SIZE + _write.start - _write.end - 1) % BUF_SIZE;
-}
-
-size_t VDIPort::ring_write(const void* buf, size_t size)
-{
-    size_t free_size = (BUF_SIZE + _write.start - _write.end - 1) % BUF_SIZE;
-    size_t n;
-
-    if (size > free_size) {
-        size = free_size;
-    }
-    if (_write.end < _write.start) {
-        memcpy(_write.end, buf, size);
-    } else {
-        n = MIN(size, (size_t)(&_write.ring[BUF_SIZE] - _write.end));
-        memcpy(_write.end, buf, n);
-        if (size > n) {
-            memcpy(_write.ring, (uint8_t*)buf + n, size - n);
-        }
-    }
-    _write.end = _write.ring + (_write.end - _write.ring + size) % BUF_SIZE;
-    return size;
-}
-
-size_t VDIPort::read_ring_continuous_remaining_size()
-{
-    DWORD size;
-
-    if (_read.start <= _read.end) {
-        size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
-    } else {
-        size = (DWORD)(_read.start - _read.end - 1);
-    }
-    return size;
-}
-
-size_t VDIPort::ring_read(void* buf, size_t size)
-{
-    size_t n;
-    size_t m = 0;
-
-    if (_read.start == _read.end) {
-        return 0;
-    }
-    if (_read.start < _read.end) {
-        n = MIN(size, (size_t)(_read.end - _read.start));
-        memcpy(buf, _read.start, n);
-    } else {
-        n = MIN(size, (size_t)(&_read.ring[BUF_SIZE] - _read.start));
-        memcpy(buf, _read.start, n);
-        if (size > n) {
-            m = MIN(size - n, (size_t)(_read.end - _read.ring));
-            memcpy((uint8_t*)buf + n, _read.ring, m);
-        }
-    }
-    _read.start = _read.ring + (_read.start - _read.ring + n + m) % BUF_SIZE;
-    return n + m;
-}
-
-int VDIPort::handle_error()
-{
-    switch (GetLastError()) {
-    case ERROR_CONNECTION_INVALID:
-        vd_printf("port reset");
-        _write.start = _write.end = _write.ring;
-        _read.start = _read.end = _read.ring;
-        return VDI_PORT_RESET;
-    default:
-        vd_printf("port io failed: %lu", GetLastError());
-        return VDI_PORT_ERROR;
-    }
-}
diff --git a/vdagent/vdi_port.h b/vdagent/vdi_port.h
deleted file mode 100644
index a0fb20e..0000000
--- a/vdagent/vdi_port.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_VDI_PORT
-#define _H_VDI_PORT
-
-#include <windows.h>
-#include <stdint.h>
-
-#define MIN(a, b) ((a) > (b) ? (b) : (a))
-
-#define BUF_SIZE    (1024 * 1024)
-
-#define VDI_PORT_BLOCKED    0
-#define VDI_PORT_RESET      -1
-#define VDI_PORT_ERROR      -2
-
-// Ring notes:
-// _end is one after the end of data
-// _start==_end means empty ring
-// _start-1==_end (modulo) means full ring
-// _start-1 is never used
-// ring_write & read on right side of the ring (update _end)
-// ring_read & write from left (update _start)
-
-typedef struct VDIPortBuffer {
-    OVERLAPPED overlap;
-    uint8_t* start;
-    uint8_t* end;
-    bool pending;
-    int bytes;
-    uint8_t ring[BUF_SIZE];
-} VDIPortBuffer;
-
-class VDIPort {
-public:
-    VDIPort();
-    virtual ~VDIPort() {}
-
-    size_t ring_write(const void* buf, size_t size);
-    size_t write_ring_free_space();
-    size_t ring_read(void* buf, size_t size);
-    size_t read_ring_size();
-    size_t read_ring_continuous_remaining_size();
-
-    virtual const char *name() = 0;
-    virtual bool init() = 0;
-    virtual unsigned get_num_events() = 0;
-    virtual void fill_events(HANDLE* handles) = 0;
-    virtual bool handle_event(int event) = 0;
-    virtual int write() = 0;
-    virtual int read() = 0;
-
-protected:
-    int handle_error();
-
-    VDIPortBuffer _write;
-    VDIPortBuffer _read;
-};
-
-#endif
diff --git a/vdagent/virtio_vdi_port.cpp b/vdagent/virtio_vdi_port.cpp
deleted file mode 100644
index be5568a..0000000
--- a/vdagent/virtio_vdi_port.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdio.h"
-#include "virtio_vdi_port.h"
-#include "vdlog.h"
-
-#define VIOSERIAL_PORT_PATH                 L"\\\\.\\Global\\com.redhat.spice.0"
-
-// Current limitation of virtio-serial windows driver (RHBZ 617000)
-#define VIOSERIAL_PORT_MAX_WRITE_BYTES      2048
-
-VirtioVDIPort* VirtioVDIPort::_singleton;
-
-VirtioVDIPort::VirtioVDIPort()
-    : VDIPort()
-    , _handle (INVALID_HANDLE_VALUE)
-{
-    _singleton = this;
-}
-
-VirtioVDIPort::~VirtioVDIPort()
-{
-    if (_handle != INVALID_HANDLE_VALUE) {
-        CloseHandle(_handle);
-    }
-    if (_read.overlap.hEvent) {
-        CloseHandle(_read.overlap.hEvent);
-    }
-    if (_write.overlap.hEvent) {
-        CloseHandle(_write.overlap.hEvent);
-    }
-}
-
-void VirtioVDIPort::fill_events(HANDLE* handles) {
-    handles[VIRTIO_VDI_PORT_EVENT_WRITE] = _write.overlap.hEvent;
-    handles[VIRTIO_VDI_PORT_EVENT_READ] = _read.overlap.hEvent;
-}
-
-bool VirtioVDIPort::handle_event(int event) {
-    bool ret;
-
-    switch (event) {
-        case VIRTIO_VDI_PORT_EVENT_WRITE:
-            ret = write_completion();
-            break;
-        case VIRTIO_VDI_PORT_EVENT_READ:
-            ret = read_completion();
-            break;
-        default:
-            vd_printf("ERROR: unexpected event %d", event);
-            ret = false;
-    }
-    return ret;
-}
-
-bool VirtioVDIPort::init()
-{
-    _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
-                         OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
-    if (_handle == INVALID_HANDLE_VALUE) {
-        vd_printf("CreateFile() %ls failed: %lu", VIOSERIAL_PORT_PATH, GetLastError());
-        return false;
-    }
-    _write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (_write.overlap.hEvent == NULL) {
-        vd_printf("CreateEvent() failed: %lu", GetLastError());
-        return false;
-    }
-    _read.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (_read.overlap.hEvent == NULL) {
-        vd_printf("CreateEvent() failed: %lu", GetLastError());
-        return false;
-    }
-    return true;
-}
-
-int VirtioVDIPort::write()
-{
-    int size;
-    int ret;
-
-    //FIXME: return VDI_PORT_NO_DATA
-    if (_write.start == _write.end) {
-        return 0;
-    }
-    if (!_write.pending) {
-        if (_write.start < _write.end) {
-            size = (int)(_write.end - _write.start);
-        } else {
-            size = (int)(&_write.ring[BUF_SIZE] - _write.start);
-        }
-        size = MIN(size, VIOSERIAL_PORT_MAX_WRITE_BYTES);
-        _write.pending = true;
-        if (WriteFile(_handle, _write.start, size, NULL, &_write.overlap)) {
-            write_completion();
-        } if (GetLastError() != ERROR_IO_PENDING) {
-            return handle_error();
-        }
-    }
-    ret = _write.bytes;
-    _write.bytes = 0;
-    return ret;
-}
-
-bool VirtioVDIPort::write_completion()
-{
-    DWORD bytes;
-
-    if (!_write.pending) {
-        return true;
-    }
-    if (!GetOverlappedResult(_handle, &_write.overlap, &bytes, FALSE)) {
-        vd_printf("GetOverlappedResult failed: %lu", GetLastError());
-        return false;
-    }
-    _write.start = _write.ring + (_write.start - _write.ring + bytes) % BUF_SIZE;
-    _write.bytes = bytes;
-    _write.pending = false;
-    return true;
-}
-
-int VirtioVDIPort::read()
-{
-    int size;
-    int ret;
-
-    if (!_read.pending) {
-        //FIXME: read_ring_continuous_remaining_size? return VDI_PORT_BUFFER_FULL
-        if ((_read.end - _read.ring + 1) % BUF_SIZE == _read.start - _read.ring) {
-            vd_printf("DEBUG: buffer full");
-            return 0;
-        }
-        if (_read.start == _read.end) {
-            _read.start = _read.end = _read.ring;
-        }
-        if (_read.start <= _read.end) {
-            size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
-        } else {
-            size = (int)(_read.start - _read.end - 1);
-        }
-        _read.pending = true;
-        if (ReadFile(_handle, _read.end, size, NULL, &_read.overlap)) {
-            read_completion();
-        } else if (GetLastError() != ERROR_IO_PENDING) {
-            return handle_error();
-        }
-    }
-    ret = _read.bytes;
-    _read.bytes = 0;
-    return ret;
-}
-
-bool VirtioVDIPort::read_completion()
-{
-    DWORD bytes;
-
-    if (!GetOverlappedResult(_handle, &_read.overlap, &bytes, FALSE)) {
-        DWORD err = GetLastError();
-
-        if (err == ERROR_OPERATION_ABORTED || err == ERROR_NO_SYSTEM_RESOURCES) {
-            _read.pending = false;
-            return true;
-        } else if (err != ERROR_MORE_DATA) {
-            vd_printf("GetOverlappedResult failed: %lu", err);
-            return false;
-        }
-    }
-    _read.end = _read.ring + (_read.end - _read.ring + bytes) % BUF_SIZE;
-    _read.bytes = bytes;
-    _read.pending = false;
-    return true;
-}
diff --git a/vdagent/virtio_vdi_port.h b/vdagent/virtio_vdi_port.h
deleted file mode 100644
index d72edf4..0000000
--- a/vdagent/virtio_vdi_port.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _H_VIRTIO_VDI_PORT
-#define _H_VIRTIO_VDI_PORT
-
-#include "vdi_port.h"
-
-enum {
-    VIRTIO_VDI_PORT_EVENT_WRITE=0,
-    VIRTIO_VDI_PORT_EVENT_READ,
-    VIRTIO_VDI_PORT_EVENT_COUNT
-};
-
-class VirtioVDIPort : public VDIPort {
-public:
-    VirtioVDIPort();
-    ~VirtioVDIPort();
-    virtual const char *name() { return "VirtioVDIPort"; }
-    virtual bool init();
-    virtual unsigned get_num_events() { return VIRTIO_VDI_PORT_EVENT_COUNT; }
-    virtual void fill_events(HANDLE* handles);
-    virtual bool handle_event(int event);
-    virtual int write();
-    virtual int read();
-
-private:
-    bool write_completion();
-    bool read_completion();
-
-private:
-    static VirtioVDIPort* _singleton;
-    HANDLE _handle;
-};
-
-#endif //_H_VIRTIO_VDI_PORT
commit f79485aeeef594d05a3bac335870953d4aa715e3
Author: Arnon Gilboa <agilboa at redhat.com>
Date:   Tue Nov 27 16:39:48 2012 +0200

    vdagent: remove vdi_port from vcproj

diff --git a/vdagent/vdagent.vcproj b/vdagent/vdagent.vcproj
index b99297e..5e7bb43 100644
--- a/vdagent/vdagent.vcproj
+++ b/vdagent/vdagent.vcproj
@@ -350,25 +350,13 @@
 				>
 			</File>
 			<File
-				RelativePath=".\pci_vdi_port.cpp"
-				>
-			</File>
-			<File
 				RelativePath=".\vdagent.cpp"
 				>
 			</File>
 			<File
-				RelativePath=".\vdi_port.cpp"
-				>
-			</File>
-			<File
 				RelativePath="..\common\vdlog.cpp"
 				>
 			</File>
-			<File
-				RelativePath=".\virtio_vdi_port.cpp"
-				>
-			</File>
 		</Filter>
 		<Filter
 			Name="Header Files"
@@ -384,10 +372,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\pci_vdi_port.h"
-				>
-			</File>
-			<File
 				RelativePath=".\resource.h"
 				>
 			</File>
@@ -396,17 +380,9 @@
 				>
 			</File>
 			<File
-				RelativePath=".\vdi_port.h"
-				>
-			</File>
-			<File
 				RelativePath="..\common\vdlog.h"
 				>
 			</File>
-			<File
-				RelativePath=".\virtio_vdi_port.h"
-				>
-			</File>
 		</Filter>
 		<Filter
 			Name="Resource Files"
commit f1873dfa9b5077d54a3ca6597eaeef9ff8e77684
Author: Arnon Gilboa <agilboa at redhat.com>
Date:   Tue Nov 27 16:39:21 2012 +0200

    vdagent: remove vdi_port, use vio_serial directly

diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index 2bb466d..85244c0 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -16,8 +16,6 @@
 */
 
 #include "vdcommon.h"
-#include "virtio_vdi_port.h"
-#include "pci_vdi_port.h"
 #include "desktop_layout.h"
 #include "display_setting.h"
 #include "ximage.h"
@@ -65,11 +63,7 @@ typedef struct ALIGN_VC VDIChunk {
 } ALIGN_GCC VDIChunk;
 
 #define VD_MESSAGE_HEADER_SIZE (sizeof(VDIChunk) + sizeof(VDAgentMessage))
-
-enum {
-    VD_EVENT_CONTROL = 0,
-    VD_STATIC_EVENTS_COUNT // Must be last
-};
+#define VD_READ_BUF_SIZE       (sizeof(VDIChunk) + VD_AGENT_MAX_DATA_SIZE)
 
 class VDAgent {
 public:
@@ -90,8 +84,6 @@ private:
     bool handle_clipboard_request(VDAgentClipboardRequest* clipboard_request);
     void handle_clipboard_release();
     bool handle_display_config(VDAgentDisplayConfig* display_config, uint32_t port);
-    void handle_port_in();
-    void handle_port_out();
     void handle_chunk(VDIChunk* chunk);
     void on_clipboard_grab();
     void on_clipboard_request(UINT format);
@@ -101,7 +93,9 @@ private:
     static HGLOBAL utf8_alloc(LPCSTR data, int size);
     static LRESULT CALLBACK wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
     static DWORD WINAPI event_thread_proc(LPVOID param);
-    static void dispatch_message(VDAgentMessage* msg, uint32_t port);
+    static VOID CALLBACK read_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlapped);
+    static VOID CALLBACK write_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlapped);
+    void dispatch_message(VDAgentMessage* msg, uint32_t port);
     uint32_t get_clipboard_format(uint32_t type);
     uint32_t get_clipboard_type(uint32_t format);
     DWORD get_cximage_format(uint32_t type);
@@ -114,7 +108,7 @@ private:
     void enqueue_chunk(VDIChunk* msg);
     bool write_message(uint32_t type, uint32_t size, void* data);
     bool write_clipboard(VDAgentMessage* msg, uint32_t size);
-    bool init_vdi_port();
+    bool init_vio_serial();
     bool send_input();
     void set_display_depth(uint32_t depth);
     void load_display_setting();
@@ -134,16 +128,19 @@ private:
     INPUT _input;
     DWORD _input_time;
     HANDLE _control_event;
-    HANDLE* _events;
     VDAgentMessage* _in_msg;
     uint32_t _in_msg_pos;
-    uint32_t _events_count;
     bool _pending_input;
     bool _running;
     bool _desktop_switch;
     DesktopLayout* _desktop_layout;
     DisplaySetting _display_setting;
-    VDIPort* _vdi_port;
+    HANDLE _vio_serial;
+    OVERLAPPED _read_overlapped;
+    OVERLAPPED _write_overlapped;
+    CHAR _read_buf[VD_READ_BUF_SIZE];
+    DWORD _read_pos;
+    DWORD _write_pos;
     mutex_t _control_mutex;
     mutex_t _message_mutex;
     std::queue<int> _control_queue;
@@ -163,6 +160,8 @@ private:
 
 VDAgent* VDAgent::_singleton = NULL;
 
+#define VIOSERIAL_PORT_PATH L"\\\\.\\Global\\com.redhat.spice.0"
+
 VDAgent* VDAgent::get()
 {
     if (!_singleton) {
@@ -181,16 +180,16 @@ VDAgent::VDAgent()
     , _mouse_y (0)
     , _input_time (0)
     , _control_event (NULL)
-    , _events (NULL)
     , _in_msg (NULL)
     , _in_msg_pos (0)
-    , _events_count (0)
     , _pending_input (false)
     , _running (false)
     , _desktop_switch (false)
     , _desktop_layout (NULL)
     , _display_setting (VD_AGENT_REGISTRY_KEY)
-    , _vdi_port (NULL)
+    , _vio_serial (NULL)
+    , _read_pos (0)
+    , _write_pos (0)
     , _logon_desktop (false)
     , _display_setting_initialized (false)
     , _client_caps (NULL)
@@ -204,7 +203,10 @@ VDAgent::VDAgent()
         swprintf_s(log_path, MAX_PATH, VD_AGENT_LOG_PATH, temp_path);
         _log = VDLog::get(log_path);
     }
-    ZeroMemory(&_input, sizeof(INPUT));
+    ZeroMemory(&_input, sizeof(_input));
+    ZeroMemory(&_read_overlapped, sizeof(_read_overlapped));
+    ZeroMemory(&_write_overlapped, sizeof(_write_overlapped));
+    ZeroMemory(_read_buf, sizeof(_read_buf));
     MUTEX_INIT(_control_mutex);
     MUTEX_INIT(_message_mutex);
 
@@ -213,7 +215,6 @@ VDAgent::VDAgent()
 
 VDAgent::~VDAgent()
 {
-    delete _events;
     delete _log;
     delete[] _client_caps;
 }
@@ -277,8 +278,13 @@ bool VDAgent::run()
     if (_desktop_layout->get_display_count() == 0) {
         vd_printf("No QXL devices!");
     }
-    if (!init_vdi_port()) {
-        vd_printf("Failed to create VDIPort instance");
+    if (!init_vio_serial()) {
+        cleanup();
+        return false;
+    }
+    if (!ReadFileEx(_vio_serial, _read_buf, sizeof(VDIChunk), &_read_overlapped, read_completion) &&
+            GetLastError() != ERROR_IO_PENDING) {
+        vd_printf("vio_serial read error %lu", GetLastError());
         cleanup();
         return false;
     }
@@ -290,12 +296,6 @@ bool VDAgent::run()
         return false;
     }
     send_announce_capabilities(true);
-
-    _events_count = VD_STATIC_EVENTS_COUNT + _vdi_port->get_num_events();
-    _events = new HANDLE[_events_count];
-    ZeroMemory(_events, _events_count);
-    _events[VD_EVENT_CONTROL] = _control_event;
-    _vdi_port->fill_events(&_events[VD_STATIC_EVENTS_COUNT]);
     vd_printf("Connected to server");
 
     while (_running) {
@@ -313,7 +313,7 @@ bool VDAgent::run()
 void VDAgent::cleanup()
 {
     CloseHandle(_control_event);
-    delete _vdi_port;
+    CloseHandle(_vio_serial);
     delete _desktop_layout;
 }
 
@@ -431,52 +431,23 @@ void VDAgent::event_dispatcher(DWORD timeout, DWORD wake_mask)
     DWORD wait_ret;
     MSG msg;
 
-    int cont_read = _vdi_port->read();
-    int cont_write = _vdi_port->write();
-    bool cont = false;
-
-    if (cont_read >= 0 && cont_write >= 0) {
-        cont = cont_read || cont_write;
-    } else if (cont_read == VDI_PORT_ERROR || cont_write == VDI_PORT_ERROR) {
-        vd_printf("VDI Port error, read %d write %d", cont_read, cont_write);
-        _running = false;
-        return;
-    } else if (cont_read == VDI_PORT_RESET || cont_write == VDI_PORT_RESET) {
-        vd_printf("VDI Port reset, read %d write %d", cont_read, cont_write);
-        _running = false;
-        return;
-    }
-    if (cont_read) {
-        handle_port_in();
-    }
-    if (cont_write) {
-        handle_port_out();
-    }
-
-    wait_ret = MsgWaitForMultipleObjects(_events_count, _events, FALSE, cont ? 0 : timeout,
-                                         wake_mask);
-
-    if (wake_mask && wait_ret == WAIT_OBJECT_0 + _events_count) {
+    wait_ret = MsgWaitForMultipleObjectsEx(1, &_control_event, timeout, wake_mask, MWMO_ALERTABLE);
+    switch (wait_ret) {
+    case WAIT_OBJECT_0:
+        handle_control_event();
+        break;
+    case WAIT_OBJECT_0 + 1:
         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
             TranslateMessage(&msg);
             DispatchMessage(&msg);
         }
-        return;
-    }
-    switch (wait_ret) {
-    case WAIT_OBJECT_0 + VD_EVENT_CONTROL:
-        handle_control_event();
         break;
+    case WAIT_IO_COMPLETION:
     case WAIT_TIMEOUT:
         break;
     default:
-        DWORD vdi_event = wait_ret - VD_STATIC_EVENTS_COUNT - WAIT_OBJECT_0;
-        if (vdi_event >= 0 && vdi_event < _vdi_port->get_num_events()) {
-            _running = _vdi_port->handle_event(vdi_event);
-        } else {
-            vd_printf("MsgWaitForMultipleObjectsEx failed: %lu %lu", wait_ret, GetLastError());
-            _running = false;
-        }
+        vd_printf("MsgWaitForMultipleObjectsEx failed: %lu %lu", wait_ret, GetLastError());
+        _running = false;
     }
 }
 
@@ -1145,29 +1116,15 @@ void VDAgent::set_clipboard_owner(int new_owner)
     _clipboard_owner = new_owner;
 }
 
-VDIPort *create_virtio_vdi_port()
-{
-    return new VirtioVDIPort();
-}
-
-VDIPort *create_pci_vdi_port()
+bool VDAgent::init_vio_serial()
 {
-    return new PCIVDIPort();
-}
-
-bool VDAgent::init_vdi_port()
-{
-    VDIPort* (*creators[])(void) = { create_virtio_vdi_port, create_pci_vdi_port };
-
-    for (unsigned int i = 0 ; i < sizeof(creators)/sizeof(creators[0]); ++i) {
-        _vdi_port = creators[i]();
-        if (_vdi_port->init()) {
-            return true;
-        }
-        delete _vdi_port;
+    _vio_serial = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
+                             OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+    if (_vio_serial == INVALID_HANDLE_VALUE) {
+        vd_printf("Failed opening %ls, error %u", VIOSERIAL_PORT_PATH, GetLastError());
+        return false;
     }
-    _vdi_port = NULL;
-    return false;
+    return true;
 }
 
 void VDAgent::dispatch_message(VDAgentMessage* msg, uint32_t port)
@@ -1213,37 +1170,42 @@ void VDAgent::dispatch_message(VDAgentMessage* msg, uint32_t port)
     }
 }
 
-void VDAgent::handle_port_in()
+VOID VDAgent::read_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlapped)
 {
-    static char buf[sizeof(VDIChunk) + VD_AGENT_MAX_DATA_SIZE] = {0, };
-    VDIChunk* chunk = (VDIChunk*)buf;
-    uint32_t chunk_size;
-
-    while (_running)  {
-        if (!chunk->hdr.size && _vdi_port->read_ring_size() >= sizeof(VDIChunk)) {
-            if (_vdi_port->ring_read(chunk, sizeof(VDIChunk)) != sizeof(VDIChunk)) {
-                vd_printf("ring_read of chunk header failed");
-                _running = false;
-                break;
-            }
-            if (sizeof(VDIChunk) + chunk->hdr.size > sizeof(buf)) {
-                vd_printf("chunk is too large, size %u port %u", chunk->hdr.size, chunk->hdr.port);
-                _running = false;
-                break;
-            }
-        }
-        chunk_size = chunk->hdr.size;
-        if (!chunk_size || _vdi_port->read_ring_size() < chunk_size) {
-            break;
-        }
-        if (_vdi_port->ring_read(chunk->data, chunk_size) != chunk_size) {
-            vd_printf("ring_read of chunk data failed");
-            _running = false;
-            break;
+    VDAgent* a = _singleton;
+    VDIChunk* chunk = (VDIChunk*)a->_read_buf;
+    DWORD count;
+
+    if (err != 0 && err != ERROR_OPERATION_ABORTED && err != ERROR_NO_SYSTEM_RESOURCES) {
+        vd_printf("vio_serial read completion error %lu", err);
+        a->_running = false;
+        return;
+    }
+
+    a->_read_pos += bytes;
+    if (a->_read_pos < sizeof(VDIChunk)) {
+        count = sizeof(VDIChunk) - a->_read_pos;
+    } else if (a->_read_pos == sizeof(VDIChunk)) {
+        count = chunk->hdr.size;
+        if (a->_read_pos + count > sizeof(a->_read_buf)) {
+            vd_printf("chunk is too large, size %u port %u", chunk->hdr.size, chunk->hdr.port);
+            a->_running = false;
+            return;
         }
-        handle_chunk(chunk);
-        chunk->hdr.size = 0;
-   }
+    } else if (a->_read_pos == sizeof(VDIChunk) + chunk->hdr.size){
+        a->handle_chunk(chunk);
+        count = sizeof(VDIChunk);
+        a->_read_pos = 0;
+    } else {
+        ASSERT(a->_read_pos < sizeof(VDIChunk) + chunk->hdr.size);
+        count = sizeof(VDIChunk) + chunk->hdr.size - a->_read_pos;
+    }
+
+    if (!ReadFileEx(a->_vio_serial, a->_read_buf + a->_read_pos, count, overlapped,
+                    read_completion) && GetLastError() != ERROR_IO_PENDING) {
+        vd_printf("vio_serial read error %lu", GetLastError());
+        a->_running = false;
+    }
 }
 
 void VDAgent::handle_chunk(VDIChunk* chunk)
@@ -1289,24 +1251,39 @@ void VDAgent::cleanup_in_msg()
     _in_msg = NULL;
 }
 
-void VDAgent::handle_port_out()
+void VDAgent::write_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlapped)
 {
-    MUTEX_LOCK(_message_mutex);
-    while (_running && !_message_queue.empty()) {
-        VDIChunk* chunk = _message_queue.front();
-        DWORD size = sizeof(VDIChunk) + chunk->hdr.size;
+    VDAgent* a = _singleton;
+    VDIChunk* chunk;
+    DWORD count;
 
-        if (size > _vdi_port->write_ring_free_space()) {
-            break;
+    ASSERT(!a->_message_queue.empty());
+    if (err != 0) {
+        vd_printf("vio_serial write completion error %lu", err);
+        a->_running = false;
+        return;
+    }
+    MUTEX_LOCK(a->_message_mutex);
+    a->_write_pos += bytes;
+    chunk = a->_message_queue.front();
+    count = sizeof(VDIChunk) + chunk->hdr.size - a->_write_pos;
+    if (count == 0) {
+        a->_message_queue.pop();
+        a->_write_pos = 0;
+        delete chunk;
+        if (!a->_message_queue.empty()) {
+            chunk = a->_message_queue.front();
+            count = sizeof(VDIChunk) + chunk->hdr.size;
         }
-        _message_queue.pop();
-        if (_vdi_port->ring_write(chunk, size) != size) {
-            vd_printf("ring_write failed");
-            _running = false;
+    }
+    if (count) {
+        if (!WriteFileEx(a->_vio_serial, (char*)chunk + a->_write_pos, count, overlapped,
+                         write_completion) && GetLastError() != ERROR_IO_PENDING) {
+            vd_printf("vio_serial write error %lu", GetLastError());
+            a->_running = false;
         }
-        delete chunk;
     }
-    MUTEX_UNLOCK(_message_mutex);
+    MUTEX_UNLOCK(a->_message_mutex);
 }
 
 VDIChunk* VDAgent::new_chunk(DWORD bytes)
@@ -1318,8 +1295,10 @@ void VDAgent::enqueue_chunk(VDIChunk* chunk)
 {
     MUTEX_LOCK(_message_mutex);
     _message_queue.push(chunk);
+    if (_message_queue.size() == 1) {
+        write_completion(0, 0, &_write_overlapped);
+    }
     MUTEX_UNLOCK(_message_mutex);
-    handle_port_out();
 }
 
 LRESULT CALLBACK VDAgent::wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
commit 9b5954165d1726a556706dd375e5c13b80fd36c9
Author: Arnon Gilboa <agilboa at redhat.com>
Date:   Tue Nov 27 11:14:24 2012 +0200

    vdagent: when SetClipboardData fails, set clipboard control event to stop wait
    
    Currently, a SetClipboardData failure is followed by useless wait for timeout
    (VD_CLIPBOARD_TIMEOUT_MS).
    
    In addition, we remove the clipboard open-empty-set-close retry, which became
    irrelevant with the current on_clipboard_request().

diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index 3f1053d..2bb466d 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -643,12 +643,10 @@ bool VDAgent::handle_clipboard(VDAgentClipboard* clipboard, uint32_t size)
 
     if (_clipboard_owner != owner_client) {
         vd_printf("Received clipboard data from client while clipboard is not owned by client");
-        set_control_event(CONTROL_CLIPBOARD);
-        return false;
+        goto fin;
     }
     if (clipboard->type == VD_AGENT_CLIPBOARD_NONE) {
-        set_control_event(CONTROL_CLIPBOARD);
-        return false;
+        goto fin;
     }
     switch (clipboard->type) {
     case VD_AGENT_CLIPBOARD_UTF8_TEXT:
@@ -664,20 +662,24 @@ bool VDAgent::handle_clipboard(VDAgentClipboard* clipboard, uint32_t size)
     }
     default:
         vd_printf("Unsupported clipboard type %u", clipboard->type);
-        return true;
+        goto fin;
     }
     format = get_clipboard_format(clipboard->type);
-    if (SetClipboardData(format, clip_data)) {
-        set_control_event(CONTROL_CLIPBOARD);
-        return true;
-    }
-    // We retry clipboard open-empty-set-close only when there is a timeout in on_clipboard_request()
-    if (!OpenClipboard(_hwnd)) {
-        return false;
+    if (format == 0) {
+        vd_printf("Unknown clipboard format, type %u", clipboard->type);
+        goto fin;
     }
-    EmptyClipboard();
     ret = !!SetClipboardData(format, clip_data);
-    CloseClipboard();
+    if (!ret) {
+        DWORD err = GetLastError();
+        if (err == ERROR_NOT_ENOUGH_MEMORY) {
+            vd_printf("Not enough memory to set clipboard data, size %u bytes", size);
+        } else {
+            vd_printf("SetClipboardData failed: %u", err);
+        }
+    }
+fin:
+    set_control_event(CONTROL_CLIPBOARD);
     return ret;
 }
 
commit c18859ff35c439985a6134c71e35861dd71b186e
Author: Arnon Gilboa <agilboa at redhat.com>
Date:   Sun Nov 25 17:11:39 2012 +0200

    vdservice: set process handle for vdagent launched on session>0
    
    The problem on XP was failing to terminate agent running on session>0,
    since during agent process creation, a handle was not set, so it was NULL.
    Therefore, the new agent created (at the session we switched to) was unable
    to open vitio-serial which was still used by the other running agent instance.
    
    rhbz#868254

diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index b2448e7..a2cf67d 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -640,6 +640,13 @@ BOOL create_session_process_as_user(IN DWORD session_id, IN BOOL use_default_tok
         ret = proc_ret.ret_value;
         if (ret) {
             *process_information = proc_ret.process_information;
+            if (process_information->hProcess == 0) {
+                process_information->hProcess = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, FALSE,
+                                                            process_information->dwProcessId);
+                if (!process_information->hProcess) {
+                    vd_printf("OpenProcess() failed %lu", GetLastError());
+                }
+            }
         } else {
             SetLastError(proc_ret.last_error);
         }


More information about the Spice-commits mailing list