BOOL rts_send_ping_pdu(rdpRpc* rpc) { STREAM* s; RTS_PDU_HEADER header; header.rpc_vers = 5; header.rpc_vers_minor = 0; header.ptype = PTYPE_RTS; header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; header.packed_drep[0] = 0x10; header.packed_drep[1] = 0x00; header.packed_drep[2] = 0x00; header.packed_drep[3] = 0x00; header.frag_length = 20; header.auth_length = 0; header.call_id = 0; header.flags = 1; header.numberOfCommands = 0; DEBUG_RPC("Sending Ping RTS PDU"); s = stream_new(header.frag_length); rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */ stream_seal(s); rpc_in_write(rpc, s->data, s->size); stream_free(s); return TRUE; }
boolean rts_send_keep_alive_pdu(rdpRpc* rpc) { STREAM* s; RTS_PDU_HEADER header; header.rpc_vers = 5; header.rpc_vers_minor = 0; header.ptype = PTYPE_RTS; header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; header.packed_drep[0] = 0x10; header.packed_drep[1] = 0x00; header.packed_drep[2] = 0x00; header.packed_drep[3] = 0x00; header.frag_length = 28; header.auth_length = 0; header.call_id = 0; header.flags = 2; header.numberOfCommands = 1; DEBUG_RPC("Sending Keep-Alive RTS PDU"); s = stream_new(header.frag_length); rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */ rts_client_keepalive_command_write(s, 0x00007530); /* ClientKeepalive (8 bytes) */ stream_seal(s); rpc_in_write(rpc, s->data, s->size); stream_free(s); return true; }
STREAM* http_request_write(HttpContext* http_context, HttpRequest* http_request) { int i; STREAM* s; int length = 0; http_request->count = 9; http_request->lines = (char**) xmalloc(sizeof(char*) * http_request->count); http_encode_line(http_request->lines[0], "%s %s HTTP/1.1", http_request->Method, http_request->URI); http_encode_line(http_request->lines[1], "Cache-Control: %s", http_context->CacheControl); http_encode_line(http_request->lines[2], "Connection: %s", http_context->Connection); http_encode_line(http_request->lines[3], "Pragma: %s", http_context->Pragma); http_encode_line(http_request->lines[4], "Accept: %s", http_context->Accept); http_encode_line(http_request->lines[5], "User-Agent: %s", http_context->UserAgent); http_encode_line(http_request->lines[6], "Content-Length: %d", http_request->ContentLength); http_encode_line(http_request->lines[7], "Host: %s", http_context->Host); if (http_request->Authorization != NULL) { http_encode_line(http_request->lines[8], "Authorization: %s", http_request->Authorization); } else if ((http_request->AuthScheme != NULL) && (http_request->AuthParam != NULL)) { http_encode_line(http_request->lines[8], "Authorization: %s %s", http_request->AuthScheme, http_request->AuthParam); } for (i = 0; i < http_request->count; i++) { length += (strlen(http_request->lines[i]) + 1); /* add +1 for each '\n' character */ } length += 1; /* empty line "\n" at end of header */ length += 1; /* null terminator */ s = stream_new(length); for (i = 0; i < http_request->count; i++) { stream_write(s, http_request->lines[i], strlen(http_request->lines[i])); stream_write(s, "\n", 1); xfree(http_request->lines[i]); } stream_write(s, "\n", 1); xfree(http_request->lines); stream_write(s, "\0", 1); /* append null terminator */ stream_rewind(s, 1); /* don't include null terminator in length */ stream_seal(s); return s; }
BOOL rts_send_CONN_B1_pdu(rdpRpc* rpc) { STREAM* s; RTS_PDU_HEADER header; BYTE* INChannelCookie; BYTE* AssociationGroupId; BYTE* VirtualConnectionCookie; header.rpc_vers = 5; header.rpc_vers_minor = 0; header.ptype = PTYPE_RTS; header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; header.packed_drep[0] = 0x10; header.packed_drep[1] = 0x00; header.packed_drep[2] = 0x00; header.packed_drep[3] = 0x00; header.frag_length = 104; header.auth_length = 0; header.call_id = 0; header.flags = 0; header.numberOfCommands = 6; DEBUG_RPC("Sending CONN_B1 RTS PDU"); s = stream_new(header.frag_length); rpc_generate_cookie((BYTE*) &(rpc->VirtualConnection->DefaultInChannelCookie)); rpc_generate_cookie((BYTE*) &(rpc->VirtualConnection->AssociationGroupId)); VirtualConnectionCookie = (BYTE*) &(rpc->VirtualConnection->Cookie); INChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultInChannelCookie); AssociationGroupId = (BYTE*) &(rpc->VirtualConnection->AssociationGroupId); rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */ rts_version_command_write(s); /* Version (8 bytes) */ rts_cookie_command_write(s, VirtualConnectionCookie); /* VirtualConnectionCookie (20 bytes) */ rts_cookie_command_write(s, INChannelCookie); /* INChannelCookie (20 bytes) */ rts_channel_lifetime_command_write(s, 0x40000000); /* ChannelLifetime (8 bytes) */ rts_client_keepalive_command_write(s, 0x000493E0); /* ClientKeepalive (8 bytes) */ rts_association_group_id_command_write(s, AssociationGroupId); /* AssociationGroupId (20 bytes) */ stream_seal(s); rpc_in_write(rpc, s->data, s->size); stream_free(s); return TRUE; }
BOOL rts_send_CONN_A1_pdu(rdpRpc* rpc) { STREAM* s; RTS_PDU_HEADER header; UINT32 ReceiveWindowSize; BYTE* OUTChannelCookie; BYTE* VirtualConnectionCookie; header.rpc_vers = 5; header.rpc_vers_minor = 0; header.ptype = PTYPE_RTS; header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; header.packed_drep[0] = 0x10; header.packed_drep[1] = 0x00; header.packed_drep[2] = 0x00; header.packed_drep[3] = 0x00; header.frag_length = 76; header.auth_length = 0; header.call_id = 0; header.flags = 0; header.numberOfCommands = 4; DEBUG_RPC("Sending CONN_A1 RTS PDU"); s = stream_new(header.frag_length); rpc_generate_cookie((BYTE*) &(rpc->VirtualConnection->Cookie)); rpc_generate_cookie((BYTE*) &(rpc->VirtualConnection->DefaultOutChannelCookie)); VirtualConnectionCookie = (BYTE*) &(rpc->VirtualConnection->Cookie); OUTChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultOutChannelCookie); ReceiveWindowSize = rpc->VirtualConnection->DefaultOutChannel->ReceiveWindow; rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */ rts_version_command_write(s); /* Version (8 bytes) */ rts_cookie_command_write(s, VirtualConnectionCookie); /* VirtualConnectionCookie (20 bytes) */ rts_cookie_command_write(s, OUTChannelCookie); /* OUTChannelCookie (20 bytes) */ rts_receive_window_size_command_write(s, ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */ stream_seal(s); rpc_out_write(rpc, s->data, s->size); stream_free(s); return TRUE; }
void test_message(void) { RFX_CONTEXT* context; STREAM* s; int i, j; RFX_RECT rect = {0, 0, 100, 80}; RFX_MESSAGE * message; rgb_data = (BYTE *) malloc(100 * 80 * 3); for (i = 0; i < 80; i++) memcpy(rgb_data + i * 100 * 3, rgb_scanline_data, 100 * 3); s = stream_new(65536); stream_clear(s); context = rfx_context_new(); context->mode = RLGR3; context->width = 800; context->height = 600; rfx_context_set_pixel_format(context, RDP_PIXEL_FORMAT_R8G8B8); for (i = 0; i < 1000; i++) { s = stream_new(65536); stream_clear(s); rfx_compose_message(context, s, &rect, 1, rgb_data, 100, 80, 100 * 3); stream_seal(s); /*hexdump(buffer, size);*/ stream_set_pos(s, 0); message = rfx_process_message(context, s->p, s->size); if (i == 0) { for (j = 0; j < message->num_tiles; j++) { dump_ppm_image(message->tiles[j]->data); } } rfx_message_free(context, message); stream_free(s); } rfx_context_free(context); free(rgb_data); }
BOOL rts_send_flow_control_ack_pdu(rdpRpc* rpc) { STREAM* s; RTS_PDU_HEADER header; UINT32 BytesReceived; UINT32 AvailableWindow; BYTE* ChannelCookie; header.rpc_vers = 5; header.rpc_vers_minor = 0; header.ptype = PTYPE_RTS; header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; header.packed_drep[0] = 0x10; header.packed_drep[1] = 0x00; header.packed_drep[2] = 0x00; header.packed_drep[3] = 0x00; header.frag_length = 56; header.auth_length = 0; header.call_id = 0; header.flags = 2; header.numberOfCommands = 2; DEBUG_RPC("Sending FlowControlAck RTS PDU"); BytesReceived = rpc->VirtualConnection->DefaultOutChannel->BytesReceived; AvailableWindow = rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow; ChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultOutChannelCookie); s = stream_new(header.frag_length); rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */ rts_destination_command_write(s, FDOutProxy); /* Destination Command (8 bytes) */ /* FlowControlAck Command (28 bytes) */ rts_flow_control_ack_command_write(s, BytesReceived, AvailableWindow, ChannelCookie); stream_seal(s); rpc_in_write(rpc, s->data, s->size); stream_free(s); return TRUE; }
int transport_check_fds(rdpTransport* transport) { int pos; int status; uint16 length; STREAM* received; wait_obj_clear(transport->recv_event); status = transport_read_nonblocking(transport); if (status < 0) return status; while ((pos = stream_get_pos(transport->recv_buffer)) > 0) { stream_set_pos(transport->recv_buffer, 0); if (tpkt_verify_header(transport->recv_buffer)) /* TPKT */ { /* Ensure the TPKT header is available. */ if (pos <= 4) { stream_set_pos(transport->recv_buffer, pos); return 0; } length = tpkt_read_header(transport->recv_buffer); } else /* Fast Path */ { /* Ensure the Fast Path header is available. */ if (pos <= 2) { stream_set_pos(transport->recv_buffer, pos); return 0; } length = fastpath_read_header(NULL, transport->recv_buffer); } if (length == 0) { printf("transport_check_fds: protocol error, not a TPKT or Fast Path header.\n"); freerdp_hexdump(stream_get_head(transport->recv_buffer), pos); return -1; } if (pos < length) { stream_set_pos(transport->recv_buffer, pos); return 0; /* Packet is not yet completely received. */ } /* * A complete packet has been received. In case there are trailing data * for the next packet, we copy it to the new receive buffer. */ received = transport->recv_buffer; transport->recv_buffer = stream_new(BUFFER_SIZE); if (pos > length) { stream_set_pos(received, length); stream_check_size(transport->recv_buffer, pos - length); stream_copy(transport->recv_buffer, received, pos - length); } stream_set_pos(received, length); stream_seal(received); stream_set_pos(received, 0); if (transport->recv_callback(transport, received, transport->recv_extra) == False) status = -1; stream_free(received); if (status < 0) return status; } return 0; }
boolean rpc_send_bind_pdu(rdpRpc* rpc) { STREAM* pdu; rpcconn_bind_hdr_t* bind_pdu; rdpSettings* settings = rpc->settings; STREAM* ntlm_stream = stream_new(0xFFFF); rpc->ntlm = ntlm_new(); DEBUG_RPC("Sending bind PDU"); ntlm_client_init(rpc->ntlm, false, settings->username, settings->domain, settings->password); ntlm_authenticate(rpc->ntlm); ntlm_stream->size = rpc->ntlm->outputBuffer.cbBuffer; ntlm_stream->p = ntlm_stream->data = rpc->ntlm->outputBuffer.pvBuffer; bind_pdu = xnew(rpcconn_bind_hdr_t); bind_pdu->rpc_vers = 5; bind_pdu->rpc_vers_minor = 0; bind_pdu->PTYPE = PTYPE_BIND; bind_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_PENDING_CANCEL | PFC_CONC_MPX; bind_pdu->packed_drep[0] = 0x10; bind_pdu->packed_drep[1] = 0x00; bind_pdu->packed_drep[2] = 0x00; bind_pdu->packed_drep[3] = 0x00; bind_pdu->frag_length = 124 + ntlm_stream->size; bind_pdu->auth_length = ntlm_stream->size; bind_pdu->call_id = 2; bind_pdu->max_xmit_frag = 0x0FF8; bind_pdu->max_recv_frag = 0x0FF8; bind_pdu->assoc_group_id = 0; bind_pdu->p_context_elem.n_context_elem = 2; bind_pdu->p_context_elem.reserved = 0; bind_pdu->p_context_elem.reserved2 = 0; bind_pdu->p_context_elem.p_cont_elem = xmalloc(sizeof(p_cont_elem_t) * bind_pdu->p_context_elem.n_context_elem); bind_pdu->p_context_elem.p_cont_elem[0].p_cont_id = 0; bind_pdu->p_context_elem.p_cont_elem[0].n_transfer_syn = 1; bind_pdu->p_context_elem.p_cont_elem[0].reserved = 0; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.time_low = 0x44e265dd; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.time_mid = 0x7daf; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.time_hi_and_version = 0x42cd; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.clock_seq_hi_and_reserved = 0x85; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.clock_seq_low = 0x60; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[0] = 0x3c; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[1] = 0xdb; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[2] = 0x6e; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[3] = 0x7a; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[4] = 0x27; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[5] = 0x29; bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_version = 0x00030001; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes = xmalloc(sizeof(p_syntax_id_t)); bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.time_low = 0x8a885d04; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.time_mid = 0x1ceb; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.time_hi_and_version = 0x11c9; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.clock_seq_hi_and_reserved = 0x9f; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.clock_seq_low = 0xe8; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[0] = 0x08; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[1] = 0x00; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[2] = 0x2b; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[3] = 0x10; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[4] = 0x48; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[5] = 0x60; bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_version = 0x00000002; bind_pdu->p_context_elem.p_cont_elem[1].p_cont_id = 1; bind_pdu->p_context_elem.p_cont_elem[1].n_transfer_syn = 1; bind_pdu->p_context_elem.p_cont_elem[1].reserved = 0; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.time_low = 0x44e265dd; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.time_mid = 0x7daf; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.time_hi_and_version = 0x42cd; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.clock_seq_hi_and_reserved = 0x85; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.clock_seq_low = 0x60; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[0] = 0x3c; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[1] = 0xdb; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[2] = 0x6e; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[3] = 0x7a; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[4] = 0x27; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[5] = 0x29; bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_version = 0x00030001; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes = xmalloc(sizeof(p_syntax_id_t)); bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.time_low = 0x6cb71c2c; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.time_mid = 0x9812; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.time_hi_and_version = 0x4540; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.clock_seq_hi_and_reserved = 0x03; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.clock_seq_low = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[0] = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[1] = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[2] = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[3] = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[4] = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[5] = 0x00; bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_version = 0x00000001; bind_pdu->auth_verifier.auth_pad = NULL; /* align(4); size_is(auth_pad_length) p*/ bind_pdu->auth_verifier.auth_type = 0x0a; /* :01 which authent service */ bind_pdu->auth_verifier.auth_level = 0x05; /* :01 which level within service */ bind_pdu->auth_verifier.auth_pad_length = 0x00; /* :01 */ bind_pdu->auth_verifier.auth_reserved = 0x00; /* :01 reserved, m.b.z. */ bind_pdu->auth_verifier.auth_context_id = 0x00000000; /* :04 */ bind_pdu->auth_verifier.auth_value = xmalloc(bind_pdu->auth_length); /* credentials; size_is(auth_length) p*/; memcpy(bind_pdu->auth_verifier.auth_value, ntlm_stream->data, bind_pdu->auth_length); stream_free(ntlm_stream); pdu = stream_new(bind_pdu->frag_length); stream_write(pdu, bind_pdu, 24); stream_write(pdu, &bind_pdu->p_context_elem, 4); stream_write(pdu, bind_pdu->p_context_elem.p_cont_elem, 24); stream_write(pdu, bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes, 20); stream_write(pdu, bind_pdu->p_context_elem.p_cont_elem + 1, 24); stream_write(pdu, bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes, 20); if (bind_pdu->auth_verifier.auth_pad_length > 0) stream_write(pdu, bind_pdu->auth_verifier.auth_pad, bind_pdu->auth_verifier.auth_pad_length); stream_write(pdu, &bind_pdu->auth_verifier.auth_type, 8); /* assumed that uint8 pointer is 32bit long (4 bytes) */ stream_write(pdu, bind_pdu->auth_verifier.auth_value, bind_pdu->auth_length); stream_seal(pdu); rpc_in_write(rpc, pdu->data, pdu->size); stream_free(pdu) ; xfree(bind_pdu); return true; }
static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL user_loggedon) { int i; int pos; BYTE c; UINT32 count; int data_len; int count_pos; STREAM* data_out; DEVICE* device; LIST_ITEM* item; data_out = stream_new(256); stream_write_UINT16(data_out, RDPDR_CTYP_CORE); stream_write_UINT16(data_out, PAKID_CORE_DEVICELIST_ANNOUNCE); count_pos = stream_get_pos(data_out); count = 0; stream_seek_UINT32(data_out); /* deviceCount */ for (item = rdpdr->devman->devices->head; item; item = item->next) { device = (DEVICE*) item->data; /** * 1. versionMinor 0x0005 doesn't send PAKID_CORE_USER_LOGGEDON * so all devices should be sent regardless of user_loggedon * 2. smartcard devices should be always sent * 3. other devices are sent only after user_loggedon */ if ((rdpdr->versionMinor == 0x0005) || (device->type == RDPDR_DTYP_SMARTCARD) || user_loggedon) { data_len = (device->data == NULL ? 0 : stream_get_length(device->data)); stream_check_size(data_out, 20 + data_len); stream_write_UINT32(data_out, device->type); /* deviceType */ stream_write_UINT32(data_out, device->id); /* deviceID */ strncpy((char*) stream_get_tail(data_out), device->name, 8); for (i = 0; i < 8; i++) { stream_peek_BYTE(data_out, c); if (c > 0x7F) stream_write_BYTE(data_out, '_'); else stream_seek_BYTE(data_out); } stream_write_UINT32(data_out, data_len); if (data_len > 0) stream_write(data_out, stream_get_data(device->data), data_len); count++; printf("registered device #%d: %s (type=%d id=%d)\n", count, device->name, device->type, device->id); } } pos = stream_get_pos(data_out); stream_set_pos(data_out, count_pos); stream_write_UINT32(data_out, count); stream_set_pos(data_out, pos); stream_seal(data_out); svc_plugin_send((rdpSvcPlugin*) rdpdr, data_out); }
int transport_check_fds(rdpTransport** ptransport) { int pos; int status; uint16 length; STREAM* received; rdpTransport* transport = *ptransport; wait_obj_clear(transport->recv_event); status = transport_read_nonblocking(transport); if (status < 0) return status; while ((pos = stream_get_pos(transport->recv_buffer)) > 0) { stream_set_pos(transport->recv_buffer, 0); if (tpkt_verify_header(transport->recv_buffer)) /* TPKT */ { /* Ensure the TPKT header is available. */ if (pos <= 4) { stream_set_pos(transport->recv_buffer, pos); return 0; } length = tpkt_read_header(transport->recv_buffer); } else /* Fast Path */ { /* Ensure the Fast Path header is available. */ if (pos <= 2) { stream_set_pos(transport->recv_buffer, pos); return 0; } /* Fastpath header can be two or three bytes long. */ length = fastpath_header_length(transport->recv_buffer); if (pos < length) { stream_set_pos(transport->recv_buffer, pos); return 0; } length = fastpath_read_header(NULL, transport->recv_buffer); } if (length == 0) { printf("transport_check_fds: protocol error, not a TPKT or Fast Path header.\n"); freerdp_hexdump(stream_get_head(transport->recv_buffer), pos); return -1; } if (pos < length) { stream_set_pos(transport->recv_buffer, pos); return 0; /* Packet is not yet completely received. */ } /* * A complete packet has been received. In case there are trailing data * for the next packet, we copy it to the new receive buffer. */ received = transport->recv_buffer; transport->recv_buffer = stream_new(BUFFER_SIZE); if (pos > length) { stream_set_pos(received, length); stream_check_size(transport->recv_buffer, pos - length); stream_copy(transport->recv_buffer, received, pos - length); } stream_set_pos(received, length); stream_seal(received); stream_set_pos(received, 0); if (transport->recv_callback(transport, received, transport->recv_extra) == false) status = -1; stream_free(received); if (status < 0) return status; /* transport might now have been freed by rdp_client_redirect and a new rdp->transport created */ transport = *ptransport; if (transport->process_single_pdu) { /* one at a time but set event if data buffered * so the main loop will call freerdp_check_fds asap */ if (stream_get_pos(transport->recv_buffer) > 0) wait_obj_set(transport->recv_event); break; } } return 0; }
int transport_check_fds(rdpTransport** ptransport) { int pos; int status; UINT16 length; int recv_status; STREAM* received; rdpTransport* transport = *ptransport; #ifdef _WIN32 WSAResetEvent(transport->TcpIn->wsa_event); #endif ResetEvent(transport->ReceiveEvent); status = transport_read_nonblocking(transport); if (status < 0) return status; while ((pos = stream_get_pos(transport->ReceiveBuffer)) > 0) { stream_set_pos(transport->ReceiveBuffer, 0); if (tpkt_verify_header(transport->ReceiveBuffer)) /* TPKT */ { /* Ensure the TPKT header is available. */ if (pos <= 4) { stream_set_pos(transport->ReceiveBuffer, pos); return 0; } length = tpkt_read_header(transport->ReceiveBuffer); } else if (nla_verify_header(transport->ReceiveBuffer)) { /* TSRequest */ /* Ensure the TSRequest header is available. */ if (pos <= 4) { stream_set_pos(transport->ReceiveBuffer, pos); return 0; } /* TSRequest header can be 2, 3 or 4 bytes long */ length = nla_header_length(transport->ReceiveBuffer); if (pos < length) { stream_set_pos(transport->ReceiveBuffer, pos); return 0; } length = nla_read_header(transport->ReceiveBuffer); } else /* Fast Path */ { /* Ensure the Fast Path header is available. */ if (pos <= 2) { stream_set_pos(transport->ReceiveBuffer, pos); return 0; } /* Fastpath header can be two or three bytes long. */ length = fastpath_header_length(transport->ReceiveBuffer); if (pos < length) { stream_set_pos(transport->ReceiveBuffer, pos); return 0; } length = fastpath_read_header(NULL, transport->ReceiveBuffer); } if (length == 0) { printf("transport_check_fds: protocol error, not a TPKT or Fast Path header.\n"); winpr_HexDump(stream_get_head(transport->ReceiveBuffer), pos); return -1; } if (pos < length) { stream_set_pos(transport->ReceiveBuffer, pos); return 0; /* Packet is not yet completely received. */ } received = transport->ReceiveBuffer; transport->ReceiveBuffer = transport_receive_pool_take(transport); stream_set_pos(received, length); stream_seal(received); stream_set_pos(received, 0); /** * ReceiveCallback return values: * * -1: synchronous failure * 0: synchronous success * 1: asynchronous return */ recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra); transport_receive_pool_return(transport, received); if (recv_status < 0) status = -1; if (status < 0) return status; /* transport might now have been freed by rdp_client_redirect and a new rdp->transport created */ transport = *ptransport; } return 0; }