From 270a562b773d1bd3711a2ffc2fc06cebafff496c Mon Sep 17 00:00:00 2001 From: Corey C Date: Fri, 12 Oct 2012 21:02:42 -0400 Subject: [PATCH] wfreerdp-server: fixed crash after disconnect --- server/Windows/wf_interface.h | 3 + server/Windows/wf_peer.c | 6 ++ server/Windows/wf_rdpsnd.c | 160 +++++++++++++++++++++++++--------- server/Windows/wf_rdpsnd.h | 2 + 4 files changed, 128 insertions(+), 43 deletions(-) diff --git a/server/Windows/wf_interface.h b/server/Windows/wf_interface.h index a3b89ef84..e7400010c 100644 --- a/server/Windows/wf_interface.h +++ b/server/Windows/wf_interface.h @@ -57,6 +57,9 @@ struct wf_info BOOL mirrorDriverActive; UINT framesWaiting; + HANDLE snd_mutex; + BOOL snd_stop; + RECT invalid; HANDLE mutex; BOOL updatePending; diff --git a/server/Windows/wf_peer.c b/server/Windows/wf_peer.c index 77ffb53d6..c0216114c 100644 --- a/server/Windows/wf_peer.c +++ b/server/Windows/wf_peer.c @@ -51,7 +51,13 @@ void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context) wf_info_peer_unregister(context->info, context); if (context->rdpsnd) + { + printf("snd_free\n"); + wf_rdpsnd_lock(); + context->info->snd_stop = TRUE; rdpsnd_server_context_free(context->rdpsnd); + wf_rdpsnd_unlock(); + } WTSDestroyVirtualChannelManager(context->vcm); } diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index da063f50f..8ef5b2775 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -32,7 +32,7 @@ #include #include "wf_rdpsnd.h" - +#include "wf_info.h" /* * Here are some temp things that shall be moved @@ -45,6 +45,9 @@ DWORD capturePos; #define BYTESPERSEC 176400 +//FIXME support multiple clients +wfPeerContext* latestPeer; + static const rdpsndFormat test_audio_formats[] = { { 0x11, 2, 22050, 1024, 4, 0, NULL }, /* IMA ADPCM, 22050 Hz, 2 channels */ @@ -106,13 +109,62 @@ static void wf_peer_rdpsnd_activated(rdpsnd_server_context* context) context->SetVolume(context, 0x7FFF, 0x7FFF); capturePos = 0; - CreateThread(NULL, 0, wf_rdpsnd_thread, context, 0, NULL); + CreateThread(NULL, 0, wf_rdpsnd_thread, latestPeer, 0, NULL); } +int wf_rdpsnd_lock() +{ + DWORD dRes; + wfInfo* wfi; + + wfi = wf_info_get_instance(); + + dRes = WaitForSingleObject(wfi->snd_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_rdpsnd_lock failed with 0x%08X\n", GetLastError()); + return -1; + break; + } + + return -1; +} + +int wf_rdpsnd_unlock() +{ + wfInfo* wfi; + + wfi = wf_info_get_instance(); + + if (ReleaseMutex(wfi->snd_mutex) == 0) + { + printf("wf_rdpsnd_unlock failed with 0x%08X\n", GetLastError()); + return -1; + } + + return TRUE; +} + BOOL wf_peer_rdpsnd_init(wfPeerContext* context) { + wfInfo* wfi; + + wfi = wf_info_get_instance(); + + wfi->snd_mutex = CreateMutex(NULL, FALSE, NULL); context->rdpsnd = rdpsnd_server_context_new(context->vcm); context->rdpsnd->data = context; @@ -129,6 +181,8 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context) context->rdpsnd->Initialize(context->rdpsnd); + latestPeer = context; + wfi->snd_stop = FALSE; return TRUE; } @@ -137,10 +191,12 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) HRESULT hr; DWORD beg, end; DWORD diff, rate; - rdpsnd_server_context* context; + wfPeerContext* context; + wfInfo* wfi; - context = (rdpsnd_server_context*)lpParam; + wfi = wf_info_get_instance(); + context = (wfPeerContext*)lpParam; rate = 1000 / 5; _tprintf(_T("Trying to start capture\n")); @@ -162,49 +218,67 @@ DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam) LONG lLockSize; beg = GetTickCount(); + if (wf_rdpsnd_lock() > 0) + { + //check for main exit condition + if (wfi->snd_stop == TRUE) + { + wf_rdpsnd_unlock(); + break; + } + + hr = capBuf->lpVtbl->GetCurrentPosition(capBuf, NULL, &dwReadPos); + if (FAILED(hr)) + { + _tprintf(_T("Failed to get read pos\n")); + wf_rdpsnd_unlock(); + break; + } + + lLockSize = dwReadPos - capturePos;//dscbd.dwBufferBytes; + if (lLockSize < 0) lLockSize += dscbd.dwBufferBytes; + + if (lLockSize == 0) + { + wf_rdpsnd_unlock(); + continue; + } + + + hr = capBuf->lpVtbl->Lock(capBuf, capturePos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L); + if (FAILED(hr)) + { + _tprintf(_T("Failed to lock sound capture buffer\n")); + wf_rdpsnd_unlock(); + break; + } + + //fwrite(pbCaptureData, 1, dwCaptureLength, pFile); + //fwrite(pbCaptureData2, 1, dwCaptureLength2, pFile); + + //FIXME: frames = bytes/(bytespersample * channels) + context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData, dwCaptureLength/4); + context->rdpsnd->SendSamples(context->rdpsnd, pbCaptureData2, dwCaptureLength2/4); - hr = capBuf->lpVtbl->GetCurrentPosition(capBuf, NULL, &dwReadPos); - if (FAILED(hr)) - { - _tprintf(_T("Failed to get read pos\n")); - break; + + hr = capBuf->lpVtbl->Unlock(capBuf, pbCaptureData, dwCaptureLength, pbCaptureData2, dwCaptureLength2); + if (FAILED(hr)) + { + _tprintf(_T("Failed to unlock sound capture buffer\n")); + wf_rdpsnd_unlock(); + return 0; + } + + //TODO keep track of location in buffer + capturePos += dwCaptureLength; + capturePos %= dscbd.dwBufferBytes; + capturePos += dwCaptureLength2; + capturePos %= dscbd.dwBufferBytes; + + wf_rdpsnd_unlock(); } - lLockSize = dwReadPos - capturePos;//dscbd.dwBufferBytes; - if (lLockSize < 0) lLockSize += dscbd.dwBufferBytes; - - if (lLockSize == 0) continue; - - hr = capBuf->lpVtbl->Lock(capBuf, capturePos, lLockSize, &pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L); - if (FAILED(hr)) - { - _tprintf(_T("Failed to lock sound capture buffer\n")); - break; - } - - //fwrite(pbCaptureData, 1, dwCaptureLength, pFile); - //fwrite(pbCaptureData2, 1, dwCaptureLength2, pFile); - - //FIXME: frames = bytes/(bytespersample * channels) - - context->SendSamples(context, pbCaptureData, dwCaptureLength/4); - context->SendSamples(context, pbCaptureData2, dwCaptureLength2/4); - - - hr = capBuf->lpVtbl->Unlock(capBuf, pbCaptureData, dwCaptureLength, pbCaptureData2, dwCaptureLength2); - if (FAILED(hr)) - { - _tprintf(_T("Failed to unlock sound capture buffer\n")); - return 0; - } - - //TODO keep track of location in buffer - capturePos += dwCaptureLength; - capturePos %= dscbd.dwBufferBytes; - capturePos += dwCaptureLength2; - capturePos %= dscbd.dwBufferBytes; - end = GetTickCount(); diff = end - beg; diff --git a/server/Windows/wf_rdpsnd.h b/server/Windows/wf_rdpsnd.h index 482cdcfd8..d54c4172d 100644 --- a/server/Windows/wf_rdpsnd.h +++ b/server/Windows/wf_rdpsnd.h @@ -26,6 +26,8 @@ #include "wf_interface.h" +int wf_rdpsnd_lock(); +int wf_rdpsnd_unlock(); BOOL wf_peer_rdpsnd_init(wfPeerContext* context); DWORD WINAPI wf_rdpsnd_thread(LPVOID lpParam);