Пример #1
0
size_t
LiteFrag::receive(uint8_t* buf, size_t bufSize, uint64_t& endpointId)
{
  if (m_rbuf == nullptr) {
    LITEFRAG_DBG(F("receive err=no-buffer"));
    return 0;
  }

  while (true) {
    ReassHdr* hdr = reinterpret_cast<ReassHdr*>(m_rbuf + m_offset);
    size_t room = m_rbufSize - m_offset - sizeof(hdr->len);
    uint8_t* fragBuf = &hdr->b0;
    uint16_t fragLen = static_cast<uint16_t>(inner.receive(fragBuf, room, endpointId));
    if (fragLen == 0) { // no incoming packet
      return 0;
    }
    if ((hdr->b0 & LiteFragHdr_b0_HB) == 0) { // no header bit
      continue;
    }
    memcpy(&hdr->len, &fragLen, sizeof(hdr->len));
    uint16_t totalLen = sizeof(hdr->len) + fragLen;

    uint16_t id;
    memcpy(&id, &hdr->id, sizeof(id));
    uint8_t seq = hdr->b0 & LiteFragHdr_b0_SEQ_MASK;

    if (seq == 0) {
      if (m_offset != 0) {
        LITEFRAG_DBG(F("discard-incomplete id=") << m_id << F(" frags=") << m_nextSeq);
        memmove(m_rbuf, hdr, totalLen);
        hdr = reinterpret_cast<ReassHdr*>(m_rbuf);
        m_offset = 0;
      }
    }
    else if (id != m_id || seq != m_nextSeq) {
      LITEFRAG_DBG(F("drop-ooo want=(") << m_id << "," << m_nextSeq <<
                   F(") got=(") << id << "," << seq << ")");
      continue;
    }

    // accept
    m_offset += totalLen;
    m_id = id;
    m_nextSeq = seq + 1;

    if ((hdr->b0 & LiteFragHdr_b0_MF) != 0) { // last frag
      size_t size = reassemble(buf, bufSize);
      m_offset = 0;
      return size;
    }
  }
  return 0;
}
Пример #2
0
void rolldown(queue *q, int p, int d[4])
{
    int i, v, t;
    dprintf("roll down\n");
    for (i = 0; i < 4; i++) {
        t = d[i];
        if (t == 0) d[i] = 9;
        else --d[i];
        v = reassemble(d);
        if (!visited[v]) enqueue(q, v);
        press_cnt[v] = press_cnt[p] + 1;;
        d[i] = t;
    }
}
Пример #3
0
void rollup(queue *q, int p, int d[4])
{
    int i, v, t;
    dprintf("roll up:\n");
    for (i = 0; i < 4; i++) {
        t = d[i]; /* save original */
        ++d[i];
        d[i] %= 10;
        v = reassemble(d);
        if (!visited[v]) enqueue(q, v);
        press_cnt[v] = press_cnt[p] + 1;;
        d[i] = t; /* restore original */
    }
}
Пример #4
0
void do_auto(const char *const *argv) {
    const char *partfile;
    struct partinfo *pi, *refi, *npi, **partlist, *otherthispart;
    struct partqueue *pq;
    unsigned int i;
    int j, ap;
    long nr;
    FILE *part;
    void *buffer;
    char *p, *q;

    if (!opt_outputfile)
        badusage(_("--auto requires the use of the --output option"));
    if (!(partfile= *argv++) || *argv)
        badusage(_("--auto requires exactly one part file argument"));

    refi= nfmalloc(sizeof(struct partqueue));
    part= fopen(partfile,"r");
    if (!part) ohshite(_("unable to read part file `%.250s'"),partfile);
    if (!read_info(part,partfile,refi)) {
        if (!opt_npquiet)
            printf(_("File `%.250s' is not part of a multipart archive.\n"),partfile);
        m_output(stdout, _("<standard output>"));
        exit(1);
    }
    fclose(part);
    scandepot();
    partlist= nfmalloc(sizeof(struct partinfo*)*refi->maxpartn);
    for (i = 0; i < refi->maxpartn; i++)
        partlist[i] = NULL;
    for (pq= queue; pq; pq= pq->nextinqueue) {
        pi= &pq->info;
        if (!partmatches(pi,refi)) continue;
        npi= nfmalloc(sizeof(struct partinfo));
        mustgetpartinfo(pi->filename,npi);
        addtopartlist(partlist,npi,refi);
    }
    /* If we already have a copy of this version we ignore it and prefer the
     * new one, but we still want to delete the one in the depot, so we
     * save its partinfo (with the filename) for later. This also prevents
     * us from accidentally deleting the source file. */
    otherthispart= partlist[refi->thispartn-1];
    partlist[refi->thispartn-1]= refi;
    for (j=refi->maxpartn-1; j>=0 && partlist[j]; j--);

    if (j>=0) {

        part= fopen(partfile,"r");
        if (!part) ohshite(_("unable to reopen part file `%.250s'"),partfile);
        buffer= nfmalloc(refi->filesize);
        nr= fread(buffer,1,refi->filesize,part);
        if (nr != refi->filesize) rerreof(part,partfile);
        if (getc(part) != EOF) ohshit(_("part file `%.250s' has trailing garbage"),partfile);
        if (ferror(part)) rerr(partfile);
        fclose(part);
        p = nfmalloc(strlen(opt_depotdir) + 50);
        q = nfmalloc(strlen(opt_depotdir) + 200);
        sprintf(p, "%st.%lx", opt_depotdir, (long)getpid());
        sprintf(q, "%s%s.%lx.%x.%x", opt_depotdir, refi->md5sum,
                refi->maxpartlen,refi->thispartn,refi->maxpartn);
        part= fopen(p,"w");
        if (!part) ohshite(_("unable to open new depot file `%.250s'"),p);
        nr= fwrite(buffer,1,refi->filesize,part);
        if (nr != refi->filesize) werr(p);
        if (fflush(part))
            ohshite(_("unable to flush file '%s'"), p);
        if (fsync(fileno(part)))
            ohshite(_("unable to sync file '%s'"), p);
        if (fclose(part)) werr(p);
        if (rename(p,q)) ohshite(_("unable to rename new depot file `%.250s' to `%.250s'"),p,q);

        printf(_("Part %d of package %s filed (still want "),refi->thispartn,refi->package);
        /* There are still some parts missing. */
        for (i=0, ap=0; i<refi->maxpartn; i++)
            if (!partlist[i])
                printf("%s%d", !ap++ ? "" : i == (unsigned int)j ? _(" and ") : ", ", i + 1);
        printf(").\n");

        dir_sync_path(opt_depotdir);
    } else {

        /* We have all the parts. */
        reassemble(partlist, opt_outputfile);

        /* OK, delete all the parts (except the new one, which we never copied). */
        partlist[refi->thispartn-1]= otherthispart;
        for (i=0; i<refi->maxpartn; i++)
            if (partlist[i])
                if (unlink(partlist[i]->filename))
                    ohshite(_("unable to delete used-up depot file `%.250s'"),partlist[i]->filename);

    }

    m_output(stderr, _("<standard error>"));
}
Пример #5
0
int
do_auto(const char *const *argv)
{
  const char *partfile;
  struct partinfo *refi, **partlist, *otherthispart;
  struct partqueue *pq;
  unsigned int i;
  int j;
  FILE *part;

  if (!opt_outputfile)
    badusage(_("--auto requires the use of the --output option"));
  if (!(partfile= *argv++) || *argv)
    badusage(_("--auto requires exactly one part file argument"));

  refi= nfmalloc(sizeof(struct partqueue));
  part= fopen(partfile,"r");
  if (!part) ohshite(_("unable to read part file `%.250s'"),partfile);
  if (!read_info(part,partfile,refi)) {
    if (!opt_npquiet)
      printf(_("File `%.250s' is not part of a multipart archive.\n"),partfile);
    m_output(stdout, _("<standard output>"));
    return 1;
  }
  fclose(part);
  scandepot();
  partlist= nfmalloc(sizeof(struct partinfo*)*refi->maxpartn);
  for (i = 0; i < refi->maxpartn; i++)
    partlist[i] = NULL;
  for (pq= queue; pq; pq= pq->nextinqueue) {
    struct partinfo *npi, *pi = &pq->info;

    if (!partmatches(pi,refi)) continue;
    npi= nfmalloc(sizeof(struct partinfo));
    mustgetpartinfo(pi->filename,npi);
    addtopartlist(partlist,npi,refi);
  }
  /* If we already have a copy of this version we ignore it and prefer the
   * new one, but we still want to delete the one in the depot, so we
   * save its partinfo (with the filename) for later. This also prevents
   * us from accidentally deleting the source file. */
  otherthispart= partlist[refi->thispartn-1];
  partlist[refi->thispartn-1]= refi;
  for (j=refi->maxpartn-1; j>=0 && partlist[j]; j--);

  if (j>=0) {
    int fd_src, fd_dst;
    int ap;
    char *p, *q;

    m_asprintf(&p, "%st.%lx", opt_depotdir, (long)getpid());
    m_asprintf(&q, "%s%s.%jx.%x.%x", opt_depotdir, refi->md5sum,
               (intmax_t)refi->maxpartlen, refi->thispartn, refi->maxpartn);

    fd_src = open(partfile, O_RDONLY);
    if (fd_src < 0)
      ohshite(_("unable to reopen part file `%.250s'"), partfile);
    fd_dst = creat(p, 0644);
    if (fd_dst < 0)
      ohshite(_("unable to open new depot file `%.250s'"), p);

    fd_fd_copy(fd_src, fd_dst, refi->filesize, _("extracting split part"));

    if (fsync(fd_dst))
      ohshite(_("unable to sync file '%s'"), p);
    if (close(fd_dst))
      ohshite(_("unable to close file '%s'"), p);
    close(fd_src);

    if (rename(p,q)) ohshite(_("unable to rename new depot file `%.250s' to `%.250s'"),p,q);
    free(q);
    free(p);

    printf(_("Part %d of package %s filed (still want "),refi->thispartn,refi->package);
    /* There are still some parts missing. */
    for (i=0, ap=0; i<refi->maxpartn; i++)
      if (!partlist[i])
        printf("%s%d", !ap++ ? "" : i == (unsigned int)j ? _(" and ") : ", ", i + 1);
    printf(").\n");

    dir_sync_path(opt_depotdir);
  } else {

    /* We have all the parts. */
    reassemble(partlist, opt_outputfile);

    /* OK, delete all the parts (except the new one, which we never copied). */
    partlist[refi->thispartn-1]= otherthispart;
    for (i=0; i<refi->maxpartn; i++)
      if (partlist[i])
        if (unlink(partlist[i]->filename))
          ohshite(_("unable to delete used-up depot file `%.250s'"),partlist[i]->filename);

  }

  m_output(stderr, _("<standard error>"));

  return 0;
}