[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH 3/6] Add named pipe server



From: Owen Smith <owen.smith@xxxxxxxxxx>

Create a threaded NamedPipe server for the device.
This will be used to pass data from the console to child processes, and
read data from the child processes to pass to the console device.

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/monitor/monitor.c | 320 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 320 insertions(+)

diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index df94934..e3979b8 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -50,6 +50,13 @@
 #define MONITOR_NAME        __MODULE__
 #define MONITOR_DISPLAYNAME MONITOR_NAME
 
+typedef struct _MONITOR_PIPE {
+    HANDLE                  Pipe;
+    HANDLE                  Event;
+    HANDLE                  Thread;
+    LIST_ENTRY              ListEntry;
+} MONITOR_PIPE, *PMONITOR_PIPE;
+
 typedef struct _MONITOR_CONTEXT {
     SERVICE_STATUS          Status;
     SERVICE_STATUS_HANDLE   Service;
@@ -67,10 +74,17 @@ typedef struct _MONITOR_CONTEXT {
     HANDLE                  MonitorThread;
     HANDLE                  DeviceEvent;
     HANDLE                  DeviceThread;
+    HANDLE                  ServerEvent;
+    HANDLE                  ServerThread;
+    CRITICAL_SECTION        CriticalSection;
+    LIST_ENTRY              ListHead;
+    DWORD                   ListCount;
 } MONITOR_CONTEXT, *PMONITOR_CONTEXT;
 
 MONITOR_CONTEXT MonitorContext;
 
+#define PIPE_NAME TEXT("\\\\.\\pipe\\xencons")
+
 #define MAXIMUM_BUFFER_SIZE 1024
 
 #define SERVICES_KEY "SYSTEM\\CurrentControlSet\\Services"
@@ -347,6 +361,219 @@ fail1:
     return FALSE;
 }
 
+static FORCEINLINE VOID
+InitializeListHead(
+    IN  PLIST_ENTRY ListEntry
+    )
+{
+    ListEntry->Flink = ListEntry;
+    ListEntry->Blink = ListEntry;
+}
+
+static FORCEINLINE VOID
+InsertTailList(
+    IN  PLIST_ENTRY ListHead,
+    IN  PLIST_ENTRY ListEntry
+    )
+{
+    ListEntry->Blink = ListHead->Blink;
+    ListEntry->Flink = ListHead;
+    ListHead->Blink->Flink = ListEntry;
+    ListHead->Blink = ListEntry;
+}
+
+static FORCEINLINE VOID
+RemoveEntryList(
+    IN  PLIST_ENTRY ListEntry
+    )
+{
+    PLIST_ENTRY     Flink;
+    PLIST_ENTRY     Blink;
+
+    Flink = ListEntry->Flink;
+    Blink = ListEntry->Blink;
+    Flink->Blink = Blink;
+    Blink->Flink = Flink;
+
+    ListEntry->Flink = ListEntry;
+    ListEntry->Blink = ListEntry;
+}
+
+DWORD WINAPI
+PipeThread(
+    IN  LPVOID          Argument
+    )
+{
+    PMONITOR_CONTEXT    Context = &MonitorContext;
+    PMONITOR_PIPE       Pipe = (PMONITOR_PIPE)Argument;
+    UCHAR               Buffer[MAXIMUM_BUFFER_SIZE];
+    OVERLAPPED          Overlapped;
+    HANDLE              Handle[2];
+    DWORD               Length;
+    DWORD               Object;
+    HRESULT             Error;
+
+    Log("====>");
+
+    memset(&Overlapped, 0, sizeof(OVERLAPPED));
+    Overlapped.hEvent = CreateEvent(NULL,
+                                    TRUE,
+                                    FALSE,
+                                    NULL);
+    if (Overlapped.hEvent == NULL)
+        goto fail1;
+
+    Handle[0] = Pipe->Event;
+    Handle[1] = Overlapped.hEvent;
+
+    EnterCriticalSection(&Context->CriticalSection);
+    InsertTailList(&Context->ListHead, &Pipe->ListEntry);
+    ++Context->ListCount;
+    LeaveCriticalSection(&Context->CriticalSection);
+
+    for (;;) {
+        (VOID) ReadFile(Pipe->Pipe,
+                        Buffer,
+                        sizeof(Buffer),
+                        NULL,
+                        &Overlapped);
+
+        Object = WaitForMultipleObjects(ARRAYSIZE(Handle),
+                                        Handle,
+                                        FALSE,
+                                        INFINITE);
+        if (Object == WAIT_OBJECT_0)
+            break;
+
+        if (!GetOverlappedResult(Pipe->Pipe,
+                                 &Overlapped,
+                                 &Length,
+                                 FALSE))
+            break;
+
+        ResetEvent(Overlapped.hEvent);
+
+        // Length bytes of Buffer have been read
+    }
+
+    EnterCriticalSection(&Context->CriticalSection);
+    RemoveEntryList(&Pipe->ListEntry);
+    --Context->ListCount;
+    LeaveCriticalSection(&Context->CriticalSection);
+
+    CloseHandle(Overlapped.hEvent);
+
+    Log("<====");
+
+    return 0;
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return 1;
+}
+
+DWORD WINAPI
+ServerThread(
+    IN  LPVOID          Argument
+    )
+{
+    PMONITOR_CONTEXT    Context = &MonitorContext;
+    OVERLAPPED          Overlapped;
+    HANDLE              Handle[2];
+    DWORD               Object;
+    HRESULT             Error;
+
+    UNREFERENCED_PARAMETER(Argument);
+
+    Log("====>");
+
+    memset(&Overlapped, 0, sizeof(OVERLAPPED));
+    Overlapped.hEvent = CreateEvent(NULL,
+                                    TRUE,
+                                    FALSE,
+                                    NULL);
+    if (Overlapped.hEvent == NULL)
+        goto fail1;
+
+    Handle[0] = Context->ServerEvent;
+    Handle[1] = Overlapped.hEvent;
+
+    for (;;) {
+        HANDLE          Pipe;
+        PMONITOR_PIPE   Instance;
+
+        Pipe = CreateNamedPipe(PIPE_NAME,
+                               PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+                               PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
+                               PIPE_UNLIMITED_INSTANCES,
+                               MAXIMUM_BUFFER_SIZE,
+                               MAXIMUM_BUFFER_SIZE,
+                               0,
+                               NULL);
+        if (Pipe == INVALID_HANDLE_VALUE)
+            break;
+
+        (VOID) ConnectNamedPipe(Pipe,
+                                &Overlapped);
+
+        Object = WaitForMultipleObjects(ARRAYSIZE(Handle),
+                                        Handle,
+                                        FALSE,
+                                        INFINITE);
+        if (Object == WAIT_OBJECT_0)
+            break;
+
+        ResetEvent(Overlapped.hEvent);
+
+        Instance = (PMONITOR_PIPE)malloc(sizeof(MONITOR_PIPE));
+        if (Instance == NULL) {
+            CloseHandle(Pipe);
+            break;
+        }
+
+        InitializeListHead(&Instance->ListEntry);
+        Instance->Pipe = Pipe;
+        Instance->Event = Context->ServerEvent;
+        Instance->Thread = CreateThread(NULL,
+                                        0,
+                                        PipeThread,
+                                        Instance,
+                                        0,
+                                        NULL);
+        if (Instance->Thread == INVALID_HANDLE_VALUE) {
+            free(Instance);
+            CloseHandle(Pipe);
+            break;
+        }
+    }
+
+    CloseHandle(Overlapped.hEvent);
+
+    Log("<====");
+
+    return 0;
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return 1;
+}
+
 DWORD WINAPI
 MonitorThread(
     IN  LPVOID          Argument
@@ -624,6 +851,8 @@ MonitorAdd(
         goto fail3;
 
     Context->DevicePath = Path;
+    InitializeListHead(&Context->ListHead);
+    InitializeCriticalSection(&Context->CriticalSection);
 
     Context->MonitorEvent = CreateEvent(NULL,
                                         TRUE,
@@ -661,10 +890,38 @@ MonitorAdd(
     if (Context->DeviceThread == INVALID_HANDLE_VALUE)
         goto fail7;
 
+    Context->ServerEvent = CreateEvent(NULL,
+                                       TRUE,
+                                       FALSE,
+                                       NULL);
+    if (Context->ServerEvent == NULL)
+        goto fail8;
+
+    Context->ServerThread = CreateThread(NULL,
+                                         0,
+                                         ServerThread,
+                                         NULL,
+                                         0,
+                                         NULL);
+    if (Context->ServerThread == INVALID_HANDLE_VALUE)
+        goto fail9;
+
     Log("<====");
 
     return;
 
+fail9:
+    Log("fail9");
+
+    CloseHandle(Context->ServerEvent);
+    Context->ServerEvent = NULL;
+
+fail8:
+    Log("fail8");
+
+    SetEvent(Context->DeviceEvent);
+    WaitForSingleObject(Context->DeviceThread, INFINITE);
+
 fail7:
     Log("fail7\n");
 
@@ -686,6 +943,9 @@ fail5:
 fail4:
     Log("fail4");
 
+    DeleteCriticalSection(&Context->CriticalSection);
+    memset(&Context->ListHead, 0, sizeof(LIST_ENTRY));
+
     free(Context->DevicePath);
     Context->DevicePath = NULL;
 
@@ -715,6 +975,56 @@ fail1:
 }
 
 static VOID
+MonitorWaitForPipeThreads(
+    VOID
+    )
+{
+    PMONITOR_CONTEXT    Context = &MonitorContext;
+    HANDLE              *Handles;
+    DWORD               Index;
+    PLIST_ENTRY         ListEntry;
+
+    EnterCriticalSection(&Context->CriticalSection);
+
+    if (Context->ListCount == 0)
+        goto fail1;
+
+    Handles = (HANDLE*)malloc(sizeof(HANDLE) * Context->ListCount);
+    if (Handles == NULL)
+        goto fail2;
+
+    Index = 0;
+    for (ListEntry = Context->ListHead.Flink;
+         ListEntry != &Context->ListHead && Index < Context->ListCount;
+         ListEntry = ListEntry->Flink) {
+        PMONITOR_PIPE Pipe = CONTAINING_RECORD(ListEntry, MONITOR_PIPE, 
ListEntry);
+        Handles[Index++] = Pipe->Thread;
+    }
+
+    Context->ListCount = 0;
+
+    LeaveCriticalSection(&Context->CriticalSection);
+
+#pragma warning(suppress:6385) // Reading invalid data from 'Handles'...
+    WaitForMultipleObjects(Index,
+                           Handles,
+                           TRUE,
+                           INFINITE);
+    free(Handles);
+    return;
+
+fail2:
+    Log("fail2");
+
+fail1:
+    Log("fail1");
+
+    LeaveCriticalSection(&Context->CriticalSection);
+
+    return;
+}
+
+static VOID
 MonitorRemove(
     VOID
     )
@@ -726,6 +1036,13 @@ MonitorRemove(
 
     Log("====>");
 
+    SetEvent(Context->ServerEvent);
+    MonitorWaitForPipeThreads();
+    WaitForSingleObject(Context->ServerThread, INFINITE);
+
+    CloseHandle(Context->ServerEvent);
+    Context->ServerEvent = NULL;
+
     SetEvent(Context->DeviceEvent);
     WaitForSingleObject(Context->DeviceThread, INFINITE);
 
@@ -738,6 +1055,9 @@ MonitorRemove(
     CloseHandle(Context->MonitorEvent);
     Context->MonitorEvent = NULL;
 
+    DeleteCriticalSection(&Context->CriticalSection);
+    memset(&Context->ListHead, 0, sizeof(LIST_ENTRY));
+
     free(Context->DevicePath);
     Context->DevicePath = NULL;
 
-- 
2.8.3


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.