Example #1
0
/*{{{  _quit -- really quit*/
int _quit()
   {
   register WINDOW *win;
   static int really_quit=0;

   if (really_quit++) {
   /* we're in bad shape */
      perror("PANIC!!  Error during _quit()!");
      setreuid(getuid(),getuid());
      abort();
      }

   MOUSE_OFF(screen,mousex,mousey);

   sleep(1);		/* let the key (if any) un-press before resetting
			the kbd */
   set_kbd(0);		/* fix up keyboard modes */
   kbd_reset();		/* reset the keyboard */
   reset_tty(0);	/* fix up console tty modes */
#ifdef MOVIE
   end_log(); 		/* turn off logging */
#endif

   /* fix pttys */
   if (geteuid() < 2)
      for(win=active;win != (WINDOW *) 0;win=W(next))
      {
	 if (W(pid)>1) killpg(W(pid),SIGHUP);
         chmod(W(tty),0666);
         chown(W(tty),0,0);
         }

   /* fix utmp file */

#ifdef WHO
   close(getdtablesize()-1); /* make sure there are enough fd's left */
   for(win=active;win != (WINDOW *) 0;win=W(next))
      if (W(tty))
          rm_utmp(W(tty));
#endif

   CLEAR(screen,BIT_CLR);
   do_cmd( 'q' );	/* do the quiting command */
	bit_destroy(screen);
   }
Example #2
0
int main(int argc, char *argv[])
{
  BITMAP *bp;
  int i;

#ifdef MOVIE
  log_start(fopen("lines.log","w"));
#endif
  bp=bit_open(SCREEN_DEV);
  bit_blit(bp,0,0,BIT_WIDE(bp),BIT_HIGH(bp),BIT_CLR,(BITMAP*)0,0,0);
  srand(getpid()*time((time_t*)0));
  for (i=0; i<1000; i++)
  bit_line(bp,rand()%BIT_WIDE(bp),rand()%BIT_HIGH(bp),rand()%BIT_WIDE(bp),rand()%BIT_HIGH(bp),BIT_SET);
  bit_destroy(bp);
#ifdef MOVIE
  log_end();
#endif
  exit(0);
}
Example #3
0
int CS_put(struct content_obj * content)
{
    content = content_copy(content);
    log_assert(g_log, content != NULL, "CS: failed to allocate content");

    pthread_mutex_lock(&_cs.lock);
    struct CS_segment * segment = (struct CS_segment * )
        hash_get(_cs.table, content_prefix(content->name));
    pthread_mutex_unlock(&_cs.lock);

    int rv = 0;
    if (content_is_segmented(content->name)) {

        if (segment) {

            pthread_mutex_lock(&segment->lock);

            int seq_no = content_seq_no(content->name);
            if (seq_no >= segment->num_chunks) {
                segment->chunks = realloc(segment->chunks, sizeof(struct content_obj * ) * (seq_no + 1));
                segment->num_chunks = seq_no + 1;
                segment->chunks[seq_no] = content;
                struct bitmap * larger = bit_create(segment->num_chunks);
                memcpy(larger->map, segment->valid->map, segment->valid->num_words);
                bit_destroy(segment->valid);
                segment->valid = larger;
                bit_set(larger, seq_no);
            } else {
                if (bit_test(segment->valid, seq_no)) {
                    content_obj_destroy(segment->chunks[seq_no]);
                }
                segment->chunks[seq_no] = content;
                bit_set(segment->valid, seq_no);
            }

            pthread_mutex_unlock(&segment->lock);

        } else {
            rv = -1;
        }

    } else {

        if (!segment) {

            segment = malloc(sizeof(struct CS_segment));
            /* this is a content matching a prefix */
            char * key = malloc(strlen(content->name->full_name));
            strcpy(key, content->name->full_name);
            segment->index_chunk = content;
            segment->chunks = NULL;
            segment->num_chunks = -1;
            segment->valid = bit_create(0);
            pthread_mutex_init(&segment->lock, NULL);

            pthread_mutex_lock(&_cs.lock);
            hash_put(_cs.table, key, (void * ) segment);
            pthread_mutex_unlock(&_cs.lock);

        } else {

            pthread_mutex_lock(&segment->lock);

            if (segment->index_chunk) {
                content_obj_destroy(segment->index_chunk);
            }
            segment->index_chunk = content;

            pthread_mutex_unlock(&segment->lock);

        }
    }

    return rv;
}
Example #4
0
/*{{{  main*/
int main(int argc, char *argv[])
{
  /*{{{  variables*/
  enum { NOTHING, LOCAL, REMOTE } in=NOTHING;
  int c;
  int x,y;
  int mouse_x,mouse_y;
  int image_width,image_height;
  int image_xoffset=0,image_yoffset=0;
  int my_width,my_height;
  int err=0,usage=0;
  BITMAP *bp;
  FILE *input;
  static struct menu_entry menu[] = { { "quit","q" } };
  char file[_POSIX_PATH_MAX];
  /*}}}  */

  /*{{{  parse arguments*/
  while ((c=getopt(argc,argv,"l:r:"))!=EOF)
  {
    switch (c)
    {
      /*{{{  l file*/
      case 'l':
      {
        if ((input=fopen(optarg,"r"))==(FILE*)0)
        {
          fprintf(stderr,"%s: Can't open %s\r\n",argv[0],optarg);
          err=1;
        }
        else in=LOCAL;
        break;
      }
      /*}}}  */
      /*{{{  r file*/
      case 'r':
      {
        char *cwd;

        in=REMOTE;
        if (*optarg!='/' && *optarg!='.')
        {
          if ((cwd=getcwd((char*)0,(size_t)0))!=(char*)0) { strcpy(file,cwd); strcat(file,"/"); strcat(file,optarg); }
          else { fprintf(stderr,"%s: Can't get current directory\r\n",argv[0]); err=1; }
        }
        else strcpy(file,optarg);
        break;
      }
      /*}}}  */
      /*{{{  default*/
      default:
      {
        usage=1;
        break;
      }
      /*}}}  */
    }
  }
  if (err) exit(err);
  if (usage || optind!=argc)
  {
    fprintf(stderr,"Usage: mgrview [-l file | -r file]\n");
    exit(1);
  }
  if (in==NOTHING) { in=LOCAL; input=stdin; }
  /*}}}  */
  /*{{{  setup*/
  ckmgrterm(argv[0]);
  m_setup(M_MODEOK);
  signal(SIGINT,clean);
  signal(SIGTERM,clean);
  signal(SIGPIPE,clean);
  m_ttyset();
  m_push(P_MENU|P_EVENT|P_FLAGS);
  m_setmode(M_ABS);
  m_setcursor(CS_INVIS);
  menu_load(1,1,menu);
  m_setevent(REDRAW, "R");
  m_setevent(RESHAPE, "R");
  m_setevent(BUTTON_1,"[%p]");
  m_setevent(BUTTON_2,"m");
  m_flush();
  /*}}}  */
  if (in==LOCAL)
  {
    /*{{{  load bitmap to client space*/
    if ((bp=bitmapread(input))==(BITMAP*)0)
    {
      fprintf(stderr,"%s: No MGR bitmap.\r\n",argv[0]);
      clean(1);
    }
    image_width=BIT_WIDE(bp);
    image_height=BIT_HIGH(bp);
    /*}}}  */
    /*{{{  transfer bitmap to server space*/
    m_func(BIT_SRC);
    m_bitcreate(IMAGE_BITMAP,image_width,image_height);
    m_bitldto(image_width,image_height,0,0,IMAGE_BITMAP,bit_size(image_width,image_height,BIT_DEPTH(bp)));
    fwrite(BIT_DATA(bp),bit_size(image_width,image_height,BIT_DEPTH(bp)),1,m_termout);
    m_flush();
    bit_destroy(bp);
    /*}}}  */
  }
  else if (in==REMOTE)
  {
    /*{{{  transfer bitmap from server fs to server space*/
    m_bitfromfile(IMAGE_BITMAP,file);
    m_get();
    if (sscanf(m_linebuf,"%d %d",&image_width,&image_height)<2)
    {
      fprintf(stderr,"%s: No MGR bitmap.\r\n",argv[0]);
      clean(1);
    }
    /*}}}  */
  }
  /*{{{  user interaction*/
  get_size((int*)0,(int*)0,&my_width,&my_height);
  display(image_xoffset,image_yoffset,my_width,my_height,image_width,image_height);
  m_flush();
  while ((c=getc(m_termin))!='q') switch (c)
  {
    /*{{{  m -- left button displays menu*/
    case 'm':
    {
      m_selectmenu(1);
      m_flush();
      break;
    }
    /*}}}  */
    /*{{{  [%d %d] -- right button*/
    case '[':
    {
      fscanf(m_termin,"%d %d]",&mouse_x,&mouse_y);
      /*{{{  compute new x start*/
      if (my_width>image_width) image_xoffset=0;
      else if (mouse_x<=0) image_xoffset=0;
      else if (mouse_x>=my_width) image_xoffset=my_width-image_width;
      else
      {
        /*{{{  move x start by difference from mouse and middle*/
        image_xoffset=image_xoffset-(mouse_x-my_width/2);
        /*}}}  */
        /*{{{  check and corrent range of x start*/
        if (image_xoffset<my_width-image_width) image_xoffset=my_width-image_width;
        else if (image_xoffset>0) image_xoffset=0;
        /*}}}  */
      }
      /*}}}  */
      /*{{{  compute new y start*/
      if (my_height>image_height) image_yoffset=0;
      else if (mouse_y<=0) image_yoffset=0;
      else if (mouse_y>=my_height) image_yoffset=my_height-image_height;
      else
      {
        /*{{{  move y start by difference from mouse and middle*/
        image_yoffset=image_yoffset-(mouse_y-my_height/2);
        /*}}}  */
        /*{{{  check and corrent range of y start*/
        if (image_yoffset<my_height-image_height) image_yoffset=my_height-image_height;
        else if (image_yoffset>0) image_yoffset=0;
        /*}}}  */
      }
      /*}}}  */
      display(image_xoffset,image_yoffset,my_width,my_height,image_width,image_height);
      m_flush();
      break;
    }
    /*}}}  */
    /*{{{  R -- redraw*/
    case 'R':
    {
      get_size((int*)0,(int*)0,&my_width,&my_height);
      /*{{{  compute new x offset*/
      if (my_width<image_width)
      {
        if (image_xoffset<my_width-image_width) image_xoffset=my_width-image_width;
      }
      else image_xoffset=0;
      /*}}}  */
      /*{{{  compute new y offset*/
      if (my_height<image_height)
      {
        if (image_yoffset<my_height-image_height) image_yoffset=my_height-image_height;
      }
      else image_yoffset=0;
      /*}}}  */
      m_func(BIT_CLR);
      m_bitwrite(0,0,my_width,my_height);
      m_func(BIT_SRC);
      m_bitcopyto(image_xoffset,image_yoffset,image_width,image_height,0,0,WINDOW_BITMAP,IMAGE_BITMAP);
      m_flush();
      break;
    }
    /*}}}  */
  }
  /*}}}  */
  /*{{{  exit*/
  m_bitdestroy(IMAGE_BITMAP);
  get_colrow(&x,&y);
  m_move(0,y-1);
  clean(0);
  /* NOTREACHED */
  return 255;
  /*}}}  */
}
Example #5
0
/*{{{  main*/
int main(int argc, char *argv[])
{
  /*{{{  variables*/
  int x, login_y, password_y;
  char loginstr[9], passwordstr[9], ret;
  char ttystr[_POSIX_PATH_MAX];
  char *background = (char *)0;
  char *fontname = (char *)0;
  /*}}}  */

  /*{{{  parse arguments*/
  {
    int c;

    while ((c = getopt(argc, argv, "b:f:")) != EOF)
      switch (c) {
      case 'b':
        background = optarg;
        break;
      case 'f':
        fontname = optarg;
        break;
      }
    /*{{{  parse tty*/
    {
      int tty;

      if (optind + 1 > argc) {
        fprintf(stderr, "Usage: %s tty\n", argv[0]);
        exit(1);
      } else {
        strcpy(ttystr, "/dev/");
        strcat(ttystr, argv[optind++]);
      }
      close(0);
      close(1);
      close(2);
      setsid();
      if ((tty = open(ttystr, O_RDWR)) != 0) {
        fprintf(stderr, "%s: Can't open controlling terminal on fd 0.\n", argv[0]);
        exit(1);
      }
      fchmod(tty, 0600);
      fchown(tty, getuid(), getgid());
      open(argv[optind], O_RDWR);
      open(argv[optind], O_RDWR);
    }
    /*}}}  */
  }
  /*}}}  */
  /*{{{  get into grafics mode*/
  signal(SIGTERM, quit);
  signal(SIGHUP, quit);
  set_tty(0);
  if ((screen = bit_open(SCREEN_DEV)) == (BITMAP *)0) {
    reset_tty(0);
    exit(EX_NOPERM);
  }
  bit_grafscreen();
  /*}}}  */
  /*{{{  load font*/
  if (fontname) {
    char fontpath[_POSIX_PATH_MAX];

    if (*fontname == '/' || *fontname == '.')
      strcpy(fontpath, fontname);
    else {
      strcpy(fontpath, ICONDIR);
      strcat(fontpath, "/");
      strcat(fontpath, fontname);
    }

    if ((font = open_font(fontname)) == (struct font *)0)
      font = open_font((char *)0);
  } else
    font = open_font((char *)0);
  /*}}}  */
  /*{{{  draw background*/
  bit_blit(screen, 0, 0, screen->wide, screen->high, BIT_CLR, (BITMAP *)0, 0, 0);
  if (background) {
    BITMAP *bp;
    FILE *fp;
    char backgroundpath[_POSIX_PATH_MAX];

    if (*background == '/' || *background == '.')
      strcpy(backgroundpath, background);
    else {
      strcpy(backgroundpath, ICONDIR);
      strcat(backgroundpath, "/");
      strcat(backgroundpath, background);
    }

    if ((fp = fopen(backgroundpath, "r")) != (FILE *)0 && (bp = bitmapread(fp)) != (BITMAP *)0) {
      int x, y;

      for (x = 0; x < screen->wide; x += bp->wide)
        bit_blit(
            screen,
            x, 0,
            screen->wide - x < bp->wide ? screen->wide - x : bp->wide,
            bp->high,
            BIT_SRC, bp, 0, 0);

      for (y = 0; y < screen->high; y += bp->high)
        bit_blit(
            screen,
            0, y,
            screen->wide,
            screen->high - y < bp->high ? screen->high - y : bp->high,
            BIT_SRC, screen, 0, 0);
    }
  }
  /*}}}  */
  /*{{{  draw hostname*/
  {
    int bx, bw, by, bh;
    char hostname[_POSIX_PATH_MAX];
    struct hostent *h;

    gethostname(hostname, sizeof(hostname));
    if ((h = gethostbyname(hostname)) != (struct hostent *)0)
      strcpy(hostname, h->h_name);
    bw = font->head.wide * (strlen(hostname) + 2);
    bh = 2 * font->head.high;
    bx = (screen->wide - bw) / 2;
    by = screen->high / 6 - bh / 2;
    cutebox(bx, by, bw, bh);
    printstr(bx + font->head.wide, by + bh - font->head.high / 2, hostname);
  }
  /*}}}  */
  /*{{{  draw login box*/
  {
    int bx, bw, by, bh;

    bx = (screen->wide - font->head.wide * 40) / 2;
    by = (screen->high - font->head.high * 8) / 2;
    bw = font->head.wide * 40;
    bh = font->head.high * 8;
    cutebox(bx, by, bw, bh);
  }
  /*}}}  */
  /*{{{  draw login box contents*/
  x = (screen->wide - font->head.wide * 18) / 2;
  login_y = screen->high / 2 - font->head.wide / 6;
  password_y = screen->high / 2 + font->head.high / 6 + font->head.high;
  printstr(x, password_y, "Password:         "******"Press ESC for terminal login");
  /*}}}  */
  while (1) {
    /*{{{  get login and password or escape*/
    printstr(x, login_y, "Login:            "******"mgr", (char *)0 };
        int i;

        sprintf(env_user, "USER=%s", pw->pw_name);
        sprintf(env_logname, "LOGNAME=%s", pw->pw_name);
        sprintf(env_home, "HOME=%s", pw->pw_dir);
        sprintf(env_shell, "SHELL=%s", pw->pw_shell == (char *)0 || pw->pw_shell[0] == '\0' ? "/bin/sh" : pw->pw_shell);
        sprintf(env_path, "PATH=%s", PATH);
        sprintf(env_mail, "MAIL=%s/%s", MAILDIR, pw->pw_name);
        if (chdir(pw->pw_dir) != 0)
          chdir("/");
        if (ttyname(0)) {
          chown(ttyname(0), pw->pw_uid, pw->pw_gid);
          chmod(ttyname(0), 0600);
        }
        for (i = 1; i <= _NSIG; i++)
          signal(i, SIG_DFL);
        bit_destroy(screen);
        reset_tty(0);
        initgroups(pw->pw_name, pw->pw_gid);
        setgid(pw->pw_gid);
        setuid(pw->pw_uid);
        sprintf(mgrlogin, "%s/.mgrlogin", pw->pw_dir);
        execve(mgrlogin, login_argv, login_env);
        execve(MGR_BINARY, login_argv, login_env);
        exit(EX_OSFILE);
      }
      /*}}}  */
      else
      /*{{{  incorrect login*/
      {
        printstr((screen->wide - font->head.wide * 16) / 2, login_y + 3 * font->head.high,
            "Login incorrect");
      }
      /*}}}  */
    }
    /*}}}  */
  }
}
Example #6
0
/*{{{  quit*/
__attribute__((noreturn)) void quit(int sig)
{
  bit_destroy(screen);
  reset_tty(0);
  exit(1);
}
Example #7
0
/*{{{  shape -- reshape a window to specified dimensions*/
int shape(int x, int y, int dx, int dy)
{
  int sx, sy, w, h;
  WINDOW *win;

  if (dx > 0) {
    sx = x;
    w = dx;
  } else {
    sx = x + dx;
    w = -dx;
  }
  if (dy > 0) {
    sy = y;
    h = dy;
  } else {
    sy = y + dy;
    h = -dy;
  }

  if (sx < 0)
    sx = 0;

  if (sx + w >= BIT_WIDE(screen))
    w = BIT_WIDE(screen) - sx;

  if (sy + h >= BIT_HIGH(screen))
    h = BIT_HIGH(screen) - sy;

  if (w < 2 * ACTIVE(borderwid) + ACTIVE(font)->head.wide * MIN_X || h < 2 * ACTIVE(borderwid) + ACTIVE(font)->head.high * MIN_Y)
    return (-1);

#ifdef MGR_ALIGN
  alignwin(screen, &sx, &w, ACTIVE(borderwid));
#endif

  /* remove current window position */
  save_win(active);
  erase_win(ACTIVE(border));
  clip_bad(active); /* invalidate clip lists */

  /* redraw remaining windows */
  repair(active);

  /* adjust window state */
  ACTIVE(x0) = sx;
  ACTIVE(y0) = sy;
  bit_destroy(ACTIVE(window));
  bit_destroy(ACTIVE(border));
  ACTIVE(border) = bit_create(screen, sx, sy, w, h);
  ACTIVE(window) = bit_create(ACTIVE(border),
      ACTIVE(borderwid),
      ACTIVE(borderwid),
      w - ACTIVE(borderwid) * 2,
      h - ACTIVE(borderwid) * 2);

  for (win = ACTIVE(next); win != (WINDOW *)0; win = W(next)) {
    if (W(flags) & W_ACTIVE && intersect(active, win))
      save_win(win);
  }

  CLEAR(ACTIVE(window), PUTOP(BIT_CLR, ACTIVE(style)));

  border(active, BORDER_THIN);
  bit_blit(ACTIVE(border), 0, 0,
      BIT_WIDE(ACTIVE(save)) - ACTIVE(borderwid),
      BIT_HIGH(ACTIVE(save)) - ACTIVE(borderwid),
      BIT_SRC, ACTIVE(save), 0, 0);

  /* make sure character cursor is in a good spot */
  if (ACTIVE(x) > BIT_WIDE(ACTIVE(window))) {
    ACTIVE(x) = 0;
    ACTIVE(y) += ((int)(ACTIVE(font)->head.high));
  }
  if (ACTIVE(y) > BIT_HIGH(ACTIVE(window))) {
#ifdef WIERD
    ACTIVE(y) = BIT_HIGH(ACTIVE(window));
    scroll(ACTIVE(window), 0, BIT_HIGH(ACTIVE(window)),
        ((int)(ACTIVE(font)->head.high)), SWAPCOLOR(ACTIVE(style)));
    bit_blit(ACTIVE(window), 0, BIT_HIGH(ACTIVE(window)) - ((int)(ACTIVE(font)->head.high)),
        BIT_WIDE(ACTIVE(save)), ((int)(ACTIVE(font)->head.high)),
        BIT_SRC, ACTIVE(save),
        ACTIVE(borderwid), BIT_HIGH(ACTIVE(save)) - ((int)(ACTIVE(font)->head.high)) - ACTIVE(borderwid));
#else
    ACTIVE(y) = BIT_HIGH(ACTIVE(window)) - ((int)(ACTIVE(font)->head.high));
#endif
  }

  bit_destroy(ACTIVE(save));
  ACTIVE(save) = (BITMAP *)0;

  /* invalidate clip lists */
  clip_bad(active);
  un_covered();
  set_size(active);
  return (0);
}
Example #8
0
static int retrieve_segment(struct segment * seg)
{
    char proc[256];
    snprintf(proc, 256, "rsg%u", g_nodeId);
    prctl(PR_SET_NAME, proc, 0, 0, 0);
    int rv = -1;
    log_print(g_log, "retrieve_segment: trying to retrieve segment %s[%d - %d].",
              seg->name->full_name, 0, seg->num_chunks-1);

    pthread_mutex_lock(&g_lock);
    int retries = g_interest_attempts;
    int timeout_ms = g_timeout_ms;
    pthread_mutex_unlock(&g_lock);
    int ttl = MAX_TTL;

    if ((seg->opts->mode & CCNFDNB_USE_RETRIES) == CCNFDNB_USE_RETRIES) {
        retries = seg->opts->retries;
    }
    if ((seg->opts->mode & CCNFDNB_USE_TIMEOUT) == CCNFDNB_USE_TIMEOUT) {
        timeout_ms = seg->opts->timeout_ms;
    }
    if ((seg->opts->mode & CCNFDNB_USE_TTL) == CCNFDNB_USE_TTL) {
        ttl = seg->opts->ttl;
    }

    struct chunk chunk_window[MAX_INTEREST_PIPELINE];
    PENTRY _pit_handles[MAX_INTEREST_PIPELINE];
    int pit_to_chunk[PIT_SIZE];
    memset(&pit_to_chunk, 0, sizeof(pit_to_chunk));
    struct bitmap * window = bit_create(MAX_INTEREST_PIPELINE);
    struct bitmap * missing = bit_create(seg->num_chunks);

    char str[MAX_NAME_LENGTH], comp[MAX_NAME_LENGTH];
    strncpy(str, seg->name->full_name, seg->name->len);

    int rtt_est = timeout_ms;
    int cwnd = 1;
    int ssthresh = DEFAULT_INTEREST_PIPELINE;
    int fullfilled = 0;
    int min_rtt_est = 10;

    int current_chunk = 0;
    cc_state state = SLOW_START;
    int tx;

    _segment_q_t seg_q;
    pthread_mutex_init(&seg_q.mutex, NULL);
    pthread_cond_init(&seg_q.cond, NULL);
    seg_q.rcv_window = 0;
    seg_q.max_window = &cwnd;
    seg_q.rcv_chunks = linked_list_init(NULL);
    seg_q.base = seg->name;
    ccnfdnl_reg_segment(&seg_q);

    int i;
    window->num_bits = cwnd;
    while (!bit_allSet(missing)) {
        tx = cwnd;
        window->num_bits = cwnd;

        log_debug(g_log, "state = %d, cwnd = %d, ssthresh = %d rtt_est = %d",
                  state, cwnd, ssthresh, rtt_est);

        while (tx && (current_chunk < seg->num_chunks)) {
            snprintf(comp, MAX_NAME_LENGTH - seg->name->len, "/%d", current_chunk);
            strncpy(str + seg->name->len, comp, seg->name->len);
            i = bit_find(window);
            if (i < 0 || i >= MAX_INTEREST_PIPELINE) {
                /* we must still be waiting for data */
                break;
            }
            chunk_window[i].intr.name = content_name_create(str);
            chunk_window[i].intr.ttl = ttl;
            chunk_window[i].seq_no = current_chunk;
            chunk_window[i].retries = retries;

            _pit_handles[i] = PIT_get_handle(chunk_window[i].intr.name);
            if (!_pit_handles[i]) {
                bit_clear(window, i);
                break;
            }
            pit_to_chunk[_pit_handles[i]->index] = i;
            pthread_mutex_unlock(_pit_handles[i]->mutex);

            struct content_obj * co = CS_get(chunk_window[i].intr.name);
            if (!co) {
                log_debug(g_log, "expressing new interest: %s", chunk_window[i].intr.name->full_name);
                ccnfdnb_fwd_interest(&chunk_window[i].intr);
                tx--;
            } else {
                log_debug(g_log, "retrieved %s from CS", co->name->full_name);

                PENTRY pe = PIT_exact_match(chunk_window[i].intr.name);
                *pe->obj = co;
                pthread_mutex_unlock(pe->mutex);

                pthread_mutex_lock(&seg_q.mutex);

                linked_list_append(seg_q.rcv_chunks, pe);
                seg_q.rcv_window++;

                pthread_mutex_unlock(&seg_q.mutex);
            }

            current_chunk++;
        }
        log_debug(g_log, "tx window full");

        pthread_mutex_lock(&seg_q.mutex);

        if (seg_q.rcv_chunks->len == 0) {
            struct timespec wait;
            ts_fromnow(&wait);
            ts_addms(&wait, 2 * rtt_est);

            rv = pthread_cond_timedwait(&seg_q.cond, &seg_q.mutex, &wait);
            if ((rv == ETIMEDOUT) && !seg_q.rcv_chunks->len) {
                /* we timed out, we need to rtx */
                rtt_est += rtt_est / 2;
                if (rtt_est > PIT_LIFETIME_MS)
                    rtt_est = PIT_LIFETIME_MS / 2;
            }
        } else {
            int pit_ages = 0;
            int pits_fulfilled = 0;
            while (seg_q.rcv_chunks->len > 0) {
                PENTRY pe = linked_list_remove(seg_q.rcv_chunks, 0);
                log_assert(g_log, pe != NULL, "invalid pit entry");

                pthread_mutex_lock(pe->mutex);
                log_debug(g_log, "pit entry %s fulfilled", (*pe->obj)->name->full_name);

                int chunk_id = pit_to_chunk[pe->index];
                log_assert(g_log, chunk_id >= 0, "invalid chunk id");

                if (chunk_window[chunk_id].seq_no == 0) {
                    seg->obj->publisher = (*pe->obj)->publisher;
                    seg->obj->timestamp = (*pe->obj)->timestamp;
                    seg->chunk_size = (*pe->obj)->size;
                }
                int offset = chunk_window[chunk_id].seq_no * seg->chunk_size;
                memcpy(&seg->obj->data[offset], (*pe->obj)->data, (*pe->obj)->size);
                content_obj_destroy(*pe->obj);

                struct timespec now;
                ts_fromnow(&now);
                ts_addms(&now, PIT_LIFETIME_MS);
                pit_ages += PIT_age(pe);
				pits_fulfilled++;

                pit_to_chunk[pe->index] = -1;
                PIT_release(pe);
                free(_pit_handles[chunk_id]);
                _pit_handles[chunk_id] = NULL;
                bit_clear(window, chunk_id);
                bit_set(missing, chunk_window[chunk_id].seq_no);
                log_debug(g_log, "retrieved chunk %s", chunk_window[chunk_id].intr.name->full_name);
                content_name_delete(chunk_window[chunk_id].intr.name);
                chunk_window[chunk_id].intr.name = NULL;
                cwnd++;
                if (state == CONG_AVOID)
                    fullfilled++;
            }

            rtt_est -= floor(pit_ages / pits_fulfilled);
            if (rtt_est < min_rtt_est)
                rtt_est = min_rtt_est;
        }

        pthread_mutex_unlock(&seg_q.mutex);

        for (i = 0; i < MAX_INTEREST_PIPELINE; i++) {
            if (bit_test(window, i)) {
                if (!_pit_handles[i]) {
                    continue;
                }
                pthread_mutex_lock(_pit_handles[i]->mutex);
                if (PIT_age(_pit_handles[i]) > (2 * rtt_est)) {
                    PIT_refresh(_pit_handles[i]);
                    chunk_window[i].retries--;
                    ccnfdnb_fwd_interest(&chunk_window[i].intr);
                    log_debug(g_log, "rtx interest: %s (rtt = %d)",
                              chunk_window[i].intr.name->full_name, rtt_est);
                    ssthresh = cwnd / 2 + 1;
                    cwnd = 1;
                    state = SLOW_START;
                }
                pthread_mutex_unlock(_pit_handles[i]->mutex);
            }
        }

        if ((cwnd >= ssthresh) && (state == SLOW_START))
            state = CONG_AVOID;
        if (state == SLOW_START)
            fullfilled = 0;
        if ((fullfilled == cwnd) && (state == CONG_AVOID)) {
            cwnd++;
            fullfilled = 0;
        }
        if (cwnd > MAX_INTEREST_PIPELINE)
            cwnd = MAX_INTEREST_PIPELINE;

        /*log_debug(g_log, "cwnd = %d, ssthresh = %d", cwnd, ssthresh);*/
    }

    log_debug(g_log, "retrieve_segment: finished for %s[%d-%d]",
              seg->name->full_name, 0, seg->num_chunks-1);

    rv = 0;

    PIT_print();
    ccnfdnl_unreg_segment(&seg_q);
    pthread_mutex_destroy(&seg_q.mutex);
    pthread_cond_destroy(&seg_q.cond);
    while (seg_q.rcv_chunks->len) {
        PENTRY pe = linked_list_remove(seg_q.rcv_chunks, 0);
        content_obj_destroy(*pe->obj);
        PIT_release(pe);
    }

    bit_destroy(window);
    bit_destroy(missing);

    return rv;
}