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 [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.
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 [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 [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.
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.
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 [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 [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 [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: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: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 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, 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 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 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 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, 3 Dec 2014 12:42:27 +0000 (13:42 +0100)]
Don't call abort() in retransmit().
The retransmission timer can sometimes get called when in one of the
closing states. This is not implemented yet, but it's better to just
ignore those cases for now than to abort().
Guus Sliepen [Tue, 2 Dec 2014 16:14:13 +0000 (17:14 +0100)]
Disable callbacks when closing a connection.
When an application calls utcp_close() on a previously established
connection, the utcp_connection is kept around to handle FIN(ACK)
packets. However, the peer could still send some data, which should not
trigger the receive callback.
Guus Sliepen [Tue, 2 Dec 2014 11:26:57 +0000 (12:26 +0100)]
Fix and refactor send buffer code.
Make generic buffer handling functions and use those. A problem was
found when resizing a buffer; if new data to be put into the buffer was
more than twice as large as the current buffer size, the code would not
reallocate the buffer large enough.
Guus Sliepen [Wed, 1 Oct 2014 17:18:40 +0000 (19:18 +0200)]
Add a poll callback to UTCP connections.
The callback is called whenever the send buffer of a connection is more
than half empty when utcp_timeout() is called. An argument is passed to
the callee informing him of the maximum number of bytes that will be
accepted when calling utcp_send().