예제 #1
0
/*** dequeue_gre **************************************************************/
int dequeue_gre (callback_t callback, int cl)
{
    pqueue_t *head;
    int status;
    /* process packets in the queue that either are expected or have 
     * timed out. */
    head = pqueue_head();
    while ( head != NULL &&
            ( (head->seq == seq_recv + 1) || /* wrap-around safe */ 
              (pqueue_expiry_time(head) <= 0) 
            )
          ) {
        /* if it is timed out... */
        if (head->seq != seq_recv + 1 ) {  /* wrap-around safe */          
            stats.rx_lost += head->seq - seq_recv - 1;
	    if (log_level >= 2)
                log("timeout waiting for %d packets", head->seq - seq_recv - 1);
        }
	if (log_level >= 2)
            log("accepting %d from queue", head->seq);
        seq_recv = head->seq;
        status = callback(cl, head->packet, head->packlen);
        pqueue_del(head);
        if (status < 0)
            return status;
        head = pqueue_head();
    }
    return 0;
}
예제 #2
0
Packet* pqueue_pop(PQueue* queue) {
	 Packet* tmp = pqueue_head(queue);
	 assert (pqueue_length(queue) > 0);
	 queue->head++;
	 queue->length--;
	 queue->head = PMOD(queue->head, queue->maxsize);
	 return tmp;
}
예제 #3
0
void pqueue_debug_print(PQueue* queue) {
	 if (pqueue_length(queue) > 0) {
		  printf("Queue head seq#%d, tail seq#%d, size %d, window size %d\n",
				 pqueue_head(queue)->seqn, pqueue_tail(queue)->seqn,
				 pqueue_length(queue), queue->maxsize);
	 } else {
		  printf("Empty queue, window size %d\n", queue->maxsize);
	 }
}
예제 #4
0
/* Main sender function. Taken from the state diagram on slide 6, chapter 5 */
void sender(int window, int timeout) {
	 int base = 1;
	 int nextseqnum = 1;
	 bool allsent = false;
	 PQueue sendQ;
	 pqueue_init(&sendQ, window);

	 while ( !(allsent && pqueue_empty(&sendQ)) ) {
		  int acknum = -1;

		  /* Send new data */
		  if (!allsent && nextseqnum < base + window) {
			   Packet* packet = add_packet(&sendQ, nextseqnum);
			   if (packet == NULL) {
					allsent = true;
			   } else {
					send_packet(packet);
					if (base == nextseqnum)
						 start_timer(timeout);
					nextseqnum++;
			   }
		  }
		  
		  /* Attempt to receive an ACK. */
		  acknum = get_ack(0);
		  if (acknum > 0) {
			   base = acknum + 1;
			   if (base == nextseqnum)
					stop_timer();
			   else
					start_timer(timeout);
		  }

		  /* Clean up the queue */
		  while (!pqueue_empty(&sendQ) && pqueue_head(&sendQ)->seqn < base) {
			   pqueue_pop(&sendQ);
		  }
		  
		  /* Handle timeouts */
		  if (cnt_active && cnt_time >= cnt_timeout) {
			   start_timer(cnt_timeout);
			   pqueue_map(&sendQ, &send_packet);
		  }
		  pqueue_debug_print(&sendQ);
	 }
	 
	 pqueue_destroy(&sendQ);
}
예제 #5
0
/*** pptp_gre_copy ************************************************************/
void pptp_gre_copy(u_int16_t call_id, u_int16_t peer_call_id, 
		   int pty_fd, int gre_fd)
{
    int max_fd;
    pptp_gre_call_id = call_id;
    pptp_gre_peer_call_id = peer_call_id;
    /* Pseudo-terminal already open. */
    ack_sent = ack_recv = seq_sent = seq_recv = 0;
    /* weird select semantics */
    max_fd = gre_fd;
    if (pty_fd > max_fd) max_fd = pty_fd;
    /* Dispatch loop */
    for (;;) { /* until error happens on gre_fd or pty_fd */
        struct timeval tv = {0, 0};
        struct timeval *tvp;
        fd_set rfds;
        int retval;
        pqueue_t *head;
        int block_usecs = -1; /* wait forever */
        /* watch terminal and socket for input */
        FD_ZERO(&rfds);
        FD_SET(gre_fd, &rfds);
        FD_SET(pty_fd, &rfds);
        /*
         * if there are multiple pending ACKs, then do a minimal timeout;
         * else if there is a single pending ACK then timeout after 0,5 seconds;
         * else block until data is available.
         */
        if (ack_sent != seq_recv) {
            if (ack_sent + 1 == seq_recv)  /* u_int wrap-around safe */
                block_usecs = 500000;
            else
                /* don't use zero, this will force a resceduling */
                /* when calling select(), giving pppd a chance to */
                /* run. */
                block_usecs = 1;
        }
        /* otherwise block_usecs == -1, which means wait forever */
        /*
         * If there is a packet in the queue, then don't wait longer than
         * the time remaining until it expires.
         */
        head = pqueue_head();
        if (head != NULL) {
            int expiry_time = pqueue_expiry_time(head);
            if (block_usecs == -1 || expiry_time < block_usecs)
                block_usecs = expiry_time;
        }
        if (block_usecs == -1) {
            tvp = NULL;
        } else {
            tvp = &tv;
            tv.tv_usec = block_usecs;
            tv.tv_sec  = tv.tv_usec / 1000000;
            tv.tv_usec %= 1000000;
        }
        retval = select(max_fd + 1, &rfds, NULL, NULL, tvp);
        if (retval > 0 && FD_ISSET(pty_fd, &rfds)) {
            if (decaps_hdlc(pty_fd, encaps_gre,  gre_fd) < 0)
                break;
        } else if (retval == 0 && ack_sent != seq_recv) {
            /* if outstanding ack */
            /* send ack with no payload */
            encaps_gre(gre_fd, NULL, 0);         
        }
        if (retval > 0 && FD_ISSET(gre_fd, &rfds)) {
            if (decaps_gre (gre_fd, encaps_hdlc, pty_fd) < 0)
                break;
        }
        if (dequeue_gre (encaps_hdlc, pty_fd) < 0)
            break;
    }
    /* Close up when done. */
    close(gre_fd);
    close(pty_fd);
}