capt_get_packet(): check for key press only every 20ms
[iptraf-ng.git] / src / capt-recvmmsg.c
blob8bcf1a8b8a90dbefdcc5069eb63517b02f84a1e5
1 /* For terms of usage/redistribution/modification see the LICENSE file */
2 /* For authors and contributors see the AUTHORS file */
4 #include "iptraf-ng-compat.h"
6 #include "packet.h"
7 #include "capt.h"
9 #define FRAMES 128
11 struct capt_data_recvmmsg {
12 char *buf;
14 struct mmsghdr *msgvec;
15 struct iovec *iov;
16 struct sockaddr_ll *from;
18 unsigned int lastslot;
19 unsigned int slot;
22 static unsigned int capt_recvmmsg_find_filled_slot(struct capt_data_recvmmsg *data)
24 for (unsigned int slot = data->lastslot; slot < FRAMES; slot++)
25 if (data->msgvec[slot].msg_len != 0)
26 return slot;
28 return FRAMES;
31 static unsigned int capt_have_packet_recvmmsg(struct capt *capt)
33 struct capt_data_recvmmsg *data = capt->priv;
35 return capt_recvmmsg_find_filled_slot(data) != FRAMES;
38 static int capt_get_packet_recvmmsg(struct capt *capt, struct pkt_hdr *pkt)
40 struct capt_data_recvmmsg *data = capt->priv;
41 int ret = 0;
43 unsigned int slot = capt_recvmmsg_find_filled_slot(data);
44 if (slot == FRAMES) {
45 /* these are set upon return from recvmsg() so clean */
46 /* them beforehand */
47 for (unsigned int i = 0; i < FRAMES; i++) {
48 data->msgvec[i].msg_hdr.msg_controllen = 0;
49 data->msgvec[i].msg_hdr.msg_flags = 0;
50 data->msgvec[i].msg_len = 0;
53 int received = recvmmsg(capt->fd, data->msgvec, FRAMES, MSG_TRUNC | MSG_DONTWAIT, NULL);
54 if (received <= 0)
55 return received;
56 slot = 0;
58 pkt->pkt_len = data->msgvec[slot].msg_len;
59 pkt->pkt_caplen = data->msgvec[slot].msg_len;
60 if (pkt->pkt_caplen > MAX_PACKET_SIZE)
61 pkt->pkt_caplen = MAX_PACKET_SIZE;
62 pkt->pkt_buf = data->buf + slot * MAX_PACKET_SIZE;
63 pkt->from = &data->from[slot];
64 pkt->pkt_payload = NULL;
65 pkt->pkt_protocol = ntohs(pkt->from->sll_protocol);
67 data->slot = slot;
69 return ret;
72 static int capt_put_packet_recvmmsg(struct capt *capt, struct pkt_hdr *pkt __unused)
74 struct capt_data_recvmmsg *data = capt->priv;
76 /* hand out processed slot to kernel */
77 if (data->slot < FRAMES) {
78 data->msgvec[data->slot].msg_len = 0;
79 data->lastslot = data->slot;
80 } else
81 data->slot = FRAMES;
83 return 0;
86 static void capt_cleanup_recvmmsg(struct capt *capt)
88 struct capt_data_recvmmsg *data = capt->priv;
90 capt->cleanup = NULL;
91 capt->put_packet = NULL;
92 capt->get_packet = NULL;
93 capt->have_packet = NULL;
95 free(data->from);
96 data->from = NULL;
97 free(data->iov);
98 data->iov = NULL;
99 free(data->msgvec);
100 data->msgvec = NULL;
101 free(data->buf);
102 data->buf = NULL;
104 free(capt->priv);
105 capt->priv = NULL;
108 int capt_setup_recvmmsg(struct capt *capt)
110 struct capt_data_recvmmsg *data;
112 data = xmallocz(sizeof(struct capt_data_recvmmsg));
113 data->buf = xmallocz(FRAMES * MAX_PACKET_SIZE);
114 data->msgvec = xmallocz(FRAMES * sizeof(*data->msgvec));
115 data->iov = xmallocz(FRAMES * sizeof(*data->iov));
116 data->from = xmallocz(FRAMES * sizeof(*data->from));
118 for (unsigned int i = 0; i < FRAMES; i++) {
119 data->iov[i].iov_len = MAX_PACKET_SIZE;
120 data->iov[i].iov_base = data->buf + i * MAX_PACKET_SIZE;
122 data->msgvec[i].msg_hdr.msg_name = &data->from[i];
123 data->msgvec[i].msg_hdr.msg_namelen = sizeof(data->from[i]);
124 data->msgvec[i].msg_hdr.msg_iov = &data->iov[i];
125 data->msgvec[i].msg_hdr.msg_iovlen = 1;
126 data->msgvec[i].msg_hdr.msg_control = NULL;
128 data->slot = FRAMES;
129 data->lastslot = 0;
131 capt->priv = data;
132 capt->have_packet = capt_have_packet_recvmmsg;
133 capt->get_packet = capt_get_packet_recvmmsg;
134 capt->put_packet = capt_put_packet_recvmmsg;
135 capt->cleanup = capt_cleanup_recvmmsg;
137 return 0;