Guus Sliepen [Sun, 8 Mar 2020 22:48:30 +0000 (23:48 +0100)]
Implement fast recovery according to RFC 5681.
Guus Sliepen [Sun, 8 Mar 2020 21:12:41 +0000 (22:12 +0100)]
Avoid sending packets smaller than the MTU if we don't need to.
If we have almost filled the congestion window but have more data in the
send buffer than we can send right now, wait until the congestion window
frees up to avoid sending small packets unnecessarily.
Guus Sliepen [Sun, 8 Mar 2020 20:57:57 +0000 (21:57 +0100)]
Implement slow start threshold according to RFC 5681.
Guus Sliepen [Sun, 8 Mar 2020 20:52:23 +0000 (21:52 +0100)]
Always announce the receive window size as the size of the receive buffer.
Since UTCP requires the application to handle incoming in-sequence data
immediately, the start of the receive buffer is always right after the
last ACKed byte, so we can always announce the size of the receive buffer
as the maximum receive window size.
Guus Sliepen [Sun, 8 Mar 2020 20:09:25 +0000 (21:09 +0100)]
Add a benchmark script.
This script sets up two network namespaces connected via a veth tunnel with
the netem qdisc to simulate "realistic" network conditions.
It first uses socat to transmit data via regular TCP, then transmits the
same amount of data using the UTCP test program. It prints the time it took
for both methods, and stores a packet trace for both methods so it can be
analyzed.
Guus Sliepen [Sun, 8 Mar 2020 19:59:59 +0000 (20:59 +0100)]
Add a Wireshark plugin to help dissect UTCP packets.
This assumes UTCP is being transported in plaintext over UDP port 9999.
Guus Sliepen [Sun, 8 Mar 2020 19:56:28 +0000 (20:56 +0100)]
Update test program to set a better default MTU.
Guus Sliepen [Sat, 8 Feb 2020 14:59:41 +0000 (15:59 +0100)]
Fix garbage being sent at start of UDP connection.
If utcp_send() was called right after utcp_connect_ex(..., UTCP_UDP),
and the handshake phase hadn't completed yet, we left some garbage in
the send buffer which wasn't cleared until two more calls to utcp_send()
were made.
Guus Sliepen [Thu, 31 Oct 2019 19:41:04 +0000 (20:41 +0100)]
Avoid a compiler warning when compiling with -DNDEBUG.
Guus Sliepen [Mon, 14 Oct 2019 20:32:35 +0000 (22:32 +0200)]
Fix retransmission timeout calculation.
The RTO calculation was missing a factor 4 multiplication of the
RTT variance, which caused it to set the RTO to a much lower value than
specified by RFC 6298. This would result in more retranmissions and a
lower throughput.
Guus Sliepen [Thu, 10 Oct 2019 20:10:44 +0000 (22:10 +0200)]
Correctly handle incoming retransmissions of SYN packets.
Guus Sliepen [Thu, 10 Oct 2019 18:48:16 +0000 (20:48 +0200)]
Replace two hardcoded timeout values with utcp->timeout.
Guus Sliepen [Thu, 10 Oct 2019 18:43:45 +0000 (20:43 +0200)]
Don't reset timers that were not set in utcp_reset_timers() and utcp_offline().
In utcp_reset_timers(), we were actually setting the connection timer even
if it was not set before, therefore causing spurious channel closures on
channels that did not have any unACKed data.
In utcp_offline(), we were setting the retransmission timer even if there
was nothing to retransmit.
Guus Sliepen [Mon, 7 Oct 2019 10:45:12 +0000 (12:45 +0200)]
Also always send an ACK back when the SYN or FIN bit is set.
Guus Sliepen [Sat, 5 Oct 2019 12:29:16 +0000 (14:29 +0200)]
Always send an ACK back when we receive data from the peer.
A previous ACK could get lost, causing the peer to resend data. If the
retransmission doesn't contain any new data, we would consider this data
to be outside our receive window, and then not resend our ACK.
Guus Sliepen [Sun, 22 Sep 2019 13:01:29 +0000 (15:01 +0200)]
Several fixes for handling UDP-like channels.
- Drop data sent before the connection is established.
- Relax checks on incoming ACK seqnos
- Always consider all data ACKed
- Disregard hdr.seq when a FIN packet is received
- Don't ACK pure data packets
Guus Sliepen [Sun, 22 Sep 2019 11:00:08 +0000 (13:00 +0200)]
Allow setting the MTU in the test program.
Guus Sliepen [Tue, 17 Sep 2019 19:45:22 +0000 (21:45 +0200)]
Call the poll callback with 0 whenever a connection is closed.
Guus Sliepen [Tue, 13 Aug 2019 18:45:34 +0000 (20:45 +0200)]
Don't abort when UTCP_NO_PARTIAL is set.
Guus Sliepen [Thu, 8 Aug 2019 13:14:09 +0000 (15:14 +0200)]
Add a flag to prevent partial writes on a UTCP connection.
Guus Sliepen [Sun, 7 Jul 2019 16:00:06 +0000 (18:00 +0200)]
Add a function to manually start the connection timeout timers.
If the application knows the peer is offline, it can call utcp_offline().
This will start the connection timers on all connections to that peer.
This can be undone by marking the peer online again. This will also reset
the retransmission timers.
Guus Sliepen [Sun, 7 Jul 2019 14:54:25 +0000 (16:54 +0200)]
Start the connection timeout timer when we have unACKed data.
Start it when we are have some data to send, and reset it whenever some of
the data is ACKed. Stop the timer if the peer has received all the data.
Also ensure the poll callback is called with len = 0 when the timeout is
hit.
Guus Sliepen [Sun, 17 Mar 2019 19:57:43 +0000 (20:57 +0100)]
Check for astyle version 3 before formatting the code.
Unfortunately, code formatters change their behaviour between versions.
The code currently requires astyle version 3.x, so check this before
running astyle. If the wrong version is installed, print an error.
Guus Sliepen [Sun, 17 Mar 2019 19:54:19 +0000 (20:54 +0100)]
Add functions to get the amount of bytes in the send and receive buffers.
utcp_get_sendq() returns the amount of bytes in the send buffer, which
corresponds to the amount of bytes not yet ACKed by the peer.
utcp_get_recvq() returns the amount of bytes in the receive buffer,
which may or may not have been acked already, but have not been read by
the application.
Guus Sliepen [Wed, 27 Feb 2019 19:05:00 +0000 (20:05 +0100)]
Keep a copy of the old receive callback before calling reset_connection().
The latter function clears the receive callback, so make a copy before
calling trying to call the receive callback for the final time.
Guus Sliepen [Mon, 25 Feb 2019 08:57:57 +0000 (09:57 +0100)]
Small fixes for utcp_abort_all_connections().
- Make utcp_reset_connection() a private function.
- Ensure we don't repeat any action when aborting a connection twice.
- Call the receive callback after resetting the connection, so the callback
function can safely call utcp_close().
SS Roop [Fri, 15 Feb 2019 05:27:32 +0000 (10:57 +0530)]
Add utcp_abort_all_connections function.
This adds a function to abort all open connections without invalidating
the utcp_connection_t handles. Its main purposes is when the application
knows communication with the peer is definitely not possible/desired anymore.
A RST packet will be sent to each connection's remote end, and the
receive callback will be invoked to indicate an error on each
connection.
Guus Sliepen [Sun, 22 Jul 2018 11:19:01 +0000 (13:19 +0200)]
Allow utcp_send() before a connection has been fully established.
This will put the data in the send buffer, and it will be sent when possible.
This also allows the socket to be shut down for writing before it has
reached the ESTABLISHED state.
Guus Sliepen [Sun, 22 Jul 2018 11:16:13 +0000 (13:16 +0200)]
Add more error messages to test program, allow socket reuse.
Guus Sliepen [Tue, 1 May 2018 12:59:06 +0000 (14:59 +0200)]
Fix all compiler warnings found using -Wall -W -pedantic.
Guus Sliepen [Mon, 2 Oct 2017 20:52:53 +0000 (22:52 +0200)]
Format the code using the Artistic Style formatter.
Guus Sliepen [Mon, 2 Oct 2017 20:40:47 +0000 (22:40 +0200)]
Convert sizeof foo to sizeof(foo).
While technically sizeof is an operator and doesn't need the parentheses
around expressions it operates on, except if they are type names, code
formatters don't seem to handle this very well.
Guus Sliepen [Mon, 2 Oct 2017 20:24:32 +0000 (22:24 +0200)]
Fix warnings when compiling with -Wall -W.
Guus Sliepen [Sun, 13 Aug 2017 19:46:24 +0000 (21:46 +0200)]
Call the receive callback for unclosed channels during utcp_exit().
This allows the application to clean up any resources associated with
these UTCP connections.
Guus Sliepen [Sun, 13 Aug 2017 19:27:00 +0000 (21:27 +0200)]
Fix SYN packet handling.
This fixes problems with SYN packets arriving out of the usual order.
This also adds a more proper handling of the aux field.
Guus Sliepen [Sun, 13 Aug 2017 15:43:48 +0000 (17:43 +0200)]
Allow timers to be reset.
The function utcp_reset_timers() will reset the retransmit timers of all
connections to zero, so they will fire immediately. The connection timeout will
be reset to the user timeout value, and if the RTO is larger than the
starting RTO, it will be set to the starting RTO.
Guus Sliepen [Sun, 13 Aug 2017 14:22:39 +0000 (16:22 +0200)]
Remove debug message.
Guus Sliepen [Sun, 13 Aug 2017 12:48:49 +0000 (14:48 +0200)]
Enable retransmit timer for SYN packets.
Guus Sliepen [Thu, 27 Jul 2017 09:25:50 +0000 (11:25 +0200)]
Call the poll callback with len = 0 on errors.
Guus Sliepen [Mon, 3 Jul 2017 21:16:01 +0000 (23:16 +0200)]
Add UDP semantics.
Basically, never retransmit, and whatever we get we immediately pass up to
the application. The only thing we do handle the TCP way is the FIN packet.
This also introduces the use of the aux entry in the header. We know that
older versions of UTCP ignore this field, and also ignore any extra data
in SYN packets, so we can add anything here in a backwards-compatible way.
Guus Sliepen [Mon, 3 Jul 2017 20:31:50 +0000 (22:31 +0200)]
Introduce utcp_connect_ex().
This takes an extra argument "flags", which can be used to change the type
of connection to create. Possible flags are UTCP_INORDER, UTCP_RELIABLE and
UTCP_FRAMED, which can be bitwise-or'd together, or UTCP_TCP or UTCP_UDP as
shortcuts for what is assumed will be common combinations of those flags.
Guus Sliepen [Sun, 2 Jul 2017 19:35:55 +0000 (21:35 +0200)]
Fix handling packets partially overlapping the start of the receive buffer.
Guus Sliepen [Sun, 2 Jul 2017 13:43:57 +0000 (15:43 +0200)]
Fix handling retransmitted data when the receive buffer is full.
Guus Sliepen [Sun, 2 Jul 2017 12:58:56 +0000 (14:58 +0200)]
Remove two unnecessary calls to abort().
Guus Sliepen [Sun, 2 Jul 2017 12:58:08 +0000 (14:58 +0200)]
Allow test program to compare input to a reference file.
Guus Sliepen [Sun, 2 Jul 2017 10:47:58 +0000 (12:47 +0200)]
Fix compiler warnings.
Guus Sliepen [Thu, 17 Dec 2015 17:07:19 +0000 (18:07 +0100)]
Fix buffer resizing logic in buffer_put_at().
When growing the buffer when it's not big enough for new data, the
current size is doubled repeatedly until it is big enough for the new
data. The required new size is stored in the variable "required",
however the doubling loop exited when the new size was at least
buf->used + len, which might be much smaller than "required" if an
out-of-order packet is received.
Guus Sliepen [Sun, 15 Nov 2015 19:35:30 +0000 (20:35 +0100)]
Only log debug messages in test program when UTCP_DEBUG is defined.
Guus Sliepen [Fri, 30 Oct 2015 22:42:35 +0000 (23:42 +0100)]
Add more debug messages.
Guus Sliepen [Fri, 30 Oct 2015 22:16:47 +0000 (23:16 +0100)]
Ensure utcp_close() works properly on a socket that is in the CLOSED state.
Guus Sliepen [Fri, 30 Oct 2015 22:16:24 +0000 (23:16 +0100)]
Log when dropping packets in the test program.
Guus Sliepen [Sun, 2 Jul 2017 10:13:24 +0000 (12:13 +0200)]
Define USEC_PER_SEC, use "sec" and "usec" in comments.
Guus Sliepen [Thu, 29 Oct 2015 15:36:39 +0000 (16:36 +0100)]
Add debug message when dropping a packet because all SACK entries are used.
Guus Sliepen [Thu, 29 Oct 2015 15:35:16 +0000 (16:35 +0100)]
Clarify description of sack_consume().
Guus Sliepen [Thu, 29 Oct 2015 15:33:45 +0000 (16:33 +0100)]
Make max() an inline function.
Guus Sliepen [Thu, 29 Oct 2015 15:31:17 +0000 (16:31 +0100)]
Don't use ?: without the middle argument.
Guus Sliepen [Thu, 29 Oct 2015 15:26:54 +0000 (16:26 +0100)]
Always check the return value of malloc().
Guus Sliepen [Mon, 19 Oct 2015 20:04:50 +0000 (22:04 +0200)]
Fix bugs in sack_consume() causing data corruption or abort()s.
Put in a lengthy comment with some ASCII-art to describe what we are
actually trying to do in this function.
Guus Sliepen [Mon, 19 Oct 2015 20:03:21 +0000 (22:03 +0200)]
Fix bug in retransmit().
The logic to check whether we actually have something to retransmit was
wrong, causing retransmit() to bail out early without setting or resetting
the timer. This also caused utcp_timeout() to return a negative value.
Guus Sliepen [Mon, 19 Oct 2015 19:18:14 +0000 (21:18 +0200)]
Ensure FIN packets start the retransmission timer as well.
Guus Sliepen [Mon, 19 Oct 2015 19:17:38 +0000 (21:17 +0200)]
Allow setting $DROPFROM without having to specify $DROPTO as well.
Guus Sliepen [Mon, 19 Oct 2015 19:17:06 +0000 (21:17 +0200)]
Simulate packet reordering.
With a configurable chance, delay a packet for a random amount of packets.
Guus Sliepen [Mon, 19 Oct 2015 18:46:27 +0000 (20:46 +0200)]
Fix a memory leak.
The receive buffer was never freed.
Guus Sliepen [Mon, 19 Oct 2015 18:45:31 +0000 (20:45 +0200)]
Make sure all of the packet header is set when retransmitting packets.
Hannes [Thu, 15 Oct 2015 18:35:04 +0000 (20:35 +0200)]
speed up utcp print_packet debug output and print in hex
Hannes [Sat, 17 Oct 2015 13:39:12 +0000 (15:39 +0200)]
handle overlapping packets
# Conflicts:
# utcp.c
Guus Sliepen [Sun, 18 Oct 2015 18:53:55 +0000 (20:53 +0200)]
Send ACKs also when receiving out-of-order data.
This is necessary to trigger the triplicate ACK detection on the sender.
Guus Sliepen [Sun, 18 Oct 2015 18:31:34 +0000 (20:31 +0200)]
Log when we start retransmission.
Guus Sliepen [Sun, 18 Oct 2015 18:31:09 +0000 (20:31 +0200)]
Get rid of an unused label.
Guus Sliepen [Sun, 18 Oct 2015 18:30:48 +0000 (20:30 +0200)]
Fix the logic for determining whether a packets has an acceptable ack seqno.
snd.last accurately tracks the last possible seqno that can be acked, so
use it. This fixes a case where retransmitted ACKs of a FIN were not handled
correctly.
Guus Sliepen [Sun, 18 Oct 2015 18:28:58 +0000 (20:28 +0200)]
Use the calculated RTO value to set the retransmission timer.
This significantly cuts down the time it takes to transfer data when there
is packet loss, because retransmission kicks in much earlier.
Guus Sliepen [Sun, 18 Oct 2015 18:24:50 +0000 (20:24 +0200)]
Measure RTT and calculate RTO.
Opportunistically measure RTT using only a single timer, without requiring
timestamps to be added to packets. Use the method described in RFC 6298 to
smoothly update the value of RTO.
Guus Sliepen [Sun, 18 Oct 2015 18:21:06 +0000 (20:21 +0200)]
Turn magic numbers into #defines.
Guus Sliepen [Sun, 18 Oct 2015 18:19:25 +0000 (20:19 +0200)]
Remove accidentily left #warning.
Guus Sliepen [Sun, 18 Oct 2015 18:18:49 +0000 (20:18 +0200)]
Minor changes in the test program.
- Add one to the timeout in milliseconds, to prevent roundoff errors from
causing us to busy-loop unnecessarily.
- Log what we are polling for and what the timeout is.
Guus Sliepen [Sun, 18 Oct 2015 18:17:13 +0000 (20:17 +0200)]
Improve documentation of retransmission timeout handling.
Guus Sliepen [Sun, 18 Oct 2015 18:15:52 +0000 (20:15 +0200)]
Document difference between snd.nxt and snd.last.
Guus Sliepen [Sun, 18 Oct 2015 11:54:14 +0000 (13:54 +0200)]
Fix a memory leak on invalid invocation of utcp_init().
Guus Sliepen [Sun, 18 Oct 2015 11:53:20 +0000 (13:53 +0200)]
Add a receive buffer.
The receive buffer kicks in the moment we get a packet which is out of order.
We store the packet in the buffer, and keep track of up to 4 ranges of bytes
of received data. When retransmission fills the first gap, we send all the
buffered data (up to the second gap if applicable) to the application.
4 byte ranges seems to be a good value for up to moderate (20%) packet loss.
This algorithm greatly reduces the amount of useless packets being sent.
A future improvement is sending the SACK information in the ACK packets,
so the congestion window can be kept large while avoiding packets being
resent unnecessarily.
Guus Sliepen [Sun, 18 Oct 2015 11:45:16 +0000 (13:45 +0200)]
Fix check for return value of malloc(), allow initially zero length buffer.
Guus Sliepen [Sun, 18 Oct 2015 11:44:43 +0000 (13:44 +0200)]
Allow putting data in a buffer at an arbitrary offset.
Guus Sliepen [Sun, 18 Oct 2015 11:43:53 +0000 (13:43 +0200)]
Fix check for return value of malloc().
Guus Sliepen [Sun, 18 Oct 2015 11:42:36 +0000 (13:42 +0200)]
When debugging, set initial segment seqno to 0.
Guus Sliepen [Sun, 18 Oct 2015 11:41:50 +0000 (13:41 +0200)]
Show total bytes sent/received in test program.
Guus Sliepen [Sun, 11 Oct 2015 21:39:23 +0000 (23:39 +0200)]
Reset the snd.nxt pointer when starting packet retransmission.
When a packet was lost, and the send buffer contains more than two packets,
this only retransmitted the first packet from the send buffer, then when it
got acked it would continue with the tail of the buffer. Then it would have
to wait for another timeout to send the next packet from the start of the
send buffer. If the application is continuously sending data, then the send
buffer would never become empty and the problem would persist.
Guus Sliepen [Sun, 11 Oct 2015 21:35:49 +0000 (23:35 +0200)]
Fix a segfault when debugging is enabled.
Guus Sliepen [Sun, 11 Oct 2015 21:35:14 +0000 (23:35 +0200)]
Log timestamps during the test.
Guus Sliepen [Sun, 11 Oct 2015 21:35:02 +0000 (23:35 +0200)]
Allow dropping a selected range of packets during tests.
Guus Sliepen [Sun, 11 Oct 2015 15:11:13 +0000 (17:11 +0200)]
Add scripts testing filetransfer.
- txttest transfers a file into one direction.
- bidirtest transfers a file both ways simultaneously.
Guus Sliepen [Sun, 11 Oct 2015 15:02:37 +0000 (17:02 +0200)]
Handle direction argument of utcp_shutdown().
For TCP, only shutting down the send direction makes sense, however to
be compatible to the BSD sockets API, keep the direction argument, and
when someone tries to shut down the receive direction, just disable the
receive callback.
Note that on most operating systems, SHUT_RD actually doesn't do
anything at all, it won't prevent reads from returning data.
Also be a bit more strict, return EINVAL or ENOTCONN when appropriate.
Guus Sliepen [Sun, 11 Oct 2015 15:00:17 +0000 (17:00 +0200)]
Define UTCP_SHUT_RD/WR/RDWR.
Don't rely on <sys/socket.h> for the definitions of SHUT_RD/WR/RDWR, add
our own. They should be compatible.
Guus Sliepen [Sun, 11 Oct 2015 14:31:59 +0000 (16:31 +0200)]
Add a function to check for active connections.
If a connection sends data in one way, then the receiver will have shut
down data in the other way, and when the sender is finished he will also
shut down his direction, so the connection looks closed to the sender,
but the receiver might actually still miss the final packets. So UTCP
should keep running until the receiver has received a FINACK and is in the
TIME_WAIT state.
We consider UTCP to be active when there is at least one connection not in
the CLOSED or TIME_WAIT state.
The test program now uses this condition, which allows a transfer of a file
to complete without missing the last few bytes.
Guus Sliepen [Sun, 11 Oct 2015 14:25:31 +0000 (16:25 +0200)]
Allow changing the accept callbacks.
This is used in the test, in order to stop accepting new connections after
the first one.
Guus Sliepen [Sun, 11 Oct 2015 14:21:22 +0000 (16:21 +0200)]
Clarify read/write direction in test program.
Guus Sliepen [Sun, 11 Oct 2015 11:32:55 +0000 (13:32 +0200)]
Use '== -1' to check for errors from functions.
As made obvious by commit
123f53f, the type of ssize_t cannot be trusted
on Windows to actually be signed, so don't use '< 0', as the compiler
will optimize the test away. POSIX also specifies only that -1 signals
an error condition, not any other negative value.
Luckily, comparing an unsigned int to -1 still works as intended.
Guus Sliepen [Wed, 10 Dec 2014 10:11:09 +0000 (11:11 +0100)]
Handle retransmissions in CLOSE_WAIT, CLOSING and LAST_ACK states.
Guus Sliepen [Wed, 10 Dec 2014 10:09:59 +0000 (11:09 +0100)]
Add fin_wanted() function that checks whether a FIN bit should be set on a packet.
Guus Sliepen [Wed, 10 Dec 2014 09:48:02 +0000 (10:48 +0100)]
Call abort() only when debugging is enabled.
Guus Sliepen [Mon, 8 Dec 2014 15:37:24 +0000 (16:37 +0100)]
Guard against NULL pointer dereferencing.
Guus Sliepen [Mon, 8 Dec 2014 15:18:30 +0000 (16:18 +0100)]
Prevent FIN bit from being sent too early.
Due to a logic bug in ack(), the FIN bit could be set on a too early packet,
if utcp_shutdown() was called with a full send buffer.