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

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) ...@@ -208,12 +208,6 @@ bound(guint32 lower, guint32 middle, guint32 upper)
return min (max (lower, middle), upper); return min (max (lower, middle), upper);
} }
static guint32
get_current_time(void)
{
return g_get_monotonic_time () / 1000;
}
static gboolean static gboolean
time_is_between(guint32 later, guint32 middle, guint32 earlier) time_is_between(guint32 later, guint32 middle, guint32 earlier)
{ {
...@@ -473,6 +467,10 @@ struct _PseudoTcpSocketPrivate { ...@@ -473,6 +467,10 @@ struct _PseudoTcpSocketPrivate {
// This is used by unit tests to test backward compatibility of // This is used by unit tests to test backward compatibility of
// PseudoTcp implementations that don't support window scaling. // PseudoTcp implementations that don't support window scaling.
gboolean support_wnd_scale; 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)) #define LARGER(a,b) (((a) - (b) - 1) < (G_MAXUINT32 >> 1))
...@@ -536,6 +534,21 @@ pseudo_tcp_set_debug_level (PseudoTcpDebugLevel level) ...@@ -536,6 +534,21 @@ pseudo_tcp_set_debug_level (PseudoTcpDebugLevel level)
debug_level = 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 static void
pseudo_tcp_socket_class_init (PseudoTcpSocketClass *cls) pseudo_tcp_socket_class_init (PseudoTcpSocketClass *cls)
{ {
...@@ -701,7 +714,6 @@ pseudo_tcp_socket_init (PseudoTcpSocket *obj) ...@@ -701,7 +714,6 @@ pseudo_tcp_socket_init (PseudoTcpSocket *obj)
* our private data is too big (150KB+) and the g_slice_allow cannot allocate * our private data is too big (150KB+) and the g_slice_allow cannot allocate
* it. So we handle the private ourselves */ * it. So we handle the private ourselves */
PseudoTcpSocketPrivate *priv = g_new0 (PseudoTcpSocketPrivate, 1); PseudoTcpSocketPrivate *priv = g_new0 (PseudoTcpSocketPrivate, 1);
guint32 now = get_current_time();
obj->priv = priv; obj->priv = priv;
...@@ -735,7 +747,7 @@ pseudo_tcp_socket_init (PseudoTcpSocket *obj) ...@@ -735,7 +747,7 @@ pseudo_tcp_socket_init (PseudoTcpSocket *obj)
priv->cwnd = 2 * priv->mss; priv->cwnd = 2 * priv->mss;
priv->ssthresh = priv->rbuf_len; 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->bOutgoing = FALSE;
priv->dup_acks = 0; priv->dup_acks = 0;
...@@ -814,7 +826,7 @@ void ...@@ -814,7 +826,7 @@ void
pseudo_tcp_socket_notify_clock(PseudoTcpSocket *self) pseudo_tcp_socket_notify_clock(PseudoTcpSocket *self)
{ {
PseudoTcpSocketPrivate *priv = self->priv; PseudoTcpSocketPrivate *priv = self->priv;
guint32 now = get_current_time (); guint32 now = get_current_time (self);
if (priv->state == TCP_CLOSED) if (priv->state == TCP_CLOSED)
return; return;
...@@ -937,7 +949,7 @@ gboolean ...@@ -937,7 +949,7 @@ gboolean
pseudo_tcp_socket_get_next_clock(PseudoTcpSocket *self, guint64 *timeout) pseudo_tcp_socket_get_next_clock(PseudoTcpSocket *self, guint64 *timeout)
{ {
PseudoTcpSocketPrivate *priv = self->priv; PseudoTcpSocketPrivate *priv = self->priv;
guint32 now = get_current_time (); guint32 now = get_current_time (self);
gsize snd_buffered; gsize snd_buffered;
if (priv->shutdown == SD_FORCEFUL) if (priv->shutdown == SD_FORCEFUL)
...@@ -1226,7 +1238,7 @@ process(PseudoTcpSocket *self, Segment *seg) ...@@ -1226,7 +1238,7 @@ process(PseudoTcpSocket *self, Segment *seg)
return FALSE; return FALSE;
} }
now = get_current_time(); now = get_current_time (self);
priv->last_traffic = priv->lastrecv = now; priv->last_traffic = priv->lastrecv = now;
priv->bOutgoing = FALSE; priv->bOutgoing = FALSE;
...@@ -1618,7 +1630,7 @@ static void ...@@ -1618,7 +1630,7 @@ static void
attempt_send(PseudoTcpSocket *self, SendFlags sflags) attempt_send(PseudoTcpSocket *self, SendFlags sflags)
{ {
PseudoTcpSocketPrivate *priv = self->priv; PseudoTcpSocketPrivate *priv = self->priv;
guint32 now = get_current_time(); guint32 now = get_current_time (self);
gboolean bFirst = TRUE; gboolean bFirst = TRUE;
if (time_diff(now, priv->lastsend) > (long) priv->rx_rto) { if (time_diff(now, priv->lastsend) > (long) priv->rx_rto) {
......
...@@ -471,6 +471,25 @@ gboolean pseudo_tcp_socket_can_send (PseudoTcpSocket *self); ...@@ -471,6 +471,25 @@ gboolean pseudo_tcp_socket_can_send (PseudoTcpSocket *self);
*/ */
gsize pseudo_tcp_socket_get_available_send_space (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: * pseudo_tcp_socket_is_closed:
* @self: The #PseudoTcpSocket object. * @self: The #PseudoTcpSocket object.
......
...@@ -302,6 +302,7 @@ pseudo_tcp_socket_get_available_bytes ...@@ -302,6 +302,7 @@ pseudo_tcp_socket_get_available_bytes
pseudo_tcp_socket_can_send pseudo_tcp_socket_can_send
pseudo_tcp_socket_get_available_send_space pseudo_tcp_socket_get_available_send_space
pseudo_tcp_socket_notify_message pseudo_tcp_socket_notify_message
pseudo_tcp_socket_set_time
<SUBSECTION Standard> <SUBSECTION Standard>
pseudo_tcp_socket_get_type pseudo_tcp_socket_get_type
PseudoTcpSocketClass 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