static inline void prepare_compressed_data(InStream & compressed_data_stream, bool compressed, uint16_t & MatchCount, uint8_t const * & MatchDetails, uint8_t const * & Literals, size_t & literals_length) { if (compressed) { unsigned expected = 2; // MatchCount(2) if (!compressed_data_stream.in_check_rem(expected)) { LOG(LOG_ERR, "RDP61_COMPRESSED_DATA: data truncated, expected=%u remains=%zu", expected, compressed_data_stream.in_remain()); throw Error(ERR_RDP61_DECOMPRESS_DATA_TRUNCATED); } MatchCount = compressed_data_stream.in_uint16_le(); expected = MatchCount * 8; // MatchCount(2) * (MatchLength(2) + MatchOutputOffset(2) + MatchHistoryOffset(4)) if (!compressed_data_stream.in_check_rem(expected)) { LOG(LOG_ERR, "RDP61_COMPRESSED_DATA: data truncated, expected=%u remains=%zu", expected, compressed_data_stream.in_remain()); throw Error(ERR_RDP61_DECOMPRESS_DATA_TRUNCATED); } MatchDetails = compressed_data_stream.get_current(); compressed_data_stream.in_skip_bytes(expected); } else { MatchCount = 0; MatchDetails = nullptr; } literals_length = compressed_data_stream.in_remain(); Literals = (literals_length ? compressed_data_stream.get_current() : nullptr); }
void receive(InStream & stream) { { const unsigned expected = 4; // allowDisplayUpdates(1) + Padding(3) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "Truncated SuppressOutputPDUData: expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } } this->allowDisplayUpdates_ = stream.in_uint8(); stream.in_skip_bytes(3); // Padding(3) if (ALLOW_DISPLAY_UPDATES == this->allowDisplayUpdates_) { { const unsigned expected = 8; // left(2) + top(2) + right(2) + bottom(2) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "Truncated SuppressOutputPDUData(2): expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } } this->left_ = stream.in_uint16_le(); this->top_ = stream.in_uint16_le(); this->right_ = stream.in_uint16_le(); this->bottom_ = stream.in_uint16_le(); } } // void receive(InStream & stream)
explicit ShareFlow_Recv(InStream & stream) : flowMarker([&stream]{ if (!stream.in_check_rem(2+1+1+1+1+2)){ LOG(LOG_ERR, "Truncated " "[2: ShareFlow PDU packet]" "[1: ShareFlow pad]" "[1: ShareFlow PDU type]" "[1: flow Identifier]" "[1: flow number]" "[2: ShareFlow PDU packet] , remains=%zu", stream.in_remain()); throw Error(ERR_SEC); } return stream.in_uint16_le(); }()) , pad(stream.in_uint8()) , pduTypeFlow(stream.in_uint8()) , flowIdentifier(stream.in_uint8()) , flowNumber(stream.in_uint8()) , mcs_channel(stream.in_uint16_le()) { LOG(LOG_INFO, "Flow control packet %.4x (offset=%zu)", this->flowMarker, stream.get_offset()); if (this->flowMarker != 0x8000) { LOG(LOG_ERR, "Expected flow control packet, got %.4x", this->flowMarker); throw Error(ERR_SEC); } LOG(LOG_INFO, "PDUTypeFlow=%u", this->pduTypeFlow); if (stream.in_remain()) { LOG(LOG_INFO, "trailing bytes in FlowPDU, remains %zu bytes", stream.in_remain()); } }
explicit ShareData_Recv(InStream & stream, rdp_mppc_dec * dec = nullptr) //============================================================================== : CheckShareData_Recv(stream) , share_id(stream.in_uint32_le()) , pad1(stream.in_uint8()) , streamid(stream.in_uint8()) , len(stream.in_uint16_le()) , pdutype2(stream.in_uint8()) , compressedType(stream.in_uint8()) , compressedLen(stream.in_uint16_le()) , payload([&stream, dec, this]() { if (this->compressedType & PACKET_COMPRESSED) { if (!dec) { LOG(LOG_INFO, "ShareData_Recv: got unexpected compressed share data"); throw Error(ERR_SEC); } const uint8_t * rdata; uint32_t rlen; dec->decompress(stream.get_data()+stream.get_offset(), stream.in_remain(), this->compressedType, rdata, rlen); return InStream(rdata, 0, rlen); } else { return InStream(stream.get_current(), stream.in_remain()); } }()) // BEGIN CONSTRUCTOR { //LOG( LOG_INFO, "ShareData_Recv: pdutype2=%u len=%u compressedLen=%u payload_size=%u" // , this->pdutype2, this->len, this->compressedLen, this->payload.size()); stream.in_skip_bytes(stream.in_remain()); } // END CONSTRUCTOR
explicit LogonInfoVersion1_Recv(InStream & stream) : cbDomain(0), cbUserName(0), SessionId(0) { memset(Domain, 0, sizeof(Domain)); memset(UserName, 0, sizeof(UserName)); unsigned expected = 4; // cbDomain(4) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "Truncated Logon Info Version 1 (data): expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } this->cbDomain = stream.in_uint32_le(); expected = 52 + // Domain(52) 4; // cbUserName(4) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "Truncated Logon Info Version 1 (data): expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } stream.in_uni_to_ascii_str(this->Domain, this->cbDomain, sizeof(this->Domain)); stream.in_skip_bytes(52 - // Domain(52) this->cbDomain); this->cbUserName = stream.in_uint32_le(); expected = 512 + // UserName(512) 4; // SessionId(4) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "Truncated Logon Info Version 1 (data): expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } stream.in_uni_to_ascii_str(this->UserName, this->cbUserName, sizeof(this->UserName)); stream.in_skip_bytes(512 - // UserName(512) this->cbUserName); this->SessionId = stream.in_uint32_le(); LOG(LOG_INFO, "Logon Info Version 1 (data): Domain=\"%s\" UserName=\"%s\" SessionId=%d", this->Domain, this->UserName, this->SessionId); } // LogonInfoVersion1_Recv(InStream & stream)
explicit SaveSessionInfoPDUData_Recv(InStream & stream) : infoType([&stream](){ if (!stream.in_check_rem(4)) { LOG(LOG_ERR, "Truncated Save Session Info PDU (data): expected=4 remains=%zu", stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } return stream.in_uint32_le(); }()), payload(stream.get_current(), stream.in_remain()) { stream.in_skip_bytes(this->payload.get_capacity()); }
explicit LogonInfoVersion2_Recv(InStream & stream) : Version(0), Size(0), SessionId(0), cbDomain(0), cbUserName(0) { memset(Pad, 0, sizeof(Pad)); memset(Domain, 0, sizeof(Domain)); memset(UserName, 0, sizeof(UserName)); unsigned expected = 2 + // Version(2) 4 + // Size(4) 4 + // SessionId(4) 4 + // cbDomain(4) 4 + // cbUserName(4) 558; // Pad(558) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "Truncated Logon Info Version 2 (data): expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } this->Version = stream.in_uint16_le(); this->Size = stream.in_uint32_le(); this->SessionId = stream.in_uint32_le(); this->cbDomain = stream.in_uint32_le(); this->cbUserName = stream.in_uint32_le(); stream.in_copy_bytes(this->Pad, sizeof(this->Pad)); expected = this->cbDomain + this->cbUserName; // SessionId(4) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "Truncated Logon Info Version 2 (data): expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } stream.in_uni_to_ascii_str(this->Domain, this->cbDomain, sizeof(this->Domain)); stream.in_uni_to_ascii_str(this->UserName, this->cbUserName, sizeof(this->UserName)); LOG(LOG_INFO, "Logon Info Version 2 (data): Domain=\"%s\" UserName=\"%s\" SessionId=%d", this->Domain, this->UserName, this->SessionId); } // LogonInfoVersion2_Recv(InStream & stream)
explicit LogonInfoField_Recv(InStream & stream) : cbFieldData([&stream](){ const unsigned expected = 4; // cbFieldData(4) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "Truncated Logon Info Field (data): expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } return stream.in_uint32_le(); }()) , payload(stream.get_current(), stream.in_remain()) { stream.in_skip_bytes(this->payload.get_capacity()); }
void recv(InStream & stream, uint16_t len) override { this->len = len; /* pad1(4) + pad2(4) + pad3(4) + pad4(4) + pad5(4) + pad6(4) + cache0Entries(2) + cache0MaximumCellSize(2) + * cache1Entries(2) + cache1MaximumCellSize(2) + cache2Entries(2) + cache2MaximumCellSize(2) */ const unsigned expected = 36; if (!stream.in_check_rem(expected)){ LOG(LOG_ERR, "Truncated BmpCacheCaps, need=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_MCS_PDU_TRUNCATED); } this->pad1 = stream.in_uint32_le(); this->pad2 = stream.in_uint32_le(); this->pad3 = stream.in_uint32_le(); this->pad4 = stream.in_uint32_le(); this->pad5 = stream.in_uint32_le(); this->pad6 = stream.in_uint32_le(); this->cache0Entries = stream.in_uint16_le(); this->cache0MaximumCellSize = stream.in_uint16_le(); this->cache1Entries = stream.in_uint16_le(); this->cache1MaximumCellSize = stream.in_uint16_le(); this->cache2Entries = stream.in_uint16_le(); this->cache2MaximumCellSize = stream.in_uint16_le(); }
explicit LogonErrorsInfo_Recv(InStream & stream) : ErrorNotificationData(0), ErrorNotificationType(0) { const unsigned expected = 4 + // ErrorNotificationData(4) 4; // ErrorNotificationType(4) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "Truncated Logon Info Field (data): expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } this->ErrorNotificationType = stream.in_uint32_le(); this->ErrorNotificationData = stream.in_uint32_le(); if ((this->ErrorNotificationType != LOGON_MSG_SESSION_CONTINUE) || (this->ErrorNotificationData != LOGON_FAILED_OTHER)) { LOG(LOG_INFO, "ErrorNotificationType=%s(0x%08X) \"%s\" ErrorNotificationData=%s(0x%08X) \"%s\"", ErrorNotificationTypeToString(this->ErrorNotificationType), this->ErrorNotificationType, ErrorNotificationTypeToMessage(this->ErrorNotificationType), ErrorNotificationDataToString(this->ErrorNotificationData), this->ErrorNotificationData, ErrorNotificationDataToMessage(this->ErrorNotificationData)); } }
void recv(InStream & stream, uint16_t len) override { this->len = len; /* terminalDescriptor(16) + pad4octetsA(4) + desktopSaveXGranularity(2) + desktopSaveYGranularity(2) + * pad2octetsA(2) + maximumOrderLevel(2) + numberFonts(2) + orderFlags(2) + orderSupport(NB_ORDER_SUPPORT) + * textFlags(2) + orderSupportExFlags(2) + pad4octetsB(4) + desktopSaveSize(4) + pad2octetsC(2) + * pad2octetsD(2) + textANSICodePage(2) + pad2octetsE(2) */ const unsigned expected = 32 + NB_ORDER_SUPPORT + 20; if (!stream.in_check_rem(expected)){ LOG(LOG_ERR, "Truncated OrderCaps, need=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_MCS_PDU_TRUNCATED); } stream.in_copy_bytes(this->terminalDescriptor, 16); this->pad4octetsA = stream.in_uint32_le(); this->desktopSaveXGranularity = stream.in_uint16_le(); this->desktopSaveYGranularity = stream.in_uint16_le(); this->pad2octetsA = stream.in_uint16_le(); this->maximumOrderLevel = stream.in_uint16_le(); this->numberFonts = stream.in_uint16_le(); this->orderFlags = stream.in_uint16_le(); stream.in_copy_bytes(this->orderSupport, NB_ORDER_SUPPORT); this->textFlags = stream.in_uint16_le(); this->orderSupportExFlags = stream.in_uint16_le(); this->pad4octetsB = stream.in_uint32_le(); this->desktopSaveSize = stream.in_uint32_le(); this->pad2octetsC = stream.in_uint16_le(); this->pad2octetsD = stream.in_uint16_le(); this->textANSICodePage = stream.in_uint16_le(); this->pad2octetsE = stream.in_uint16_le(); }
explicit ClientInputEventPDU_Recv(InStream & stream) : numEvents( [&stream](){ if (!stream.in_check_rem(2)) { LOG(LOG_ERR, "SlowPath::ClientInputEventPDU: data truncated (numEvents)"); throw Error(ERR_RDP_SLOWPATH); } auto numEvents = stream.in_uint16_le(); const unsigned expected = 2 // pad(2) + numEvents * 12 // (time(4) + mes_type(2) + device_flags(2) + param1(2) + param2(2)) * 12 ; if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "SlowPath::ClientInputEventPDU: data truncated, expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_SLOWPATH); } stream.in_skip_bytes(2); // pad return numEvents; }() ) // (time(4) + mes_type(2) + device_flags(2) + param1(2) + param2(2)) * 12 , payload(stream.get_current(), this->numEvents * 12) { // This is the constructor body, we skip payload now that it is packaged stream.in_skip_bytes(this->payload.get_capacity()); }
explicit ShareControl_Recv(InStream & stream) : totalLength([&stream]() { if (!stream.in_check_rem(2+2)){ LOG(LOG_ERR, "Truncated [4: ShareControl packet] , remains=%zu", stream.in_remain()); throw Error(ERR_SEC); } return stream.in_uint16_le(); }()) , pduType(stream.in_uint16_le() & 0xF) , PDUSource([&stream, this]() { if (this->pduType == PDUTYPE_DEACTIVATEALLPDU && this->totalLength == 4) { // should not happen // but DEACTIVATEALLPDU seems to be broken on windows 2000 return static_cast<uint16_t>(0); } return stream.in_uint16_le(); }()) , payload([&stream, this]() { if (this->pduType == PDUTYPE_DEACTIVATEALLPDU && this->totalLength == 4) { // should not happen // but DEACTIVATEALLPDU seems to be broken on windows 2000 return InStream(stream.get_current(), 0); } if (this->totalLength < 6) { LOG(LOG_ERR, "ShareControl packet too short totalLength=%u pduType=%u mcs_channel=%u", this->totalLength, this->pduType, this->PDUSource); throw Error(ERR_SEC); } if (!stream.in_check_rem(this->totalLength - 6)) { LOG(LOG_ERR, "Truncated ShareControl packet, need=%u remains=%zu", this->totalLength - 6, stream.in_remain()); throw Error(ERR_SEC); } return InStream(stream.get_current(), this->totalLength - 6); }()) // body of constructor { if (this->totalLength == 0x8000) { LOG(LOG_ERR, "Expected ShareControl header, got flowMarker"); throw Error(ERR_SEC); } stream.in_skip_bytes(this->payload.get_capacity()); }
~ShareData_Recv() noexcept(false) { if (!this->payload.check_end()) { LOG( LOG_INFO , "~ShareData_Recv: some payload data were not consumed len=%u compressedLen=%u remains=%zu" , this->len, this->compressedLen, payload.in_remain()); throw Error(ERR_SEC); } }
void receive(InStream & stream) { unsigned expected = 18; /* destLeft(2) + destTop(2) + destRight(2) + destBottom(2) + width(2) + height(2) + bitsPerPixel(2) + flags(2) + bitmapLength(2) */ if (!stream.in_check_rem(expected)) { LOG( LOG_ERR , "BitmapData::receive TS_BITMAP_DATA - Truncated data, need=%u, remains=%zu" , expected, stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } this->dest_left = stream.in_uint16_le(); this->dest_top = stream.in_uint16_le(); this->dest_right = stream.in_uint16_le(); this->dest_bottom = stream.in_uint16_le(); this->width = stream.in_uint16_le(); this->height = stream.in_uint16_le(); this->bits_per_pixel = stream.in_uint16_le(); this->flags = stream.in_uint16_le(); this->bitmap_length = stream.in_uint16_le(); assert( (this->bits_per_pixel == 32) || (this->bits_per_pixel == 24) || (this->bits_per_pixel == 16) || (this->bits_per_pixel == 15) || (this->bits_per_pixel == 8 )); if ( (this->flags & BITMAP_COMPRESSION) && !(this->flags & NO_BITMAP_COMPRESSION_HDR)) { expected = 8; /* cbCompFirstRowSize(2) + cbCompMainBodySize(2) + cbScanWidth(2) + cbUncompressedSize(2) */ if (!stream.in_check_rem(expected)) { LOG( LOG_ERR , "BitmapData::receive TS_CD_HEADER - Truncated data, need=18, remains=%zu" , stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } stream.in_skip_bytes(2); /* cbCompFirstRowSize (2 bytes) */ this->cb_comp_main_body_size = stream.in_uint16_le(); this->cb_scan_width = stream.in_uint16_le(); this->cb_uncompressed_size = stream.in_uint16_le(); } }
explicit UnusedEvent_Recv(InStream & stream) { const unsigned expected = 6; // pad4Octets(4) + pad2Octets(2) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "SlowPath::UnusedEvent: data truncated, expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_SLOWPATH); } stream.in_skip_bytes(6); // pad4Octets(4) + pad2Octets(2) }
void recv(InStream & stream, uint16_t len)override { this->len = len; if (!stream.in_check_rem(2)) { LOG(LOG_ERR, "Truncated CompDeskCaps, need=2 remains=%zu", stream.in_remain()); throw Error(ERR_MCS_PDU_TRUNCATED); } this->CompDeskSupportLevel = stream.in_uint16_le(); }
void recv(InStream & stream, uint16_t len)override { this->len = len; if (!stream.in_check_rem(4)){ LOG(LOG_ERR, "Truncated BrushCacheCaps, need=4 remains=%zu", stream.in_remain()); throw Error(ERR_MCS_PDU_TRUNCATED); } this->brushSupportLevel = stream.in_uint32_le(); }
explicit PlainNotify_Recv(InStream & stream) { memset(Pad, 0, sizeof(Pad)); const unsigned expected = 576; // Pad(576) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "Truncated Plain Notify (data): expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_DATA_TRUNCATED); } stream.in_copy_bytes(this->Pad, sizeof(this->Pad)); }
explicit SynchronizeEvent_Recv(InStream & stream) : toggleFlags(0) { const unsigned expected = 6; // pad2Octets(2) + toggleFlags(2) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "SlowPath::SynchronizeEvent: data truncated, expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_SLOWPATH); } stream.in_skip_bytes(2); // pad2Octets this->toggleFlags = stream.in_uint32_le(); }
explicit CheckShareData_Recv(const InStream & stream) { // share_id(4) // + ignored(1) // + streamid(1) // + len(2) // + pdutype2(1) // + compressedType(1) // + compressedLen(2) const unsigned expected = 12; if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "sdata packet len too short: need %u, remains=%zu", expected, stream.in_remain()); throw Error(ERR_SEC); } }
void recv(InStream & stream, uint16_t len)override { this->len = len; unsigned int expected = 2 + 2 + ((this->len < 10) ? 0 : 2); /* colorPointerFlag(2) + colorPointerCacheSize(2) + pointerCacheSize*/ if (!stream.in_check_rem(expected)){ LOG(LOG_ERR, "Truncated CAPSTYPE_POINTER, need=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_MCS_PDU_TRUNCATED); } this->colorPointerFlag = stream.in_uint16_le(); this->colorPointerCacheSize = stream.in_uint16_le(); if (this->len < 10) return; this->pointerCacheSize = stream.in_uint16_le(); }
explicit UnicodeKeyboardEvent_Recv(InStream & stream) : keyboardFlags(0) , unicodeCode(0) { const unsigned expected = 6; // keyboardFlags(2) + unicodeCode(2) + pad2Octets(2) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "SlowPath::UnicodeKeyboardEvent: data truncated, expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_SLOWPATH); } this->keyboardFlags = stream.in_uint16_le(); this->unicodeCode = stream.in_uint16_le(); stream.in_skip_bytes(2); // pad2Octets }
explicit ExtendedMouseEvent_Recv(InStream & stream) : pointerFlags(0) , xPos(0) , yPos(0) { const unsigned expected = 6; // pointerFlags(2) + xPos(2) + yPos(2) if (!stream.in_check_rem(expected)) { LOG(LOG_ERR, "SlowPath::ExtendedMouseEvent: data truncated, expected=%u remains=%zu", expected, stream.in_remain()); throw Error(ERR_RDP_SLOWPATH); } this->pointerFlags = stream.in_uint16_le(); this->xPos = stream.in_uint16_le(); this->yPos = stream.in_uint16_le(); }
void recv(InStream & stream, uint16_t len)override { this->len = len; if (len != CAPLEN_BITMAPCACHE_REV2 || !stream.in_check_rem(len)) { LOG(LOG_ERR, "Broken CAPSTYPE_BITMAPCACHE_REV2, need=%u (%" PRIu16 ") remains=%zu", CAPLEN_BITMAPCACHE_REV2, len, stream.in_remain()); throw Error(ERR_MCS_PDU_TRUNCATED); } this->cacheFlags = stream.in_uint16_le(); this->pad1 = stream.in_uint8(); this->numCellCaches = stream.in_uint8(); this->bitmapCache0CellInfo = stream.in_uint32_le(); this->bitmapCache1CellInfo = stream.in_uint32_le(); this->bitmapCache2CellInfo = stream.in_uint32_le(); this->bitmapCache3CellInfo = stream.in_uint32_le(); this->bitmapCache4CellInfo = stream.in_uint32_le(); stream.in_skip_bytes(12); }
void do_recv(char ** pbuffer, size_t len) override { size_t total_len = 0; while (total_len < len){ size_t remaining = in_stream.in_remain(); if (remaining >= (len - total_len)){ in_stream.in_copy_bytes(*pbuffer + total_len, len - total_len); *pbuffer += len; return; } in_stream.in_copy_bytes(*pbuffer + total_len, remaining); total_len += remaining; switch (this->chunk_type){ case PARTIAL_IMAGE_CHUNK: { const size_t header_sz = 8; char header_buf[header_sz]; InStream header(header_buf); auto * p = header_buf; this->trans->recv(&p, header_sz); this->chunk_type = header.in_uint16_le(); this->chunk_size = header.in_uint32_le(); this->chunk_count = header.in_uint16_le(); this->in_stream = InStream(this->buf, this->chunk_size - 8); p = this->buf; this->trans->recv(&p, this->chunk_size - 8); } break; case LAST_IMAGE_CHUNK: LOG(LOG_ERR, "Failed to read embedded image from WRM (transport closed)"); throw Error(ERR_TRANSPORT_NO_MORE_DATA); default: LOG(LOG_ERR, "Failed to read embedded image from WRM"); throw Error(ERR_TRANSPORT_READ_FAILED); } } }
void ClientRDPSNDChannel::receive(InStream & chunk) { if (this->wave_data_to_wait) { this->wave_data_to_wait -= chunk.in_remain(); if (this->wave_data_to_wait < 0) { this->wave_data_to_wait = 0; } if (this->last_PDU_is_WaveInfo) { chunk.in_skip_bytes(4); this->last_PDU_is_WaveInfo = false; } if (this->impl_sound) { this->impl_sound->setData(chunk.get_current(), chunk.in_remain()); } if (!(this->wave_data_to_wait)) { if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU"); } LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 1"); if (this->impl_sound) { LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 2"); uint8_t data[] = {'\0'}; LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 3"); this->impl_sound->setData(data, 1); LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 4"); this->impl_sound->play(); LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 5"); // LOG(LOG_INFO, "ClientRDPSNDChannel::receive play!!!"); } LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 6"); StaticOutStream<16> out_stream; rdpsnd::RDPSNDPDUHeader header(rdpsnd::SNDC_WAVECONFIRM, 4); header.emit(out_stream); LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 7"); rdpsnd::WaveConfirmPDU wc(this->last_wTimeStamp, this->last_cBlockNo); wc.emit(out_stream); InStream chunk_to_send(out_stream.get_bytes()); LOG(LOG_INFO, "SERVER >> RDPEA: Wave PDU 8"); this->callback->send_to_mod_channel( channel_names::rdpsnd , chunk_to_send , out_stream.get_offset() , this->channel_flags ); if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "CLIENT >> RDPEA: Wave Confirm PDU"); } } } else { rdpsnd::RDPSNDPDUHeader header; header.receive(chunk); switch (header.msgType) { case rdpsnd::SNDC_FORMATS: { if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "SERVER >> RDPEA: Server Audio Formats and Version PDU"); } rdpsnd::ServerAudioFormatsandVersionHeader safsvh; safsvh.receive(chunk); StaticOutStream<1024> out_stream; rdpsnd::RDPSNDPDUHeader header_out(rdpsnd::SNDC_FORMATS, 38); header_out.emit(out_stream); rdpsnd::ClientAudioFormatsandVersionHeader cafvh( this->dwFlags , this->dwVolume , this->dwPitch , this->wDGramPort , this->wNumberOfFormats , this->wVersion ); cafvh.emit(out_stream); for (uint16_t i = 0; i < safsvh.wNumberOfFormats; i++) { rdpsnd::AudioFormat format; format.receive(chunk); // format.log(); if (format.wFormatTag == rdpsnd::WAVE_FORMAT_PCM) { format.emit(out_stream); if (this->impl_sound) { this->impl_sound->n_sample_per_sec = format.nSamplesPerSec; this->impl_sound->bit_per_sample = format.wBitsPerSample; this->impl_sound->n_channels = format.nChannels; this->impl_sound->n_block_align = format.nBlockAlign; this->impl_sound->bit_per_sec = format.nSamplesPerSec * (format.wBitsPerSample/8) * format.nChannels; } else { //LOG(LOG_WARNING, "No Sound System module found"); } } } InStream chunk_to_send(out_stream.get_bytes()); this->callback->send_to_mod_channel( channel_names::rdpsnd , chunk_to_send , out_stream.get_offset() , this->channel_flags ); if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "CLIENT >> RDPEA: Client Audio Formats and Version PDU"); } StaticOutStream<32> quality_stream; rdpsnd::RDPSNDPDUHeader header_quality(rdpsnd::SNDC_QUALITYMODE, 8); header_quality.emit(quality_stream); rdpsnd::QualityModePDU qm(rdpsnd::HIGH_QUALITY); qm.emit(quality_stream); InStream chunk_to_send2(quality_stream.get_bytes()); this->callback->send_to_mod_channel( channel_names::rdpsnd , chunk_to_send2 , quality_stream.get_offset() , this->channel_flags ); if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "CLIENT >> RDPEA: Quality Mode PDU"); } } break; case rdpsnd::SNDC_TRAINING: { if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "SERVER >> RDPEA: Training PDU"); } rdpsnd::TrainingPDU train; train.receive(chunk); StaticOutStream<32> out_stream; rdpsnd::RDPSNDPDUHeader header_quality(rdpsnd::SNDC_TRAINING, 4); header_quality.emit(out_stream); rdpsnd::TrainingConfirmPDU train_conf(train.wTimeStamp, train.wPackSize); train_conf.emit(out_stream); InStream chunk_to_send(out_stream.get_bytes()); this->callback->send_to_mod_channel( channel_names::rdpsnd , chunk_to_send , out_stream.get_offset() , this->channel_flags ); if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "CLIENT >> RDPEA: Training Confirm PDU"); } } break; case rdpsnd::SNDC_WAVE: { if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "SERVER >> RDPEA: Wave Info PDU"); } this->wave_data_to_wait = header.BodySize - 8; rdpsnd::WaveInfoPDU wi; wi.receive(chunk); this->last_cBlockNo = wi.cBlockNo; this->last_wTimeStamp = wi.wTimeStamp; if (this->impl_sound) { this->impl_sound->init(header.BodySize - 12); this->impl_sound->setData(wi.Data, 4); } this->last_PDU_is_WaveInfo = true; } break; case rdpsnd::SNDC_CLOSE: if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "SERVER >> RDPEA: Close PDU"); } break; case rdpsnd::SNDC_SETVOLUME: if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "SERVER >> RDPEA: SNDC_SETVOLUME PDU"); } { rdpsnd::VolumePDU v; v.receive(chunk); } break; case rdpsnd::SNDC_SETPITCH: if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "SERVER >> RDPEA: SNDC_SETPITCH PDU"); } { rdpsnd::PitchPDU p; p.receive(chunk); } break; // case rdpsnd::SNDC_CRYPTKEY: // LOG(LOG_INFO, "SERVER >> RDPEA: SNDC_CRYPTKEY PDU"); // break; // case rdpsnd::SNDC_WAVEENCRYPT: // LOG(LOG_INFO, "SERVER >> RDPEA: SNDC_WAVEENCRYPT PDU"); // break; case rdpsnd::SNDC_QUALITYMODE: if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "SERVER >> RDPEA: SNDC_QUALITYMODE PDU"); } { rdpsnd::QualityModePDU qm; qm.receive(chunk); } break; case rdpsnd::SNDC_WAVE2: if (bool(this->verbose & RDPVerbose::rdpsnd)) { LOG(LOG_INFO, "SERVER >> RDPEA: SNDC_WAVE2 PDU"); } { this->wave_data_to_wait = header.BodySize - 12; rdpsnd::Wave2PDU w2; w2.receive(chunk); if (this->impl_sound) { this->impl_sound->init(header.BodySize - 12); this->impl_sound->setData(chunk.get_current(), chunk.in_remain()); } this->last_PDU_is_WaveInfo = true; } break; default: LOG(LOG_WARNING, "SERVER >> RDPEA: Unknown message type: %x", header.msgType); break; } } }
explicit InputEvent_Recv(InStream & stream) : eventTime([&stream](){ // time(4) + mes_type(2) + device_flags(2) + param1(2) + param2(2) if (!stream.in_check_rem(12)) { LOG(LOG_ERR, "SlowPath::InputEvent: data truncated, expected=12 remains=%zu", stream.in_remain()); throw Error(ERR_RDP_SLOWPATH); } return stream.in_uint32_le(); }()) , messageType(stream.in_uint16_le()) // device_flags(2) + param1(2) + param2(2) , payload(stream.get_current(), 6) // Body of constructor { stream.in_skip_bytes(this->payload.get_capacity()); }