two minor bugfixes.
[vde.git] / vde-2 / packetq.c
blobb0696dff0115d8063db6ef09b6e81a5ae45fd2d8
1 /*
2 * packetq - packet queue management. try to send packets several times before discarding.
3 * Copyright 2005 Renzo Davoli
4 * Licensed under the GPLv2
5 */
7 #include <config.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/time.h>
11 #include <time.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <syslog.h>
17 #include <consmgmt.h>
18 #include <vde.h>
20 #ifdef VDE_PQ
21 #include "packetq.h"
23 int packetq_timeout= -1;
24 static int countq;
25 #define TIMEOUT 5
26 #define TIMES 10
27 #define MAXQLEN 4192
29 struct packetqq {
30 int (*sender)(int fd, int fd_ctl, void *packet, int len, void *data, int port);
31 int fd;
32 int fd_ctl;
33 void *packet;
34 int len;
35 void *data;
36 int port;
37 int times;
38 struct packetqq *next;
41 static struct packetqq *pqh=NULL;
42 static struct packetqq *pqt=NULL;
43 static struct timeval last_try;
45 void packetq_add(int (*sender)(int fd, int fd_ctl, void *packet, int len, void *data, int port),
46 int fd, int fd_ctl, void *packet, int len, void *data, int port)
48 if (countq < MAXQLEN) {
49 struct packetqq *new=malloc(sizeof(struct packetqq));
50 void *packetcopy=malloc(len);
51 if (new != NULL && packetcopy != NULL && len > 0) {
52 countq++;
53 new->sender=sender;
54 new->fd=fd;
55 new->fd_ctl=fd_ctl;
56 memcpy(packetcopy,packet,len);
57 new->packet=packetcopy;
58 new->len=len;
59 new->data=data;
60 new->port=port;
61 new->times=TIMES;
62 new->next=NULL;
63 if (pqh==NULL) {
64 gettimeofday(&last_try,NULL);
65 packetq_timeout=TIMEOUT;
66 pqh=pqt=new;
67 } else {
68 pqt->next=new;
69 pqt=new;
71 } else {
72 if (new != NULL) free(new);
73 if (packetcopy != NULL) free(packetcopy);
78 static struct packetqq *packetq_scantry(struct packetqq *h,struct packetqq **t,fd_set *fds)
80 if (h != NULL) {
81 int sendrv=!(FD_ISSET(h->fd,fds));
82 h->times--;
83 if ((sendrv && (sendrv=h->sender(h->fd,h->fd_ctl,h->packet,h->len,h->data,h->port)) == 0) /*send OK*/
84 || h->times<=0) { /*or max number of attempts reached*/
85 struct packetqq *next;
86 #if 0
87 /* this error code is unreachable! (sendrv==0 here) */
88 if (sendrv != 0) {
89 if (sendrv < 0)
90 printlog(LOG_WARNING,"packetqueue port %d: %s",h->port,strerror(-sendrv));
91 else
92 printlog(LOG_WARNING,"packetqueue port %d: partial send (%d bytes lost)",h->port,sendrv);
94 #endif
95 next=h->next;
96 countq--;
97 free(h->packet);
98 free(h);
99 return packetq_scantry(next,t,fds);
100 } else {
101 FD_SET(h->fd,fds);
102 h->next=packetq_scantry(h->next,t,fds);
103 if (h->next == NULL) *t=h;
104 return h;
106 } else
107 return NULL;
110 void packetq_try(void)
112 if (pqh != NULL) {
113 struct timeval this_try;
114 gettimeofday(&this_try,NULL);
115 packetq_timeout=TIMEOUT - ((this_try.tv_sec-last_try.tv_sec) * 1000 +
116 (this_try.tv_usec-last_try.tv_usec) / 1000);
117 if (packetq_timeout <= 0) {
118 fd_set fds;
119 FD_ZERO(&fds);
120 pqh=packetq_scantry(pqh,&pqt,&fds);
121 if (pqh != NULL) {
122 gettimeofday(&last_try,NULL);
123 packetq_timeout=TIMEOUT;
124 } else
125 packetq_timeout = -1;
130 static struct packetqq *packetq_scandelfd(int fd,struct packetqq *h,struct packetqq **t)
132 if (h != NULL) {
133 if (fd == h->fd) {
134 struct packetqq *next=h->next;
135 countq--;
136 free(h->packet);
137 free(h);
138 return packetq_scandelfd(fd,next,t);
139 } else {
140 h->next=packetq_scandelfd(fd,h->next,t);
141 if (h->next == NULL) *t=h;
142 return h;
144 } else
145 return NULL;
148 void packetq_delfd(int fd)
150 pqh=packetq_scandelfd(fd,pqh,&pqt);
151 if (pqh == NULL)
152 packetq_timeout = -1;
155 int packetq_count()
157 return countq;
159 #endif