mirror of https://github.com/FreeRDP/FreeRDP
Merge pull request #10 from llyzs/chanman
Initial chanman implementation
This commit is contained in:
commit
3d16920e94
|
@ -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)
|
||||
|
@ -56,6 +57,9 @@ test_big_endian(BIG_ENDIAN)
|
|||
# Path to put keymaps
|
||||
set(FREERDP_KEYMAP_PATH "${CMAKE_INSTALL_PREFIX}/freerdp/keymaps")
|
||||
|
||||
# Path to put plugins
|
||||
set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_PREFIX}/lib/freerdp")
|
||||
|
||||
# Include directories
|
||||
include_directories(${CMAKE_SOURCE_DIR})
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
|
@ -81,7 +85,7 @@ add_subdirectory(libfreerdp-asn1)
|
|||
add_subdirectory(libfreerdp-utils)
|
||||
add_subdirectory(libfreerdp-kbd)
|
||||
add_subdirectory(libfreerdp-gdi)
|
||||
|
||||
add_subdirectory(libfreerdp-chanman)
|
||||
add_subdirectory(libfreerdp-core)
|
||||
|
||||
add_subdirectory(freerdp-ui)
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
option(WITH_DEBUG_TRANSPORT "Print transport debug message." OFF)
|
||||
option(WITH_DEBUG_CHANMAN "Print channel manager debug message." OFF)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -43,6 +43,8 @@ add_executable(test_freerdp
|
|||
test_utils.h
|
||||
test_transport.c
|
||||
test_transport.h
|
||||
test_chanman.c
|
||||
test_chanman.h
|
||||
test_freerdp.c
|
||||
test_freerdp.h)
|
||||
|
||||
|
@ -52,4 +54,5 @@ target_link_libraries(test_freerdp freerdp-core)
|
|||
target_link_libraries(test_freerdp freerdp-gdi)
|
||||
target_link_libraries(test_freerdp freerdp-asn1)
|
||||
target_link_libraries(test_freerdp freerdp-utils)
|
||||
target_link_libraries(test_freerdp freerdp-chanman)
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* Channel Manager Unit Tests
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/chanman.h>
|
||||
|
||||
#include "test_chanman.h"
|
||||
|
||||
int init_chanman_suite(void)
|
||||
{
|
||||
freerdp_chanman_global_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clean_chanman_suite(void)
|
||||
{
|
||||
freerdp_chanman_global_uninit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int add_chanman_suite(void)
|
||||
{
|
||||
add_test_suite(chanman);
|
||||
|
||||
add_test_function(chanman);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_chanman(void)
|
||||
{
|
||||
rdpChanMan* chan_man;
|
||||
rdpSettings settings = { 0 };
|
||||
|
||||
chan_man = freerdp_chanman_new();
|
||||
|
||||
freerdp_chanman_close(chan_man, NULL);
|
||||
freerdp_chanman_free(chan_man);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* Channel Manager Unit Tests
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
* 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 "test_freerdp.h"
|
||||
|
||||
int init_chanman_suite(void);
|
||||
int clean_chanman_suite(void);
|
||||
int add_chanman_suite(void);
|
||||
|
||||
void test_chanman(void);
|
|
@ -29,6 +29,7 @@
|
|||
#include "test_stream.h"
|
||||
#include "test_utils.h"
|
||||
#include "test_transport.h"
|
||||
#include "test_chanman.h"
|
||||
#include "test_freerdp.h"
|
||||
|
||||
void dump_data(unsigned char * p, int len, int width, char* name)
|
||||
|
@ -119,6 +120,7 @@ int main(int argc, char* argv[])
|
|||
add_stream_suite();
|
||||
add_utils_suite();
|
||||
add_transport_suite();
|
||||
add_chanman_suite();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -148,6 +150,10 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
add_transport_suite();
|
||||
}
|
||||
else if (strcmp("chanman", argv[*pindex]) == 0)
|
||||
{
|
||||
add_chanman_suite();
|
||||
}
|
||||
else if (strcmp("per", argv[*pindex]) == 0)
|
||||
{
|
||||
add_per_suite();
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/utils/mutex.h>
|
||||
#include <freerdp/utils/semaphore.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
|
||||
#include "test_utils.h"
|
||||
|
||||
|
@ -42,6 +44,8 @@ int add_utils_suite(void)
|
|||
|
||||
add_test_function(mutex);
|
||||
add_test_function(semaphore);
|
||||
add_test_function(load_plugin);
|
||||
add_test_function(wait_obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -65,3 +69,34 @@ void test_semaphore(void)
|
|||
freerdp_sem_signal(sem);
|
||||
freerdp_sem_free(sem);
|
||||
}
|
||||
|
||||
void test_load_plugin(void)
|
||||
{
|
||||
void* entry;
|
||||
|
||||
entry = freerdp_load_plugin("cliprdr", "VirtualChannelEntry");
|
||||
CU_ASSERT(entry != NULL);
|
||||
}
|
||||
|
||||
void test_wait_obj(void)
|
||||
{
|
||||
struct wait_obj* wo;
|
||||
int set;
|
||||
|
||||
wo = wait_obj_new();
|
||||
|
||||
set = wait_obj_is_set(wo);
|
||||
CU_ASSERT(set == 0);
|
||||
|
||||
wait_obj_set(wo);
|
||||
set = wait_obj_is_set(wo);
|
||||
CU_ASSERT(set == 1);
|
||||
|
||||
wait_obj_clear(wo);
|
||||
set = wait_obj_is_set(wo);
|
||||
CU_ASSERT(set == 0);
|
||||
|
||||
wait_obj_select(&wo, 1, 1000);
|
||||
|
||||
wait_obj_free(wo);
|
||||
}
|
||||
|
|
|
@ -25,3 +25,5 @@ int add_list_suite(void);
|
|||
|
||||
void test_mutex(void);
|
||||
void test_semaphore(void);
|
||||
void test_load_plugin(void);
|
||||
void test_wait_obj(void);
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* Virtual Channel Manager
|
||||
*
|
||||
* Copyright 2009-2011 Jay Sorg
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* 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 __FREERDP_CHANMAN_H
|
||||
#define __FREERDP_CHANMAN_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct rdp_chan_man rdpChanMan;
|
||||
|
||||
FREERDP_API int freerdp_chanman_global_init(void);
|
||||
FREERDP_API int freerdp_chanman_global_uninit(void);
|
||||
FREERDP_API rdpChanMan* freerdp_chanman_new(void);
|
||||
FREERDP_API void freerdp_chanman_free(rdpChanMan* chan_man);
|
||||
FREERDP_API int freerdp_chanman_load_plugin(rdpChanMan* chan_man, rdpSettings* settings,
|
||||
const char* name, void* data);
|
||||
FREERDP_API int freerdp_chanman_pre_connect(rdpChanMan* chan_man, rdpInst* inst);
|
||||
FREERDP_API int freerdp_chanman_post_connect(rdpChanMan* chan_man, rdpInst* inst);
|
||||
FREERDP_API int freerdp_chanman_data(rdpInst* inst, int chan_id, char* data, int data_size,
|
||||
int flags, int total_size);
|
||||
FREERDP_API int freerdp_chanman_get_fds(rdpChanMan* chan_man, rdpInst* inst, void** read_fds,
|
||||
int* read_count, void** write_fds, int* write_count);
|
||||
FREERDP_API int freerdp_chanman_check_fds(rdpChanMan* chan_man, rdpInst* inst);
|
||||
FREERDP_API FRDP_EVENT* freerdp_chanman_pop_event(rdpChanMan* chan_man);
|
||||
FREERDP_API void freerdp_chanman_free_event(rdpChanMan* chan_man, FRDP_EVENT* event);
|
||||
FREERDP_API void freerdp_chanman_close(rdpChanMan* chan_man, rdpInst* inst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -42,4 +42,38 @@ enum RDP_NEG_FAILURE_FAILURECODES
|
|||
HYBRID_REQUIRED_BY_SERVER = 0x00000005
|
||||
};
|
||||
|
||||
/**
|
||||
* Static Virtual Channel Flags
|
||||
*/
|
||||
enum RDP_SVC_CHANNEL_FLAG
|
||||
{
|
||||
CHANNEL_FLAG_MIDDLE = 0,
|
||||
CHANNEL_FLAG_FIRST = 0x01,
|
||||
CHANNEL_FLAG_LAST = 0x02,
|
||||
CHANNEL_FLAG_ONLY = (CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST),
|
||||
CHANNEL_FLAG_SHOW_PROTOCOL = 0x10,
|
||||
CHANNEL_FLAG_SUSPEND = 0x20,
|
||||
CHANNEL_FLAG_RESUME = 0x40,
|
||||
CHANNEL_FLAG_FAIL = 0x100
|
||||
};
|
||||
|
||||
//#define CHANNEL_FLAG_ONLY (CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST)
|
||||
|
||||
/**
|
||||
* Static Virtual Channel Options
|
||||
*/
|
||||
enum RDP_SVC_CHANNEL_OPTION
|
||||
{
|
||||
CHANNEL_OPTION_SHOW_PROTOCOL = 0x00200000,
|
||||
CHANNEL_OPTION_COMPRESS = 0x00400000,
|
||||
CHANNEL_OPTION_COMPRESS_RDP = 0x00800000,
|
||||
CHANNEL_OPTION_PRI_LOW = 0x02000000,
|
||||
CHANNEL_OPTION_PRI_MED = 0x04000000,
|
||||
CHANNEL_OPTION_PRI_HIGH = 0x08000000,
|
||||
CHANNEL_OPTION_ENCRYPT_CS = 0x10000000,
|
||||
CHANNEL_OPTION_ENCRYPT_SC = 0x20000000,
|
||||
CHANNEL_OPTION_ENCRYPT_RDP = 0x40000000,
|
||||
CHANNEL_OPTION_INITIALIZED = 0x80000000
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* Static Virtual Channel Interface
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* MS compatible SVC plugin interface
|
||||
* reference:
|
||||
* http://msdn.microsoft.com/en-us/library/aa383580.aspx
|
||||
*/
|
||||
|
||||
#ifndef __FREERDP_SVC_H
|
||||
#define __FREERDP_SVC_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#define CHANNEL_EXPORT_FUNC_NAME "VirtualChannelEntry"
|
||||
|
||||
#define CHANNEL_NAME_LEN 7
|
||||
|
||||
struct _CHANNEL_DEF
|
||||
{
|
||||
char name[CHANNEL_NAME_LEN + 1];
|
||||
uint32 options;
|
||||
};
|
||||
typedef struct _CHANNEL_DEF CHANNEL_DEF;
|
||||
typedef CHANNEL_DEF* PCHANNEL_DEF;
|
||||
typedef CHANNEL_DEF** PPCHANNEL_DEF;
|
||||
|
||||
typedef void (FREERDP_CC * PCHANNEL_INIT_EVENT_FN)(void* pInitHandle,
|
||||
uint32 event, void* pData, uint32 dataLength);
|
||||
|
||||
#define CHANNEL_EVENT_INITIALIZED 0
|
||||
#define CHANNEL_EVENT_CONNECTED 1
|
||||
#define CHANNEL_EVENT_V1_CONNECTED 2
|
||||
#define CHANNEL_EVENT_DISCONNECTED 3
|
||||
#define CHANNEL_EVENT_TERMINATED 4
|
||||
|
||||
typedef void (FREERDP_CC * PCHANNEL_OPEN_EVENT_FN)(uint32 openHandle,
|
||||
uint32 event, void* pData, uint32 dataLength,
|
||||
uint32 totalLength, uint32 dataFlags);
|
||||
|
||||
#define CHANNEL_EVENT_DATA_RECEIVED 10
|
||||
#define CHANNEL_EVENT_WRITE_COMPLETE 11
|
||||
#define CHANNEL_EVENT_WRITE_CANCELLED 12
|
||||
|
||||
#define CHANNEL_RC_OK 0
|
||||
#define CHANNEL_RC_ALREADY_INITIALIZED 1
|
||||
#define CHANNEL_RC_NOT_INITIALIZED 2
|
||||
#define CHANNEL_RC_ALREADY_CONNECTED 3
|
||||
#define CHANNEL_RC_NOT_CONNECTED 4
|
||||
#define CHANNEL_RC_TOO_MANY_CHANNELS 5
|
||||
#define CHANNEL_RC_BAD_CHANNEL 6
|
||||
#define CHANNEL_RC_BAD_CHANNEL_HANDLE 7
|
||||
#define CHANNEL_RC_NO_BUFFER 8
|
||||
#define CHANNEL_RC_BAD_INIT_HANDLE 9
|
||||
#define CHANNEL_RC_NOT_OPEN 10
|
||||
#define CHANNEL_RC_BAD_PROC 11
|
||||
#define CHANNEL_RC_NO_MEMORY 12
|
||||
#define CHANNEL_RC_UNKNOWN_CHANNEL_NAME 13
|
||||
#define CHANNEL_RC_ALREADY_OPEN 14
|
||||
#define CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY 15
|
||||
#define CHANNEL_RC_NULL_DATA 16
|
||||
#define CHANNEL_RC_ZERO_LENGTH 17
|
||||
|
||||
#define VIRTUAL_CHANNEL_VERSION_WIN2000 1
|
||||
|
||||
typedef uint32 (FREERDP_CC * PVIRTUALCHANNELINIT)(void** ppInitHandle,
|
||||
PCHANNEL_DEF pChannel, int channelCount, uint32 versionRequested,
|
||||
PCHANNEL_INIT_EVENT_FN pChannelInitEventProc);
|
||||
typedef uint32 (FREERDP_CC * PVIRTUALCHANNELOPEN)(void* pInitHandle,
|
||||
uint32* pOpenHandle, char* pChannelName,
|
||||
PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc);
|
||||
typedef uint32 (FREERDP_CC * PVIRTUALCHANNELCLOSE)(uint32 openHandle);
|
||||
|
||||
typedef uint32 (FREERDP_CC * PVIRTUALCHANNELWRITE)(uint32 openHandle,
|
||||
void* pData, uint32 dataLength, void* pUserData);
|
||||
|
||||
typedef uint32 (FREERDP_CC * PVIRTUALCHANNELEVENTPUSH)(uint32 openHandle,
|
||||
FRDP_EVENT* event);
|
||||
|
||||
struct _CHANNEL_ENTRY_POINTS
|
||||
{
|
||||
uint32 cbSize;
|
||||
uint32 protocolVersion;
|
||||
PVIRTUALCHANNELINIT pVirtualChannelInit;
|
||||
PVIRTUALCHANNELOPEN pVirtualChannelOpen;
|
||||
PVIRTUALCHANNELCLOSE pVirtualChannelClose;
|
||||
PVIRTUALCHANNELWRITE pVirtualChannelWrite;
|
||||
};
|
||||
typedef struct _CHANNEL_ENTRY_POINTS CHANNEL_ENTRY_POINTS;
|
||||
typedef CHANNEL_ENTRY_POINTS* PCHANNEL_ENTRY_POINTS;
|
||||
|
||||
typedef int (FREERDP_CC * PVIRTUALCHANNELENTRY)(PCHANNEL_ENTRY_POINTS pEntryPoints);
|
||||
|
||||
struct _CHANNEL_ENTRY_POINTS_EX
|
||||
{
|
||||
uint32 cbSize;
|
||||
uint32 protocolVersion;
|
||||
PVIRTUALCHANNELINIT pVirtualChannelInit;
|
||||
PVIRTUALCHANNELOPEN pVirtualChannelOpen;
|
||||
PVIRTUALCHANNELCLOSE pVirtualChannelClose;
|
||||
PVIRTUALCHANNELWRITE pVirtualChannelWrite;
|
||||
void* pExtendedData; /* extended data field to pass initial parameters */
|
||||
PVIRTUALCHANNELEVENTPUSH pVirtualChannelEventPush;
|
||||
};
|
||||
typedef struct _CHANNEL_ENTRY_POINTS_EX CHANNEL_ENTRY_POINTS_EX;
|
||||
typedef CHANNEL_ENTRY_POINTS_EX* PCHANNEL_ENTRY_POINTS_EX;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* Plugin Loading Utils
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
* 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 __LOAD_PLUGIN_UTILS_H
|
||||
#define __LOAD_PLUGIN_UTILS_H
|
||||
|
||||
void* freerdp_load_plugin(const char* name, const char* entry_name);
|
||||
|
||||
#endif /* __LOAD_PLUGIN_UTILS_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
|
|
@ -0,0 +1,29 @@
|
|||
# FreeRDP: A Remote Desktop Protocol Client
|
||||
# libfreerdp-chanman cmake build script
|
||||
#
|
||||
# Copyright 2011 O.S. Systems Software Ltda.
|
||||
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
|
||||
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# 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.
|
||||
|
||||
set(FREERDP_CHANMAN_SRCS
|
||||
libchanman.c
|
||||
libchanman.h)
|
||||
|
||||
add_library(freerdp-chanman SHARED ${FREERDP_CHANMAN_SRCS})
|
||||
|
||||
set_target_properties(freerdp-chanman PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION})
|
||||
|
||||
install(TARGETS freerdp-chanman DESTINATION lib)
|
||||
|
|
@ -0,0 +1,870 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* Virtual Channel Manager
|
||||
*
|
||||
* Copyright 2009-2011 Jay Sorg
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* MS compatible plugin interface
|
||||
* reference:
|
||||
* http://msdn.microsoft.com/en-us/library/aa383580.aspx
|
||||
*
|
||||
* Notes on threads:
|
||||
* Many virtual channel plugins are built using threads.
|
||||
* Non main threads may call MyVirtualChannelOpen,
|
||||
* MyVirtualChannelClose, or MyVirtualChannelWrite.
|
||||
* Since the plugin's VirtualChannelEntry function is called
|
||||
* from the main thread, MyVirtualChannelInit has to be called
|
||||
* from the main thread.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/chanman.h>
|
||||
#include <freerdp/svc.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/semaphore.h>
|
||||
#include <freerdp/utils/mutex.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
|
||||
#include "libchanman.h"
|
||||
|
||||
#define CHANNEL_MAX_COUNT 30
|
||||
|
||||
struct lib_data
|
||||
{
|
||||
PVIRTUALCHANNELENTRY entry; /* the one and only exported function */
|
||||
PCHANNEL_INIT_EVENT_FN init_event_proc;
|
||||
void* init_handle;
|
||||
};
|
||||
|
||||
struct chan_data
|
||||
{
|
||||
char name[CHANNEL_NAME_LEN + 1];
|
||||
int open_handle;
|
||||
int options;
|
||||
int flags; /* 0 nothing 1 init 2 open */
|
||||
PCHANNEL_OPEN_EVENT_FN open_event_proc;
|
||||
};
|
||||
|
||||
typedef struct rdp_init_handle rdpInitHandle;
|
||||
struct rdp_init_handle
|
||||
{
|
||||
rdpChanMan* chan_man;
|
||||
};
|
||||
|
||||
struct rdp_chan_man
|
||||
{
|
||||
/**
|
||||
* Only the main thread alters these arrays, before any
|
||||
* library thread is allowed in(post_connect is called)
|
||||
* so no need to use mutex locking
|
||||
* After post_connect, each library thread can only access it's
|
||||
* own array items
|
||||
* ie, no two threads can access index 0, ...
|
||||
*/
|
||||
struct lib_data libs[CHANNEL_MAX_COUNT];
|
||||
int num_libs;
|
||||
struct chan_data chans[CHANNEL_MAX_COUNT];
|
||||
int num_chans;
|
||||
rdpInitHandle init_handles[CHANNEL_MAX_COUNT];
|
||||
int num_init_handles;
|
||||
|
||||
/* control for entry into MyVirtualChannelInit */
|
||||
int can_call_init;
|
||||
rdpSettings* settings;
|
||||
|
||||
/* true once freerdp_chanman_post_connect is called */
|
||||
int is_connected;
|
||||
|
||||
/* used for locating the chan_man for a given instance */
|
||||
rdpInst* inst;
|
||||
|
||||
/* signal for incoming data or event */
|
||||
struct wait_obj* signal;
|
||||
|
||||
/* used for sync write */
|
||||
freerdp_sem sync_data_sem;
|
||||
void* sync_data;
|
||||
uint32 sync_data_length;
|
||||
void* sync_user_data;
|
||||
int sync_index;
|
||||
|
||||
/* used for sync event */
|
||||
freerdp_sem event_sem;
|
||||
FRDP_EVENT* event;
|
||||
};
|
||||
|
||||
/**
|
||||
* The current channel manager reference passes from VirtualChannelEntry to
|
||||
* VirtualChannelInit for the pInitHandle.
|
||||
*/
|
||||
static rdpChanMan* g_init_chan_man;
|
||||
|
||||
/* The list of all channel managers. */
|
||||
typedef struct rdp_chan_man_list rdpChanManList;
|
||||
struct rdp_chan_man_list
|
||||
{
|
||||
rdpChanMan* chan_man;
|
||||
rdpChanManList* next;
|
||||
};
|
||||
|
||||
static rdpChanManList* g_chan_man_list;
|
||||
|
||||
/* To generate unique sequence for all open handles */
|
||||
static int g_open_handle_sequence;
|
||||
|
||||
/* For locking the global resources */
|
||||
static freerdp_mutex g_mutex_init;
|
||||
static freerdp_mutex g_mutex_list;
|
||||
|
||||
/* returns the chan_man for the open handle passed in */
|
||||
static rdpChanMan* freerdp_chanman_find_by_open_handle(int open_handle, int* pindex)
|
||||
{
|
||||
rdpChanManList* list;
|
||||
rdpChanMan* chan_man;
|
||||
int lindex;
|
||||
|
||||
freerdp_mutex_lock(g_mutex_list);
|
||||
for (list = g_chan_man_list; list; list = list->next)
|
||||
{
|
||||
chan_man = list->chan_man;
|
||||
for (lindex = 0; lindex < chan_man->num_chans; lindex++)
|
||||
{
|
||||
if (chan_man->chans[lindex].open_handle == open_handle)
|
||||
{
|
||||
freerdp_mutex_unlock(g_mutex_list);
|
||||
*pindex = lindex;
|
||||
return chan_man;
|
||||
}
|
||||
}
|
||||
}
|
||||
freerdp_mutex_unlock(g_mutex_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* returns the chan_man for the rdp instance passed in */
|
||||
static rdpChanMan* freerdp_chanman_find_by_rdp_inst(rdpInst* inst)
|
||||
{
|
||||
rdpChanManList* list;
|
||||
rdpChanMan* chan_man;
|
||||
|
||||
freerdp_mutex_lock(g_mutex_list);
|
||||
for (list = g_chan_man_list; list; list = list->next)
|
||||
{
|
||||
chan_man = list->chan_man;
|
||||
if (chan_man->inst == inst)
|
||||
{
|
||||
freerdp_mutex_unlock(g_mutex_list);
|
||||
return chan_man;
|
||||
}
|
||||
}
|
||||
freerdp_mutex_unlock(g_mutex_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* returns struct chan_data for the channel name passed in */
|
||||
static struct chan_data* freerdp_chanman_find_chan_data_by_name(rdpChanMan* chan_man,
|
||||
const char* chan_name, int* pindex)
|
||||
{
|
||||
int lindex;
|
||||
struct chan_data* lchan_data;
|
||||
|
||||
for (lindex = 0; lindex < chan_man->num_chans; lindex++)
|
||||
{
|
||||
lchan_data = chan_man->chans + lindex;
|
||||
if (strcmp(chan_name, lchan_data->name) == 0)
|
||||
{
|
||||
if (pindex != 0)
|
||||
{
|
||||
*pindex = lindex;
|
||||
}
|
||||
return lchan_data;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* returns struct rdp_chan for the channel id passed in */
|
||||
static struct rdp_chan* freerdp_chanman_find_rdp_chan_by_id(rdpChanMan* chan_man,
|
||||
rdpSettings* settings, int chan_id, int* pindex)
|
||||
{
|
||||
int lindex;
|
||||
int lcount;
|
||||
struct rdp_chan* lrdp_chan;
|
||||
|
||||
lcount = settings->num_channels;
|
||||
for (lindex = 0; lindex < lcount; lindex++)
|
||||
{
|
||||
lrdp_chan = settings->channels + lindex;
|
||||
if (lrdp_chan->chan_id == chan_id)
|
||||
{
|
||||
if (pindex != 0)
|
||||
{
|
||||
*pindex = lindex;
|
||||
}
|
||||
return lrdp_chan;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* returns struct rdp_chan for the channel name passed in */
|
||||
static struct rdp_chan* freerdp_chanman_find_rdp_chan_by_name(rdpChanMan* chan_man,
|
||||
rdpSettings* settings, const char* chan_name, int* pindex)
|
||||
{
|
||||
int lindex;
|
||||
int lcount;
|
||||
struct rdp_chan* lrdp_chan;
|
||||
|
||||
lcount = settings->num_channels;
|
||||
for (lindex = 0; lindex < lcount; lindex++)
|
||||
{
|
||||
lrdp_chan = settings->channels + lindex;
|
||||
if (strcmp(chan_name, lrdp_chan->name) == 0)
|
||||
{
|
||||
if (pindex != 0)
|
||||
{
|
||||
*pindex = lindex;
|
||||
}
|
||||
return lrdp_chan;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* must be called by same thread that calls freerdp_chanman_load_plugin
|
||||
* according to MS docs
|
||||
* only called from main thread
|
||||
*/
|
||||
static uint32 FREERDP_CC MyVirtualChannelInit(void** ppInitHandle, PCHANNEL_DEF pChannel,
|
||||
int channelCount, uint32 versionRequested,
|
||||
PCHANNEL_INIT_EVENT_FN pChannelInitEventProc)
|
||||
{
|
||||
rdpChanMan* chan_man;
|
||||
int index;
|
||||
struct lib_data* llib;
|
||||
struct chan_data* lchan;
|
||||
struct rdp_chan* lrdp_chan;
|
||||
PCHANNEL_DEF lchan_def;
|
||||
|
||||
chan_man = g_init_chan_man;
|
||||
chan_man->init_handles[chan_man->num_init_handles].chan_man = chan_man;
|
||||
*ppInitHandle = &chan_man->init_handles[chan_man->num_init_handles];
|
||||
chan_man->num_init_handles++;
|
||||
|
||||
DEBUG_CHANMAN("MyVirtualChannelInit:");
|
||||
if (!chan_man->can_call_init)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelInit: error not in entry");
|
||||
return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY;
|
||||
}
|
||||
if (ppInitHandle == 0)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelInit: error bad pphan");
|
||||
return CHANNEL_RC_BAD_INIT_HANDLE;
|
||||
}
|
||||
if (chan_man->num_chans + channelCount >= CHANNEL_MAX_COUNT)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelInit: error too many channels");
|
||||
return CHANNEL_RC_TOO_MANY_CHANNELS;
|
||||
}
|
||||
if (pChannel == 0)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelInit: error bad pchan");
|
||||
return CHANNEL_RC_BAD_CHANNEL;
|
||||
}
|
||||
if (chan_man->is_connected)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelInit: error already connected");
|
||||
return CHANNEL_RC_ALREADY_CONNECTED;
|
||||
}
|
||||
if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelInit: warning version");
|
||||
}
|
||||
for (index = 0; index < channelCount; index++)
|
||||
{
|
||||
lchan_def = pChannel + index;
|
||||
if (freerdp_chanman_find_chan_data_by_name(chan_man, lchan_def->name, 0) != 0)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelInit: error channel already used");
|
||||
return CHANNEL_RC_BAD_CHANNEL;
|
||||
}
|
||||
}
|
||||
llib = chan_man->libs + chan_man->num_libs;
|
||||
llib->init_event_proc = pChannelInitEventProc;
|
||||
llib->init_handle = *ppInitHandle;
|
||||
chan_man->num_libs++;
|
||||
for (index = 0; index < channelCount; index++)
|
||||
{
|
||||
lchan_def = pChannel + index;
|
||||
lchan = chan_man->chans + chan_man->num_chans;
|
||||
|
||||
freerdp_mutex_lock(g_mutex_list);
|
||||
lchan->open_handle = g_open_handle_sequence++;
|
||||
freerdp_mutex_unlock(g_mutex_list);
|
||||
|
||||
lchan->flags = 1; /* init */
|
||||
strncpy(lchan->name, lchan_def->name, CHANNEL_NAME_LEN);
|
||||
lchan->options = lchan_def->options;
|
||||
if (chan_man->settings->num_channels < 16)
|
||||
{
|
||||
lrdp_chan = chan_man->settings->channels + chan_man->settings->num_channels;
|
||||
strncpy(lrdp_chan->name, lchan_def->name, 7);
|
||||
lrdp_chan->options = lchan_def->options;
|
||||
chan_man->settings->num_channels++;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelInit: warning more than 16 channels");
|
||||
}
|
||||
chan_man->num_chans++;
|
||||
}
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* can be called from any thread
|
||||
* thread safe because no 2 threads can have the same channel name registered
|
||||
*/
|
||||
static uint32 FREERDP_CC MyVirtualChannelOpen(void* pInitHandle, uint32* pOpenHandle,
|
||||
char* pChannelName, PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc)
|
||||
{
|
||||
rdpChanMan* chan_man;
|
||||
int index;
|
||||
struct chan_data* lchan;
|
||||
|
||||
DEBUG_CHANMAN("MyVirtualChannelOpen:");
|
||||
chan_man = ((rdpInitHandle*)pInitHandle)->chan_man;
|
||||
if (pOpenHandle == 0)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelOpen: error bad chanhan");
|
||||
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
|
||||
}
|
||||
if (pChannelOpenEventProc == 0)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelOpen: error bad proc");
|
||||
return CHANNEL_RC_BAD_PROC;
|
||||
}
|
||||
if (!chan_man->is_connected)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelOpen: error not connected");
|
||||
return CHANNEL_RC_NOT_CONNECTED;
|
||||
}
|
||||
lchan = freerdp_chanman_find_chan_data_by_name(chan_man, pChannelName, &index);
|
||||
if (lchan == 0)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelOpen: error chan name");
|
||||
return CHANNEL_RC_UNKNOWN_CHANNEL_NAME;
|
||||
}
|
||||
if (lchan->flags == 2)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelOpen: error chan already open\n");
|
||||
return CHANNEL_RC_ALREADY_OPEN;
|
||||
}
|
||||
|
||||
lchan->flags = 2; /* open */
|
||||
lchan->open_event_proc = pChannelOpenEventProc;
|
||||
*pOpenHandle = lchan->open_handle;
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* can be called from any thread
|
||||
* thread safe because no 2 threads can have the same openHandle
|
||||
*/
|
||||
static uint32 FREERDP_CC MyVirtualChannelClose(uint32 openHandle)
|
||||
{
|
||||
rdpChanMan* chan_man;
|
||||
struct chan_data* lchan;
|
||||
int index;
|
||||
|
||||
DEBUG_CHANMAN("MyVirtualChannelClose:");
|
||||
chan_man = freerdp_chanman_find_by_open_handle(openHandle, &index);
|
||||
if ((chan_man == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT))
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelClose: error bad chanhan\n");
|
||||
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
|
||||
}
|
||||
if (!chan_man->is_connected)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelClose: error not connected\n");
|
||||
return CHANNEL_RC_NOT_CONNECTED;
|
||||
}
|
||||
lchan = chan_man->chans + index;
|
||||
if (lchan->flags != 2)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelClose: error not open\n");
|
||||
return CHANNEL_RC_NOT_OPEN;
|
||||
}
|
||||
lchan->flags = 0;
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/* can be called from any thread */
|
||||
static uint32 FREERDP_CC MyVirtualChannelWrite(uint32 openHandle, void* pData, uint32 dataLength,
|
||||
void* pUserData)
|
||||
{
|
||||
rdpChanMan* chan_man;
|
||||
struct chan_data* lchan;
|
||||
int index;
|
||||
|
||||
chan_man = freerdp_chanman_find_by_open_handle(openHandle, &index);
|
||||
if ((chan_man == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT))
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelWrite: error bad chanhan");
|
||||
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
|
||||
}
|
||||
if (!chan_man->is_connected)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelWrite: error not connected");
|
||||
return CHANNEL_RC_NOT_CONNECTED;
|
||||
}
|
||||
if (pData == 0)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelWrite: error bad pData");
|
||||
return CHANNEL_RC_NULL_DATA;
|
||||
}
|
||||
if (dataLength == 0)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelWrite: error bad dataLength");
|
||||
return CHANNEL_RC_ZERO_LENGTH;
|
||||
}
|
||||
lchan = chan_man->chans + index;
|
||||
if (lchan->flags != 2)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelWrite: error not open");
|
||||
return CHANNEL_RC_NOT_OPEN;
|
||||
}
|
||||
freerdp_sem_wait(chan_man->sync_data_sem); /* lock chan_man->sync* vars */
|
||||
if (!chan_man->is_connected)
|
||||
{
|
||||
freerdp_sem_signal(chan_man->sync_data_sem);
|
||||
DEBUG_CHANMAN("MyVirtualChannelWrite: error not connected");
|
||||
return CHANNEL_RC_NOT_CONNECTED;
|
||||
}
|
||||
chan_man->sync_data = pData;
|
||||
chan_man->sync_data_length = dataLength;
|
||||
chan_man->sync_user_data = pUserData;
|
||||
chan_man->sync_index = index;
|
||||
/* set the event */
|
||||
wait_obj_set(chan_man->signal);
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static uint32 FREERDP_CC MyVirtualChannelEventPush(uint32 openHandle, FRDP_EVENT* event)
|
||||
{
|
||||
rdpChanMan* chan_man;
|
||||
struct chan_data* lchan;
|
||||
int index;
|
||||
|
||||
chan_man = freerdp_chanman_find_by_open_handle(openHandle, &index);
|
||||
if ((chan_man == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT))
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelEventPush: error bad chanhan");
|
||||
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
|
||||
}
|
||||
if (!chan_man->is_connected)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelEventPush: error not connected");
|
||||
return CHANNEL_RC_NOT_CONNECTED;
|
||||
}
|
||||
if (event == NULL)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelEventPush: error bad event");
|
||||
return CHANNEL_RC_NULL_DATA;
|
||||
}
|
||||
lchan = chan_man->chans + index;
|
||||
if (lchan->flags != 2)
|
||||
{
|
||||
DEBUG_CHANMAN("MyVirtualChannelEventPush: error not open");
|
||||
return CHANNEL_RC_NOT_OPEN;
|
||||
}
|
||||
freerdp_sem_wait(chan_man->event_sem); /* lock chan_man->event */
|
||||
if (!chan_man->is_connected)
|
||||
{
|
||||
freerdp_sem_signal(chan_man->event_sem);
|
||||
DEBUG_CHANMAN("MyVirtualChannelEventPush: error not connected");
|
||||
return CHANNEL_RC_NOT_CONNECTED;
|
||||
}
|
||||
chan_man->event = event;
|
||||
/* set the event */
|
||||
wait_obj_set(chan_man->signal);
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* this is called shortly after the application starts and
|
||||
* before any other function in the file
|
||||
* called only from main thread
|
||||
*/
|
||||
int freerdp_chanman_global_init(void)
|
||||
{
|
||||
g_init_chan_man = NULL;
|
||||
g_chan_man_list = NULL;
|
||||
g_open_handle_sequence = 1;
|
||||
g_mutex_init = freerdp_mutex_new();
|
||||
g_mutex_list = freerdp_mutex_new();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int freerdp_chanman_global_uninit(void)
|
||||
{
|
||||
while (g_chan_man_list)
|
||||
freerdp_chanman_free(g_chan_man_list->chan_man);
|
||||
|
||||
freerdp_mutex_free(g_mutex_init);
|
||||
freerdp_mutex_free(g_mutex_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdpChanMan* freerdp_chanman_new(void)
|
||||
{
|
||||
rdpChanMan* chan_man;
|
||||
rdpChanManList* list;
|
||||
|
||||
chan_man = (rdpChanMan*)xmalloc(sizeof(rdpChanMan));
|
||||
memset(chan_man, 0, sizeof(rdpChanMan));
|
||||
|
||||
chan_man->sync_data_sem = freerdp_sem_new(1);
|
||||
chan_man->event_sem = freerdp_sem_new(1);
|
||||
chan_man->signal = wait_obj_new();
|
||||
|
||||
/* Add it to the global list */
|
||||
list = (rdpChanManList*)xmalloc(sizeof(rdpChanManList));
|
||||
list->chan_man = chan_man;
|
||||
|
||||
freerdp_mutex_lock(g_mutex_list);
|
||||
list->next = g_chan_man_list;
|
||||
g_chan_man_list = list;
|
||||
freerdp_mutex_unlock(g_mutex_list);
|
||||
|
||||
return chan_man;
|
||||
}
|
||||
|
||||
void freerdp_chanman_free(rdpChanMan * chan_man)
|
||||
{
|
||||
rdpChanManList * list;
|
||||
rdpChanManList * prev;
|
||||
|
||||
freerdp_sem_free(chan_man->sync_data_sem);
|
||||
freerdp_sem_free(chan_man->event_sem);
|
||||
wait_obj_free(chan_man->signal);
|
||||
|
||||
/* Remove from global list */
|
||||
freerdp_mutex_lock(g_mutex_list);
|
||||
for (prev = NULL, list = g_chan_man_list; list; prev = list, list = list->next)
|
||||
{
|
||||
if (list->chan_man == chan_man)
|
||||
break;
|
||||
}
|
||||
if (list)
|
||||
{
|
||||
if (prev)
|
||||
prev->next = list->next;
|
||||
else
|
||||
g_chan_man_list = list->next;
|
||||
xfree(list);
|
||||
}
|
||||
freerdp_mutex_unlock(g_mutex_list);
|
||||
|
||||
xfree(chan_man);
|
||||
}
|
||||
|
||||
/**
|
||||
* this is called when processing the command line parameters
|
||||
* called only from main thread
|
||||
*/
|
||||
int freerdp_chanman_load_plugin(rdpChanMan* chan_man, rdpSettings* settings,
|
||||
const char* name, void* data)
|
||||
{
|
||||
struct lib_data* lib;
|
||||
CHANNEL_ENTRY_POINTS_EX ep;
|
||||
int ok;
|
||||
|
||||
DEBUG_CHANMAN("freerdp_chanman_load_plugin: %s", filename);
|
||||
if (chan_man->num_libs + 1 >= CHANNEL_MAX_COUNT)
|
||||
{
|
||||
DEBUG_CHANMAN("freerdp_chanman_load_plugin: too many channels");
|
||||
return 1;
|
||||
}
|
||||
lib = chan_man->libs + chan_man->num_libs;
|
||||
lib->entry = (PVIRTUALCHANNELENTRY)freerdp_load_plugin(name, CHANNEL_EXPORT_FUNC_NAME);
|
||||
if (lib->entry == NULL)
|
||||
{
|
||||
DEBUG_CHANMAN("freerdp_chanman_load_plugin: failed to find export function");
|
||||
return 1;
|
||||
}
|
||||
ep.cbSize = sizeof(ep);
|
||||
ep.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000;
|
||||
ep.pVirtualChannelInit = MyVirtualChannelInit;
|
||||
ep.pVirtualChannelOpen = MyVirtualChannelOpen;
|
||||
ep.pVirtualChannelClose = MyVirtualChannelClose;
|
||||
ep.pVirtualChannelWrite = MyVirtualChannelWrite;
|
||||
ep.pExtendedData = data;
|
||||
ep.pVirtualChannelEventPush = MyVirtualChannelEventPush;
|
||||
|
||||
/* enable MyVirtualChannelInit */
|
||||
chan_man->can_call_init = 1;
|
||||
chan_man->settings = settings;
|
||||
|
||||
freerdp_mutex_lock(g_mutex_init);
|
||||
g_init_chan_man = chan_man;
|
||||
ok = lib->entry((PCHANNEL_ENTRY_POINTS)&ep);
|
||||
g_init_chan_man = NULL;
|
||||
freerdp_mutex_unlock(g_mutex_init);
|
||||
|
||||
/* disable MyVirtualChannelInit */
|
||||
chan_man->settings = 0;
|
||||
chan_man->can_call_init = 0;
|
||||
if (!ok)
|
||||
{
|
||||
DEBUG_CHANMAN("freerdp_chanman_load_plugin: export function call failed");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* go through and inform all the libraries that we are initialized
|
||||
* called only from main thread
|
||||
*/
|
||||
int freerdp_chanman_pre_connect(rdpChanMan* chan_man, rdpInst* inst)
|
||||
{
|
||||
int index;
|
||||
struct lib_data* llib;
|
||||
CHANNEL_DEF lchannel_def;
|
||||
void* dummy;
|
||||
|
||||
DEBUG_CHANMAN("freerdp_chanman_pre_connect:");
|
||||
chan_man->inst = inst;
|
||||
|
||||
/**
|
||||
* If rdpsnd is registered but not rdpdr, it's necessary to register a fake
|
||||
* rdpdr channel to make sound work. This is a workaround for Window 7 and
|
||||
* Windows 2008
|
||||
*/
|
||||
if (freerdp_chanman_find_chan_data_by_name(chan_man, "rdpsnd", 0) != 0 &&
|
||||
freerdp_chanman_find_chan_data_by_name(chan_man, "rdpdr", 0) == 0)
|
||||
{
|
||||
lchannel_def.options = CHANNEL_OPTION_INITIALIZED |
|
||||
CHANNEL_OPTION_ENCRYPT_RDP;
|
||||
strcpy(lchannel_def.name, "rdpdr");
|
||||
chan_man->can_call_init = 1;
|
||||
chan_man->settings = inst->settings;
|
||||
freerdp_mutex_lock(g_mutex_init);
|
||||
g_init_chan_man = chan_man;
|
||||
MyVirtualChannelInit(&dummy, &lchannel_def, 1,
|
||||
VIRTUAL_CHANNEL_VERSION_WIN2000, 0);
|
||||
g_init_chan_man = NULL;
|
||||
freerdp_mutex_unlock(g_mutex_init);
|
||||
chan_man->can_call_init = 0;
|
||||
chan_man->settings = 0;
|
||||
DEBUG_CHANMAN("freerdp_chanman_pre_connect: registered fake rdpdr for rdpsnd.");
|
||||
}
|
||||
|
||||
for (index = 0; index < chan_man->num_libs; index++)
|
||||
{
|
||||
llib = chan_man->libs + index;
|
||||
if (llib->init_event_proc != 0)
|
||||
{
|
||||
llib->init_event_proc(llib->init_handle, CHANNEL_EVENT_INITIALIZED,
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* go through and inform all the libraries that we are connected
|
||||
* this will tell the libraries that its ok to call MyVirtualChannelOpen
|
||||
* called only from main thread
|
||||
*/
|
||||
int freerdp_chanman_post_connect(rdpChanMan* chan_man, rdpInst* inst)
|
||||
{
|
||||
int index;
|
||||
struct lib_data* llib;
|
||||
char* hostname;
|
||||
int hostname_len;
|
||||
|
||||
chan_man->is_connected = 1;
|
||||
hostname = inst->settings->hostname;
|
||||
hostname_len = strlen(hostname);
|
||||
DEBUG_CHANMAN("freerdp_chanman_post_connect: hostname [%s] chan_man->num_libs [%d]",
|
||||
hostname, chan_man->num_libs);
|
||||
for (index = 0; index < chan_man->num_libs; index++)
|
||||
{
|
||||
llib = chan_man->libs + index;
|
||||
if (llib->init_event_proc != 0)
|
||||
{
|
||||
llib->init_event_proc(llib->init_handle, CHANNEL_EVENT_CONNECTED,
|
||||
hostname, hostname_len);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* data comming from the server to the client
|
||||
* called only from main thread
|
||||
*/
|
||||
int freerdp_chanman_data(rdpInst* inst, int chan_id, char* data, int data_size,
|
||||
int flags, int total_size)
|
||||
{
|
||||
rdpChanMan* chan_man;
|
||||
struct rdp_chan* lrdp_chan;
|
||||
struct chan_data* lchan_data;
|
||||
int index;
|
||||
|
||||
chan_man = freerdp_chanman_find_by_rdp_inst(inst);
|
||||
if (chan_man == 0)
|
||||
{
|
||||
DEBUG_CHANMAN("freerdp_chanman_data: could not find channel manager");
|
||||
return 1;
|
||||
}
|
||||
|
||||
lrdp_chan = freerdp_chanman_find_rdp_chan_by_id(chan_man, inst->settings,
|
||||
chan_id, &index);
|
||||
if (lrdp_chan == 0)
|
||||
{
|
||||
DEBUG_CHANMAN("freerdp_chanman_data: could not find channel id");
|
||||
return 1;
|
||||
}
|
||||
lchan_data = freerdp_chanman_find_chan_data_by_name(chan_man, lrdp_chan->name,
|
||||
&index);
|
||||
if (lchan_data == 0)
|
||||
{
|
||||
DEBUG_CHANMAN("freerdp_chanman_data: could not find channel name");
|
||||
return 1;
|
||||
}
|
||||
if (lchan_data->open_event_proc != 0)
|
||||
{
|
||||
lchan_data->open_event_proc(lchan_data->open_handle,
|
||||
CHANNEL_EVENT_DATA_RECEIVED,
|
||||
data, data_size, total_size, flags);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* called only from main thread
|
||||
*/
|
||||
static void freerdp_chanman_process_sync(rdpChanMan* chan_man, rdpInst* inst)
|
||||
{
|
||||
void* ldata;
|
||||
uint32 ldata_len;
|
||||
void* luser_data;
|
||||
int lindex;
|
||||
struct chan_data* lchan_data;
|
||||
struct rdp_chan* lrdp_chan;
|
||||
|
||||
if (chan_man->sync_data == NULL)
|
||||
return;
|
||||
|
||||
ldata = chan_man->sync_data;
|
||||
ldata_len = chan_man->sync_data_length;
|
||||
luser_data = chan_man->sync_user_data;
|
||||
lindex = chan_man->sync_index;
|
||||
chan_man->sync_data = NULL;
|
||||
chan_man->sync_data_length = 0;
|
||||
chan_man->sync_user_data = NULL;
|
||||
chan_man->sync_index = 0;
|
||||
freerdp_sem_signal(chan_man->sync_data_sem); /* release chan_man->sync* vars */
|
||||
lchan_data = chan_man->chans + lindex;
|
||||
lrdp_chan = freerdp_chanman_find_rdp_chan_by_name(chan_man, inst->settings,
|
||||
lchan_data->name, &lindex);
|
||||
if (lrdp_chan != 0)
|
||||
{
|
||||
inst->rdp_channel_data(inst, lrdp_chan->chan_id, ldata, ldata_len);
|
||||
}
|
||||
if (lchan_data->open_event_proc != 0)
|
||||
{
|
||||
lchan_data->open_event_proc(lchan_data->open_handle,
|
||||
CHANNEL_EVENT_WRITE_COMPLETE,
|
||||
luser_data, sizeof(void *), sizeof(void *), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* called only from main thread
|
||||
*/
|
||||
int freerdp_chanman_get_fds(rdpChanMan* chan_man, rdpInst* inst, void** read_fds,
|
||||
int* read_count, void** write_fds, int* write_count)
|
||||
{
|
||||
wait_obj_get_fds(chan_man->signal, read_fds, read_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* called only from main thread
|
||||
*/
|
||||
int freerdp_chanman_check_fds(rdpChanMan * chan_man, rdpInst * inst)
|
||||
{
|
||||
if (wait_obj_is_set(chan_man->signal))
|
||||
{
|
||||
wait_obj_clear(chan_man->signal);
|
||||
freerdp_chanman_process_sync(chan_man, inst);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRDP_EVENT* freerdp_chanman_pop_event(rdpChanMan* chan_man)
|
||||
{
|
||||
FRDP_EVENT* event;
|
||||
|
||||
if (chan_man->event == NULL)
|
||||
return NULL;
|
||||
event = chan_man->event;
|
||||
chan_man->event = NULL;
|
||||
freerdp_sem_signal(chan_man->event_sem); /* release chan_man->event */
|
||||
return event;
|
||||
}
|
||||
|
||||
void freerdp_chanman_free_event(rdpChanMan* chan_man, FRDP_EVENT * event)
|
||||
{
|
||||
event->event_callback(event);
|
||||
}
|
||||
|
||||
void freerdp_chanman_close(rdpChanMan* chan_man, rdpInst* inst)
|
||||
{
|
||||
int index;
|
||||
struct lib_data* llib;
|
||||
|
||||
DEBUG_CHANMAN("freerdp_chanman_close:");
|
||||
chan_man->is_connected = 0;
|
||||
freerdp_chanman_check_fds(chan_man, inst);
|
||||
/* tell all libraries we are shutting down */
|
||||
for (index = 0; index < chan_man->num_libs; index++)
|
||||
{
|
||||
llib = chan_man->libs + index;
|
||||
if (llib->init_event_proc != 0)
|
||||
{
|
||||
llib->init_event_proc(llib->init_handle, CHANNEL_EVENT_TERMINATED,
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* Virtual Channel Manager
|
||||
*
|
||||
* Copyright 2009-2011 Jay Sorg
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* 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 __LIBCHANMAN_H
|
||||
#define __LIBCHANMAN_H
|
||||
|
||||
#include <freerdp/utils/debug.h>
|
||||
|
||||
#ifdef WITH_DEBUG_CHANMAN
|
||||
#define DEBUG_CHANMAN(fmt, ...) DEBUG_CLASS(CHANMAN, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_CHANMAN(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#endif /* __LIBCHANMAN_H */
|
|
@ -20,11 +20,15 @@
|
|||
set(FREERDP_UTILS_SRCS
|
||||
blob.c
|
||||
hexdump.c
|
||||
load_plugin.c
|
||||
memory.c
|
||||
mutex.c
|
||||
semaphore.c
|
||||
stream.c
|
||||
unicode.c)
|
||||
unicode.c
|
||||
wait_obj.c)
|
||||
|
||||
add_definitions(-DPLUGIN_PATH="${FREERDP_PLUGIN_PATH}")
|
||||
|
||||
add_library(freerdp-utils SHARED ${FREERDP_UTILS_SRCS})
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* Plugin Loading Utils
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#define DLOPEN(f) LoadLibrary(f)
|
||||
#define DLSYM(f, n) GetProcAddress(f, n)
|
||||
#define DLCLOSE(f) FreeLibrary(f)
|
||||
#define PATH_SEPARATOR '\\'
|
||||
#define PLUGIN_EXT "dll"
|
||||
|
||||
#else
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h>
|
||||
#define DLOPEN(f) dlopen(f, RTLD_LOCAL | RTLD_LAZY)
|
||||
#define DLSYM(f, n) dlsym(f, n)
|
||||
#define DLCLOSE(f) dlclose(f)
|
||||
#define PATH_SEPARATOR '/'
|
||||
#define PLUGIN_EXT "so"
|
||||
|
||||
#endif
|
||||
|
||||
void* freerdp_load_plugin(const char* name, const char* entry_name)
|
||||
{
|
||||
char path[255];
|
||||
void* module;
|
||||
void* entry;
|
||||
|
||||
if (strchr(name, PATH_SEPARATOR) == NULL)
|
||||
{
|
||||
snprintf(path, sizeof(path), PLUGIN_PATH "%c%s." PLUGIN_EXT, PATH_SEPARATOR, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(path, name, sizeof(path));
|
||||
}
|
||||
|
||||
module = DLOPEN(path);
|
||||
if (module == NULL)
|
||||
{
|
||||
printf("freerdp_load_plugin: failed to open %s.\n", path);
|
||||
return NULL;
|
||||
}
|
||||
entry = DLSYM(module, entry_name);
|
||||
if (entry == NULL)
|
||||
{
|
||||
printf("freerdp_load_plugin: failed to load %s.\n", path);
|
||||
return NULL;
|
||||
}
|
||||
return entry;
|
||||
}
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#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)++;
|
||||
}
|
Loading…
Reference in New Issue