diff --git a/server/Mac/CMakeLists.txt b/server/Mac/CMakeLists.txt index 7e953ce52..3714e1e18 100644 --- a/server/Mac/CMakeLists.txt +++ b/server/Mac/CMakeLists.txt @@ -25,6 +25,8 @@ FIND_LIBRARY(APP_SERVICES ApplicationServices) set(${MODULE_PREFIX}_SRCS mfreerdp.c mfreerdp.h + mf_interface.c + mf_interface.h mf_event.c mf_event.h mf_peer.c diff --git a/server/Mac/mf_info.c b/server/Mac/mf_info.c index 1ba8ae572..fbeafe0b8 100644 --- a/server/Mac/mf_info.c +++ b/server/Mac/mf_info.c @@ -1,6 +1,6 @@ /** * FreeRDP: A Remote Desktop Protocol Client -* FreeRDP Windows Server +* FreeRDP Mac OS X Server * * Copyright 2012 Corey Clayton * @@ -17,354 +17,288 @@ * limitations under the License. */ -/* + #ifdef HAVE_CONFIG_H #include "config.h" #endif #include +#include -#include -#include +#include "mf_info.h" +//#include "mf_update.h" -#include "wf_info.h" -#include "wf_update.h" -#include "wf_mirage.h" -#include "wf_dxgi.h" +static mfInfo* mfInfoInstance = NULL; +//static int _IDcount = 0; -static wfInfo* wfInfoInstance = NULL; -static int _IDcount = 0; - -int wf_info_lock(wfInfo* wfi) +int mf_info_lock(mfInfo* mfi) { - DWORD dRes; - - dRes = WaitForSingleObject(wfi->mutex, INFINITE); - - switch (dRes) - { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: - return TRUE; - break; - - case WAIT_TIMEOUT: - return FALSE; - break; - - case WAIT_FAILED: - printf("wf_info_lock failed with 0x%08X\n", GetLastError()); - return -1; - break; - } - - return -1; + + int status = pthread_mutex_lock(&mfi->mutex); + + switch (status) { + case 0: + return TRUE; + break; + + default: + printf("mf_info_lock failed with %#X\n", status); + return -1; + break; + } + } -int wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds) +int mf_info_try_lock(mfInfo* mfi, UINT32 ms) { - DWORD dRes; - - dRes = WaitForSingleObject(wfi->mutex, dwMilliseconds); - - switch (dRes) - { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: - return TRUE; - break; - - case WAIT_TIMEOUT: - return FALSE; - break; - - case WAIT_FAILED: - printf("wf_info_try_lock failed with 0x%08X\n", GetLastError()); - return -1; - break; - } - - return -1; + + int status = pthread_mutex_trylock(&mfi->mutex); + + switch (status) { + case 0: + return TRUE; + break; + + case EBUSY: + return FALSE; + break; + + default: + printf("mf_info_try_lock failed with %#X\n", status); + return -1; + break; + } + } -int wf_info_unlock(wfInfo* wfi) +int mf_info_unlock(mfInfo* mfi) { - if (ReleaseMutex(wfi->mutex) == 0) - { - printf("wf_info_unlock failed with 0x%08X\n", GetLastError()); - return -1; - } - - return TRUE; + int status = pthread_mutex_unlock(&mfi->mutex); + + switch (status) { + case 0: + return TRUE; + break; + + default: + printf("mf_info_unlock failed with %#X\n", status); + return -1; + break; + } + } -wfInfo* wf_info_init() +mfInfo* mf_info_init() { - wfInfo* wfi; + mfInfo* mfi; + mfi = (mfInfo*) malloc(sizeof(mfInfo)); + memset(mfi, 0, sizeof(mfInfo)); - wfi = (wfInfo*) malloc(sizeof(wfInfo)); - ZeroMemory(wfi, sizeof(wfInfo)); - - if (wfi != NULL) + if (mfi != NULL) { - HKEY hKey; +/* HKEY hKey; LONG status; DWORD dwType; DWORD dwSize; DWORD dwValue; - - wfi->mutex = CreateMutex(NULL, FALSE, NULL); - - if (wfi->mutex == NULL) +*/ + + int mutexInitStatus = pthread_mutex_init(&mfi->mutex, NULL); + + if (mutexInitStatus != 0) { - _tprintf(_T("CreateMutex error: %d\n"), GetLastError()); + printf(_T("CreateMutex error: %#X\n"), mutexInitStatus); } - wfi->updateEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - printf("updateEvent created\n"); - - wfi->updateSemaphore = CreateSemaphore(NULL, 0, 32, NULL); - - wfi->updateThread = CreateThread(NULL, 0, wf_update_thread, wfi, CREATE_SUSPENDED, NULL); - - if (!wfi->updateThread) - { - _tprintf(_T("Failed to create update thread\n")); - } - - wfi->peers = (freerdp_peer**) malloc(sizeof(freerdp_peer*) * WF_INFO_MAXPEERS); - memset(wfi->peers, 0, sizeof(freerdp_peer*) * WF_INFO_MAXPEERS); + mfi->peers = (freerdp_peer**) malloc(sizeof(freerdp_peer*) * MF_INFO_MAXPEERS); + memset(mfi->peers, 0, sizeof(freerdp_peer*) * MF_INFO_MAXPEERS); //Set FPS - wfi->framesPerSecond = WF_INFO_DEFAULT_FPS; + mfi->framesPerSecond = MF_INFO_DEFAULT_FPS; - status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey); + /*status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey); if (status == ERROR_SUCCESS) { if (RegQueryValueEx(hKey, _T("FramesPerSecond"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS) - wfi->framesPerSecond = dwValue; + mfi->framesPerSecond = dwValue; } - RegCloseKey(hKey); + RegCloseKey(hKey);*/ //Set input toggle - wfi->input_disabled = FALSE; + mfi->input_disabled = FALSE; - status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey); + /*status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey); if (status == ERROR_SUCCESS) { if (RegQueryValueEx(hKey, _T("DisableInput"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS) { if (dwValue != 0) - wfi->input_disabled = TRUE; + mfi->input_disabled = TRUE; } } - RegCloseKey(hKey); + RegCloseKey(hKey);*/ } - return wfi; + return mfi; } -wfInfo* wf_info_get_instance() +mfInfo* mf_info_get_instance() { - if (wfInfoInstance == NULL) - wfInfoInstance = wf_info_init(); + if (mfInfoInstance == NULL) + mfInfoInstance = mf_info_init(); - return wfInfoInstance; + return mfInfoInstance; } -void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context) +void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context) { - if (wf_info_lock(wfi) > 0) + if (mf_info_lock(mfi) > 0) { int i; int peerId; - if (wfi->peerCount == WF_INFO_MAXPEERS) + if (mfi->peerCount == MF_INFO_MAXPEERS) { - context->socketClose = TRUE; - wf_info_unlock(wfi); + printf("TODO: socketClose on OS X\n"); + //context->socketClose = TRUE; + mf_info_unlock(mfi); return; } - context->info = wfi; - context->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - + context->info = mfi; + //get the offset of the top left corner of selected screen - EnumDisplayMonitors(NULL, NULL, wf_info_monEnumCB, 0); - _IDcount = 0; + //EnumDisplayMonitors(NULL, NULL, mf_info_monEnumCB, 0); + //_IDcount = 0; + + //initialize screen capture + if (mfi->peerCount == 0) + //mf_dxgi_init(mfi); -#ifdef WITH_WIN8 - if (wfi->peerCount == 0) - wf_dxgi_init(wfi); -#else - wf_mirror_driver_activate(wfi); -#endif //look trhough the array of peers until an empty slot - for(i=0; ipeers[i] == NULL) + if (mfi->peers[i] == NULL) { peerId = i; break; } } - wfi->peers[peerId] = ((rdpContext*) context)->peer; - wfi->peers[peerId]->pId = peerId; - wfi->peerCount++; - printf("Registering Peer: id=%d #=%d\n", peerId, wfi->peerCount); + mfi->peers[peerId] = ((rdpContext*) context)->peer; + mfi->peers[peerId]->pId = peerId; + mfi->peerCount++; + printf("Registering Peer: id=%d #=%d\n", peerId, mfi->peerCount); - wf_info_unlock(wfi); + mf_info_unlock(mfi); - wfreerdp_server_peer_callback_event(peerId, WF_SRV_CALLBACK_EVENT_CONNECT); + //mfreerdp_server_peer_callback_event(peerId, MF_SRV_CALLBACK_EVENT_CONNECT); } } -void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context) +void mf_info_peer_unregister(mfInfo* mfi, mfPeerContext* context) { - if (wf_info_lock(wfi) > 0) + if (mf_info_lock(mfi) > 0) { int peerId; peerId = ((rdpContext*) context)->peer->pId; - wfi->peers[peerId] = NULL; - wfi->peerCount--; - CloseHandle(context->updateEvent); + mfi->peers[peerId] = NULL; + mfi->peerCount--; - printf("Unregistering Peer: id=%d, #=%d\n", peerId, wfi->peerCount); + printf("Unregistering Peer: id=%d, #=%d\n", peerId, mfi->peerCount); -#ifdef WITH_WIN8 - if (wfi->peerCount == 0) - wf_dxgi_cleanup(wfi); -#endif + //screen capture cleanup + if (mfi->peerCount == 0) + //mf_dxgi_cleanup(mfi); - wf_info_unlock(wfi); + mf_info_unlock(mfi); - wfreerdp_server_peer_callback_event(peerId, WF_SRV_CALLBACK_EVENT_DISCONNECT); + //mfreerdp_server_peer_callback_event(peerId, MF_SRV_CALLBACK_EVENT_DISCONNECT); } } -BOOL wf_info_have_updates(wfInfo* wfi) +BOOL mf_info_have_updates(mfInfo* mfi) { -#ifdef WITH_WIN8 - if(wfi->framesWaiting == 0) + if(mfi->framesWaiting == 0) return FALSE; -#else - if (wfi->nextUpdate == wfi->lastUpdate) - return FALSE; -#endif + return TRUE; } -void wf_info_update_changes(wfInfo* wfi) +void mf_info_update_changes(mfInfo* mfi) { -#ifdef WITH_WIN8 - wf_dxgi_nextFrame(wfi, wfi->framesPerSecond * 1000); +/*#ifdef WITH_WIN8 + mf_dxgi_nextFrame(mfi, mfi->framesPerSecond * 1000); #else GETCHANGESBUF* buf; - buf = (GETCHANGESBUF*) wfi->changeBuffer; - wfi->nextUpdate = buf->buffer->counter; -#endif + buf = (GETCHANGESBUF*) mfi->changeBuffer; + mfi->nextUpdate = buf->buffer->counter; +#endif*/ } -void wf_info_find_invalid_region(wfInfo* wfi) +void mf_info_find_invalid_region(mfInfo* mfi) { -#ifdef WITH_WIN8 - wf_dxgi_getInvalidRegion(&wfi->invalid); -#else - int i; - GETCHANGESBUF* buf; - - buf = (GETCHANGESBUF*) wfi->changeBuffer; - - for (i = wfi->lastUpdate; i != wfi->nextUpdate; i = (i + 1) % MAXCHANGES_BUF) - { - LPRECT lpR = &buf->buffer->pointrect[i].rect; - - //need to make sure we only get updates from the selected screen - if ( (lpR->left >= wfi->servscreen_xoffset) && - (lpR->right <= (wfi->servscreen_xoffset + wfi->servscreen_width) ) && - (lpR->top >= wfi->servscreen_yoffset) && - (lpR->bottom <= (wfi->servscreen_yoffset + wfi->servscreen_height) ) ) - { - UnionRect(&wfi->invalid, &wfi->invalid, lpR); - } - else - { - continue; - } - } -#endif - - if (wfi->invalid.left < 0) - wfi->invalid.left = 0; - - if (wfi->invalid.top < 0) - wfi->invalid.top = 0; - - if (wfi->invalid.right >= wfi->servscreen_width) - wfi->invalid.right = wfi->servscreen_width - 1; - - if (wfi->invalid.bottom >= wfi->servscreen_height) - wfi->invalid.bottom = wfi->servscreen_height - 1; - - //printf("invalid region: (%d, %d), (%d, %d)\n", wfi->invalid.left, wfi->invalid.top, wfi->invalid.right, wfi->invalid.bottom); + //fixme } -void wf_info_clear_invalid_region(wfInfo* wfi) +void mf_info_clear_invalid_region(mfInfo* mfi) { - wfi->lastUpdate = wfi->nextUpdate; - SetRectEmpty(&wfi->invalid); + //mfi->lastUpdate = mfi->nextUpdate; + //SetRectEmpty(&mfi->invalid); } -void wf_info_invalidate_full_screen(wfInfo* wfi) +void mf_info_invalidate_full_screen(mfInfo* mfi) { - SetRect(&wfi->invalid, 0, 0, wfi->servscreen_width, wfi->servscreen_height); + //SetRect(&mfi->invalid, 0, 0, mfi->servscreen_width, mfi->servscreen_height); } -BOOL wf_info_have_invalid_region(wfInfo* wfi) +BOOL mf_info_have_invalid_region(mfInfo* mfi) { - return IsRectEmpty(&wfi->invalid); + //return IsRectEmpty(&mfi->invalid); } -void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits, int* pitch) +void mf_info_getScreenData(mfInfo* mfi, long* width, long* height, BYTE** pBits, int* pitch) { - *width = (wfi->invalid.right - wfi->invalid.left); - *height = (wfi->invalid.bottom - wfi->invalid.top); + /* + *width = (mfi->invalid.right - mfi->invalid.left); + *height = (mfi->invalid.bottom - mfi->invalid.top); #ifdef WITH_WIN8 - wf_dxgi_getPixelData(wfi, pBits, pitch, &wfi->invalid); + mf_dxgi_getPixelData(mfi, pBits, pitch, &mfi->invalid); #else { long offset; GETCHANGESBUF* changes; - changes = (GETCHANGESBUF*) wfi->changeBuffer; + changes = (GETCHANGESBUF*) mfi->changeBuffer; *width += 1; *height += 1; - offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->virtscreen_width * 4); + offset = (4 * mfi->invalid.left) + (mfi->invalid.top * mfi->virtscreen_width * 4); *pBits = ((BYTE*) (changes->Userbuffer)) + offset; - *pitch = wfi->virtscreen_width * 4; + *pitch = mfi->virtscreen_width * 4; } #endif + */ } -BOOL CALLBACK wf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +/* +BOOL CALLBACK mf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - wfInfo * wfi; + mfInfo * mfi; - wfi = wf_info_get_instance(); + mfi = mf_info_get_instance(); - if(_IDcount == wfi->screenID) + if(_IDcount == mfi->screenID) { - wfi->servscreen_xoffset = lprcMonitor->left; - wfi->servscreen_yoffset = lprcMonitor->top; + mfi->servscreen_xoffset = lprcMonitor->left; + mfi->servscreen_yoffset = lprcMonitor->top; } _IDcount++; diff --git a/server/Mac/mf_info.h b/server/Mac/mf_info.h index 8c1b6ae3f..7d0168862 100644 --- a/server/Mac/mf_info.h +++ b/server/Mac/mf_info.h @@ -1,6 +1,6 @@ /** * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Windows Server + * FreeRDP Mac OS X Server * * Copyright 2012 Corey Clayton * @@ -17,29 +17,34 @@ * limitations under the License. */ -#ifndef WF_INFO_H -#define WF_INFO_H +#ifndef MF_INFO_H +#define MF_INFO_H -#include "wf_interface.h" +#define MF_INFO_DEFAULT_FPS 1 +#define MF_INFO_MAXPEERS 1 -#define WF_INFO_DEFAULT_FPS 24 -#define WF_INFO_MAXPEERS 32 -int wf_info_lock(wfInfo* wfi); -int wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds); -int wf_info_unlock(wfInfo* wfi); -wfInfo* wf_info_get_instance(); -void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context); -void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context); +#include +#include -BOOL wf_info_have_updates(wfInfo* wfi); -void wf_info_update_changes(wfInfo* wfi); -void wf_info_find_invalid_region(wfInfo* wfi); -void wf_info_clear_invalid_region(wfInfo* wfi); -void wf_info_invalidate_full_screen(wfInfo* wfi); -BOOL wf_info_have_invalid_region(wfInfo* wfi); -void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, BYTE** pBits, int* pitch); -BOOL CALLBACK wf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData); +#include "mf_interface.h" -#endif /* WF_INFO_H */ \ No newline at end of file +int mf_info_lock(mfInfo* mfi); +int mf_info_try_lock(mfInfo* mfi, UINT32 ms); +int mf_info_unlock(mfInfo* mfi); + +mfInfo* mf_info_get_instance(); +void mf_info_peer_register(mfInfo* mfi, mfPeerContext* context); +void mf_info_peer_unregister(mfInfo* mfi, mfPeerContext* context); + +BOOL mf_info_have_updates(mfInfo* mfi); +void mf_info_update_changes(mfInfo* mfi); +void mf_info_find_invalid_region(mfInfo* mfi); +void mf_info_clear_invalid_region(mfInfo* mfi); +void mf_info_invalidate_full_screen(mfInfo* mfi); +BOOL mf_info_have_invalid_region(mfInfo* mfi); +void mf_info_getScreenData(mfInfo* mfi, long* width, long* height, BYTE** pBits, int* pitch); +//BOOL CALLBACK mf_info_monEnumCB(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData); + +#endif /* mf_info_H */ \ No newline at end of file diff --git a/server/Mac/mf_interface.c b/server/Mac/mf_interface.c new file mode 100644 index 000000000..e69de29bb diff --git a/server/Mac/mf_interface.h b/server/Mac/mf_interface.h new file mode 100644 index 000000000..618249597 --- /dev/null +++ b/server/Mac/mf_interface.h @@ -0,0 +1,115 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * FreeRDP Mac OS X Server + * + * Copyright 2012 Marc-Andre Moreau + * Copyright 2012 Corey Clayton + * + * 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 MF_INTERFACE_H +#define MF_INTERFACE_H + +#include + +#include +#include +#include + +#ifdef WITH_SERVER_CHANNELS +#include +#endif + +#ifdef CHANNEL_RDPSND_SERVER +#include +#include "mf_rdpsnd.h" +#endif + +#ifdef CHANNEL_AUDIN_SERVER +#include "mf_audin.h" +#endif + +typedef struct mf_info mfInfo; +typedef struct mf_peer_context mfPeerContext; + +struct mf_peer_context +{ + rdpContext _p; + + mfInfo* info; + STREAM* s; + BOOL activated; + UINT32 frame_id; + BOOL audin_open; + RFX_CONTEXT* rfx_context; + NSC_CONTEXT* nsc_context; + +#ifdef WITH_SERVER_CHANNELS + WTSVirtualChannelManager* vcm; +#endif +#ifdef CHANNEL_AUDIN_SERVER + audin_server_context* audin; +#endif + +#ifdef CHANNEL_RDPSND_SERVER + rdpsnd_server_context* rdpsnd; +#endif +}; + + +struct mf_info +{ + //STREAM* s; + + //screen and monitor info + int screenID; + int virtscreen_width; + int virtscreen_height; + int servscreen_width; + int servscreen_height; + int servscreen_xoffset; + int servscreen_yoffset; + + //int frame_idx; + int bitsPerPixel; + //HDC driverDC; + int peerCount; + int activePeerCount; + //void* changeBuffer; + int framesPerSecond; + //LPTSTR deviceKey; + //TCHAR deviceName[32]; + freerdp_peer** peers; + //BOOL mirrorDriverActive; + unsigned int framesWaiting; + + //HANDLE snd_mutex; + //BOOL snd_stop; + + RFX_RECT invalid; + pthread_mutex_t mutex; + //BOOL updatePending; + //HANDLE updateEvent; + //HANDLE updateThread; + //HANDLE updateSemaphore; + //RFX_CONTEXT* rfx_context; + //unsigned long lastUpdate; + //unsigned long nextUpdate; + //SURFACE_BITS_COMMAND cmd; + + BOOL input_disabled; + BOOL force_all_disconnect; +}; + +#endif \ No newline at end of file diff --git a/server/Mac/mf_peer.c b/server/Mac/mf_peer.c index 02d2ebc96..50dea209c 100644 --- a/server/Mac/mf_peer.c +++ b/server/Mac/mf_peer.c @@ -542,7 +542,7 @@ void wf_peer_read_settings(freerdp_peer* client) client->settings->PrivateKeyFile = _strdup("server.key"); }*/ -static void* mf_peer_main_loop(void* arg) +void* mf_peer_main_loop(void* arg) { int i; int fds; diff --git a/server/Mac/mf_peer.h b/server/Mac/mf_peer.h index 3f0149328..0f8096ab2 100644 --- a/server/Mac/mf_peer.h +++ b/server/Mac/mf_peer.h @@ -20,47 +20,7 @@ #ifndef WF_PEER_H #define WF_PEER_H -#include - -#include - -#ifdef WITH_SERVER_CHANNELS -#include -#endif - -#ifdef CHANNEL_RDPSND_SERVER -#include -#include "mf_rdpsnd.h" -#endif - -#ifdef CHANNEL_AUDIN_SERVER -#include "mf_audin.h" -#endif - - -struct mf_peer_context -{ - rdpContext _p; - - STREAM* s; - BOOL activated; - UINT32 frame_id; - BOOL audin_open; - RFX_CONTEXT* rfx_context; - NSC_CONTEXT* nsc_context; - -#ifdef WITH_SERVER_CHANNELS - WTSVirtualChannelManager* vcm; -#endif -#ifdef CHANNEL_AUDIN_SERVER - audin_server_context* audin; -#endif - -#ifdef CHANNEL_RDPSND_SERVER - rdpsnd_server_context* rdpsnd; -#endif -}; -typedef struct mf_peer_context mfPeerContext; +#include "mf_interface.h" BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount); BOOL mf_peer_check_fds(freerdp_peer* client); @@ -79,6 +39,6 @@ void mf_peer_synchronize_event(rdpInput* input, UINT32 flags); void mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client); -static void* mf_peer_main_loop(void* arg); +void* mf_peer_main_loop(void* arg); #endif /* MF_PEER_H */