static void pbrpc_main_loop(pbRPCContext* context) { int status; DWORD nCount; HANDLE events[32]; rdsServer* server = g_Server; pbrpc_connect(context); while (context->isConnected) { nCount = 0; events[nCount++] = context->stopEvent; events[nCount++] = Queue_Event(context->writeQueue); events[nCount++] = context->hPipe; status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (status == WAIT_FAILED) { break; } if (WaitForSingleObject(context->stopEvent, 0) == WAIT_OBJECT_0) { break; } if (WaitForSingleObject(context->hPipe, 0) == WAIT_OBJECT_0) { status = pbrpc_process_message_in(server); if (status < 0) { fprintf(stderr, "Transport problem reconnecting..\n"); pbrpc_reconnect(context); continue; } } if (WaitForSingleObject(Queue_Event(context->writeQueue), 0) == WAIT_OBJECT_0) { FDSAPI_MSG_PACKET* msg = NULL; while ((msg = Queue_Dequeue(context->writeQueue))) { status = pbrpc_process_message_out(server, msg); pbrpc_message_free(msg, FALSE); } if (status < 0) { fprintf(stderr, "Transport problem reconnecting..\n"); pbrpc_reconnect(context); continue; } } } }
static void* rpc_client_thread(void* arg) { rdpRpc* rpc; DWORD status; DWORD nCount; HANDLE events[3]; HANDLE ReadEvent; int fd; rpc = (rdpRpc*) arg; fd = BIO_get_fd(rpc->TlsOut->bio, NULL); ReadEvent = CreateFileDescriptorEvent(NULL, TRUE, FALSE, fd); nCount = 0; events[nCount++] = rpc->client->StopEvent; events[nCount++] = Queue_Event(rpc->client->SendQueue); events[nCount++] = ReadEvent; /* Do a first free run in case some bytes were set from the HTTP headers. * We also have to do it because most of the time the underlying socket has notified, * and the ssl layer has eaten all bytes, so we won't be notified any more even if the * bytes are buffered locally */ if (rpc_client_on_read_event(rpc) < 0) { WLog_ERR(TAG, "an error occured when treating first packet"); goto out; } while (rpc->transport->layer != TRANSPORT_LAYER_CLOSED) { status = WaitForMultipleObjects(nCount, events, FALSE, 100); if (status == WAIT_TIMEOUT) continue; if (WaitForSingleObject(rpc->client->StopEvent, 0) == WAIT_OBJECT_0) break; if (WaitForSingleObject(ReadEvent, 0) == WAIT_OBJECT_0) { if (rpc_client_on_read_event(rpc) < 0) break; } if (WaitForSingleObject(Queue_Event(rpc->client->SendQueue), 0) == WAIT_OBJECT_0) { rpc_send_dequeue_pdu(rpc); } } out: CloseHandle(ReadEvent); return NULL; }
RPC_PDU* rpc_recv_dequeue_pdu(rdpRpc* rpc) { RPC_PDU* pdu; DWORD dwMilliseconds; DWORD result; dwMilliseconds = rpc->client->SynchronousReceive ? SYNCHRONOUS_TIMEOUT * 4 : 0; result = WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds); if (result == WAIT_TIMEOUT) { WLog_ERR(TAG, "timed out waiting for receive event"); return NULL; } if (result != WAIT_OBJECT_0) return NULL; pdu = (RPC_PDU*)Queue_Dequeue(rpc->client->ReceiveQueue); #ifdef WITH_DEBUG_TSG if (pdu) { WLog_DBG(TAG, "Receiving PDU (length: %d, CallId: %d)", pdu->s->length, pdu->CallId); winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(pdu->s), Stream_Length(pdu->s)); } else { WLog_DBG(TAG, "Receiving a NULL PDU"); } #endif return pdu; }
static void* serial_thread_func(void* arg) { IRP* irp; DWORD status; SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg; HANDLE ev[] = {serial->stopEvent, Queue_Event(serial->queue)}; while (1) { status = WaitForMultipleObjects(2, ev, FALSE, 1); if (WAIT_OBJECT_0 == status) break; serial->nfds = 1; FD_ZERO(&serial->read_fds); FD_ZERO(&serial->write_fds); serial->tv.tv_sec = 0; serial->tv.tv_usec = 0; serial->select_timeout = 0; if (status == WAIT_OBJECT_0 + 1) { if ((irp = (IRP*) Queue_Dequeue(serial->queue))) serial_process_irp(serial, irp); continue; } serial_check_fds(serial); } return NULL; }
RPC_PDU* rpc_recv_dequeue_pdu(rdpRpc* rpc) { RPC_PDU* pdu; DWORD dwMilliseconds; pdu = NULL; dwMilliseconds = rpc->client->SynchronousReceive ? INFINITE : 0; if (WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds) == WAIT_OBJECT_0) { pdu = (RPC_PDU*) Queue_Dequeue(rpc->client->ReceiveQueue); #ifdef WITH_DEBUG_TSG if (pdu) { fprintf(stderr, "Receiving PDU (length: %d, CallId: %d)\n", pdu->s->length, pdu->CallId); winpr_HexDump(Stream_Buffer(pdu->s), Stream_Length(pdu->s)); fprintf(stderr, "\n"); } #endif return pdu; } return pdu; }
RPC_PDU* rpc_client_receive_pool_take(rdpRpc* rpc) { RPC_PDU* pdu = NULL; if (WaitForSingleObject(Queue_Event(rpc->client->ReceivePool), 0) == WAIT_OBJECT_0) pdu = Queue_Dequeue(rpc->client->ReceivePool); if (!pdu) { pdu = (RPC_PDU*)malloc(sizeof(RPC_PDU)); if (!pdu) return NULL; pdu->s = Stream_New(NULL, rpc->max_recv_frag); if (!pdu->s) { free(pdu); return NULL; } } pdu->CallId = 0; pdu->Flags = 0; Stream_Length(pdu->s) = 0; Stream_SetPosition(pdu->s, 0); return pdu; }
static void* tsmf_stream_ack_func(void *arg) { HANDLE hdl[2]; TSMF_STREAM* stream = (TSMF_STREAM*) arg; DEBUG_TSMF("in %d", stream->stream_id); hdl[0] = stream->stopEvent; hdl[1] = Queue_Event(stream->sample_ack_list); while (1) { DWORD ev = WaitForMultipleObjects(2, hdl, FALSE, INFINITE); if (ev == WAIT_OBJECT_0) break; if (!stream->decoder) continue; if (stream->decoder->SetAckFunc) continue; if (tsmf_stream_process_ack(stream, FALSE)) break; } DEBUG_TSMF("out %d", stream->stream_id); ExitThread(0); return NULL; }
BOOL tsg_set_blocking_mode(rdpTsg* tsg, BOOL blocking) { tsg->rpc->client->SynchronousSend = TRUE; tsg->rpc->client->SynchronousReceive = blocking; tsg->transport->GatewayEvent = Queue_Event(tsg->rpc->client->ReceiveQueue); return TRUE; }
static void* rpc_client_thread(void* arg) { rdpRpc* rpc; DWORD status; DWORD nCount; HANDLE events[3]; HANDLE ReadEvent; rpc = (rdpRpc*) arg; ReadEvent = CreateFileDescriptorEvent(NULL, TRUE, FALSE, rpc->TlsOut->sockfd); nCount = 0; events[nCount++] = rpc->client->StopEvent; events[nCount++] = Queue_Event(rpc->client->SendQueue); events[nCount++] = ReadEvent; while (1) { status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(rpc->client->StopEvent, 0) == WAIT_OBJECT_0) { break; } if (WaitForSingleObject(ReadEvent, 0) == WAIT_OBJECT_0) { if (rpc_client_on_read_event(rpc) < 0) break; } if (WaitForSingleObject(Queue_Event(rpc->client->SendQueue), 0) == WAIT_OBJECT_0) { rpc_send_dequeue_pdu(rpc); } } CloseHandle(ReadEvent); rpc_client_free(rpc); return NULL; }
wStream* rpc_client_fragment_pool_take(rdpRpc* rpc) { wStream* fragment = NULL; if (WaitForSingleObject(Queue_Event(rpc->client->FragmentPool), 0) == WAIT_OBJECT_0) fragment = Queue_Dequeue(rpc->client->FragmentPool); if (!fragment) fragment = Stream_New(NULL, rpc->max_recv_frag); return fragment; }
RPC_PDU* rpc_recv_peek_pdu(rdpRpc* rpc) { DWORD dwMilliseconds; DWORD result; dwMilliseconds = rpc->client->SynchronousReceive ? SYNCHRONOUS_TIMEOUT : 0; result = WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds); if (result != WAIT_OBJECT_0) return NULL; return (RPC_PDU*)Queue_Peek(rpc->client->ReceiveQueue); }
static void* update_thread(void* arg) { rdpUpdate* update; update = (rdpUpdate*) arg; while (WaitForSingleObject(Queue_Event(update->queue), INFINITE) == WAIT_OBJECT_0) { } return NULL; }
STREAM* transport_receive_pool_take(rdpTransport* transport) { STREAM* pdu = NULL; if (WaitForSingleObject(Queue_Event(transport->ReceivePool), 0) == WAIT_OBJECT_0) pdu = Queue_Dequeue(transport->ReceivePool); if (!pdu) pdu = stream_new(BUFFER_SIZE); pdu->p = pdu->data; return pdu; }
static void* tsmf_stream_playback_func(void *arg) { HANDLE hdl[2]; TSMF_SAMPLE* sample; TSMF_STREAM* stream = (TSMF_STREAM *) arg; TSMF_PRESENTATION* presentation = stream->presentation; DEBUG_TSMF("in %d", stream->stream_id); if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO && stream->sample_rate && stream->channels && stream->bits_per_sample) { if (stream->decoder) { if (stream->decoder->GetDecodedData) { stream->audio = tsmf_load_audio_device( presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL, presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL); if (stream->audio) { stream->audio->SetFormat(stream->audio, stream->sample_rate, stream->channels, stream->bits_per_sample); } } } } hdl[0] = stream->stopEvent; hdl[1] = Queue_Event(stream->sample_list); while (!(WaitForMultipleObjects(2, hdl, FALSE, INFINITE) == WAIT_OBJECT_0)) { sample = tsmf_stream_pop_sample(stream, 0); if (sample) tsmf_sample_playback(sample); } if (stream->audio) { stream->audio->Free(stream->audio); stream->audio = NULL; } DEBUG_TSMF("out %d", stream->stream_id); ExitThread(0); return NULL; }
RPC_PDU* rpc_recv_peek_pdu(rdpRpc* rpc) { RPC_PDU* pdu; DWORD dwMilliseconds; pdu = NULL; dwMilliseconds = rpc->client->SynchronousReceive ? INFINITE : 0; if (WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds) == WAIT_OBJECT_0) { pdu = (RPC_PDU*) Queue_Peek(rpc->client->ReceiveQueue); return pdu; } return pdu; }
RFX_TILE* rfx_tile_pool_take(RFX_CONTEXT* context) { RFX_TILE* tile = NULL; if (WaitForSingleObject(Queue_Event(context->priv->TilePool), 0) == WAIT_OBJECT_0) tile = Queue_Dequeue(context->priv->TilePool); if (!tile) { tile = (RFX_TILE*) malloc(sizeof(RFX_TILE)); tile->x = tile->y = 0; tile->data = (BYTE*) malloc(4096 * 4); /* 64x64 * 4 */ } return tile; }
static void* tsmf_stream_ack_func(void *arg) { HANDLE hdl[2]; TSMF_STREAM* stream = (TSMF_STREAM*) arg; UINT error = CHANNEL_RC_OK; DEBUG_TSMF("in %d", stream->stream_id); hdl[0] = stream->stopEvent; hdl[1] = Queue_Event(stream->sample_ack_list); while (1) { DWORD ev = WaitForMultipleObjects(2, hdl, FALSE, INFINITE); if (ev == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error); break; } if (ev == WAIT_OBJECT_0) break; if (!stream->decoder) continue; if (stream->decoder->SetAckFunc) continue; if (tsmf_stream_process_ack(stream, FALSE)) { error = ERROR_INTERNAL_ERROR; WLog_ERR(TAG, "tsmf_stream_process_ack failed!"); break; } } if (error && stream->rdpcontext) setChannelError(stream->rdpcontext, error, "tsmf_stream_ack_func reported an error"); DEBUG_TSMF("out %d", stream->stream_id); ExitThread(0); return NULL; }
static void* serial_thread_func(void* arg) { IRP* irp; DWORD status; SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg; while (1) { if (WaitForSingleObject(serial->stopEvent, 0) == WAIT_OBJECT_0) break; if (WaitForSingleObject(Queue_Event(serial->queue), 10) == WAIT_OBJECT_0) break; serial->nfds = 1; FD_ZERO(&serial->read_fds); FD_ZERO(&serial->write_fds); serial->tv.tv_sec = 1; serial->tv.tv_usec = 0; serial->select_timeout = 0; irp = (IRP*) Queue_Dequeue(serial->queue); if (irp) serial_process_irp(serial, irp); status = WaitForSingleObject(serial->in_event, 0); if ((status == WAIT_OBJECT_0) || (status == WAIT_TIMEOUT)) { if (serial_check_fds(serial)) ResetEvent(serial->in_event); } } return NULL; }
static void* thread_pool_work_func(void* arg) { DWORD status; PTP_POOL pool; PTP_WORK work; HANDLE events[2]; PTP_CALLBACK_INSTANCE callbackInstance; pool = (PTP_POOL) arg; events[0] = pool->TerminateEvent; events[1] = Queue_Event(pool->PendingQueue); while (1) { status = WaitForMultipleObjects(2, events, FALSE, INFINITE); if (status == WAIT_OBJECT_0) break; if (status != (WAIT_OBJECT_0 + 1)) break; callbackInstance = (PTP_CALLBACK_INSTANCE) Queue_Dequeue(pool->PendingQueue); if (callbackInstance) { work = callbackInstance->Work; work->WorkCallback(callbackInstance, work->CallbackParameter, work); CountdownEvent_Signal(pool->WorkComplete, 1); free(callbackInstance); } } ExitThread(0); return NULL; }
static void* serial_thread_func(void* arg) { IRP* irp; DWORD status; SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg; HANDLE ev[] = {serial->stopEvent, Queue_Event(serial->queue), serial->newEvent}; assert(NULL != serial); while (1) { status = WaitForMultipleObjects(3, ev, FALSE, INFINITE); if (WAIT_OBJECT_0 == status) break; else if (status == WAIT_OBJECT_0 + 1) { FD_ZERO(&serial->read_fds); FD_ZERO(&serial->write_fds); serial->tv.tv_sec = 0; serial->tv.tv_usec = 0; serial->select_timeout = 0; if ((irp = (IRP*) Queue_Dequeue(serial->queue))) serial_process_irp(serial, irp); } else if (status == WAIT_OBJECT_0 + 2) ResetEvent(serial->newEvent); if(serial->tty) serial_check_fds(serial); } ExitThread(0); return NULL; }
static void* smartcard_thread_func(void* arg) { IRP* irp; DWORD nCount; DWORD status; HANDLE hEvents[2]; wMessage message; SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) arg; UINT error = CHANNEL_RC_OK; nCount = 0; hEvents[nCount++] = MessageQueue_Event(smartcard->IrpQueue); hEvents[nCount++] = Queue_Event(smartcard->CompletedIrpQueue); while (1) { status = WaitForMultipleObjects(nCount, hEvents, FALSE, INFINITE); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error); break; } status = WaitForSingleObject(MessageQueue_Event(smartcard->IrpQueue), 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); break; } if (status == WAIT_OBJECT_0) { if (!MessageQueue_Peek(smartcard->IrpQueue, &message, TRUE)) { WLog_ERR(TAG, "MessageQueue_Peek failed!"); error = ERROR_INTERNAL_ERROR; break; } if (message.id == WMQ_QUIT) { while (1) { status = WaitForSingleObject(Queue_Event(smartcard->CompletedIrpQueue), 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); goto out; } if (status == WAIT_TIMEOUT) break; irp = (IRP*) Queue_Dequeue(smartcard->CompletedIrpQueue); if (irp) { if (irp->thread) { status = WaitForSingleObject(irp->thread, INFINITE); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); goto out; } CloseHandle(irp->thread); irp->thread = NULL; } if ((error = smartcard_complete_irp(smartcard, irp))) { WLog_ERR(TAG, "smartcard_complete_irp failed with error %lu!", error); goto out; } } } break; } irp = (IRP*) message.wParam; if (irp) { if ((error = smartcard_process_irp(smartcard, irp))) { WLog_ERR(TAG, "smartcard_process_irp failed with error %lu!", error); goto out; } } } status = WaitForSingleObject(Queue_Event(smartcard->CompletedIrpQueue), 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); break; } if (status == WAIT_OBJECT_0) { irp = (IRP*) Queue_Dequeue(smartcard->CompletedIrpQueue); if (irp) { if (irp->thread) { status = WaitForSingleObject(irp->thread, INFINITE); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); break; } CloseHandle(irp->thread); irp->thread = NULL; } if ((error = smartcard_complete_irp(smartcard, irp))) { if (error == CHANNEL_RC_NOT_CONNECTED) { error = CHANNEL_RC_OK; goto out; } WLog_ERR(TAG, "smartcard_complete_irp failed with error %lu!", error); goto out; } } } } out: if (error && smartcard->rdpcontext) setChannelError(smartcard->rdpcontext, error, "smartcard_thread_func reported an error"); ExitThread((DWORD)error); return NULL; }
static void* smartcard_thread_func(void* arg) { IRP* irp; DWORD nCount; DWORD status; HANDLE hEvents[2]; wMessage message; SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) arg; nCount = 0; hEvents[nCount++] = MessageQueue_Event(smartcard->IrpQueue); hEvents[nCount++] = Queue_Event(smartcard->CompletedIrpQueue); while (1) { status = WaitForMultipleObjects(nCount, hEvents, FALSE, INFINITE); if (WaitForSingleObject(MessageQueue_Event(smartcard->IrpQueue), 0) == WAIT_OBJECT_0) { if (!MessageQueue_Peek(smartcard->IrpQueue, &message, TRUE)) break; if (message.id == WMQ_QUIT) { while (WaitForSingleObject(Queue_Event(smartcard->CompletedIrpQueue), 0) == WAIT_OBJECT_0) { irp = (IRP*) Queue_Dequeue(smartcard->CompletedIrpQueue); if (irp) { if (irp->thread) { WaitForSingleObject(irp->thread, INFINITE); CloseHandle(irp->thread); irp->thread = NULL; } smartcard_complete_irp(smartcard, irp); } } break; } irp = (IRP*) message.wParam; if (irp) { smartcard_process_irp(smartcard, irp); } } if (WaitForSingleObject(Queue_Event(smartcard->CompletedIrpQueue), 0) == WAIT_OBJECT_0) { irp = (IRP*) Queue_Dequeue(smartcard->CompletedIrpQueue); if (irp) { if (irp->thread) { WaitForSingleObject(irp->thread, INFINITE); CloseHandle(irp->thread); irp->thread = NULL; } smartcard_complete_irp(smartcard, irp); } } } ExitThread(0); return NULL; }
static void* tsmf_stream_ack_func(void *arg) { HANDLE hdl[2]; TSMF_STREAM* stream = (TSMF_STREAM*) arg; UINT error = CHANNEL_RC_OK; DEBUG_TSMF("in %d", stream->stream_id); hdl[0] = stream->stopEvent; hdl[1] = Queue_Event(stream->sample_ack_list); while (1) { DWORD ev = WaitForMultipleObjects(2, hdl, FALSE, 1000); if (ev == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error); break; } if (stream->decoder) if (stream->decoder->BufferLevel) stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder); if (stream->eos) { while ((stream->currentBufferLevel > 0) || !(tsmf_stream_process_ack(stream, TRUE))) { DEBUG_TSMF("END OF STREAM PROCESSING!"); if (stream->decoder->BufferLevel) stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder); else stream->currentBufferLevel = 1; USleep(1000); } tsmf_send_eos_response(stream->eos_channel_callback, stream->eos_message_id); stream->eos = 0; if (stream->delayed_stop) { DEBUG_TSMF("Finishing delayed stream stop, now that eos has processed."); tsmf_stream_flush(stream); if (stream->decoder->Control) stream->decoder->Control(stream->decoder, Control_Stop, NULL); } } /* Stream stopped force all of the acks to happen */ if (ev == WAIT_OBJECT_0) { DEBUG_TSMF("ack: Stream stopped!"); while(1) { if (tsmf_stream_process_ack(stream, TRUE)) break; USleep(1000); } break; } if (tsmf_stream_process_ack(stream, FALSE)) continue; if (stream->currentBufferLevel > stream->minBufferLevel) USleep(1000); } if (error && stream->rdpcontext) setChannelError(stream->rdpcontext, error, "tsmf_stream_ack_func reported an error"); DEBUG_TSMF("out %d", stream->stream_id); ExitThread(0); return NULL; }
static void* tsmf_stream_playback_func(void *arg) { HANDLE hdl[2]; TSMF_SAMPLE* sample = NULL; TSMF_STREAM* stream = (TSMF_STREAM *) arg; TSMF_PRESENTATION* presentation = stream->presentation; UINT error = CHANNEL_RC_OK; DWORD status; DEBUG_TSMF("in %d", stream->stream_id); if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO && stream->sample_rate && stream->channels && stream->bits_per_sample) { if (stream->decoder) { if (stream->decoder->GetDecodedData) { stream->audio = tsmf_load_audio_device( presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL, presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL); if (stream->audio) { stream->audio->SetFormat(stream->audio, stream->sample_rate, stream->channels, stream->bits_per_sample); } } } } hdl[0] = stream->stopEvent; hdl[1] = Queue_Event(stream->sample_list); while (1) { status = WaitForMultipleObjects(2, hdl, FALSE, 1000); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error); break; } status = WaitForSingleObject(stream->stopEvent, 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); break; } if (status == WAIT_OBJECT_0) break; if (stream->decoder) if (stream->decoder->BufferLevel) stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder); sample = tsmf_stream_pop_sample(stream, 0); if (sample && !tsmf_sample_playback(sample)) { WLog_ERR(TAG, "error playing sample"); error = ERROR_INTERNAL_ERROR; break; } if (stream->currentBufferLevel > stream->minBufferLevel) USleep(1000); } if (stream->audio) { stream->audio->Free(stream->audio); stream->audio = NULL; } if (error && stream->rdpcontext) setChannelError(stream->rdpcontext, error, "tsmf_stream_playback_func reported an error"); DEBUG_TSMF("out %d", stream->stream_id); ExitThread(0); return NULL; }