Logo Search packages:      
Sourcecode: vde2 version File versions  Download package

packetq.c

/*
 * packetq - packet queue management. try to send packets several times before discarding.
 * Copyright 2005 Renzo Davoli
 * Licensed under the GPLv2
 */

#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <syslog.h>

#include <consmgmt.h>
#include <vde.h>

#ifdef VDE_PQ
#include "packetq.h"

int packetq_timeout= -1;
static int countq;
#define TIMEOUT 5
#define TIMES 10
#define MAXQLEN 4192

struct packetqq {
      int (*sender)(int fd, int fd_ctl, void *packet, int len, void *data, int port);
      int fd; 
      int fd_ctl; 
      void *packet; 
      int len; 
      void *data; 
      int port;
      int times;
      struct packetqq *next;
};

static struct packetqq *pqh=NULL;
static struct packetqq *pqt=NULL;
static struct timeval last_try;

void packetq_add(int (*sender)(int fd, int fd_ctl, void *packet, int len, void *data, int port),
            int fd, int fd_ctl, void *packet, int len, void *data, int port)
{
      if (countq < MAXQLEN) {
            struct packetqq *new=malloc(sizeof(struct packetqq));
            void *packetcopy=malloc(len);
            if (new != NULL && packetcopy != NULL && len > 0) {
                  countq++;
                  new->sender=sender;
                  new->fd=fd;
                  new->fd_ctl=fd_ctl;
                  memcpy(packetcopy,packet,len);
                  new->packet=packetcopy;
                  new->len=len;
                  new->data=data;
                  new->port=port;
                  new->times=TIMES;
                  new->next=NULL;
                  if (pqh==NULL) {
                        gettimeofday(&last_try,NULL);
                        packetq_timeout=TIMEOUT;
                        pqh=pqt=new;
                  } else {
                        pqt->next=new;
                        pqt=new;
                  }
            } else {
                  if (new != NULL) free(new);
                  if (packetcopy != NULL) free(packetcopy);
            }
      }
}

static struct packetqq *packetq_scantry(struct packetqq *h,struct packetqq **t,fd_set *fds)
{
      if (h != NULL) {
            int sendrv=!(FD_ISSET(h->fd,fds));
            h->times--;
            if ((sendrv && (sendrv=h->sender(h->fd,h->fd_ctl,h->packet,h->len,h->data,h->port)) == 0)   /*send OK*/
                        || h->times<=0) { /*or max number of attempts reached*/
                  struct packetqq *next;
#if 0
                  /* this error code is unreachable! (sendrv==0 here) */
                  if (sendrv != 0) {
                        if (sendrv < 0) 
                              printlog(LOG_WARNING,"packetqueue port %d: %s",h->port,strerror(-sendrv));
                        else
                              printlog(LOG_WARNING,"packetqueue port %d: partial send (%d bytes lost)",h->port,sendrv);
                  }
#endif
                  next=h->next;
                  countq--;
                  free(h->packet);
                  free(h);
                  return packetq_scantry(next,t,fds);
            } else {
                  FD_SET(h->fd,fds);
                  h->next=packetq_scantry(h->next,t,fds);
                  if (h->next == NULL) *t=h;
                  return h;
            }
      } else
            return NULL;
}

void packetq_try(void)
{
      if (pqh != NULL) {
            struct timeval this_try;
            gettimeofday(&this_try,NULL);
            packetq_timeout=TIMEOUT - ((this_try.tv_sec-last_try.tv_sec) * 1000 + 
                        (this_try.tv_usec-last_try.tv_usec) / 1000);
            if (packetq_timeout <= 0) {
                  fd_set fds;
                  FD_ZERO(&fds);
                  pqh=packetq_scantry(pqh,&pqt,&fds); 
                  if (pqh != NULL) {
                        gettimeofday(&last_try,NULL);
                        packetq_timeout=TIMEOUT;
                  } else
                        packetq_timeout = -1;
            }
      }
}

static struct packetqq *packetq_scandelfd(int fd,struct packetqq *h,struct packetqq **t)
{
      if (h != NULL) {
            if (fd == h->fd) {
                  struct packetqq *next=h->next;
                  countq--;
                  free(h->packet);
                  free(h);
                  return packetq_scandelfd(fd,next,t);
            } else {
                  h->next=packetq_scandelfd(fd,h->next,t);
                  if (h->next == NULL) *t=h;
                  return h;
            }
      } else
            return NULL;
}

void packetq_delfd(int fd)
{
      pqh=packetq_scandelfd(fd,pqh,&pqt);
      if (pqh == NULL)
            packetq_timeout = -1;
}

int packetq_count()
{
      return countq;
}
#endif

Generated by  Doxygen 1.6.0   Back to index