int curvecpr_client_connected (struct curvecpr_client *client) { struct curvecpr_client_cf *cf = &client->cf; struct curvecpr_session *s = &client->session; struct curvecpr_packet_hello p; /* Copy some data into the session. */ curvecpr_bytes_copy(s->their_extension, cf->their_extension, 16); curvecpr_bytes_copy(s->their_global_pk, cf->their_global_pk, 32); /* Generate keys. */ s->my_session_nonce = curvecpr_util_random_mod_n(281474976710656LL); crypto_box_keypair(s->my_session_pk, s->my_session_sk); crypto_box_beforenm(s->my_session_their_global_key, s->their_global_pk, s->my_session_sk); crypto_box_beforenm(s->my_global_their_global_key, s->their_global_pk, cf->my_global_sk); /* Packet identifier. */ curvecpr_bytes_copy(p.id, "QvnQ5XlH", 8); /* Extensions. */ curvecpr_bytes_copy(p.server_extension, s->their_extension, 16); curvecpr_bytes_copy(p.client_extension, cf->my_extension, 16); /* The client's session-specific public key. */ curvecpr_bytes_copy(p.client_session_pk, s->my_session_pk, 32); /* A series of zero bytes for padding. */ curvecpr_bytes_copy(p._, _zeros, 64); /* The encrypted data (again, all zeros). Nonce generation is included. */ { unsigned char nonce[24]; unsigned char data[96] = { 0 }; /* The nonce for the upcoming encrypted data. */ curvecpr_bytes_copy(nonce, "CurveCP-client-H", 16); curvecpr_session_next_nonce(s, nonce + 16); curvecpr_bytes_copy(p.nonce, nonce + 16, 8); /* Actual encryption. */ crypto_box_afternm(data, _zeros, 96, nonce, s->my_session_their_global_key); curvecpr_bytes_copy(p.box, data + 16, 80); } if (cf->ops.send(client, (const unsigned char *)&p, sizeof(struct curvecpr_packet_hello))) return -EAGAIN; return 0; }
static void _update (struct curvecpr_chicago *chicago, long long rtt_ns) { chicago->rtt_latest = rtt_ns; /* Initialization. */ if (!chicago->rtt_average) { chicago->wr_rate = chicago->rtt_latest; chicago->rtt_average = chicago->rtt_latest; chicago->rtt_deviation = chicago->rtt_latest / 2; chicago->rtt_highwater = chicago->rtt_latest; chicago->rtt_lowwater = chicago->rtt_latest; } /* Jacobson's retransmission timeout calculation. */ long long rtt_delta = chicago->rtt_latest - chicago->rtt_average; chicago->rtt_average += rtt_delta / 8; if (rtt_delta < 0) rtt_delta = -rtt_delta; rtt_delta -= chicago->rtt_deviation; chicago->rtt_deviation += rtt_delta / 4; chicago->rtt_timeout = chicago->rtt_average + 4 * chicago->rtt_deviation; /* Adjust for delayed acknowledgements with anti-spiking. */ chicago->rtt_timeout += 8 * chicago->wr_rate; /* Recognize top and bottom of congestion cycle. */ rtt_delta = chicago->rtt_latest - chicago->rtt_highwater; chicago->rtt_highwater += rtt_delta / 1024; rtt_delta = chicago->rtt_latest - chicago->rtt_lowwater; if (rtt_delta > 0) chicago->rtt_lowwater += rtt_delta / 8192; else chicago->rtt_lowwater += rtt_delta / 256; if (chicago->rtt_average > chicago->rtt_highwater + 5000000) chicago->seen_recent_high = 1; else if (chicago->rtt_average < chicago->rtt_lowwater) chicago->seen_recent_low = 1; /* Should we update? Only after we've seen ~16 packets. */ if (chicago->clock >= chicago->ns_last_update + 16 * chicago->wr_rate) { /* Maybe it's been too long (bad timeout -- 10 seconds)... */ if (chicago->clock - chicago->ns_last_update > 10000000000LL) { chicago->wr_rate = 1000000000; chicago->wr_rate += curvecpr_util_random_mod_n(chicago->wr_rate / 8); } chicago->ns_last_update = chicago->clock; if (chicago->wr_rate >= 131072) { /* Additive increase: adjust 1/N by a constant c. * * RTT-fair additive increase: adjust 1/N by a constant c every N * nanoseconds. * * Approximation: adjust 1/N by cN every N nanoseconds (i.e., * N <- 1/(1/N + cN) = N/(1 + cN^2) every N nanoseconds). */ if (chicago->wr_rate < 16777216) { /* N/(1 + cN^2) ~= N - cN^3 */ long long u = chicago->wr_rate / 131072; chicago->wr_rate -= u * u * u; } else { double d = chicago->wr_rate; chicago->wr_rate = d / (1 + d * d / 2251799813685248.0); } } if (chicago->rtt_phase == 0) { if (chicago->seen_older_high) { chicago->rtt_phase = 1; chicago->ns_last_edge = chicago->clock; chicago->wr_rate += curvecpr_util_random_mod_n(chicago->wr_rate / 4); } } else { if (chicago->seen_older_low) chicago->rtt_phase = 0; } chicago->seen_older_high = chicago->seen_recent_high; chicago->seen_older_low = chicago->seen_recent_low; chicago->seen_recent_high = 0; chicago->seen_recent_low = 0; _try_update_rates(chicago); } }