Beispiel #1
0
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;
}
Beispiel #2
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);
    }
}