void rdp_recv_server_font_map_pdu(rdpRdp* rdp, STREAM* s, rdpSettings* settings)
{
rdp->activated = True;
- rdp->transport->tcp->set_blocking_mode(rdp->transport->tcp, False);
}
void rdp_recv_deactivate_all(rdpRdp* rdp, STREAM* s)
stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor (should be 0x00) */
rdp->activated = False;
- rdp->transport->tcp->set_blocking_mode(rdp->transport->tcp, True);
}
rdp->licensed = True;
rdp_client_activate(rdp);
+ rdp_set_blocking_mode(rdp, False);
return True;
}
boolean freerdp_check_fds(freerdp* instance)
{
rdpRdp* rdp;
+ int status;
rdp = (rdpRdp*) instance->rdp;
- rdp_recv(rdp);
+ status = rdp_check_fds(rdp);
+ if (status < 0)
+ return False;
return True;
}
}
/**
- * Receive an RDP packet.\n
+ * Process an RDP packet.\n
* @param rdp RDP module
+ * @param s stream
*/
-void rdp_recv(rdpRdp* rdp)
+void rdp_process_pdu(rdpRdp* rdp, STREAM* s)
{
- STREAM* s;
int length;
uint16 pduType;
uint16 pduLength;
uint16 sec_flags;
enum DomainMCSPDU MCSPDU;
- s = transport_recv_stream_init(rdp->transport, 4096);
- transport_read(rdp->transport, s);
-
MCSPDU = DomainMCSPDU_SendDataIndication;
mcs_read_domain_mcspdu_header(s, &MCSPDU, &length);
}
/**
+ * Receive an RDP packet.\n
+ * @param rdp RDP module
+ */
+
+void rdp_recv(rdpRdp* rdp)
+{
+ STREAM* s;
+
+ s = transport_recv_stream_init(rdp->transport, 4096);
+ transport_read(rdp->transport, s);
+
+ rdp_process_pdu(rdp, s);
+}
+
+static int rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
+{
+ rdpRdp* rdp = (rdpRdp*) extra;
+
+ rdp_process_pdu(rdp, s);
+
+ return 1;
+}
+
+/**
+ * Set non-blocking mode information.
+ * @param rdp RDP module
+ * @param blocking blocking mode
+ */
+void rdp_set_blocking_mode(rdpRdp* rdp, boolean blocking)
+{
+ rdp->transport->recv_callback = rdp_recv_callback;
+ rdp->transport->recv_extra = rdp;
+ transport_set_blocking_mode(rdp->transport, blocking);
+}
+
+int rdp_check_fds(rdpRdp* rdp)
+{
+ return transport_check_fds(rdp->transport);
+}
+
+/**
* Instantiate new RDP module.
* @return new RDP module
*/
void rdp_send(rdpRdp* rdp, STREAM* s);
void rdp_recv(rdpRdp* rdp);
+void rdp_set_blocking_mode(rdpRdp* rdp, boolean blocking);
+int rdp_check_fds(rdpRdp* rdp);
+
rdpRdp* rdp_new();
void rdp_free(rdpRdp* rdp);
return status;
}
+static int transport_read_nonblocking(rdpTransport* transport)
+{
+ int status;
+
+ stream_check_size(transport->recv_buffer, 4096);
+ status = transport_read(transport, transport->recv_buffer);
+
+ if (status <= 0)
+ return status;
+
+ stream_seek(transport->recv_buffer, status);
+
+ return status;
+}
+
int transport_write(rdpTransport* transport, STREAM* s)
{
int status = -1;
int transport_check_fds(rdpTransport* transport)
{
+ int pos;
+ int status;
+ uint8 header;
+ uint16 length;
+ STREAM* received;
+
+ status = transport_read_nonblocking(transport);
+ if (status <= 0)
+ return status;
+
+ while ((pos = stream_get_pos(transport->recv_buffer)) > 0)
+ {
+ /* Ensure the TPKT or Fast Path header is available. */
+ if (pos <= 4)
+ return 0;
+
+ stream_set_pos(transport->recv_buffer, 0);
+ stream_peek_uint8(transport->recv_buffer, header);
+ if (header == 0x03) /* TPKT */
+ length = tpkt_read_header(transport->recv_buffer);
+ else /* TODO: Fast Path */
+ length = 0;
+
+ if (length == 0)
+ {
+ printf("transport_check_fds: protocol error, not a TPKT header (%d).\n", header);
+ 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, 0);
+ status = transport->recv_callback(transport, received, transport->recv_extra);
+ stream_free(received);
+
+ if (status < 0)
+ return status;
+ }
+
return 0;
}
transport->state = TRANSPORT_STATE_NEGO;
}
+boolean transport_set_blocking_mode(rdpTransport* transport, boolean blocking)
+{
+ transport->blocking = blocking;
+ return transport->tcp->set_blocking_mode(transport->tcp, blocking);
+}
+
rdpTransport* transport_new(rdpSettings* settings)
{
rdpTransport* transport;
/* buffers for blocking read/write */
transport->recv_stream = stream_new(BUFFER_SIZE);
transport->send_stream = stream_new(BUFFER_SIZE);
+
+ transport->blocking = True;
}
return transport;
void* recv_extra;
STREAM* recv_buffer;
TransportRecv recv_callback;
+ boolean blocking;
};
STREAM* transport_recv_stream_init(rdpTransport* transport, int size);
int transport_read(rdpTransport* transport, STREAM* s);
int transport_write(rdpTransport* transport, STREAM* s);
int transport_check_fds(rdpTransport* transport);
+boolean transport_set_blocking_mode(rdpTransport* transport, boolean blocking);
rdpTransport* transport_new(rdpSettings* settings);
void transport_free(rdpTransport* transport);