diff --git a/CMakeLists.txt b/CMakeLists.txt index 464d00503..0c00c34f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ check_include_files(sys/param.h HAVE_SYS_PARAM_H) check_include_files(sys/socket.h HAVE_SYS_SOCKET_H) check_include_files(netdb.h HAVE_NETDB_H) check_include_files(fcntl.h HAVE_FCNTL_H) +check_include_files(unistd.h HAVE_UNISTD_H) # Endian test_big_endian(BIG_ENDIAN) diff --git a/cmake/ConfigOptions.cmake b/cmake/ConfigOptions.cmake index 0f3469b64..8c1f25675 100644 --- a/cmake/ConfigOptions.cmake +++ b/cmake/ConfigOptions.cmake @@ -1 +1,2 @@ option(WITH_DEBUG_TRANSPORT "Print transport debug message." OFF) +option(WITH_DEBUG_CHANMAN "Print channel manager debug message." OFF) diff --git a/config.h.in b/config.h.in index 204974a86..77cd75c75 100644 --- a/config.h.in +++ b/config.h.in @@ -3,9 +3,11 @@ #cmakedefine HAVE_SYS_SOCKET_H #cmakedefine HAVE_NETDB_H #cmakedefine HAVE_FCNTL_H +#cmakedefine HAVE_UNISTD_H /* Endian */ #cmakedefine BIG_ENDIAN /* Options */ #cmakedefine WITH_DEBUG_TRANSPORT +#cmakedefine WITH_DEBUG_CHANMAN diff --git a/include/freerdp/utils/wait_obj.h b/include/freerdp/utils/wait_obj.h new file mode 100644 index 000000000..34a21f480 --- /dev/null +++ b/include/freerdp/utils/wait_obj.h @@ -0,0 +1,31 @@ +/** + * FreeRDP: A Remote Desktop Protocol client. + * Virtual Channel Manager + * + * Copyright 2009-2011 Jay Sorg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * 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. + */ + +#ifndef __WAIT_OBJ_UTILS +#define __WAIT_OBJ_UTILS + +struct wait_obj* wait_obj_new(void); +void wait_obj_free(struct wait_obj* obj); +int wait_obj_is_set(struct wait_obj* obj); +void wait_obj_set(struct wait_obj* obj); +void wait_obj_clear(struct wait_obj* obj); +int wait_obj_select(struct wait_obj** listobj, int numobj, int timeout); +void wait_obj_get_fds(struct wait_obj* obj, void** fds, int* count); + +#endif diff --git a/libfreerdp-utils/CMakeLists.txt b/libfreerdp-utils/CMakeLists.txt index f8ad0d8c4..4ef3760c0 100644 --- a/libfreerdp-utils/CMakeLists.txt +++ b/libfreerdp-utils/CMakeLists.txt @@ -25,7 +25,8 @@ set(FREERDP_UTILS_SRCS mutex.c semaphore.c stream.c - unicode.c) + unicode.c + wait_obj.c) add_definitions(-DPLUGIN_PATH="${FREERDP_PLUGIN_PATH}") diff --git a/libfreerdp-utils/wait_obj.c b/libfreerdp-utils/wait_obj.c new file mode 100644 index 000000000..5c8bc2a15 --- /dev/null +++ b/libfreerdp-utils/wait_obj.c @@ -0,0 +1,190 @@ +/** + * FreeRDP: A Remote Desktop Protocol client. + * Virtual Channel Manager + * + * Copyright 2009-2011 Jay Sorg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * 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. + */ + +#include "config.h" +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +struct wait_obj +{ +#ifdef _WIN32 + HANDLE event; +#else + int pipe_fd[2]; +#endif +}; + +struct wait_obj* +wait_obj_new(void) +{ + struct wait_obj* obj; + + obj = (struct wait_obj*)xmalloc(sizeof(struct wait_obj)); + +#ifdef _WIN32 + obj->event = CreateEvent(NULL, TRUE, FALSE, NULL); +#else + obj->pipe_fd[0] = -1; + obj->pipe_fd[1] = -1; + if (pipe(obj->pipe_fd) < 0) + { + printf("wait_obj_new: pipe failed\n"); + xfree(obj); + return NULL; + } +#endif + + return obj; +} + +void +wait_obj_free(struct wait_obj* obj) +{ + if (obj) + { + +#ifdef _WIN32 + if (obj->event) + { + CloseHandle(obj->event); + obj->event = NULL; + } +#else + if (obj->pipe_fd[0] != -1) + { + close(obj->pipe_fd[0]); + obj->pipe_fd[0] = -1; + } + if (obj->pipe_fd[1] != -1) + { + close(obj->pipe_fd[1]); + obj->pipe_fd[1] = -1; + } +#endif + + xfree(obj); + } +} + +int +wait_obj_is_set(struct wait_obj* obj) +{ +#ifdef _WIN32 + return (WaitForSingleObject(obj->event, 0) == WAIT_OBJECT_0); +#else + fd_set rfds; + int num_set; + struct timeval time; + + FD_ZERO(&rfds); + FD_SET(obj->pipe_fd[0], &rfds); + memset(&time, 0, sizeof(time)); + num_set = select(obj->pipe_fd[0] + 1, &rfds, 0, 0, &time); + return (num_set == 1); +#endif +} + +void +wait_obj_set(struct wait_obj* obj) +{ +#ifdef _WIN32 + SetEvent(obj->event); +#else + int len; + + if (wait_obj_is_set(obj)) + return; + len = write(obj->pipe_fd[1], "sig", 4); + if (len != 4) + printf("wait_obj_set: error\n"); +#endif +} + +void +wait_obj_clear(struct wait_obj* obj) +{ +#ifdef _WIN32 + ResetEvent(chan_man->chan_event); +#else + int len; + + while (wait_obj_is_set(obj)) + { + len = read(obj->pipe_fd[0], &len, 4); + if (len != 4) + printf("wait_obj_clear: error\n"); + } +#endif +} + +int +wait_obj_select(struct wait_obj** listobj, int numobj, int timeout) +{ + int max; + int rv; + int index; + int sock; + struct timeval time; + struct timeval * ptime; + fd_set fds; + + ptime = 0; + if (timeout >= 0) + { + time.tv_sec = timeout / 1000; + time.tv_usec = (timeout * 1000) % 1000000; + ptime = &time; + } + max = 0; + FD_ZERO(&fds); + if (listobj) + { + for (index = 0; index < numobj; index++) + { + sock = listobj[index]->pipe_fd[0]; + FD_SET(sock, &fds); + if (sock > max) + { + max = sock; + } + } + } + rv = select(max + 1, &fds, 0, 0, ptime); + return rv; +} + +void wait_obj_get_fds(struct wait_obj* obj, void** fds, int* count) +{ +#ifdef _WIN32 + fds[*count] = (void*) obj->event; +#else + if (obj->pipe_fd[0] == -1) + return; + + fds[*count] = (void*)(long) obj->pipe_fd[0]; +#endif + (*count)++; +}