int transport_write(rdpTransport* transport, STREAM* s) { int status = -1; int length; length = stream_get_length(s); stream_set_pos(s, 0); #ifdef WITH_DEBUG_TRANSPORT if (length > 0) { printf("Local > Remote\n"); winpr_HexDump(s->data, length); } #endif while (length > 0) { if (transport->layer == TRANSPORT_LAYER_TLS) status = tls_write(transport->TlsOut, stream_get_tail(s), length); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_write(transport->TcpOut, stream_get_tail(s), length); else if (transport->layer == TRANSPORT_LAYER_TSG) status = tsg_write(transport->tsg, stream_get_tail(s), length); if (status < 0) break; /* error occurred */ if (status == 0) { /* when sending is blocked in nonblocking mode, the receiving buffer should be checked */ if (!transport->blocking) { /* and in case we do have buffered some data, we set the event so next loop will get it */ if (transport_read_nonblocking(transport) > 0) SetEvent(transport->ReceiveEvent); } if (transport->layer == TRANSPORT_LAYER_TLS) tls_wait_write(transport->TlsOut); else if (transport->layer == TRANSPORT_LAYER_TCP) tcp_wait_write(transport->TcpOut); else USleep(transport->SleepInterval); } length -= status; stream_seek(s, status); } if (status < 0) { /* A write error indicates that the peer has dropped the connection */ transport->layer = TRANSPORT_LAYER_CLOSED; } return status; }
int transport_write(rdpTransport* transport, STREAM* s) { int status = -1; int length; int sent = 0; length = stream_get_length(s); stream_set_pos(s, 0); #ifdef WITH_DEBUG_TRANSPORT if (length > 0) { printf("Local > Remote\n"); freerdp_hexdump(s->data, length); } #endif while (sent < length) { if (transport->layer == TRANSPORT_LAYER_TLS) status = tls_write(transport->tls, stream_get_tail(s), length); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_write(transport->tcp, stream_get_tail(s), length); if (status < 0) break; /* error occurred */ if (status == 0) { /* blocking while sending */ freerdp_usleep(transport->usleep_interval); /* when sending is blocked in nonblocking mode, the receiving buffer should be checked */ if (!transport->blocking) { /* and in case we do have buffered some data, we set the event so next loop will get it */ if (transport_read_nonblocking(transport) > 0) wait_obj_set(transport->recv_event); } } sent += status; stream_seek(s, status); } if (status < 0) { /* A write error indicates that the peer has dropped the connection */ transport->layer = TRANSPORT_LAYER_CLOSED; } return status; }
int transport_write(rdpTransport* transport, STREAM* s) { int status = -1; int length; int sent = 0; length = stream_get_length(s); stream_set_pos(s, 0); #ifdef WITH_DEBUG_TRANSPORT if (length > 0) { printf("Client > Server\n"); freerdp_hexdump(s->data, length); } #endif while (sent < length) { if (transport->layer == TRANSPORT_LAYER_TLS) status = tls_write(transport->tls, stream_get_tail(s), length); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_write(transport->tcp, stream_get_tail(s), length); if (status < 0) break; /* error occurred */ if (status == 0) { /* blocking while sending */ nanosleep(&transport->ts, NULL); /* when sending is blocked in nonblocking mode, the receiving buffer should be checked */ if (!transport->blocking) transport_read_nonblocking(transport); } sent += status; stream_seek(s, status); } if (!transport->blocking) transport_check_fds(transport); return status; }
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; }
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; }
int transport_check_fds(rdpTransport* transport) { int pos; int status; UINT16 length; int recv_status; wStream* received; if (!transport) return -1; #ifdef _WIN32 WSAResetEvent(transport->TcpIn->wsa_event); #endif ResetEvent(transport->ReceiveEvent); status = transport_read_nonblocking(transport); if (status < 0) return status; while ((pos = Stream_GetPosition(transport->ReceiveBuffer)) > 0) { Stream_SetPosition(transport->ReceiveBuffer, 0); if (tpkt_verify_header(transport->ReceiveBuffer)) /* TPKT */ { /* Ensure the TPKT header is available. */ if (pos <= 4) { Stream_SetPosition(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_SetPosition(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_SetPosition(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_SetPosition(transport->ReceiveBuffer, pos); return 0; } /* Fastpath header can be two or three bytes long. */ length = fastpath_header_length(transport->ReceiveBuffer); if (pos < length) { Stream_SetPosition(transport->ReceiveBuffer, pos); return 0; } length = fastpath_read_header(NULL, transport->ReceiveBuffer); } if (length == 0) { fprintf(stderr, "transport_check_fds: protocol error, not a TPKT or Fast Path header.\n"); winpr_HexDump(Stream_Buffer(transport->ReceiveBuffer), pos); return -1; } if (pos < length) { Stream_SetPosition(transport->ReceiveBuffer, pos); return 0; /* Packet is not yet completely received. */ } received = transport->ReceiveBuffer; transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0); Stream_SetPosition(received, length); Stream_SealLength(received); Stream_SetPosition(received, 0); /** * status: * -1: error * 0: success * 1: redirection */ recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra); if (recv_status == 1) { /** * Last call to ReceiveCallback resulted in a session redirection, * which means the current rdpTransport* transport pointer has been freed. * Return 0 for success, the rest of this function is meant for non-redirected cases. */ return 0; } Stream_Release(received); if (recv_status < 0) status = -1; if (status < 0) return status; } return 0; }
int transport_write(rdpTransport* transport, wStream* s) { int length; int status = -1; WaitForSingleObject(transport->WriteMutex, INFINITE); length = Stream_GetPosition(s); Stream_SetPosition(s, 0); #ifdef WITH_DEBUG_TRANSPORT if (length > 0) { fprintf(stderr, "Local > Remote\n"); winpr_HexDump(Stream_Buffer(s), length); } #endif if (length > 0) { WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND); } while (length > 0) { if (transport->layer == TRANSPORT_LAYER_TLS) status = tls_write(transport->TlsOut, Stream_Pointer(s), length); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_write(transport->TcpOut, Stream_Pointer(s), length); else if (transport->layer == TRANSPORT_LAYER_TSG) status = tsg_write(transport->tsg, Stream_Pointer(s), length); else if (transport->layer == TRANSPORT_LAYER_TSG_TLS) status = tls_write(transport->TsgTls, Stream_Pointer(s), length); if (status < 0) break; /* error occurred */ if (status == 0) { /* when sending is blocked in nonblocking mode, the receiving buffer should be checked */ if (!transport->blocking) { /* and in case we do have buffered some data, we set the event so next loop will get it */ if (transport_read_nonblocking(transport) > 0) SetEvent(transport->ReceiveEvent); } if (transport->layer == TRANSPORT_LAYER_TLS) tls_wait_write(transport->TlsOut); else if (transport->layer == TRANSPORT_LAYER_TCP) tcp_wait_write(transport->TcpOut); else if (transport->layer == TRANSPORT_LAYER_TSG_TLS) tls_wait_write(transport->TsgTls); else USleep(transport->SleepInterval); } length -= status; Stream_Seek(s, status); } if (status < 0) { /* A write error indicates that the peer has dropped the connection */ transport->layer = TRANSPORT_LAYER_CLOSED; } if (s->pool) Stream_Release(s); ReleaseMutex(transport->WriteMutex); return status; }
int transport_check_fds(rdpTransport** ptransport) { int pos; int status; UINT16 length; int recv_status; wStream* 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_GetPosition(transport->ReceiveBuffer)) > 0) { Stream_SetPosition(transport->ReceiveBuffer, 0); if (tpkt_verify_header(transport->ReceiveBuffer)) /* TPKT */ { /* Ensure the TPKT header is available. */ if (pos <= 4) { Stream_SetPosition(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_SetPosition(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_SetPosition(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_SetPosition(transport->ReceiveBuffer, pos); return 0; } /* Fastpath header can be two or three bytes long. */ length = fastpath_header_length(transport->ReceiveBuffer); if (pos < length) { Stream_SetPosition(transport->ReceiveBuffer, pos); return 0; } length = fastpath_read_header(NULL, transport->ReceiveBuffer); } if (length == 0) { fprintf(stderr, "transport_check_fds: protocol error, not a TPKT or Fast Path header.\n"); winpr_HexDump(Stream_Buffer(transport->ReceiveBuffer), pos); return -1; } if (pos < length) { Stream_SetPosition(transport->ReceiveBuffer, pos); return 0; /* Packet is not yet completely received. */ } received = transport->ReceiveBuffer; transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0); Stream_SetPosition(received, length); Stream_SealLength(received); Stream_SetPosition(received, 0); recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra); if (transport == *ptransport) /* transport might now have been freed by rdp_client_redirect and a new rdp->transport created */ /* so only release if still valid */ Stream_Release(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; }