Commit 5db9af99 authored by Olivier Crête's avatar Olivier Crête

pseudotcp: Make it possible to disable the Nagle Algorithm

Syncs with libjingle SVN rev 56
parent 42358dde
...@@ -153,7 +153,8 @@ const guint16 PACKET_MAXIMUMS[] = { ...@@ -153,7 +153,8 @@ const guint16 PACKET_MAXIMUMS[] = {
#define MIN_RTO 250 #define MIN_RTO 250
#define DEF_RTO 3000 /* 3 seconds (RFC1122, Sec 4.2.3.1) */ #define DEF_RTO 3000 /* 3 seconds (RFC1122, Sec 4.2.3.1) */
#define MAX_RTO 60000 /* 60 seconds */ #define MAX_RTO 60000 /* 60 seconds */
#define ACK_DELAY 100 /* 100 milliseconds */ #define DEFAULT_ACK_DELAY 100 /* 100 milliseconds */
#define DEFAULT_NO_DELAY FALSE
/* /*
#define FLAG_FIN 0x01 #define FLAG_FIN 0x01
...@@ -310,6 +311,8 @@ struct _PseudoTcpSocketPrivate { ...@@ -310,6 +311,8 @@ struct _PseudoTcpSocketPrivate {
guint32 recover; guint32 recover;
guint32 t_ack; guint32 t_ack;
gboolean use_nagling;
guint32 ack_delay;
}; };
...@@ -319,6 +322,8 @@ enum ...@@ -319,6 +322,8 @@ enum
PROP_CONVERSATION = 1, PROP_CONVERSATION = 1,
PROP_CALLBACKS, PROP_CALLBACKS,
PROP_STATE, PROP_STATE,
PROP_ACK_DELAY,
PROP_NO_DELAY,
LAST_PROPERTY LAST_PROPERTY
}; };
...@@ -393,6 +398,17 @@ pseudo_tcp_socket_class_init (PseudoTcpSocketClass *cls) ...@@ -393,6 +398,17 @@ pseudo_tcp_socket_class_init (PseudoTcpSocketClass *cls)
TCP_LISTEN, TCP_CLOSED, TCP_LISTEN, TCP_LISTEN, TCP_CLOSED, TCP_LISTEN,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_ACK_DELAY,
g_param_spec_uint ("ack-delay", "ACK Delay",
"Delayed ACK timeout (in milliseconds)",
0, G_MAXUINT, DEFAULT_ACK_DELAY,
G_PARAM_READWRITE| G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_NO_DELAY,
g_param_spec_boolean ("no-delay", "No Delay",
"Disable the Nagle algorithm (like the TCP_NODELAY option)",
DEFAULT_NO_DELAY,
G_PARAM_READWRITE| G_PARAM_STATIC_STRINGS));
} }
...@@ -414,6 +430,12 @@ pseudo_tcp_socket_get_property (GObject *object, ...@@ -414,6 +430,12 @@ pseudo_tcp_socket_get_property (GObject *object,
case PROP_STATE: case PROP_STATE:
g_value_set_uint (value, self->priv->state); g_value_set_uint (value, self->priv->state);
break; break;
case PROP_ACK_DELAY:
g_value_set_uint (value, self->priv->ack_delay);
break;
case PROP_NO_DELAY:
g_value_set_boolean (value, !self->priv->use_nagling);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break; break;
...@@ -438,6 +460,12 @@ pseudo_tcp_socket_set_property (GObject *object, ...@@ -438,6 +460,12 @@ pseudo_tcp_socket_set_property (GObject *object,
self->priv->callbacks = *c; self->priv->callbacks = *c;
} }
break; break;
case PROP_ACK_DELAY:
self->priv->ack_delay = g_value_get_uint (value);
break;
case PROP_NO_DELAY:
self->priv->use_nagling = !g_value_get_boolean (value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break; break;
...@@ -518,6 +546,9 @@ pseudo_tcp_socket_init (PseudoTcpSocket *obj) ...@@ -518,6 +546,9 @@ pseudo_tcp_socket_init (PseudoTcpSocket *obj)
priv->rx_rto = DEF_RTO; priv->rx_rto = DEF_RTO;
priv->rx_srtt = priv->rx_rttvar = 0; priv->rx_srtt = priv->rx_rttvar = 0;
priv->ack_delay = DEFAULT_ACK_DELAY;
priv->use_nagling = !DEFAULT_NO_DELAY;
} }
PseudoTcpSocket *pseudo_tcp_socket_new (guint32 conversation, PseudoTcpSocket *pseudo_tcp_socket_new (guint32 conversation,
...@@ -619,7 +650,7 @@ pseudo_tcp_socket_notify_clock(PseudoTcpSocket *self) ...@@ -619,7 +650,7 @@ pseudo_tcp_socket_notify_clock(PseudoTcpSocket *self)
} }
// Check if it's time to send delayed acks // Check if it's time to send delayed acks
if (priv->t_ack && (time_diff(priv->t_ack + ACK_DELAY, now) <= 0)) { if (priv->t_ack && (time_diff(priv->t_ack + priv->ack_delay, now) <= 0)) {
packet(self, priv->snd_nxt, 0, 0, 0); packet(self, priv->snd_nxt, 0, 0, 0);
} }
...@@ -659,7 +690,7 @@ pseudo_tcp_socket_get_next_clock(PseudoTcpSocket *self, long *timeout) ...@@ -659,7 +690,7 @@ pseudo_tcp_socket_get_next_clock(PseudoTcpSocket *self, long *timeout)
*timeout = DEFAULT_TIMEOUT; *timeout = DEFAULT_TIMEOUT;
if (priv->t_ack) { if (priv->t_ack) {
*timeout = min(*timeout, time_diff(priv->t_ack + ACK_DELAY, now)); *timeout = min(*timeout, time_diff(priv->t_ack + priv->ack_delay, now));
} }
if (priv->rto_base) { if (priv->rto_base) {
*timeout = min(*timeout, time_diff(priv->rto_base + priv->rx_rto, now)); *timeout = min(*timeout, time_diff(priv->rto_base + priv->rx_rto, now));
...@@ -1092,7 +1123,11 @@ process(PseudoTcpSocket *self, Segment *seg) ...@@ -1092,7 +1123,11 @@ process(PseudoTcpSocket *self, Segment *seg)
if (seg->seq != priv->rcv_nxt) { if (seg->seq != priv->rcv_nxt) {
sflags = sfImmediateAck; // (Fast Recovery) sflags = sfImmediateAck; // (Fast Recovery)
} else if (seg->len != 0) { } else if (seg->len != 0) {
sflags = sfDelayedAck; if (priv->ack_delay == 0) {
sflags = sfImmediateAck;
} else {
sflags = sfDelayedAck;
}
} }
if (sflags == sfImmediateAck) { if (sflags == sfImmediateAck) {
if (seg->seq > priv->rcv_nxt) { if (seg->seq > priv->rcv_nxt) {
...@@ -1322,7 +1357,11 @@ attempt_send(PseudoTcpSocket *self, SendFlags sflags) ...@@ -1322,7 +1357,11 @@ attempt_send(PseudoTcpSocket *self, SendFlags sflags)
} }
// Nagle algorithm // Nagle algorithm
if ((priv->snd_nxt > priv->snd_una) && (nAvailable < priv->mss)) { // If there is data already in-flight, and we haven't a full segment of
// data ready to send then hold off until we get more to send, or the
// in-flight data is acknowledged.
if (priv->use_nagling && (priv->snd_nxt > priv->snd_una) &&
(nAvailable < priv->mss)) {
return; return;
} }
......
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