wStream* transport_send_stream_init(rdpTransport* transport, int size) { wStream* s = transport->SendStream; Stream_EnsureCapacity(s, size); Stream_SetPosition(s, 0); return s; }
int rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version) { ULONG written; RdpeiServerPrivate *priv = context->priv; if (priv->automataState != STATE_INITIAL) { fprintf(stderr, "%s: called from unexpected state %d\n", __FUNCTION__, priv->automataState); return -1; } Stream_SetPosition(priv->outputStream, 0); Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4); Stream_Write_UINT16(priv->outputStream, EVENTID_SC_READY); Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4); Stream_Write_UINT32(priv->outputStream, version); if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream), Stream_GetPosition(priv->outputStream), &written)) { fprintf(stderr, "%s: error writing ready message\n", __FUNCTION__); return -1; } priv->automataState = STATE_WAITING_CLIENT_READY; return 0; }
wStream* transport_recv_stream_init(rdpTransport* transport, int size) { wStream* s = transport->ReceiveStream; Stream_EnsureCapacity(s, size); Stream_SetPosition(s, 0); return s; }
static wStream* rdg_receive_packet(rdpRdg* rdg) { wStream* s; size_t packetLength; s = Stream_New(NULL, 1024); if (!s) return NULL; if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s), sizeof(RdgPacketHeader))) { Stream_Free(s, TRUE); return NULL; } Stream_Seek(s, 4); Stream_Read_UINT32(s, packetLength); if (!Stream_EnsureCapacity(s, packetLength)) { Stream_Free(s, TRUE); return NULL; } if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s) + sizeof(RdgPacketHeader), packetLength - sizeof(RdgPacketHeader))) { Stream_Free(s, TRUE); return NULL; } Stream_SetLength(s, packetLength); return s; }
int rdpei_server_resume(RdpeiServerContext *context) { ULONG written; RdpeiServerPrivate *priv = context->priv; switch (priv->automataState) { case STATE_WAITING_FRAME: fprintf(stderr, "%s: not suspended\n", __FUNCTION__); return 0; case STATE_SUSPENDED: break; default: fprintf(stderr, "%s: called from unexpected state %d\n", __FUNCTION__, priv->automataState); return -1; } Stream_SetPosition(priv->outputStream, 0); Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH); Stream_Write_UINT16(priv->outputStream, EVENTID_RESUME_TOUCH); Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH); if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream), Stream_GetPosition(priv->outputStream), &written)) { fprintf(stderr, "%s: error writing resumeTouch message\n", __FUNCTION__); return -1; } priv->automataState = STATE_WAITING_FRAME; return 0; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version) { ULONG written; RdpeiServerPrivate *priv = context->priv; if (priv->automataState != STATE_INITIAL) { WLog_ERR(TAG, "called from unexpected state %d", (int)priv->automataState); return ERROR_INVALID_STATE; } Stream_SetPosition(priv->outputStream, 0); if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4)) { WLog_ERR(TAG, "Stream_EnsureCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT16(priv->outputStream, EVENTID_SC_READY); Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4); Stream_Write_UINT32(priv->outputStream, version); if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream), Stream_GetPosition(priv->outputStream), &written)) { WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); return ERROR_INTERNAL_ERROR; } priv->automataState = STATE_WAITING_CLIENT_READY; return CHANNEL_RC_OK; }
wStream* transport_send_stream_init(rdpTransport* transport, int size) { wStream* s; s = StreamPool_Take(transport->ReceivePool, size); Stream_EnsureCapacity(s, size); Stream_SetPosition(s, 0); return s; }
wStream* rdg_receive_packet(rdpRdg* rdg) { int status; wStream* s; RdgPacketHeader* packet; UINT32 readCount = 0; s = Stream_New(NULL, 1024); if (!s) return NULL; packet = (RdgPacketHeader*) Stream_Buffer(s); while (readCount < sizeof(RdgPacketHeader)) { status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), sizeof(RdgPacketHeader) - readCount); if (status < 0) { continue; } readCount += status; Stream_Seek(s, readCount); } if (Stream_Capacity(s) < packet->packetLength) { if (!Stream_EnsureCapacity(s, packet->packetLength)) { Stream_Free(s, TRUE); return NULL; } packet = (RdgPacketHeader*) Stream_Buffer(s); } while (readCount < packet->packetLength) { status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), packet->packetLength - readCount); if (status < 0) { continue; } readCount += status; Stream_Seek(s, readCount); } Stream_SealLength(s); return s; }
wStream* transport_send_stream_init(rdpTransport* transport, int size) { wStream* s; if (!(s = StreamPool_Take(transport->ReceivePool, size))) return NULL; if (!Stream_EnsureCapacity(s, size)) { Stream_Release(s); return NULL; } Stream_SetPosition(s, 0); return s; }
static int transport_read_nonblocking(rdpTransport* transport) { int status; Stream_EnsureCapacity(transport->ReceiveBuffer, 32 * 1024); status = transport_read(transport, transport->ReceiveBuffer); if (status <= 0) return status; Stream_Seek(transport->ReceiveBuffer, status); return status; }
BOOL tf_peer_dump_rfx(freerdp_peer* client) { wStream* s; UINT32 prev_seconds; UINT32 prev_useconds; rdpUpdate* update; rdpPcap* pcap_rfx; pcap_record record; s = Stream_New(NULL, 512); if (!s) return FALSE; update = client->update; if (!(pcap_rfx = pcap_open(test_pcap_file, FALSE))) return FALSE; prev_seconds = prev_useconds = 0; while (pcap_has_next_record(pcap_rfx)) { if (!pcap_get_next_record_header(pcap_rfx, &record)) break; if (!Stream_EnsureCapacity(s, record.length)) break; record.data = Stream_Buffer(s); pcap_get_next_record_content(pcap_rfx, &record); Stream_SetPointer(s, Stream_Buffer(s) + Stream_Capacity(s)); if (test_dump_rfx_realtime && test_sleep_tsdiff(&prev_seconds, &prev_useconds, record.header.ts_sec, record.header.ts_usec) == FALSE) break; update->SurfaceCommand(update->context, s); if (client->CheckFileDescriptor(client) != TRUE) break; } Stream_Free(s, TRUE); pcap_close(pcap_rfx); return TRUE; }
wStream* StreamPool_Take(wStreamPool* pool, size_t size) { int index; int foundIndex; wStream* s = NULL; BOOL found = FALSE; if (pool->synchronized) WaitForSingleObject(pool->mutex, INFINITE); if (size == 0) size = pool->defaultSize; for (index = 0; index < pool->aSize; index++) { s = pool->aArray[index]; if (Stream_Capacity(s) >= size) { foundIndex = index; found = TRUE; break; } } if (!found) { s = Stream_New(NULL, size); } else { StreamPool_ShiftAvailable(pool, foundIndex, -1); Stream_EnsureCapacity(s, size); Stream_Pointer(s) = Stream_Buffer(s); } s->pool = pool; s->count = 1; StreamPool_AddUsed(pool, s); if (pool->synchronized) ReleaseMutex(pool->mutex); return s; }
wStream* StreamPool_Take(wStreamPool* pool, size_t size) { int index; int foundIndex; wStream* s = NULL; BOOL found = FALSE; if (pool->synchronized) EnterCriticalSection(&pool->lock); if (size == 0) size = pool->defaultSize; for (index = 0; index < pool->aSize; index++) { s = pool->aArray[index]; if (Stream_Capacity(s) >= size) { foundIndex = index; found = TRUE; break; } } if (!found) { s = Stream_New(NULL, size); } else { StreamPool_ShiftAvailable(pool, foundIndex, -1); Stream_EnsureCapacity(s, size); Stream_Pointer(s) = Stream_Buffer(s); } s->pool = pool; s->count = 1; StreamPool_AddUsed(pool, s); if (pool->synchronized) LeaveCriticalSection(&pool->lock); return s; }
static BOOL TestStream_Extent(UINT32 maxSize) { UINT32 i; wStream *s = NULL; BOOL result = FALSE; if (!(s = Stream_New(NULL, 1))) { printf("%s: Stream_New failed\n", __FUNCTION__); return FALSE; } for (i = 1; i < maxSize; i++) { if (i % 2) { if (!Stream_EnsureRemainingCapacity(s, i)) goto fail; } else { if (!Stream_EnsureCapacity(s, i)) goto fail; } Stream_SetPosition(s, i); Stream_SealLength(s); if (!TestStream_Verify(s, i, i, i)) { printf("%s: failed to verify stream in iteration %"PRIu32"\n", __FUNCTION__, i); goto fail; } } result = TRUE; fail: if (s) { Stream_Free(s, TRUE); } return result; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT rdpei_server_resume(RdpeiServerContext *context) { ULONG written; RdpeiServerPrivate *priv = context->priv; switch (priv->automataState) { case STATE_WAITING_FRAME: WLog_ERR(TAG, "not suspended"); return CHANNEL_RC_OK; case STATE_SUSPENDED: break; default: WLog_ERR(TAG, "called from unexpected state %d", (int)priv->automataState); return ERROR_INVALID_STATE; } Stream_SetPosition(priv->outputStream, 0); if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH)) { WLog_ERR(TAG, "Stream_EnsureCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT16(priv->outputStream, EVENTID_RESUME_TOUCH); Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH); if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream), Stream_GetPosition(priv->outputStream), &written)) { WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); return ERROR_INTERNAL_ERROR; } priv->automataState = STATE_WAITING_FRAME; return CHANNEL_RC_OK; }
void Stream_EnsureRemainingCapacity(wStream* s, size_t size) { if (Stream_GetPosition(s) + size > Stream_Capacity(s)) Stream_EnsureCapacity(s, Stream_Capacity(s) + size); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT rdpsnd_server_handle_messages(RdpsndServerContext *context) { DWORD bytesReturned; UINT ret = CHANNEL_RC_OK; RdpsndServerPrivate *priv = context->priv; wStream *s = priv->input_stream; if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned)) { if (GetLastError() == ERROR_NO_DATA) return ERROR_NO_DATA; WLog_ERR(TAG, "channel connection closed"); return ERROR_INTERNAL_ERROR; } priv->expectedBytes -= bytesReturned; Stream_Seek(s, bytesReturned); if (priv->expectedBytes) return CHANNEL_RC_OK; Stream_SealLength(s); Stream_SetPosition(s, 0); if (priv->waitingHeader) { /* header case */ Stream_Read_UINT8(s, priv->msgType); Stream_Seek_UINT8(s); /* bPad */ Stream_Read_UINT16(s, priv->expectedBytes); priv->waitingHeader = FALSE; Stream_SetPosition(s, 0); if (priv->expectedBytes) { if (!Stream_EnsureCapacity(s, priv->expectedBytes)) { WLog_ERR(TAG, "Stream_EnsureCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } return CHANNEL_RC_OK; } } /* when here we have the header + the body */ #ifdef WITH_DEBUG_SND WLog_DBG(TAG, "message type %d", priv->msgType); #endif priv->expectedBytes = 4; priv->waitingHeader = TRUE; switch (priv->msgType) { case SNDC_WAVECONFIRM: ret = rdpsnd_server_recv_waveconfirm(context, s); break; case SNDC_FORMATS: ret = rdpsnd_server_recv_formats(context, s); if ((ret == CHANNEL_RC_OK) && (context->clientVersion < 6)) IFCALL(context->Activated, context); break; case SNDC_QUALITYMODE: ret = rdpsnd_server_recv_quality_mode(context, s); Stream_SetPosition(s, 0); /* in case the Activated callback tries to treat some messages */ if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= 6)) IFCALL(context->Activated, context); break; default: WLog_ERR(TAG, "UNKOWN MESSAGE TYPE!! (%#0X)", priv->msgType); ret = ERROR_INVALID_DATA; break; } Stream_SetPosition(s, 0); return ret; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT cliprdr_server_read(CliprdrServerContext* context) { wStream* s; int position; DWORD BytesToRead; DWORD BytesReturned; CLIPRDR_HEADER header; CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; UINT error; DWORD status; s = cliprdr->s; if (Stream_GetPosition(s) < CLIPRDR_HEADER_LENGTH) { BytesReturned = 0; BytesToRead = CLIPRDR_HEADER_LENGTH - Stream_GetPosition(s); status = WaitForSingleObject(cliprdr->ChannelEvent, 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error); return error; } if (status == WAIT_TIMEOUT) return CHANNEL_RC_OK; if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0, (PCHAR) Stream_Pointer(s), BytesToRead, &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); return ERROR_INTERNAL_ERROR; } Stream_Seek(s, BytesReturned); } if (Stream_GetPosition(s) >= CLIPRDR_HEADER_LENGTH) { position = Stream_GetPosition(s); Stream_SetPosition(s, 0); Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */ Stream_Read_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */ Stream_Read_UINT32(s, header.dataLen); /* dataLen (4 bytes) */ if (!Stream_EnsureCapacity(s, (header.dataLen + CLIPRDR_HEADER_LENGTH))) { WLog_ERR(TAG, "Stream_EnsureCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_SetPosition(s, position); if (Stream_GetPosition(s) < (header.dataLen + CLIPRDR_HEADER_LENGTH)) { BytesReturned = 0; BytesToRead = (header.dataLen + CLIPRDR_HEADER_LENGTH) - Stream_GetPosition(s); status = WaitForSingleObject(cliprdr->ChannelEvent, 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error); return error; } if (status == WAIT_TIMEOUT) return CHANNEL_RC_OK; if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0, (PCHAR) Stream_Pointer(s), BytesToRead, &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); return ERROR_INTERNAL_ERROR; } Stream_Seek(s, BytesReturned); } if (Stream_GetPosition(s) >= (header.dataLen + CLIPRDR_HEADER_LENGTH)) { Stream_SetPosition(s, (header.dataLen + CLIPRDR_HEADER_LENGTH)); Stream_SealLength(s); Stream_SetPosition(s, CLIPRDR_HEADER_LENGTH); if ((error = cliprdr_server_receive_pdu(context, s, &header))) { WLog_ERR(TAG, "cliprdr_server_receive_pdu failed with error code %lu!", error); return error; } Stream_SetPosition(s, 0); /* check for trailing zero bytes */ status = WaitForSingleObject(cliprdr->ChannelEvent, 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error); return error; } if (status == WAIT_TIMEOUT) return CHANNEL_RC_OK; BytesReturned = 0; BytesToRead = 4; if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0, (PCHAR) Stream_Pointer(s), BytesToRead, &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); return ERROR_INTERNAL_ERROR; } if (BytesReturned == 4) { Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */ Stream_Read_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */ if (!header.msgType) { /* ignore trailing bytes */ Stream_SetPosition(s, 0); } } else { Stream_Seek(s, BytesReturned); } } } return CHANNEL_RC_OK; }
/** * @brief Try to read a complete PDU (NLA, fast-path or tpkt) from the underlying transport. * * If possible a complete PDU is read, in case of non blocking transport this might not succeed. * Except in case of an error the passed stream will point to the last byte read (correct * position). When the pdu read is completed the stream is sealed and the pointer set to 0 * * @param[in] transport rdpTransport * @param[in] s wStream * @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 number of * bytes of the *complete* pdu read */ int transport_read_pdu(rdpTransport* transport, wStream* s) { int status; int position; int pduLength; BYTE* header; position = 0; pduLength = 0; if (!transport) return -1; if (!s) return -1; position = Stream_GetPosition(s); /* Make sure there is enough space for the longest header within the stream */ if (!Stream_EnsureCapacity(s, 4)) return -1; /* Make sure at least two bytes are read for further processing */ if (position < 2 && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1) { /* No data available at the moment */ return status; } /* update position value for further checks */ position = Stream_GetPosition(s); header = Stream_Buffer(s); if (transport->NlaMode) { /* * In case NlaMode is set TSRequest package(s) are expected * 0x30 = DER encoded data with these bits set: * bit 6 P/C constructed * bit 5 tag number - sequence */ if (header[0] == 0x30) { /* TSRequest (NLA) */ if (header[1] & 0x80) { if ((header[1] & ~(0x80)) == 1) { /* check for header bytes already was readed in previous calls */ if (position < 3 && (status = transport_read_layer_bytes(transport, s, 3 - position)) != 1) return status; pduLength = header[2]; pduLength += 3; } else if ((header[1] & ~(0x80)) == 2) { /* check for header bytes already was readed in previous calls */ if (position < 4 && (status = transport_read_layer_bytes(transport, s, 4 - position)) != 1) return status; pduLength = (header[2] << 8) | header[3]; pduLength += 4; } else { WLog_ERR(TAG, "Error reading TSRequest!"); return -1; } } else { pduLength = header[1]; pduLength += 2; } } } else { if (header[0] == 0x03) { /* TPKT header */ /* check for header bytes already was readed in previous calls */ if (position < 4 && (status = transport_read_layer_bytes(transport, s, 4 - position)) != 1) return status; pduLength = (header[2] << 8) | header[3]; /* min and max values according to ITU-T Rec. T.123 (01/2007) section 8 */ if (pduLength < 7 || pduLength > 0xFFFF) { WLog_ERR(TAG, "tpkt - invalid pduLength: %d", pduLength); return -1; } } else { /* Fast-Path Header */ if (header[1] & 0x80) { /* check for header bytes already was readed in previous calls */ if (position < 3 && (status = transport_read_layer_bytes(transport, s, 3 - position)) != 1) return status; pduLength = ((header[1] & 0x7F) << 8) | header[2]; } else pduLength = header[1]; /* * fast-path has 7 bits for length so the maximum size, including headers is 0x8000 * The theoretical minimum fast-path PDU consists only of two header bytes plus one * byte for data (e.g. fast-path input synchronize pdu) */ if (pduLength < 3 || pduLength > 0x8000) { WLog_ERR(TAG, "fast path - invalid pduLength: %d", pduLength); return -1; } } } if (!Stream_EnsureCapacity(s, Stream_GetPosition(s) + pduLength)) return -1; status = transport_read_layer_bytes(transport, s, pduLength - Stream_GetPosition(s)); if (status != 1) return status; if (Stream_GetPosition(s) >= pduLength) WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND); Stream_SealLength(s); Stream_SetPosition(s, 0); return Stream_Length(s); }
BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, BYTE* data, int size) { DWORD i; int left; wStream* s; UINT32 flags; int chunkSize; rdpMcs* mcs = rdp->mcs; rdpMcsChannel* channel = NULL; for (i = 0; i < mcs->channelCount; i++) { if (mcs->channels[i].ChannelId == channelId) { channel = &mcs->channels[i]; break; } } if (!channel) { DEBUG_WARN( "freerdp_channel_send: unknown channelId %d\n", channelId); return FALSE; } flags = CHANNEL_FLAG_FIRST; left = size; while (left > 0) { s = rdp_send_stream_init(rdp); if (left > (int) rdp->settings->VirtualChannelChunkSize) { chunkSize = rdp->settings->VirtualChannelChunkSize; } else { chunkSize = left; flags |= CHANNEL_FLAG_LAST; } if ((channel->options & CHANNEL_OPTION_SHOW_PROTOCOL)) { flags |= CHANNEL_FLAG_SHOW_PROTOCOL; } Stream_Write_UINT32(s, size); Stream_Write_UINT32(s, flags); Stream_EnsureCapacity(s, chunkSize); Stream_Write(s, data, chunkSize); rdp_send(rdp, s, channelId); data += chunkSize; left -= chunkSize; flags = 0; } return TRUE; }
/** * @brief Try to read a complete PDU (NLA, fast-path or tpkt) from the underlying transport. * * If possible a complete PDU is read, in case of non blocking transport this might not succeed. * Except in case of an error the passed stream will point to the last byte read (correct * position). When the pdu read is completed the stream is sealed and the pointer set to 0 * * @param[in] transport rdpTransport * @param[in] s wStream * @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 number of * bytes of the *complete* pdu read */ int transport_read_pdu(rdpTransport* transport, wStream* s) { int status; int position; int pduLength; BYTE *header; position = 0; pduLength = 0; if (!transport) return -1; if (!s) return -1; position = Stream_GetPosition(s); /* Make sure there is enough space for the longest header within the stream */ Stream_EnsureCapacity(s, 4); /* Make sure at least two bytes are read for futher processing */ if (position < 2 && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1) { /* No data available at the moment */ return status; } header = Stream_Buffer(s); if (transport->NlaMode) { /* * In case NlaMode is set TSRequest package(s) are expected * 0x30 = DER encoded data with these bits set: * bit 6 P/C constructed * bit 5 tag number - sequence */ if (header[0] == 0x30) { /* TSRequest (NLA) */ if (header[1] & 0x80) { if ((header[1] & ~(0x80)) == 1) { if ((status = transport_read_layer_bytes(transport, s, 1)) != 1) return status; pduLength = header[2]; pduLength += 3; } else if ((header[1] & ~(0x80)) == 2) { if ((status = transport_read_layer_bytes(transport, s, 2)) != 1) return status; pduLength = (header[2] << 8) | header[3]; pduLength += 4; } else { fprintf(stderr, "Error reading TSRequest!\n"); return -1; } } else { pduLength = header[1]; pduLength += 2; } } } else { if (header[0] == 0x03) { /* TPKT header */ if ((status = transport_read_layer_bytes(transport, s, 2)) != 1) return status; pduLength = (header[2] << 8) | header[3]; /* min and max values according to ITU-T Rec. T.123 (01/2007) section 8 */ if (pduLength < 7 || pduLength > 0xFFFF) { fprintf(stderr, "%s: tpkt - invalid pduLength: %d\n", __FUNCTION__, pduLength); return -1; } } else { /* Fast-Path Header */ if (header[1] & 0x80) { if ((status = transport_read_layer_bytes(transport, s, 1)) != 1) return status; pduLength = ((header[1] & 0x7F) << 8) | header[2]; } else pduLength = header[1]; /* * fast-path has 7 bits for length so the maximum size, including headers is 0x8000 * The theoretical minimum fast-path PDU consists only of two header bytes plus one * byte for data (e.g. fast-path input synchronize pdu) */ if (pduLength < 3 || pduLength > 0x8000) { fprintf(stderr, "%s: fast path - invalid pduLength: %d\n", __FUNCTION__, pduLength); return -1; } } } Stream_EnsureCapacity(s, Stream_GetPosition(s) + pduLength); status = transport_read_layer_bytes(transport, s, pduLength - Stream_GetPosition(s)); if (status != 1) return status; #ifdef WITH_DEBUG_TRANSPORT /* dump when whole PDU is read */ if (Stream_GetPosition(s) >= pduLength) { fprintf(stderr, "Local < Remote\n"); winpr_HexDump(Stream_Buffer(s), pduLength); } #endif if (Stream_GetPosition(s) >= pduLength) WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND); Stream_SealLength(s); Stream_SetPosition(s, 0); return Stream_Length(s); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT rdpei_server_handle_messages(RdpeiServerContext *context) { DWORD bytesReturned; RdpeiServerPrivate *priv = context->priv; wStream *s = priv->inputStream; UINT error = CHANNEL_RC_OK; if (!WTSVirtualChannelRead(priv->channelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned)) { if (GetLastError() == ERROR_NO_DATA) return ERROR_READ_FAULT; WLog_DBG(TAG, "channel connection closed"); return CHANNEL_RC_OK; } priv->expectedBytes -= bytesReturned; Stream_Seek(s, bytesReturned); if (priv->expectedBytes) return CHANNEL_RC_OK; Stream_SealLength(s); Stream_SetPosition(s, 0); if (priv->waitingHeaders) { UINT32 pduLen; /* header case */ Stream_Read_UINT16(s, priv->currentMsgType); Stream_Read_UINT16(s, pduLen); if (pduLen < RDPINPUT_HEADER_LENGTH) { WLog_ERR(TAG, "invalid pduLength %d", pduLen); return ERROR_INVALID_DATA; } priv->expectedBytes = pduLen - RDPINPUT_HEADER_LENGTH; priv->waitingHeaders = FALSE; Stream_SetPosition(s, 0); if (priv->expectedBytes) { if (!Stream_EnsureCapacity(s, priv->expectedBytes)) { WLog_ERR(TAG, "Stream_EnsureCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } return CHANNEL_RC_OK; } } /* when here we have the header + the body */ switch (priv->currentMsgType) { case EVENTID_CS_READY: if (priv->automataState != STATE_WAITING_CLIENT_READY) { WLog_ERR(TAG, "not expecting a CS_READY packet in this state(%d)", (int)priv->automataState); return ERROR_INVALID_STATE; } if ((error = read_cs_ready_message(context, s))) { WLog_ERR(TAG, "read_cs_ready_message failed with error %lu", error); return error; } break; case EVENTID_TOUCH: if ((error = read_touch_event(context, s))) { WLog_ERR(TAG, "read_touch_event failed with error %lu", error); return error; } break; case EVENTID_DISMISS_HOVERING_CONTACT: if ((error = read_dismiss_hovering_contact(context, s))) { WLog_ERR(TAG, "read_dismiss_hovering_contact failed with error %lu", error); return error; } break; default: WLog_ERR(TAG, "unexpected message type 0x%x", priv->currentMsgType); } Stream_SetPosition(s, 0); priv->waitingHeaders = TRUE; priv->expectedBytes = RDPINPUT_HEADER_LENGTH; return error; }
BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, BYTE* data, int size) { DWORD i; int left; wStream* s; UINT32 flags; int chunkSize; rdpMcs* mcs = rdp->mcs; rdpMcsChannel* channel = NULL; for (i = 0; i < mcs->channelCount; i++) { if (mcs->channels[i].ChannelId == channelId) { channel = &mcs->channels[i]; break; } } if (!channel) { WLog_ERR(TAG, "freerdp_channel_send: unknown channelId %"PRIu16"", channelId); return FALSE; } flags = CHANNEL_FLAG_FIRST; left = size; while (left > 0) { s = rdp_send_stream_init(rdp); if (!s) return FALSE; if (left > (int) rdp->settings->VirtualChannelChunkSize) { chunkSize = rdp->settings->VirtualChannelChunkSize; } else { chunkSize = left; flags |= CHANNEL_FLAG_LAST; } if ((channel->options & CHANNEL_OPTION_SHOW_PROTOCOL)) { flags |= CHANNEL_FLAG_SHOW_PROTOCOL; } Stream_Write_UINT32(s, size); Stream_Write_UINT32(s, flags); if (!Stream_EnsureCapacity(s, chunkSize)) { Stream_Release(s); return FALSE; } Stream_Write(s, data, chunkSize); /* WLog_DBG(TAG, "%s: sending data (flags=0x%x size=%d)", __FUNCTION__, flags, size); */ if (!rdp_send(rdp, s, channelId)) { Stream_Release(s); return FALSE; } data += chunkSize; left -= chunkSize; flags = 0; } return TRUE; }
BOOL rdpsnd_server_handle_messages(RdpsndServerContext *context) { DWORD bytesReturned; BOOL ret; RdpsndServerPrivate *priv = context->priv; wStream *s = priv->input_stream; if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned)) { if (GetLastError() == ERROR_NO_DATA) return TRUE; CLOG_ERR( "%s: channel connection closed\n", __FUNCTION__); return FALSE; } priv->expectedBytes -= bytesReturned; Stream_Seek(s, bytesReturned); if (priv->expectedBytes) return TRUE; Stream_SetPosition(s, 0); if (priv->waitingHeader) { /* header case */ Stream_Read_UINT8(s, priv->msgType); Stream_Seek_UINT8(s); /* bPad */ Stream_Read_UINT16(s, priv->expectedBytes); priv->waitingHeader = FALSE; Stream_SetPosition(s, 0); if (priv->expectedBytes) { Stream_EnsureCapacity(s, priv->expectedBytes); return TRUE; } } /* when here we have the header + the body */ #ifdef WITH_DEBUG_SND CLOG_ERR( "%s: message type %d\n", __FUNCTION__, priv->msgType); #endif priv->expectedBytes = 4; priv->waitingHeader = TRUE; switch (priv->msgType) { case SNDC_WAVECONFIRM: ret = rdpsnd_server_recv_waveconfirm(context, s); break; case SNDC_FORMATS: ret = rdpsnd_server_recv_formats(context, s); break; case SNDC_QUALITYMODE: ret = rdpsnd_server_recv_quality_mode(context, s); Stream_SetPosition(s, 0); /* in case the Activated callback tries to treat some messages */ if (ret) { IFCALL(context->Activated, context); } break; default: CLOG_ERR( "%s: UNKOWN MESSAGE TYPE!! (%#0X)\n\n", __FUNCTION__, priv->msgType); ret = FALSE; break; } Stream_SetPosition(s, 0); return ret; }
int rpc_client_on_fragment_received_event(rdpRpc* rpc) { BYTE* buffer; UINT32 StubOffset; UINT32 StubLength; wStream* fragment; rpcconn_hdr_t* header; freerdp* instance; instance = (freerdp*) rpc->transport->settings->instance; if (!rpc->client->pdu) rpc->client->pdu = rpc_client_receive_pool_take(rpc); fragment = Queue_Dequeue(rpc->client->FragmentQueue); buffer = (BYTE*) Stream_Buffer(fragment); header = (rpcconn_hdr_t*) Stream_Buffer(fragment); if (rpc->State < RPC_CLIENT_STATE_CONTEXT_NEGOTIATED) { rpc->client->pdu->Flags = 0; rpc->client->pdu->CallId = header->common.call_id; Stream_EnsureCapacity(rpc->client->pdu->s, Stream_Length(fragment)); Stream_Write(rpc->client->pdu->s, buffer, Stream_Length(fragment)); Stream_Length(rpc->client->pdu->s) = Stream_GetPosition(rpc->client->pdu->s); rpc_client_fragment_pool_return(rpc, fragment); Queue_Enqueue(rpc->client->ReceiveQueue, rpc->client->pdu); SetEvent(rpc->transport->ReceiveEvent); rpc->client->pdu = NULL; return 0; } if (header->common.ptype == PTYPE_RTS) { if (rpc->VirtualConnection->State >= VIRTUAL_CONNECTION_STATE_OPENED) { //fprintf(stderr, "Receiving Out-of-Sequence RTS PDU\n"); rts_recv_out_of_sequence_pdu(rpc, buffer, header->common.frag_length); rpc_client_fragment_pool_return(rpc, fragment); } else { fprintf(stderr, "warning: unhandled RTS PDU\n"); } return 0; } else if (header->common.ptype == PTYPE_FAULT) { rpc_recv_fault_pdu(header); return -1; } if (header->common.ptype != PTYPE_RESPONSE) { fprintf(stderr, "Unexpected RPC PDU type: %d\n", header->common.ptype); return -1; } rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header->common.frag_length; rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= header->common.frag_length; if (!rpc_get_stub_data_info(rpc, buffer, &StubOffset, &StubLength)) { fprintf(stderr, "rpc_recv_pdu_fragment: expected stub\n"); return -1; } if (StubLength == 4) { //fprintf(stderr, "Ignoring TsProxySendToServer Response\n"); printf("Got stub length 4 with flags %d and callid %d\n", header->common.pfc_flags, header->common.call_id); /* received a disconnect request from the server? */ if ((header->common.call_id == rpc->PipeCallId) && (header->common.pfc_flags & PFC_LAST_FRAG)) { TerminateEventArgs e; instance->context->rdp->disconnect = TRUE; rpc->transport->tsg->state = TSG_STATE_TUNNEL_CLOSE_PENDING; EventArgsInit(&e, "freerdp"); e.code = 0; PubSub_OnTerminate(instance->context->pubSub, instance->context, &e); } rpc_client_fragment_pool_return(rpc, fragment); return 0; } Stream_EnsureCapacity(rpc->client->pdu->s, header->response.alloc_hint); buffer = (BYTE*) Stream_Buffer(fragment); header = (rpcconn_hdr_t*) Stream_Buffer(fragment); if (rpc->StubFragCount == 0) rpc->StubCallId = header->common.call_id; if (rpc->StubCallId != header->common.call_id) { fprintf(stderr, "invalid call_id: actual: %d, expected: %d, frag_count: %d\n", rpc->StubCallId, header->common.call_id, rpc->StubFragCount); } Stream_Write(rpc->client->pdu->s, &buffer[StubOffset], StubLength); rpc->StubFragCount++; rpc_client_fragment_pool_return(rpc, fragment); if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < (rpc->ReceiveWindow / 2)) { //fprintf(stderr, "Sending Flow Control Ack PDU\n"); rts_send_flow_control_ack_pdu(rpc); } /** * If alloc_hint is set to a nonzero value and a request or a response is fragmented into multiple * PDUs, implementations of these extensions SHOULD set the alloc_hint field in every PDU to be the * combined stub data length of all remaining fragment PDUs. */ if (header->response.alloc_hint == StubLength) { rpc->client->pdu->Flags = RPC_PDU_FLAG_STUB; rpc->client->pdu->CallId = rpc->StubCallId; Stream_Length(rpc->client->pdu->s) = Stream_GetPosition(rpc->client->pdu->s); rpc->StubFragCount = 0; rpc->StubCallId = 0; Queue_Enqueue(rpc->client->ReceiveQueue, rpc->client->pdu); rpc->client->pdu = NULL; return 0; } return 0; }
int rpc_client_on_fragment_received_event(rdpRpc* rpc) { BYTE* buffer; UINT32 StubOffset; UINT32 StubLength; wStream* fragment; rpcconn_hdr_t* header; if (!rpc->client->pdu) rpc->client->pdu = rpc_client_receive_pool_take(rpc); fragment = Queue_Dequeue(rpc->client->FragmentQueue); buffer = (BYTE*) Stream_Buffer(fragment); header = (rpcconn_hdr_t*) Stream_Buffer(fragment); if (rpc->State < RPC_CLIENT_STATE_CONTEXT_NEGOTIATED) { rpc->client->pdu->Flags = 0; rpc->client->pdu->CallId = header->common.call_id; Stream_EnsureCapacity(rpc->client->pdu->s, Stream_Length(fragment)); Stream_Write(rpc->client->pdu->s, buffer, Stream_Length(fragment)); Stream_Length(rpc->client->pdu->s) = Stream_Position(rpc->client->pdu->s); rpc_client_fragment_pool_return(rpc, fragment); Queue_Enqueue(rpc->client->ReceiveQueue, rpc->client->pdu); SetEvent(rpc->transport->ReceiveEvent); rpc->client->pdu = NULL; return 0; } if (header->common.ptype == PTYPE_RTS) { if (rpc->VirtualConnection->State >= VIRTUAL_CONNECTION_STATE_OPENED) { //printf("Receiving Out-of-Sequence RTS PDU\n"); rts_recv_out_of_sequence_pdu(rpc, buffer, header->common.frag_length); rpc_client_fragment_pool_return(rpc, fragment); } else { printf("warning: unhandled RTS PDU\n"); } return 0; } else if (header->common.ptype == PTYPE_FAULT) { rpc_recv_fault_pdu(header); return -1; } if (header->common.ptype != PTYPE_RESPONSE) { printf("Unexpected RPC PDU type: %d\n", header->common.ptype); return -1; } rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header->common.frag_length; rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= header->common.frag_length; if (!rpc_get_stub_data_info(rpc, buffer, &StubOffset, &StubLength)) { printf("rpc_recv_pdu_fragment: expected stub\n"); return -1; } if (StubLength == 4) { //printf("Ignoring TsProxySendToServer Response\n"); rpc_client_fragment_pool_return(rpc, fragment); return 0; } Stream_EnsureCapacity(rpc->client->pdu->s, header->response.alloc_hint); buffer = (BYTE*) Stream_Buffer(fragment); header = (rpcconn_hdr_t*) Stream_Buffer(fragment); if (rpc->StubFragCount == 0) rpc->StubCallId = header->common.call_id; if (rpc->StubCallId != header->common.call_id) { printf("invalid call_id: actual: %d, expected: %d, frag_count: %d\n", rpc->StubCallId, header->common.call_id, rpc->StubFragCount); } Stream_Write(rpc->client->pdu->s, &buffer[StubOffset], StubLength); rpc->StubFragCount++; rpc_client_fragment_pool_return(rpc, fragment); if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < (rpc->ReceiveWindow / 2)) { //printf("Sending Flow Control Ack PDU\n"); rts_send_flow_control_ack_pdu(rpc); } /** * If alloc_hint is set to a nonzero value and a request or a response is fragmented into multiple * PDUs, implementations of these extensions SHOULD set the alloc_hint field in every PDU to be the * combined stub data length of all remaining fragment PDUs. */ if (header->response.alloc_hint == StubLength) { rpc->client->pdu->Flags = RPC_PDU_FLAG_STUB; rpc->client->pdu->CallId = rpc->StubCallId; Stream_Length(rpc->client->pdu->s) = Stream_Position(rpc->client->pdu->s); rpc->StubFragCount = 0; rpc->StubCallId = 0; Queue_Enqueue(rpc->client->ReceiveQueue, rpc->client->pdu); rpc->client->pdu = NULL; return 0; } return 0; }
BOOL rts_connect(rdpRpc* rpc) { RPC_PDU* pdu; rpcconn_rts_hdr_t* rts; HttpResponse* http_response; freerdp* instance = (freerdp*) rpc->settings->instance; rdpContext* context = instance->context; /** * Connection Opening * * When opening a virtual connection to the server, an implementation of this protocol MUST perform * the following sequence of steps: * * 1. Send an IN channel request as specified in section 2.1.2.1.1, containing the connection timeout, * ResourceType UUID, and Session UUID values, if any, supplied by the higher-layer protocol or application. * * 2. Send an OUT channel request as specified in section 2.1.2.1.2. * * 3. Send a CONN/A1 RTS PDU as specified in section 2.2.4.2 * * 4. Send a CONN/B1 RTS PDU as specified in section 2.2.4.5 * * 5. Wait for the connection establishment protocol sequence as specified in 3.2.1.5.3.1 to complete * * An implementation MAY execute steps 1 and 2 in parallel. An implementation SHOULD execute steps * 3 and 4 in parallel. An implementation MUST execute step 3 after completion of step 1 and execute * step 4 after completion of step 2. * */ rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_INITIAL; WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_INITIAL"); rpc->client->SynchronousSend = TRUE; rpc->client->SynchronousReceive = TRUE; if (!rpc_ntlm_http_out_connect(rpc)) { WLog_ERR(TAG, "rpc_out_connect_http error!"); return FALSE; } if (rts_send_CONN_A1_pdu(rpc) != 0) { WLog_ERR(TAG, "rpc_send_CONN_A1_pdu error!"); return FALSE; } if (!rpc_ntlm_http_in_connect(rpc)) { WLog_ERR(TAG, "rpc_in_connect_http error!"); return FALSE; } if (rts_send_CONN_B1_pdu(rpc) < 0) { WLog_ERR(TAG, "rpc_send_CONN_B1_pdu error!"); return FALSE; } rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT; WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT"); /** * Receive OUT Channel Response * * A client implementation MUST NOT accept the OUT channel HTTP response in any state other than * Out Channel Wait. If received in any other state, this HTTP response is a protocol error. Therefore, * the client MUST consider the virtual connection opening a failure and indicate this to higher layers * in an implementation-specific way. The Microsoft Windows® implementation returns * RPC_S_PROTOCOL_ERROR, as specified in [MS-ERREF], to higher-layer protocols. * * If this HTTP response is received in Out Channel Wait state, the client MUST process the fields of * this response as defined in this section. * * First, the client MUST determine whether the response indicates a success or a failure. If the status * code is set to 200, the client MUST interpret this as a success, and it MUST do the following: * * 1. Ignore the values of all other header fields. * * 2. Transition to Wait_A3W state. * * 3. Wait for network events. * * 4. Skip the rest of the processing in this section. * * If the status code is not set to 200, the client MUST interpret this as a failure and follow the same * processing rules as specified in section 3.2.2.5.6. * */ http_response = http_response_recv(rpc->TlsOut); if (!http_response) { WLog_ERR(TAG, "unable to retrieve OUT Channel Response!"); return FALSE; } if (http_response->StatusCode != HTTP_STATUS_OK) { WLog_ERR(TAG, "error! Status Code: %d", http_response->StatusCode); http_response_print(http_response); http_response_free(http_response); if (http_response->StatusCode == HTTP_STATUS_DENIED) { if (!connectErrorCode) { connectErrorCode = AUTHENTICATIONERROR; } if (!freerdp_get_last_error(context)) { freerdp_set_last_error(context, FREERDP_ERROR_AUTHENTICATION_FAILED); } } return FALSE; } if (http_response->bodyLen) { /* inject bytes we have read in the body as a received packet for the RPC client */ rpc->client->RecvFrag = rpc_client_fragment_pool_take(rpc); Stream_EnsureCapacity(rpc->client->RecvFrag, http_response->bodyLen); CopyMemory(rpc->client->RecvFrag, http_response->BodyContent, http_response->bodyLen); } //http_response_print(http_response); http_response_free(http_response); rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_WAIT_A3W; WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_WAIT_A3W"); /** * Receive CONN_A3 RTS PDU * * A client implementation MUST NOT accept the CONN/A3 RTS PDU in any state other than * Wait_A3W. If received in any other state, this PDU is a protocol error and the client * MUST consider the virtual connection opening a failure and indicate this to higher * layers in an implementation-specific way. * * Set the ConnectionTimeout in the Ping Originator of the Client's IN Channel to the * ConnectionTimeout in the CONN/A3 PDU. * * If this RTS PDU is received in Wait_A3W state, the client MUST transition the state * machine to Wait_C2 state and wait for network events. * */ rpc_client_start(rpc); pdu = rpc_recv_dequeue_pdu(rpc); if (!pdu) return FALSE; rts = (rpcconn_rts_hdr_t*) Stream_Buffer(pdu->s); if (!rts_match_pdu_signature(rpc, &RTS_PDU_CONN_A3_SIGNATURE, rts)) { WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/A3"); return FALSE; } rts_recv_CONN_A3_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s)); rpc_client_receive_pool_return(rpc, pdu); rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_WAIT_C2; WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_WAIT_C2"); /** * Receive CONN_C2 RTS PDU * * A client implementation MUST NOT accept the CONN/C2 RTS PDU in any state other than Wait_C2. * If received in any other state, this PDU is a protocol error and the client MUST consider the virtual * connection opening a failure and indicate this to higher layers in an implementation-specific way. * * If this RTS PDU is received in Wait_C2 state, the client implementation MUST do the following: * * 1. Transition the state machine to opened state. * * 2. Set the connection time-out protocol variable to the value of the ConnectionTimeout field from * the CONN/C2 RTS PDU. * * 3. Set the PeerReceiveWindow value in the SendingChannel of the Client IN Channel to the * ReceiveWindowSize value in the CONN/C2 PDU. * * 4. Indicate to higher-layer protocols that the virtual connection opening is a success. * */ pdu = rpc_recv_dequeue_pdu(rpc); if (!pdu) return FALSE; rts = (rpcconn_rts_hdr_t*) Stream_Buffer(pdu->s); if (!rts_match_pdu_signature(rpc, &RTS_PDU_CONN_C2_SIGNATURE, rts)) { WLog_ERR(TAG, "unexpected RTS PDU: Expected CONN/C2"); return FALSE; } rts_recv_CONN_C2_pdu(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s)); rpc_client_receive_pool_return(rpc, pdu); rpc->VirtualConnection->State = VIRTUAL_CONNECTION_STATE_OPENED; WLog_DBG(TAG, "VIRTUAL_CONNECTION_STATE_OPENED"); rpc->client->SynchronousSend = TRUE; rpc->client->SynchronousReceive = TRUE; return TRUE; }
int rdpei_server_handle_messages(RdpeiServerContext *context) { DWORD bytesReturned; RdpeiServerPrivate *priv = context->priv; wStream *s = priv->inputStream; if (!WTSVirtualChannelRead(priv->channelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned)) { if (GetLastError() == ERROR_NO_DATA) return -1; fprintf(stderr, "%s: channel connection closed\n", __FUNCTION__); return 0; } priv->expectedBytes -= bytesReturned; Stream_Seek(s, bytesReturned); if (priv->expectedBytes) return 1; Stream_SealLength(s); Stream_SetPosition(s, 0); if (priv->waitingHeaders) { UINT32 pduLen; /* header case */ Stream_Read_UINT16(s, priv->currentMsgType); Stream_Read_UINT16(s, pduLen); if (pduLen < RDPINPUT_HEADER_LENGTH) { fprintf(stderr, "%s: invalid pduLength %d\n", __FUNCTION__, pduLen); return -1; } priv->expectedBytes = pduLen - RDPINPUT_HEADER_LENGTH; priv->waitingHeaders = FALSE; Stream_SetPosition(s, 0); if (priv->expectedBytes) { Stream_EnsureCapacity(s, priv->expectedBytes); return 1; } } /* when here we have the header + the body */ switch (priv->currentMsgType) { case EVENTID_CS_READY: if (priv->automataState != STATE_WAITING_CLIENT_READY) { fprintf(stderr, "%s: not expecting a CS_READY packet in this state(%d)\n", __FUNCTION__, (int)priv->automataState); return 0; } if (read_cs_ready_message(context, s) < 0) return 0; break; case EVENTID_TOUCH: if (read_touch_event(context, s) < 0) { fprintf(stderr, "%s: error in touch event packet\n", __FUNCTION__); return 0; } break; case EVENTID_DISMISS_HOVERING_CONTACT: if (read_dismiss_hovering_contact(context, s) < 0) { fprintf(stderr, "%s: error reading read_dismiss_hovering_contact\n", __FUNCTION__); return 0; } break; default: fprintf(stderr, "%s: unexpected message type 0x%x\n", __FUNCTION__, priv->currentMsgType); } Stream_SetPosition(s, 0); priv->waitingHeaders = TRUE; priv->expectedBytes = RDPINPUT_HEADER_LENGTH; return 1; }