コード例 #1
0
ファイル: proxy_common.c プロジェクト: PumpkinSpace/uftp
/**
 * Sets the timeout time for a given group list member
 */
void set_timeout(struct pr_group_list_t *group, int pending_reset, int rescale)
{
    int pending, i;

    if (group->phase == PR_PHASE_READY) {
        if (!rescale) {
            gettimeofday(&group->start_phase_timeout_time, NULL);
        }
        group->phase_timeout_time = group->start_phase_timeout_time;
        add_timeval_d(&group->phase_timeout_time, 2 * group->grtt);
    }

    glog5(group, "set timeout: pending_reset=%d", pending_reset);
    for (pending = 0, i = 0; (i < MAX_PEND) && !pending; i++) {
        if (group->pending[i].msg != 0) {
            glog5(group, "set timeout: found pending %s",
                         func_name(group->pending[i].msg));
            pending = group->pending[i].msg;
        }
    }
    if (pending) {
        if (pending_reset) {
            if (!rescale) {
                gettimeofday(&group->start_timeout_time, NULL);
            }
            group->timeout_time = group->start_timeout_time;
            add_timeval_d(&group->timeout_time, 1 * group->grtt);
        }
    } else {
        if (!rescale) {
            gettimeofday(&group->start_timeout_time, NULL);
        }
        group->timeout_time = group->start_timeout_time;
        if (group->robust * group->grtt < 1.0) {
            add_timeval_d(&group->timeout_time, 1.0);
        } else {
            add_timeval_d(&group->timeout_time, group->robust * group->grtt);
        }
    }
}
コード例 #2
0
ファイル: client_common.c プロジェクト: No9/uftp
/**
 * Sets the timeout time for a given group list member
 */
void set_timeout(struct group_list_t *group, int rescale)
{
    if (!rescale) {
        gettimeofday(&group->start_timeout_time, NULL);
    }
    group->timeout_time = group->start_timeout_time;
    switch (group->phase) {
    case PHASE_REGISTERED:
        add_timeval_d(&group->timeout_time, 4 * group->grtt);
        break;
    case PHASE_RECEIVING:
    case PHASE_MIDGROUP:
        if (group->robust * group->grtt < 1.0) {
            add_timeval_d(&group->timeout_time, 1.0);
        } else {
            add_timeval_d(&group->timeout_time, group->robust * group->grtt);
        }
        break;
    case PHASE_COMPLETE:
        add_timeval_d(&group->timeout_time, 4 * group->grtt);
        break;
    }
}
コード例 #3
0
ファイル: client_transfer.c プロジェクト: No9/uftp
/**
 * Starts a new feedback round under TFMCC
 */
void init_tfmcc_fb_round(struct group_list_t *group, uint16_t new_ccseq)
{
    double urand, backoff;
    group->ccseq = new_ccseq;

    urand = (double)(rand32() + 0.0) / 0xFFFFFFFF;
    if (urand == 0.0) urand = 1.0;
    backoff = 6 * group->grtt * (1 + log(urand) / log(group->gsize));
    if (backoff < 0) backoff = 0.0;
    gettimeofday(&group->cc_time, NULL);
    add_timeval_d(&group->cc_time, (backoff > 0) ? backoff : 0);
    group->initrate = current_cc_rate(group);
    glog3(group, "Starting feedback round %d: backoff = %.3f, initrate = %d",
                 new_ccseq, backoff, group->initrate);
}
コード例 #4
0
ファイル: client_transfer.c プロジェクト: No9/uftp
/**
 * Reads an expected FILESEG and writes it to the proper place in the file
 */
void handle_fileseg(struct group_list_t *group, const unsigned char *message,
                    unsigned meslen, uint16_t txseq)
{
    const struct fileseg_h *fileseg;
    const struct tfmcc_data_info_he *tfmcc;
    const unsigned char *data;
    const uint8_t *he;
    int datalen, section, cache_offset, status_idx;
    uint32_t seq, i;
    unsigned extlen;

    if (group->fileinfo.ftype != FTYPE_REG) {
        glog2(group, "Rejecting FILESEG: not a regular file");
        return;
    }
    fileseg = (const struct fileseg_h *)message;
    data = message + (fileseg->hlen * 4);
    datalen = meslen - (fileseg->hlen * 4);

    if ((meslen < (fileseg->hlen * 4U)) ||
            ((fileseg->hlen * 4U) < sizeof(struct fileseg_h))) {
        glog2(group, "Rejecting FILESEG: invalid message size");
        return;
    }
    if (ntohs(fileseg->file_id) != group->file_id) {
        glog2(group, "Rejecting FILESEG: got incorrect file_id %04X",
                     ntohs(fileseg->file_id));
        return;
    }

    tfmcc = NULL;
    if (fileseg->hlen * 4U > sizeof(struct fileseg_h)) {
        he = (const uint8_t *)fileseg + sizeof(struct fileseg_h);
        if (*he == EXT_TFMCC_DATA_INFO) {
            tfmcc = (const struct tfmcc_data_info_he *)he;
            extlen = tfmcc->extlen * 4U;
            if ((extlen > (fileseg->hlen * 4U) - sizeof(struct fileseg_h)) ||
                    extlen < sizeof(struct tfmcc_data_info_he)) {
                glog2(group, "Rejecting FILESEG: invalid extension size");
                return;
            }
        }
    }

    section = ntohs(fileseg->section);
    if (section >= group->fileinfo.big_sections) {
        seq = (group->fileinfo.big_sections * group->fileinfo.secsize_big) +
                ((section - group->fileinfo.big_sections) *
                group->fileinfo.secsize_small) + ntohs(fileseg->sec_block);
    } else {
        seq = (section * group->fileinfo.secsize_big) +
                ntohs(fileseg->sec_block);
    }

    if ((datalen != group->blocksize) &&
            (seq != group->fileinfo.blocks - 1)) {
        glog2(group, "Rejecting FILESEG: invalid data size %d", datalen);
        return;
    }
    if (log_level >= 5) {
        glog5(group, "Got packet %d", seq);
    } else if (log_level == 4) {
        if (seq != group->fileinfo.last_block + 1) {
            glog4(group, "Got packet %d, last was %d",
                         seq, group->fileinfo.last_block);
        }
    }

    if ((group->cc_type == CC_TFMCC) && tfmcc) {
        handle_tfmcc_data_info(group, tfmcc);
    }

    group->fileinfo.got_data = 1;
    group->fileinfo.last_block = seq;
    if (txseq == group->max_txseq) {
        if ((section > group->fileinfo.last_section) &&
                (group->fileinfo.nak_time.tv_sec == 0)) {
            // Start timer to send NAKs
            gettimeofday(&group->fileinfo.nak_time, NULL);
            add_timeval_d(&group->fileinfo.nak_time, 1 * group->grtt);
            group->fileinfo.nak_section_first = group->fileinfo.last_section;
            group->fileinfo.nak_section_last = section;
            group->fileinfo.got_done = 0;
            glog3(group, "New section, set NAK timer for sections %d - %d",
                         group->fileinfo.nak_section_first,
                         group->fileinfo.nak_section_last);
        }
        group->fileinfo.last_section = section;
    }
    if (group->fileinfo.naklist[seq]) {
        if ((seq >= group->fileinfo.cache_start) &&
                (seq <= group->fileinfo.cache_end + MAXMISORDER)) {
            cache_offset=(seq - group->fileinfo.cache_start) * group->blocksize;
            if (seq > group->fileinfo.cache_end) {
                if ((cache_offset + datalen) > cache_len) {
                    glog4(group, "Disk cache full, flushing");
                    if (!flush_disk_cache(group)) {
                        return;
                    }
                    cache_offset = (seq - group->fileinfo.cache_start) *
                                   group->blocksize;
                } else {
                    for (i = group->fileinfo.cache_end; i <= seq; i++) {
                        if (!group->fileinfo.naklist[i]) {
                            glog3(group, "Cache gap seq %d "
                                         "already received, flushing", i);
                            if (!flush_disk_cache(group)) {
                                return;
                            }
                            group->fileinfo.cache_start = seq;
                            cache_offset = 0;
                            break;
                        }
                    }
                    group->fileinfo.cache_end = seq;
                }
            }
        } else {
            if (group->fileinfo.cache_len != 0) {
                glog3(group, "Seq %d out of cache range, flushing", seq);
                if (!flush_disk_cache(group)) {
                    return;
                }
            }
            cache_offset = 0;
            group->fileinfo.cache_start = seq;
            group->fileinfo.cache_end = seq;
        }
        group->fileinfo.cache_len = ((group->fileinfo.cache_end -
                group->fileinfo.cache_start) * group->blocksize) + datalen;
        status_idx = seq - group->fileinfo.cache_start;
        if (group->fileinfo.cache_len > cache_len) {
            glog0(group, "Cache overrun: "
                         "current cache len = %d, status_idx = %d",
                         group->fileinfo.cache_len, status_idx);
        }
        group->fileinfo.cache_status[status_idx] = 1;
        memcpy(&group->fileinfo.cache[cache_offset], data, datalen);
    }
    set_timeout(group, 0);
}
コード例 #5
0
ファイル: client_announce.c プロジェクト: PumpkinSpace/uftp
/**
 * Read in the contents of an ANNOUNCE.
 */
int read_announce(struct group_list_t *group, unsigned char *packet,
                  union sockaddr_u *src, struct timeval rxtime, int packetlen)
{
    struct uftp_h *header;
    struct announce_h *announce;
    struct enc_info_he *encinfo;
    uint8_t *publicmcast, *privatemcast;
    uint8_t *he;
    unsigned int iplen, extlen;

    header = (struct uftp_h *)packet;
    announce = (struct announce_h *)(packet + sizeof(struct uftp_h));
    encinfo = NULL;

    group->phase = PHASE_REGISTERED;
    group->version = header->version;
    group->group_id = ntohl(header->group_id);
    group->group_inst = header->group_inst;
    group->src_id = header->src_id;
    if (has_proxy) {
        group->replyaddr = proxy_info.addr;
    } else {
        group->replyaddr = *src;
    }
    group->grtt = unquantize_grtt(header->grtt);
    group->rtt = 0;
    group->robust = announce->robust;
    group->cc_type = announce->cc_type;
    group->gsize = unquantize_gsize(header->gsize);
    group->blocksize = ntohs(announce->blocksize);
    group->last_server_ts.tv_sec = ntohl(announce->tstamp_sec);
    group->last_server_ts.tv_usec = ntohl(announce->tstamp_usec);
    group->last_server_rx_ts = rxtime;
    group->restart = ((group->group_inst != 0) && (strcmp(tempdir, "")));
    group->sync_preview = ((announce->flags & FLAG_SYNC_PREVIEW) != 0);
    group->sync_mode = group->sync_preview ||
            ((announce->flags & FLAG_SYNC_MODE) != 0);
    iplen = ((announce->flags & FLAG_IPV6) != 0) ?
                sizeof(struct in6_addr) : sizeof(struct in_addr);
    publicmcast = ((uint8_t *)announce) + sizeof(struct announce_h);
    privatemcast = publicmcast + iplen;
    if ((announce->flags & FLAG_IPV6) != 0) {
        group->multi.sin6.sin6_family = AF_INET6;
#ifdef SOCKADDR_LEN
        group->multi.sin6.sin6_len = sizeof(struct sockaddr_in6);
#endif
        memcpy(&group->multi.sin6.sin6_addr.s6_addr, privatemcast, iplen);
    } else {
        group->multi.sin.sin_family = AF_INET;
#ifdef SOCKADDR_LEN
        group->multi.sin.sin_len = sizeof(struct sockaddr_in);
#endif
        memcpy(&group->multi.sin.sin_addr.s_addr, privatemcast, iplen);
    }
    group->fileinfo.fd = -1;

    if ((announce->hlen * 4U) < sizeof(struct announce_h) + (2U * iplen)) {
        glog1(group, "Rejecting ANNOUNCE from %08X: invalid header size",
                     ntohl(group->src_id));
        send_abort(group, "Invalid header size");
        return 0;
    }
    if ((announce->hlen * 4U) > sizeof(struct announce_h) + (2U * iplen)) {
        he = (unsigned char *)announce + sizeof(struct announce_h) +
                (2U * iplen);
        if (*he == EXT_ENC_INFO) {
            encinfo = (struct enc_info_he *)he;
            extlen = encinfo->extlen * 4U;
            if ((extlen > ((announce->hlen * 4U) -
                            sizeof(struct announce_h))) ||
                    (extlen < sizeof(struct enc_info_he)) ||
                    (extlen != (sizeof(struct enc_info_he) +
                                ntohs(encinfo->keylen) + ntohs(encinfo->dhlen) +
                                ntohs(encinfo->siglen)))) {
                glog1(group, "Rejecting ANNOUNCE from %08X: "
                             "invalid extension size", ntohl(group->src_id));
                send_abort(group, "Invalid extension size");
                return 0;
            }
        }
    }

    if (encinfo != NULL) {
        if (!read_announce_encryption(group, encinfo, packet, packetlen)) {
            return 0;
        }
    } else if (encrypted_only) {
        glog1(group, "No unencrypted transfers allowed");
        send_abort(group, "No unencrypted transfers allowed");
        return 0;
    } else {
        group->keyextype = KEYEX_NONE;
        group->keytype = KEY_NONE;
        group->hashtype = HASH_NONE;
        group->sigtype = SIG_NONE;
        group->client_auth = 0;
    }
    gettimeofday(&group->expire_time, NULL);
    if (4 * group->robust * group->grtt < 1.0) {
        add_timeval_d(&group->expire_time, 1.0);
    } else {
        add_timeval_d(&group->expire_time, 4 * group->robust * group->grtt);
    }
    group->fileinfo.nak_time.tv_sec = 0;
    group->fileinfo.nak_time.tv_usec = 0;

    // Size of data packet, used in transmission speed calculations
    group->datapacketsize = group->blocksize + sizeof(struct fileseg_h);
    if (group->cc_type == CC_TFMCC) {
        group->datapacketsize += sizeof(struct tfmcc_data_info_he);
    }
    if (group->keytype != KEY_NONE) {
        group->datapacketsize += ((group->sigtype == SIG_KEYEX) ?
                group->server_pubkeylen : (group->sigtype == SIG_HMAC) ?
                group->hmaclen : 0) + KEYBLSIZE + sizeof(struct encrypted_h);
    }
    // 8 = UDP size, 20 = IPv4 size, 40 = IPv6 size
    if ((announce->flags & FLAG_IPV6) != 0) {
        group->datapacketsize += sizeof(struct uftp_h) + 8 + 40;
    } else {
        group->datapacketsize += sizeof(struct uftp_h) + 8 + 20;
    }

    if (group->cc_type != CC_NONE) {
        group->loss_history= safe_calloc(0x10000,sizeof(struct loss_history_t));
        group->slowstart = 1;
        group->seq_wrap = 0;
        group->start_txseq = ntohs(header->seq);
        group->max_txseq = group->start_txseq;
        group->loss_history[group->start_txseq].found = 1;
        group->loss_history[group->start_txseq].t = rxtime;
        group->loss_history[group->start_txseq].size = packetlen;
    }

    return 1;
}