Merge branch 'awakecoding' of github.com:vworkspace/FreeRDP
Conflicts: winpr/libwinpr/pipe/pipe.c
This commit is contained in:
commit
4dc6ffdaaa
@ -167,16 +167,26 @@ BOOL CloseHandle(HANDLE hObject)
|
||||
|
||||
pipe = (WINPR_NAMED_PIPE*) Object;
|
||||
|
||||
if (pipe->clientfd != -1)
|
||||
close(pipe->clientfd);
|
||||
if (--pipe->dwRefCount == 0)
|
||||
{
|
||||
ArrayList_Remove(WinPR_GetBaseNamedPipeList(), pipe);
|
||||
|
||||
if (pipe->serverfd != -1)
|
||||
close(pipe->serverfd);
|
||||
if (pipe->pBaseNamedPipe)
|
||||
{
|
||||
CloseHandle((HANDLE) pipe->pBaseNamedPipe);
|
||||
}
|
||||
|
||||
free((char *)pipe->lpFileName);
|
||||
free((char *)pipe->lpFilePath);
|
||||
free((char *)pipe->name);
|
||||
free(pipe);
|
||||
if (pipe->clientfd != -1)
|
||||
close(pipe->clientfd);
|
||||
|
||||
if (pipe->serverfd != -1)
|
||||
close(pipe->serverfd);
|
||||
|
||||
free((char *)pipe->lpFileName);
|
||||
free((char *)pipe->lpFilePath);
|
||||
free((char *)pipe->name);
|
||||
free(pipe);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -44,6 +44,39 @@
|
||||
|
||||
#include "pipe.h"
|
||||
|
||||
/*
|
||||
* Since the WINPR implementation of named pipes makes use of UNIX domain
|
||||
* sockets, it is not possible to bind the same name more than once (i.e.,
|
||||
* SO_REUSEADDR does not work with UNIX domain sockets). As a result, the
|
||||
* first call to CreateNamedPipe must create the UNIX domain socket and
|
||||
* subsequent calls to CreateNamedPipe will reference the first named pipe
|
||||
* handle and duplicate the socket descriptor.
|
||||
*
|
||||
* The following array keeps track of the named pipe handles for the first
|
||||
* instance. If multiple instances are created, subsequent instances store
|
||||
* a pointer to the first instance and a reference count is maintained. When
|
||||
* the last instance is closed, the named pipe handle is removed from the list.
|
||||
*/
|
||||
|
||||
static wArrayList* g_BaseNamedPipeList = NULL;
|
||||
|
||||
static BOOL g_Initialized = FALSE;
|
||||
|
||||
static void InitWinPRPipeModule()
|
||||
{
|
||||
if (g_Initialized) return;
|
||||
|
||||
g_BaseNamedPipeList = ArrayList_New(TRUE);
|
||||
|
||||
g_Initialized = TRUE;
|
||||
}
|
||||
|
||||
wArrayList* WinPR_GetBaseNamedPipeList()
|
||||
{
|
||||
return g_BaseNamedPipeList;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unnamed pipe
|
||||
*/
|
||||
@ -96,15 +129,34 @@ BOOL CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpP
|
||||
HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances,
|
||||
DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
||||
{
|
||||
int index;
|
||||
int status;
|
||||
HANDLE hNamedPipe;
|
||||
char* lpPipePath;
|
||||
struct sockaddr_un s;
|
||||
WINPR_NAMED_PIPE* pNamedPipe;
|
||||
WINPR_NAMED_PIPE* pBaseNamedPipe;
|
||||
|
||||
if (!lpName)
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
||||
InitWinPRPipeModule();
|
||||
|
||||
/* Find the base named pipe instance (i.e., the first instance). */
|
||||
pBaseNamedPipe = NULL;
|
||||
|
||||
ArrayList_Lock(g_BaseNamedPipeList);
|
||||
for (index = 0; index < ArrayList_Count(g_BaseNamedPipeList); index++)
|
||||
{
|
||||
WINPR_NAMED_PIPE* p = (WINPR_NAMED_PIPE*) ArrayList_GetItem(g_BaseNamedPipeList, index);
|
||||
if (strcmp(p->name, lpName) == 0)
|
||||
{
|
||||
pBaseNamedPipe = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ArrayList_Unlock(g_BaseNamedPipeList);
|
||||
|
||||
pNamedPipe = (WINPR_NAMED_PIPE*) malloc(sizeof(WINPR_NAMED_PIPE));
|
||||
hNamedPipe = (HANDLE) pNamedPipe;
|
||||
|
||||
@ -122,54 +174,73 @@ HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD
|
||||
pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
|
||||
pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpName);
|
||||
|
||||
lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
|
||||
|
||||
if (!PathFileExistsA(lpPipePath))
|
||||
{
|
||||
CreateDirectoryA(lpPipePath, 0);
|
||||
UnixChangeFileMode(lpPipePath, 0xFFFF);
|
||||
}
|
||||
|
||||
free(lpPipePath);
|
||||
|
||||
if (PathFileExistsA(pNamedPipe->lpFilePath))
|
||||
{
|
||||
DeleteFileA(pNamedPipe->lpFilePath);
|
||||
}
|
||||
|
||||
pNamedPipe->clientfd = -1;
|
||||
pNamedPipe->ServerMode = TRUE;
|
||||
|
||||
pNamedPipe->serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
pNamedPipe->pBaseNamedPipe = pBaseNamedPipe;
|
||||
pNamedPipe->dwRefCount = 1;
|
||||
|
||||
if (pNamedPipe->serverfd == -1)
|
||||
/* If this is the first instance of the named pipe... */
|
||||
if (pBaseNamedPipe == NULL)
|
||||
{
|
||||
fprintf(stderr, "CreateNamedPipeA: socket error, %s\n", strerror(errno));
|
||||
goto err_out;
|
||||
/* Create the UNIX domain socket and start listening. */
|
||||
lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
|
||||
|
||||
if (!PathFileExistsA(lpPipePath))
|
||||
{
|
||||
CreateDirectoryA(lpPipePath, 0);
|
||||
UnixChangeFileMode(lpPipePath, 0xFFFF);
|
||||
}
|
||||
|
||||
free(lpPipePath);
|
||||
|
||||
if (PathFileExistsA(pNamedPipe->lpFilePath))
|
||||
{
|
||||
DeleteFileA(pNamedPipe->lpFilePath);
|
||||
}
|
||||
|
||||
pNamedPipe->serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
if (pNamedPipe->serverfd == -1)
|
||||
{
|
||||
fprintf(stderr, "CreateNamedPipeA: socket error, %s\n", strerror(errno));
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
ZeroMemory(&s, sizeof(struct sockaddr_un));
|
||||
s.sun_family = AF_UNIX;
|
||||
strcpy(s.sun_path, pNamedPipe->lpFilePath);
|
||||
|
||||
status = bind(pNamedPipe->serverfd, (struct sockaddr*) &s, sizeof(struct sockaddr_un));
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
fprintf(stderr, "CreateNamedPipeA: bind error, %s\n", strerror(errno));
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
status = listen(pNamedPipe->serverfd, 2);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
fprintf(stderr, "CreateNamedPipeA: listen error, %s\n", strerror(errno));
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
UnixChangeFileMode(pNamedPipe->lpFilePath, 0xFFFF);
|
||||
|
||||
/* Add the named pipe to the list of base named pipe instances. */
|
||||
ArrayList_Add(g_BaseNamedPipeList, pNamedPipe);
|
||||
}
|
||||
|
||||
ZeroMemory(&s, sizeof(struct sockaddr_un));
|
||||
s.sun_family = AF_UNIX;
|
||||
strcpy(s.sun_path, pNamedPipe->lpFilePath);
|
||||
|
||||
status = bind(pNamedPipe->serverfd, (struct sockaddr*) &s, sizeof(struct sockaddr_un));
|
||||
|
||||
if (status != 0)
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "CreateNamedPipeA: bind error, %s\n", strerror(errno));
|
||||
goto err_out;
|
||||
/* Duplicate the file handle for the UNIX domain socket in the first instance. */
|
||||
pNamedPipe->serverfd = dup(pBaseNamedPipe->serverfd);
|
||||
|
||||
/* Update the reference count in the base named pipe instance. */
|
||||
pBaseNamedPipe->dwRefCount++;
|
||||
}
|
||||
|
||||
status = listen(pNamedPipe->serverfd, 2);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
fprintf(stderr, "CreateNamedPipeA: listen error, %s\n", strerror(errno));
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
UnixChangeFileMode(pNamedPipe->lpFilePath, 0xFFFF);
|
||||
|
||||
if (dwOpenMode & FILE_FLAG_OVERLAPPED)
|
||||
{
|
||||
#if 0
|
||||
@ -181,6 +252,7 @@ HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD
|
||||
}
|
||||
|
||||
return hNamedPipe;
|
||||
|
||||
err_out:
|
||||
if (pNamedPipe) {
|
||||
if (pNamedPipe->serverfd != -1)
|
||||
|
@ -23,6 +23,7 @@
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <winpr/pipe.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include "../handle/handle.h"
|
||||
|
||||
@ -34,10 +35,16 @@ struct winpr_pipe
|
||||
};
|
||||
typedef struct winpr_pipe WINPR_PIPE;
|
||||
|
||||
typedef struct winpr_named_pipe WINPR_NAMED_PIPE;
|
||||
|
||||
struct winpr_named_pipe
|
||||
{
|
||||
WINPR_HANDLE_DEF();
|
||||
|
||||
WINPR_NAMED_PIPE* pBaseNamedPipe;
|
||||
|
||||
DWORD dwRefCount;
|
||||
|
||||
int clientfd;
|
||||
int serverfd;
|
||||
|
||||
@ -55,7 +62,16 @@ struct winpr_named_pipe
|
||||
DWORD dwFlagsAndAttributes;
|
||||
LPOVERLAPPED lpOverlapped;
|
||||
};
|
||||
typedef struct winpr_named_pipe WINPR_NAMED_PIPE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
wArrayList* WinPR_GetBaseNamedPipeList();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user