diff options
Diffstat (limited to 'xrdpapi')
-rw-r--r-- | xrdpapi/simple.c | 189 | ||||
-rw-r--r-- | xrdpapi/xrdpapi.c | 406 | ||||
-rw-r--r-- | xrdpapi/xrdpapi.h | 72 |
3 files changed, 386 insertions, 281 deletions
diff --git a/xrdpapi/simple.c b/xrdpapi/simple.c index 7f309ab8..e6f5bd16 100644 --- a/xrdpapi/simple.c +++ b/xrdpapi/simple.c @@ -1,7 +1,8 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2012 + * Copyright (C) Jay Sorg 2012 + * Copyright (C) Laxmikant Rashinkar 2012 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +15,20 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. + * + * sample program to demonstrate use of xrdpapi + * */ /* - * Basic test for virtual channel use + * build instructions: + * gcc simple.c -o simple -L./.libs -lxrdpapi */ -// These headers are required for the windows terminal services calls. +#ifdef __WIN32__ +#include <mstsapi.h> +#endif + #include "xrdpapi.h" #include <stdlib.h> #include <stdio.h> @@ -28,92 +36,143 @@ #include <string.h> #include <errno.h> -#define DSIZE (1024 * 4) +/* forward declarations */ +int run_echo_test(); +int run_tsmf_test(); -int main() +int +main(int argc, char **argv) { - - // Initialize the data for send/receive - void *hFile; - char *data; - char *data1; - data = (char *)malloc(DSIZE); - data1 = (char *)malloc(DSIZE); - int ret; - void *vcFileHandlePtr = NULL; - memset(data, 0xca, DSIZE); - memset(data1, 0, DSIZE); - unsigned int written = 0; - - // Open the skel channel in current session - - //void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "skel", 0); - void *channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "TSMF", WTS_CHANNEL_OPTION_DYNAMIC); - ret = WTSVirtualChannelQuery(channel, WTSVirtualFileHandle, vcFileHandlePtr, &written); - - // Write the data to the channel - ret = WTSVirtualChannelWrite(channel, data, DSIZE, &written); - - if (!ret) + if (argc < 2) { - - long err = errno; - printf("error 1 0x%8.8x\n", err); - usleep(100000); + printf("usage: simple <echo|tsmf>\n"); return 1; } - else - { - printf("Sent bytes!\n"); - } - if (written != DSIZE) + if (strcasecmp(argv[1], "echo") == 0) { - long err = errno; - printf("error 2 0x%8.8x\n", err); - usleep(100000); - return 1; + return run_echo_test(); } - else + else if (strcasecmp(argv[1], "tsmf") == 0) { - printf("Read bytes!\n"); + return run_tsmf_test(); } - - ret = WTSVirtualChannelRead(channel, 100, data1, DSIZE, &written); - - if (!ret) + else { - long err = errno; - printf("error 3 0x%8.8x\n", err); - usleep(100000); + printf("usage: simple <echo|tsmf>\n"); return 1; } +} - if (written != DSIZE) +/** + * perform an ECHO test with a Microsoft Windows RDP client + * + * A Microsoft Windows RDP client echos data written + * to a dynamic virtual channel named ECHO + * + * NOTE: THIS TEST WILL FAIL IF CONNECTED FROM A NON + * WINDOWS RDP CLIENT + * + * @return 0 on success, -1 on failure + */ +int +run_echo_test() +{ + char out_buf[8192]; + char in_buf[1700]; + void *channel; + int bytes_left; + int rv; + int count; + int pkt_count; + int i; + int bytes_written; + int bytes_read; + + unsigned char c; + unsigned char *rd_ptr; + unsigned char *wr_ptr; + + /* fill out_buf[] with incremental values */ + for (i = 0, c = 0; i < 8192; i++, c++) { - long err = errno; - printf("error 4 0x%8.8x\n", err); - usleep(100000); - return 1; + out_buf[i] = c; } - else + + /* open a virtual channel named ECHO */ + channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "ECHO", WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW); + if (channel == NULL) { - printf("Read bytes!\n"); + printf("### WTSVirtualChannelOpenEx() failed!\n"); + return -1; } - ret = WTSVirtualChannelClose(channel); + bytes_left = 8192; + wr_ptr = out_buf; + rd_ptr = out_buf; + pkt_count = 1; - if (memcmp(data, data1, DSIZE) == 0) + while (bytes_left > 0) { + /* write data to virtual channel */ + count = (bytes_left > 1700) ? 1700 : bytes_left; + rv = WTSVirtualChannelWrite(channel, wr_ptr, count, &bytes_written); + if ((rv == 0) || (bytes_written == 0)) + { + printf("### WTSVirtualChannelWrite() failed\n"); + return -1; + } + + count = bytes_written; + + while (count) + { + /* read back the echo */ + rv = WTSVirtualChannelRead(channel, 5000, in_buf, count, &bytes_read); + if ((rv == 0) || (bytes_read == 0)) + { + printf("### WTSVirtualChannelRead() failed\n"); + return -1; + } + + /* validate the echo */ + for (i = 0; i < bytes_read; i++, rd_ptr++) + { + if (*rd_ptr != (unsigned char) in_buf[i]) + { + printf("### data mismatch: expected 0x%x got 0x%x\n", + (unsigned char) *rd_ptr, (unsigned char) in_buf[i]); + return -1; + } + } + count -= bytes_read; + } + + bytes_left -= bytes_written; + wr_ptr += bytes_written; + printf("### pkt %d passed echo test\n", pkt_count++); } - else + + WTSVirtualChannelClose(channel); + return 0; +} + +int +run_tsmf_test() +{ + void *channel; + + printf("this test not yet implemented!\n"); + return 1; + + /* open virtual channel */ + channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "TSMF", WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW); + if (channel == NULL) { - printf("error data no match\n"); + printf("### WTSVirtualChannelOpenEx() failed!\n"); return 1; } - printf("Done!\n"); - - usleep(100000); - return 0; + WTSVirtualChannelClose(channel); + return 0; } diff --git a/xrdpapi/xrdpapi.c b/xrdpapi/xrdpapi.c index 85a13a8e..e320ef5d 100644 --- a/xrdpapi/xrdpapi.c +++ b/xrdpapi/xrdpapi.c @@ -1,8 +1,8 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Thomas Goddard 2012 * Copyright (C) Jay Sorg 2012 + * Copyright (C) Laxmikant Rashinkar 2012 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,6 @@ * limitations under the License. */ -/* do not use os_calls in here */ - #define LOG_LEVEL 1 #define LLOG(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0) @@ -29,6 +27,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <stdint.h> #include <fcntl.h> #include <errno.h> #include <sys/types.h> @@ -40,69 +39,31 @@ struct wts_obj { - int fd; - int status; - char name[8]; - char dname[128]; - int display_num; - int flags; + int fd; + int status; + char name[8]; + char dname[128]; + int display_num; + uint32_t flags; }; -/*****************************************************************************/ -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; +/* helper functions used by WTSxxx API - do not invoke directly */ +static int get_display_num_from_display(char *display_text); +static int send_init(struct wts_obj *wts); +static int can_send(int sck, int millis); +static int can_recv(int sck, int millis); - 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); -} - -/*****************************************************************************/ +/* + * Opens a handle to the server end of a specified virtual channel - this + * call is deprecated - use WTSVirtualChannelOpenEx() instead + * + * @param hServer + * @param SessionId - current session ID; *must* be WTS_CURRENT_SERVER_HANDLE + * @param pVirtualName - virtual channel name when using SVC + * - name of endpoint listener when using DVC + * + * @return a valid pointer on success, NULL on error + ******************************************************************************/ void * WTSVirtualChannelOpen(void *hServer, unsigned int SessionId, const char *pVirtualName) @@ -115,98 +76,34 @@ WTSVirtualChannelOpen(void *hServer, unsigned int SessionId, 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); - strncpy(initmsg, wts->name, 8); - initmsg[16] = (wts->flags >> 0) & 0xff; - initmsg[17] = (wts->flags >> 8) & 0xff; - initmsg[18] = (wts->flags >> 16) & 0xff; - initmsg[19] = (wts->flags >> 24) & 0xff; - LLOGLN(10, ("send_init: sending %s", initmsg)); - - if (!can_send(wts->fd, 500)) - { - return 1; - } - - if (send(wts->fd, initmsg, 64, 0) != 64) - { - return 1; - } - - LLOGLN(10, ("send_init: send ok!")); - return 0; -} - -/*****************************************************************************/ +/* + * Opens a handle to the server end of a specified virtual channel + * + * @param SessionId - current session ID; *must* be WTS_CURRENT_SERVER_HANDLE + * @param pVirtualName - virtual channel name when using SVC + * - name of endpoint listener when using DVC + * @param flags - type of channel and channel priority if DVC + * + * @return a valid pointer on success, NULL on error + ******************************************************************************/ void * -WTSVirtualChannelOpenEx(unsigned int SessionId, - const char *pVirtualName, +WTSVirtualChannelOpenEx(unsigned int SessionId, const char *pVirtualName, unsigned int flags) { - struct wts_obj *wts; - char *display_text; - struct sockaddr_un s; - int bytes; - unsigned long llong; + struct wts_obj *wts; + char *display_text; + int bytes; + unsigned long llong; + struct sockaddr_un s; if (SessionId != WTS_CURRENT_SESSION) { - LLOGLN(0, ("WTSVirtualChannelOpenEx: SessionId bad")); + LLOGLN(0, ("WTSVirtualChannelOpenEx: bad SessionId")); return 0; } - wts = (struct wts_obj *)malloc(sizeof(struct wts_obj)); - memset(wts, 0, sizeof(struct wts_obj)); + wts = (struct wts_obj *) calloc(1, sizeof(struct wts_obj)); + wts->fd = -1; wts->flags = flags; display_text = getenv("DISPLAY"); @@ -216,37 +113,40 @@ WTSVirtualChannelOpenEx(unsigned int SessionId, wts->display_num = get_display_num_from_display(display_text); } - if (wts->display_num > 0) + 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) - { - LLOGLN(10, ("WTSVirtualChannelOpenEx: connected ok, name %s", pVirtualName)); - strncpy(wts->name, pVirtualName, 8); - - /* wait for connection to complete and send init */ - if (send_init(wts) == 0) - { - /* all ok */ - wts->status = 1; - } - } + LLOGLN(0, ("WTSVirtualChannelOpenEx: fatal errror; display is 0")); + free(wts); + return NULL; } - else + + /* we use unix domain socket to communicate with chansrv */ + 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 chansrv session */ + 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) { - LLOGLN(0, ("WTSVirtualChannelOpenEx: display is 0")); + LLOGLN(10, ("WTSVirtualChannelOpenEx: connected ok, name %s", pVirtualName)); + 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; @@ -312,7 +212,7 @@ WTSVirtualChannelRead(void *hChannelHandle, unsigned int TimeOut, unsigned int *pBytesRead) { struct wts_obj *wts; - int error; + int rv; int lerrno; wts = (struct wts_obj *)hChannelHandle; @@ -329,9 +229,9 @@ WTSVirtualChannelRead(void *hChannelHandle, unsigned int TimeOut, if (can_recv(wts->fd, TimeOut)) { - error = recv(wts->fd, Buffer, BufferSize, 0); + rv = recv(wts->fd, Buffer, BufferSize, 0); - if (error == -1) + if (rv == -1) { lerrno = errno; @@ -341,16 +241,15 @@ WTSVirtualChannelRead(void *hChannelHandle, unsigned int TimeOut, *pBytesRead = 0; return 1; } - return 0; } - else if (error == 0) + else if (rv == 0) { return 0; } - else if (error > 0) + else if (rv > 0) { - *pBytesRead = error; + *pBytesRead = rv; return 1; } } @@ -419,3 +318,148 @@ WTSFreeMemory(void *pMemory) free(pMemory); } } + +/***************************************************************************** +** ** +** ** +** Helper functions used by WTSxxx API - do not invoke directly ** +** ** +** ** +*****************************************************************************/ + +/* + * check if socket is in a writable state - i.e will not block on write + * + * @param sck socket to check + * @param millis timeout value in milliseconds + * + * @return 0 if write will block + * @return 1 if write will not block + ******************************************************************************/ +static int +can_send(int sck, int millis) +{ + struct timeval time; + fd_set wfds; + int select_rv; + + /* setup for a select call */ + FD_ZERO(&wfds); + FD_SET(sck, &wfds); + time.tv_sec = millis / 1000; + time.tv_usec = (millis * 1000) % 1000000; + + /* check if it is ok to write to specified socket */ + select_rv = select(sck + 1, 0, &wfds, 0, &time); + + return (select_rv > 0) ? 1 : 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); + + /* insert channel name */ + strncpy(initmsg, wts->name, 8); + + /* insert open mode flags */ + initmsg[16] = (wts->flags >> 0) & 0xff; + initmsg[17] = (wts->flags >> 8) & 0xff; + initmsg[18] = (wts->flags >> 16) & 0xff; + initmsg[19] = (wts->flags >> 24) & 0xff; + + if (!can_send(wts->fd, 500)) + { + LLOGLN(10, ("send_init: send() will block!")); + return 1; + } + + if (send(wts->fd, initmsg, 64, 0) != 64) + { + LLOGLN(10, ("send_init: send() failed!")); + return 1; + } + + LLOGLN(10, ("send_init: sent ok!")); + return 0; +} + +/*****************************************************************************/ +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); +} diff --git a/xrdpapi/xrdpapi.h b/xrdpapi/xrdpapi.h index 82f9b809..fdb998cf 100644 --- a/xrdpapi/xrdpapi.h +++ b/xrdpapi/xrdpapi.h @@ -1,8 +1,9 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Thomas Goddard 2012 * Copyright (C) Jay Sorg 2012 + * Copyright (C) Thomas Goddard 2012 + * Copyright (C) Laxmikant Rashinkar 2012 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,46 +30,47 @@ extern "C" { #endif -#define WTS_CURRENT_SERVER_HANDLE 0 -#define WTS_CURRENT_SESSION 0xffffffff -#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001 -#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW 0x00000000 -#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED 0x00000002 -#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH 0x00000004 -#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL 0x00000006 -#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_COMPRESS 0x00000008 +#define WTS_CURRENT_SERVER_HANDLE 0x00000000 +#define WTS_CURRENT_SESSION 0xffffffff + +#define WTS_CHANNEL_OPTION_STATIC 0x00000000 +#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001 +#define WTS_CHANNEL_OPTION_DYNAMIC_NO_COMPRESS 0x00000001 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW 0x00000001 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED 0x00000002 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH 0x00000003 +#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL 0x00000004 typedef enum _WTS_VIRTUAL_CLASS { - WTSVirtualClientData, - WTSVirtualFileHandle + WTSVirtualClientData, + WTSVirtualFileHandle } WTS_VIRTUAL_CLASS; /* - Reference: - http://msdn.microsoft.com/en-us/library/windows/desktop/aa383464(v=vs.85).aspx -*/ -void* -WTSVirtualChannelOpen(void* hServer, unsigned int SessionId, - const char* pVirtualName); -void* -WTSVirtualChannelOpenEx(unsigned int SessionId, - const char* pVirtualName, - unsigned int flags); -int -WTSVirtualChannelWrite(void* hChannelHandle, const char* Buffer, - unsigned int Length, unsigned int* pBytesWritten); -int -WTSVirtualChannelRead(void* hChannelHandle, unsigned int TimeOut, - char* Buffer, unsigned int BufferSize, - unsigned int* pBytesRead); -int -WTSVirtualChannelClose(void* hChannelHandle); -int -WTSVirtualChannelQuery(void* hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, - void** ppBuffer, unsigned int* pBytesReturned); -void -WTSFreeMemory(void* pMemory); + * Reference: + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa383464(v=vs.85).aspx + */ + +void* WTSVirtualChannelOpen(void* hServer, unsigned int SessionId, + const char* pVirtualName); + +void* WTSVirtualChannelOpenEx(unsigned int SessionId, + const char* pVirtualName, unsigned int flags); + +int WTSVirtualChannelWrite(void* hChannelHandle, const char* Buffer, + unsigned int Length, unsigned int* pBytesWritten); + +int WTSVirtualChannelRead(void* hChannelHandle, unsigned int TimeOut, + char* Buffer, unsigned int BufferSize, + unsigned int* pBytesRead); + +int WTSVirtualChannelClose(void* hChannelHandle); + +int WTSVirtualChannelQuery(void* hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, + void** ppBuffer, unsigned int* pBytesReturned); + +void WTSFreeMemory(void* pMemory); #ifdef __cplusplus } |