Commit e87f334a authored by Philip Withnall's avatar Philip Withnall Committed by Olivier Crête
Browse files

pseudotcp: Allow the ‘current’ time to be set

This is needed for the upcoming new test suite for pseudo-TCP. It
shouldn’t be used in normal code — only in tests.

Ideally, the pseudo-TCP code should originally never have called
g_get_monotonic_time() itself, and should have always taken a time
parameter from the caller; then it would be more testable.
Unfortunately, API guarantees prevent this from being changed now.
parent 6b6983e1
......@@ -208,12 +208,6 @@ bound(guint32 lower, guint32 middle, guint32 upper)
return min (max (lower, middle), upper);
}
static guint32
get_current_time(void)
{
return g_get_monotonic_time () / 1000;
}
static gboolean
time_is_between(guint32 later, guint32 middle, guint32 earlier)
{
......@@ -473,6 +467,10 @@ struct _PseudoTcpSocketPrivate {
// This is used by unit tests to test backward compatibility of
// PseudoTcp implementations that don't support window scaling.
gboolean support_wnd_scale;
/* Current time. Typically only used for testing, when non-zero. When zero,
* the system monotonic clock is used. Units: monotonic milliseconds. */
guint32 current_time;
};
#define LARGER(a,b) (((a) - (b) - 1) < (G_MAXUINT32 >> 1))
......@@ -536,6 +534,21 @@ pseudo_tcp_set_debug_level (PseudoTcpDebugLevel level)
debug_level = level;
}
static guint32
get_current_time (PseudoTcpSocket *socket)
{
if (G_UNLIKELY (socket->priv->current_time != 0))
return socket->priv->current_time;
return g_get_monotonic_time () / 1000;
}
void
pseudo_tcp_socket_set_time (PseudoTcpSocket *self, guint32 current_time)
{
self->priv->current_time = current_time;
}
static void
pseudo_tcp_socket_class_init (PseudoTcpSocketClass *cls)
{
......@@ -701,7 +714,6 @@ pseudo_tcp_socket_init (PseudoTcpSocket *obj)
* our private data is too big (150KB+) and the g_slice_allow cannot allocate
* it. So we handle the private ourselves */
PseudoTcpSocketPrivate *priv = g_new0 (PseudoTcpSocketPrivate, 1);
guint32 now = get_current_time();
obj->priv = priv;
......@@ -735,7 +747,7 @@ pseudo_tcp_socket_init (PseudoTcpSocket *obj)
priv->cwnd = 2 * priv->mss;
priv->ssthresh = priv->rbuf_len;
priv->lastrecv = priv->lastsend = priv->last_traffic = now;
priv->lastrecv = priv->lastsend = priv->last_traffic = 0;
priv->bOutgoing = FALSE;
priv->dup_acks = 0;
......@@ -814,7 +826,7 @@ void
pseudo_tcp_socket_notify_clock(PseudoTcpSocket *self)
{
PseudoTcpSocketPrivate *priv = self->priv;
guint32 now = get_current_time ();
guint32 now = get_current_time (self);
if (priv->state == TCP_CLOSED)
return;
......@@ -937,7 +949,7 @@ gboolean
pseudo_tcp_socket_get_next_clock(PseudoTcpSocket *self, guint64 *timeout)
{
PseudoTcpSocketPrivate *priv = self->priv;
guint32 now = get_current_time ();
guint32 now = get_current_time (self);
gsize snd_buffered;
if (priv->shutdown == SD_FORCEFUL)
......@@ -1226,7 +1238,7 @@ process(PseudoTcpSocket *self, Segment *seg)
return FALSE;
}
now = get_current_time();
now = get_current_time (self);
priv->last_traffic = priv->lastrecv = now;
priv->bOutgoing = FALSE;
......@@ -1618,7 +1630,7 @@ static void
attempt_send(PseudoTcpSocket *self, SendFlags sflags)
{
PseudoTcpSocketPrivate *priv = self->priv;
guint32 now = get_current_time();
guint32 now = get_current_time (self);
gboolean bFirst = TRUE;
if (time_diff(now, priv->lastsend) > (long) priv->rx_rto) {
......
......@@ -471,6 +471,25 @@ gboolean pseudo_tcp_socket_can_send (PseudoTcpSocket *self);
*/
gsize pseudo_tcp_socket_get_available_send_space (PseudoTcpSocket *self);
/**
* pseudo_tcp_socket_set_time:
* @self: The #PseudoTcpSocket object.
* @current_time: Current monotonic time, in milliseconds; or zero to use the
* system monotonic clock.
*
* Sets the current monotonic time to be used by the TCP socket when calculating
* timeouts and expiry times. If this function is not called, or is called with
* @current_time as zero, g_get_monotonic_time() will be used. Otherwise, the
* specified @current_time will be used until it is updated by calling this
* function again.
*
* This function is intended for testing only, and should not be used in
* production code.
*
* Since: UNRELEASED
*/
void pseudo_tcp_socket_set_time (PseudoTcpSocket *self, guint32 current_time);
/**
* pseudo_tcp_socket_is_closed:
* @self: The #PseudoTcpSocket object.
......
......@@ -302,6 +302,7 @@ pseudo_tcp_socket_get_available_bytes
pseudo_tcp_socket_can_send
pseudo_tcp_socket_get_available_send_space
pseudo_tcp_socket_notify_message
pseudo_tcp_socket_set_time
<SUBSECTION Standard>
pseudo_tcp_socket_get_type
PseudoTcpSocketClass
......
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