Commit a72a93e5 authored by Philip Withnall's avatar Philip Withnall Committed by Olivier Crête

pseudotcp: Fix pseudo_tcp_socket_recv() in state TCP_CLOSE_WAIT

Previously, pseudo_tcp_socket_recv() would start returning 0 (EOS) as
soon as a FIN segment was received from the peer, even if there was
unread data already in the receive buffer.

Instead, the unread data should all be accessible before
pseudo_tcp_socket_recv() starts returning 0.
parent 02699917
......@@ -1152,9 +1152,7 @@ pseudo_tcp_socket_recv(PseudoTcpSocket *self, char * buffer, size_t len)
gsize available_space;
/* Received a FIN from the peer, so return 0. RFC 793, §3.5, Case 2. */
if (priv->support_fin_ack &&
(priv->shutdown_reads ||
pseudo_tcp_state_has_received_fin (priv->state))) {
if (priv->support_fin_ack && priv->shutdown_reads) {
return 0;
}
......@@ -1176,7 +1174,7 @@ pseudo_tcp_socket_recv(PseudoTcpSocket *self, char * buffer, size_t len)
bytesread = pseudo_tcp_fifo_read (&priv->rbuf, (guint8 *) buffer, len);
// If there's no data in |m_rbuf|.
if (bytesread == 0) {
if (bytesread == 0 && !pseudo_tcp_state_has_received_fin (priv->state)) {
priv->bReadEnable = TRUE;
priv->error = EWOULDBLOCK;
return -1;
......
......@@ -1141,6 +1141,41 @@ pseudotcp_compatibility (void)
data_clear (&data);
}
/* Check that after receiving a FIN, queued data can still be read */
static void
pseudotcp_close_recv_queued (void)
{
Data data = { 0, };
guint8 buf[100];
/* Establish a connection. */
establish_connection (&data);
g_assert_cmpint (pseudo_tcp_socket_send (data.left, "foo", 3), ==, 3);
expect_data (data.left, data.left_sent, 7, 7, 3);
forward_segment_ltr (&data);
increment_time_both (&data, 100); /* Delayed ACK */
expect_ack (data.right, data.right_sent, 7, 10);
forward_segment_rtl (&data);
close_socket (data.left);
expect_fin (data.left, data.left_sent, 10, 7);
forward_segment_ltr (&data);
expect_ack (data.right, data.right_sent, 7, 11);
forward_segment_rtl (&data);
/* Check that the data can be read */
g_assert_cmpint (pseudo_tcp_socket_recv (data.right, (char *) buf, sizeof (buf)), ==, 3);
/* Now the socket should be empty */
g_assert_cmpint (pseudo_tcp_socket_recv (data.right, (char *) buf, sizeof (buf)), ==, 0);
data_clear (&data);
}
int
main (int argc, char *argv[])
{
......@@ -1209,6 +1244,9 @@ main (int argc, char *argv[])
g_test_add_func ("/pseudotcp/close/rst-afterwards",
pseudotcp_close_rst_afterwards);
g_test_add_func ("/pseudotcp/close/recv-queued",
pseudotcp_close_recv_queued);
g_test_add_func ("/pseudotcp/compatibility",
pseudotcp_compatibility);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment