예제 #1
0
int
pbuf_decode(struct pbuf *playout_buf, struct timeval curr_time,
                             decode_frame_t decode_func, void *data)
{
        /* Find the first complete frame that has reached it's playout */
        /* time, and decode it into the framebuffer. Mark the frame as */
        /* decoded, but otherwise leave it in the playout buffer.      */
        struct pbuf_node *curr;

        pbuf_validate(playout_buf);

        curr = playout_buf->frst;
        while (curr != NULL) {
                if (!curr->decoded && tv_gt(curr_time, curr->playout_time)) {
                        if (frame_complete(curr)) {
                                int ret = decode_func(curr->cdata, data);
                                curr->decoded = 1;
                                return ret;
                        } else {
                                debug_msg
                                    ("Unable to decode frame due to missing data (RTP TS=%u)\n",
                                     curr->rtp_timestamp);
                        }
                }
                curr = curr->nxt;
        }
        return 0;
}
예제 #2
0
static void
collapse_quad (quadrant * pquad)
{
    Bool freed;
    segment *pseg;
    segment *tmpseg;

    if ((pquad == NULL) || (pquad->seglist_head == NULL))
	return;

    pseg = pquad->seglist_head;
    while (pseg != NULL) {
	freed = FALSE;
	if (pseg->next == NULL)
	    break;

	/* if this segment has not been ACKed, then neither have the */
	/* ones that follow, so no need to continue */
	if (!pseg->acked)
	    break;

	/* if this segment and the next one have both been ACKed and they */
	/* "fit together", then collapse them into one (larger) segment   */
	if (pseg->acked && pseg->next->acked &&
	    (pseg->seq_lastbyte + 1 == pseg->next->seq_firstbyte)) {
	    pseg->seq_lastbyte = pseg->next->seq_lastbyte;

	    /* the new ACK count is the ACK count of the later segment */
	    pseg->acked = pseg->next->acked;

	    /* the new "transmit time" is the greater of the two */
	    if (tv_gt (pseg->next->time, pseg->time))
		pseg->time = pseg->next->time;

	    tmpseg = pseg->next;
	    pseg->next = pseg->next->next;
	    if (pseg->next != NULL)
		pseg->next->prev = pseg;
	    if (tmpseg == pquad->seglist_tail)
		pquad->seglist_tail = pseg;
	    free (tmpseg);
	    freed = TRUE;
	}

	if (!freed)
	    pseg = pseg->next;
	/* else, see if the next one also can be collapsed into me */
    }

    /* see if the quadrant is now "full" */
    if ((pquad->seglist_head->seq_lastbyte -
	 pquad->seglist_head->seq_firstbyte + 1) == QUADSIZE) {
	pquad->full = TRUE;
    }
}
예제 #3
0
int tfrc_feedback_is_due(struct tfrc *state, struct timeval curr_time)
{
        /* Determine if it is time to send feedback to the sender */
        validate_tfrc_state(state);

        if ((state->RTT == 0) || tv_gt(state->feedback_timer, curr_time)) {
                /* Not yet time to send feedback to the sender... */
                return FALSE;
        }
        return TRUE;
}
예제 #4
0
void pbuf_remove(struct pbuf *playout_buf, struct timeval curr_time)
{
        /* Remove previously decoded frames that have passed their playout  */
        /* time from the playout buffer. Incomplete frames that have passed */
        /* their playout time are also discarded.                           */

        struct pbuf_node *curr, *temp;

        pbuf_validate(playout_buf);

        curr = playout_buf->frst;
        while (curr != NULL) {
                temp = curr->nxt;
                if (tv_gt(curr_time, curr->playout_time)) {
                        if (curr == playout_buf->frst) {
                                playout_buf->frst = curr->nxt;
                        }
                        if (curr == playout_buf->last) {
                                playout_buf->last = curr->prv;
                        }
                        if (curr->nxt != NULL) {
                                curr->nxt->prv = curr->prv;
                        }
                        if (curr->prv != NULL) {
                                curr->prv->nxt = curr->nxt;
                        }
                        free_cdata(curr->cdata);
                        free(curr);
                } else {
                        /* The playout buffer is stored in order, so once  */
                        /* we see one packet that has not yet reached it's */
                        /* playout time, we can be sure none of the others */
                        /* will have done so...                            */
                        break;
                }
                curr = temp;
        }

        pbuf_validate(playout_buf);
        return;
}
예제 #5
0
struct audio_frame *audio_cap_testcard_read(void *state)
{
        struct state_audio_capture_testcard *s;
        s = (struct state_audio_capture_testcard *) state;
        struct timeval curr_time;

        gettimeofday(&curr_time, NULL);

        if(tv_gt(s->next_audio_time, curr_time)) {
                usleep(tv_diff_usec(s->next_audio_time, curr_time));
        } else {
                // we missed more than 2 "frame times", in that case, just drop the packages
                if (tv_diff_usec(curr_time, s->next_audio_time) > 2 * (1000 * 1000 * CHUNK / 48000)) {
                        s->next_audio_time = curr_time;
                        fprintf(stderr, MODULE_NAME "Warning: skipping some samples (late grab call).\n");
                }
        }

        tv_add_usec(&s->next_audio_time, 1000 * 1000 * CHUNK / 48000);

        if(s->current_sample == TONE) {
                s->audio.data = (char* )(s->audio_tone + s->samples_played * AUDIO_CHANNELS); // it is short so _not_ (* 2)
        } else {
                s->audio.data = (char *)(s->audio_silence + s->samples_played * AUDIO_CHANNELS);
        }

        s->samples_played += CHUNK;
        if(s->samples_played >= AUDIO_SAMPLE_RATE) {
                s->samples_played = 0;
                if(s->current_sample == TONE) {
                        s->current_sample = SILENCE;
                } else {
                        s->current_sample = TONE;
                }
        }

        return &s->audio;
}
예제 #6
0
enum t_ack
ack_in (tcptrace_context_t *context,
        tcb * ptcb,
	seqnum ack,
	unsigned tcp_data_length,
	u_long eff_win)
{
    tcptrace_runtime_options_t *options = context->options;
    quadrant *pquad;
    quadrant *pquad_prev;
    segment *pseg;
    Bool changed_one = FALSE;
    Bool intervening_xmits = FALSE;
    timeval last_xmit = { 0, 0 };
    enum t_ack ret = 0;

    enum dup_ack_handling { BSD_VERSION = 1, /* Handling of duplicate ack's
						based on the specifications of
						BSD code */
	LEGACY_VERSION = 2  /* Handling of duplicate ack's according to the 
			       old versions of "tcptrace" */
    };
    enum dup_ack_handling dup_ack_type;	/* default type is the code based on
					   BSD specifications */


    /* check each segment in the segment list for the PREVIOUS quadrant */
    pquad = whichquad (ptcb->ss, ack);
    pquad_prev = pquad->prev;
    for (pseg = pquad_prev->seglist_head; pseg != NULL; pseg = pseg->next) {
	if (!pseg->acked) {
	    ++pseg->acked;
	    changed_one = TRUE;
	    ++ptcb->rtt_cumack;

	    /* keep track of the newest transmission */
	    if (tv_gt (pseg->time, last_xmit))
		last_xmit = pseg->time;
	}
    }
    if (changed_one)
	collapse_quad (pquad_prev);

    /* check each segment in the segment list for the CURRENT quadrant */
    changed_one = FALSE;
    for (pseg = pquad->seglist_head; pseg != NULL; pseg = pseg->next) {
	if (ack <= pseg->seq_firstbyte) {
	    /* doesn't cover anything else on the list */
	    break;
	}

	/* keep track of the newest transmission */
	if (tv_gt (pseg->time, last_xmit))
	    last_xmit = pseg->time;

	/* (ELSE) ACK covers this sequence */
	if (pseg->acked) {
	    /* default will be the BSD version, it can be changed by giving 
	       '--turn_off_BSD_dupack' switch */
	    dup_ack_type = (options->dup_ack_handling) ? BSD_VERSION : LEGACY_VERSION;

	    /* default type is the specifications based on BSD code */
	    switch (dup_ack_type) {
	    case LEGACY_VERSION:
		if (ack == (pseg->seq_lastbyte + 1)) {
		    ++pseg->acked;	/* already acked this one */
		    ++ptcb->rtt_dupack;	/* one more duplicate ack */
		    ret = CUMUL;
		    if (pseg->acked == 4) {
			/* some people say these CAN'T have data */
			if ((tcp_data_length == 0)
			    || options->triple_dupack_allows_data) {
			    ++ptcb->rtt_triple_dupack;
			    ret = TRIPLE;
			}
		    }
		}
		break;
	    case BSD_VERSION:
		/* For an acknowledgement to be considered as duplicate ACK in 
		   BSD version, following rules must be followed:
		   1) the received segment should contain the biggest ACK TCP 
		   has seen,
		   2) the length of the segment containing dup ack should be 0,
		   3) advertised window in this segment should not change,
		   4) and there must be some outstanding data */

		if ((ack == (pseg->seq_lastbyte + 1)) &&
		      (ack == ptcb->ptwin->ack) &&
		      (tcp_data_length == 0) &&
		      (eff_win == ptcb->ptwin->win_last) &&
		      (ptcb->owin_tot > 0)) {	
		    ++ptcb->rtt_dupack;
		    ret = CUMUL;

		    /* already acked this one */
		    ++pseg->acked;
		    if (pseg->acked == 4) {
			++ptcb->rtt_triple_dupack;
			ret = TRIPLE;
		    }
		} else
		    pseg->acked = 1;	/* received segment is not pure
					   duplicate acknowledgement */
	    }
	    continue;
	}
	/* ELSE !acked */

	++pseg->acked;
	changed_one = TRUE;

	if (ack == (pseg->seq_lastbyte + 1)) {
	    /* if ANY preceding segment was xmitted after this one,
	       the the RTT sample is invalid */
	    intervening_xmits = (tv_gt (last_xmit, pseg->time));

	    ret = rtt_ackin(context, ptcb, pseg, intervening_xmits);
	} else {
	    /* cumulatively ACKed */
	    ++ptcb->rtt_cumack;
	    ret = CUMUL;
	}
    }
    if (changed_one)
	collapse_quad (pquad);
    return (ret);
}
예제 #7
0
/**
 * //<aa>
 * - ptcb: the tcb of the direction opposite to the one in which this ack has been sent.
 * //</aa>
 */
enum t_ack
ack_in (tcb * ptcb, seqnum ack, unsigned tcp_data_length)
{
  quadrant *pquad;
  quadrant *pquad_prev;
  segment *pseg;
  Bool changed_one = FALSE;
  Bool intervening_xmits = FALSE;
  timeval last_xmit = { 0, 0 };
  enum t_ack ret = 0;


  /* check each segment in the segment list for the PREVIOUS quadrant */
  pquad = whichquad (ptcb->ss, ack);
  pquad_prev = pquad->prev;
  for (pseg = pquad_prev->seglist_head; pseg != NULL; pseg = pseg->next)
    {
      if (!pseg->acked)
        {
          ++pseg->acked;
          changed_one = TRUE;
          ++ptcb->rtt_cumack;

          /* keep track of the newest transmission */
          if (tv_gt (pseg->time, last_xmit))
            last_xmit = pseg->time;
        }
    }
  if (changed_one)
    collapse_quad (pquad_prev);

  /* check each segment in the segment list for the CURRENT quadrant */
  changed_one = FALSE;
  for (pseg = pquad->seglist_head; pseg != NULL; pseg = pseg->next)
    {
      if (ack <= pseg->seq_firstbyte)
        {
          /* doesn't cover anything else on the list */
          break;
        }

      /* keep track of the newest transmission */
      if (tv_gt (pseg->time, last_xmit))
        last_xmit = pseg->time;

      /* (ELSE) ACK covers this sequence */
      if (pseg->acked)
      {
          /* already acked this one */
          ++pseg->acked;
          if (ack == (pseg->seq_lastbyte + 1)){
              ++ptcb->rtt_dupack;       /* one more duplicate ack */
              ret = CUMUL;
              if (pseg->acked == 4)
                {
                  /* some people say these CAN'T have data */
                  if ((tcp_data_length == 0))
                    {
                      ++ptcb->rtt_triple_dupack;
                      ret = TRIPLE;
                    }
                }
          }
          continue;
      }
      /* ELSE !acked */ //<aa>This is the firt time that this segment has been acked </aa>

      ++pseg->acked;
      changed_one = TRUE;

      if (ack == (pseg->seq_lastbyte + 1)){
          /* if ANY preceding segment was xmitted after this one,
             the the RTT sample is invalid */
          intervening_xmits = (tv_gt (last_xmit, pseg->time));
	  //<aa> The RTT is valid only if the segment being acked with the present ack is 
	  // the last transmitted one;
	  // In order to be sure of this, we check if last_xmit > pseg_time. If this is the
	  // case, intervening_xmits is true and the RTT is not valid.
	  // If, instead, intervening_xmits is false, the RTT is valid </aa>
	  // to be sure that the present

          ret = rtt_ackin (ptcb, pseg, intervening_xmits);
      }
      else
        {
          /* cumulatively ACKed */
          ++ptcb->rtt_cumack;
          ret = CUMUL;
        }
    }
  if (changed_one)
    collapse_quad (pquad);
  return (ret);
}