From 97ec29f9fff14aa28d1a0e22c3fcfea00a9dd4df Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Thu, 2 Aug 2012 14:39:35 -0700 Subject: [PATCH] xrdpapi: complete basic WTSVirtual* functions --- xrdpapi/xrdpapi.c | 308 +++++++++++++++++++++++++++++++++++++++++++++- xrdpapi/xrdpapi.h | 18 ++- 2 files changed, 318 insertions(+), 8 deletions(-) diff --git a/xrdpapi/xrdpapi.c b/xrdpapi/xrdpapi.c index 3afc8594..3190cd39 100644 --- a/xrdpapi/xrdpapi.c +++ b/xrdpapi/xrdpapi.c @@ -17,16 +17,148 @@ * limitations under the License. */ +/* do not use os_calls in here */ + #include #include #include +#include +#include +#include +#include +#include +#include +#include + #include "xrdpapi.h" +struct wts_obj +{ + int fd; + int status; + char name[8]; + char dname[128]; + int display_num; +}; + +/*****************************************************************************/ +static int +get_display_num_from_display(char* display_text) +{ + int index; + int mode; + int host_index; + int disp_index; + int scre_index; + char host[256]; + char disp[256]; + char scre[256]; + + index = 0; + host_index = 0; + disp_index = 0; + scre_index = 0; + mode = 0; + while (display_text[index] != 0) + { + if (display_text[index] == ':') + { + mode = 1; + } + else if (display_text[index] == '.') + { + mode = 2; + } + else if (mode == 0) + { + host[host_index] = display_text[index]; + host_index++; + } + else if (mode == 1) + { + disp[disp_index] = display_text[index]; + disp_index++; + } + else if (mode == 2) + { + scre[scre_index] = display_text[index]; + scre_index++; + } + index++; + } + host[host_index] = 0; + disp[disp_index] = 0; + scre[scre_index] = 0; + return atoi(disp); +} + /*****************************************************************************/ void* WTSVirtualChannelOpen(void* hServer, unsigned int SessionId, const char* pVirtualName) { + if (hServer != WTS_CURRENT_SERVER_HANDLE) + { + return 0; + } + return WTSVirtualChannelOpenEx(SessionId, pVirtualName, 0); +} + +/*****************************************************************************/ +static int +can_send(int sck, int millis) +{ + struct timeval time; + fd_set wfds; + int select_rv; + + FD_ZERO(&wfds); + FD_SET(sck, &wfds); + time.tv_sec = millis / 1000; + time.tv_usec = (millis * 1000) % 1000000; + select_rv = select(sck + 1, 0, &wfds, 0, &time); + if (select_rv > 0) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ +static int +can_recv(int sck, int millis) +{ + struct timeval time; + fd_set rfds; + int select_rv; + + FD_ZERO(&rfds); + FD_SET(sck, &rfds); + time.tv_sec = millis / 1000; + time.tv_usec = (millis * 1000) % 1000000; + select_rv = select(sck + 1, &rfds, 0, 0, &time); + if (select_rv > 0) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ +static int +send_init(struct wts_obj* wts) +{ + char initmsg[64]; + + memset(initmsg, 0, 64); + if (!can_send(wts->fd, 500)) + { + return 1; + } + if (send(wts->fd, initmsg, 64, 0) != 64) + { + return 1; + } return 0; } @@ -36,7 +168,50 @@ WTSVirtualChannelOpenEx(unsigned int SessionId, const char* pVirtualName, unsigned int flags) { - return 0; + struct wts_obj* wts; + char* display_text; + struct sockaddr_un s; + int bytes; + unsigned long llong; + + if (SessionId != WTS_CURRENT_SESSION) + { + return 0; + } + wts = (struct wts_obj*)malloc(sizeof(struct wts_obj)); + memset(wts, 0, sizeof(struct wts_obj)); + wts->fd = -1; + display_text = getenv("DISPLAY"); + if (display_text != 0) + { + wts->display_num = get_display_num_from_display(display_text); + } + if (wts->display_num > 0) + { + wts->fd = socket(AF_UNIX, SOCK_STREAM, 0); + /* set non blocking */ + llong = fcntl(wts->fd, F_GETFL); + llong = llong | O_NONBLOCK; + fcntl(wts->fd, F_SETFL, llong); + /* connect to session chansrv */ + memset(&s, 0, sizeof(struct sockaddr_un)); + s.sun_family = AF_UNIX; + bytes = sizeof(s.sun_path); + snprintf(s.sun_path, bytes - 1, "/tmp/.xrdp/xrdpapi_%d", wts->display_num); + s.sun_path[bytes - 1] = 0; + bytes = sizeof(struct sockaddr_un); + if (connect(wts->fd, (struct sockaddr*)&s, bytes) == 0) + { + strncpy(wts->name, pVirtualName, 8); + /* wait for connection to complete and send init */ + if (send_init(wts) == 0) + { + /* all ok */ + wts->status = 1; + } + } + } + return wts; } /*****************************************************************************/ @@ -44,21 +219,144 @@ int WTSVirtualChannelWrite(void* hChannelHandle, const char* Buffer, unsigned int Length, unsigned int* pBytesWritten) { - return 0; + struct wts_obj* wts; + int error; + int lerrno; + + wts = (struct wts_obj*)hChannelHandle; + if (wts == 0) + { + return 0; + } + if (wts->status != 1) + { + return 0; + } + if (can_send(wts->fd, 0)) + { + error = send(wts->fd, Buffer, Length, 0); + if (error == -1) + { + lerrno = errno; + if ((lerrno == EWOULDBLOCK) || (lerrno == EAGAIN) || + (lerrno == EINPROGRESS)) + { + *pBytesWritten = 0; + return 1; + } + return 0; + } + else if (error == 0) + { + return 0; + } + else if (error > 0) + { + *pBytesWritten = error; + return 1; + } + } + *pBytesWritten = 0; + return 1; } /*****************************************************************************/ int -WTSVirtualChannelRead(void* nChannelHandle, unsigned int TimeOut, +WTSVirtualChannelRead(void* hChannelHandle, unsigned int TimeOut, char* Buffer, unsigned int BufferSize, unsigned int* pBytesRead) { - return 0; + struct wts_obj* wts; + int error; + int lerrno; + + wts = (struct wts_obj*)hChannelHandle; + if (wts == 0) + { + return 0; + } + if (wts->status != 1) + { + return 0; + } + if (can_recv(wts->fd, TimeOut)) + { + error = recv(wts->fd, Buffer, BufferSize, 0); + if (error == -1) + { + lerrno = errno; + if ((lerrno == EWOULDBLOCK) || (lerrno == EAGAIN) || + (lerrno == EINPROGRESS)) + { + *pBytesRead = 0; + return 1; + } + return 0; + } + else if (error == 0) + { + return 0; + } + else if (error > 0) + { + *pBytesRead = error; + return 1; + } + } + *pBytesRead = 0; + return 1; } /*****************************************************************************/ int -WTSVirtualChannelClose(void* openHandle) +WTSVirtualChannelClose(void* hChannelHandle) { + struct wts_obj* wts; + + wts = (struct wts_obj*)hChannelHandle; + if (wts == 0) + { + return 0; + } + if (wts->fd != -1) + { + close(wts->fd); + } + free(wts); + return 1; +} + +/*****************************************************************************/ +int +WTSVirtualChannelQuery(void* hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, + void** ppBuffer, unsigned int* pBytesReturned) +{ + struct wts_obj* wts; + + wts = (struct wts_obj*)hChannelHandle; + if (wts == 0) + { + return 0; + } + if (wts->status != 1) + { + return 0; + } + if (WtsVirtualClass == WTSVirtualFileHandle) + { + *pBytesReturned = 4; + *ppBuffer = malloc(4); + memcpy(*ppBuffer, &(wts->fd), 4); + } return 0; } + +/*****************************************************************************/ +void +WTSFreeMemory(void* pMemory) +{ + if (pMemory != 0) + { + free(pMemory); + } +} diff --git a/xrdpapi/xrdpapi.h b/xrdpapi/xrdpapi.h index c4571e46..cb451559 100644 --- a/xrdpapi/xrdpapi.h +++ b/xrdpapi/xrdpapi.h @@ -17,7 +17,8 @@ * limitations under the License. */ /* - xrdpapi header + xrdpapi header, do not use os_calls.h, arch.h or any xrdp internal headers + this file is included in 3rd party apps */ #if !defined(XRDPAPI_H_) @@ -26,6 +27,12 @@ #define WTS_CURRENT_SERVER_HANDLE 0 #define WTS_CURRENT_SESSION 0xffffffff +typedef enum _WTS_VIRTUAL_CLASS +{ + WTSVirtualClientData, + WTSVirtualFileHandle +} WTS_VIRTUAL_CLASS; + /* Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/aa383464(v=vs.85).aspx @@ -41,10 +48,15 @@ int WTSVirtualChannelWrite(void* hChannelHandle, const char* Buffer, unsigned int Length, unsigned int* pBytesWritten); int -WTSVirtualChannelRead(void* nChannelHandle, unsigned int TimeOut, +WTSVirtualChannelRead(void* hChannelHandle, unsigned int TimeOut, char* Buffer, unsigned int BufferSize, unsigned int* pBytesRead); int -WTSVirtualChannelClose(void* openHandle); +WTSVirtualChannelClose(void* hChannelHandle); +int +WTSVirtualChannelQuery(void* hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, + void** ppBuffer, unsigned int* pBytesReturned); +void +WTSFreeMemory(void* pMemory); #endif /* XRDPAPI_H_ */