Implement recvmmsg

This commit is contained in:
Dennis Felsing 2018-07-25 16:06:00 +02:00
parent 473048dac0
commit de5fe64be5
4 changed files with 90 additions and 9 deletions

View file

@ -1494,29 +1494,80 @@ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size
#endif /* FUZZING */
}
int net_udp_recv(NETSOCKET sock, NETADDR *addr, void *data, int maxsize)
void net_init_mmsgs(MMSGS* m)
{
#if defined(CONF_PLATFORM_LINUX)
m->pos = 0;
m->size = 0;
mem_zero(m->msgs, sizeof(m->msgs));
mem_zero(m->iovecs, sizeof(m->iovecs));
mem_zero(m->sockaddrs, sizeof(m->sockaddrs));
for(int i = 0; i < VLEN; ++i)
{
m->iovecs[i].iov_base = m->bufs[i];
m->iovecs[i].iov_len = PACKETSIZE;
m->msgs[i].msg_hdr.msg_iov = &m->iovecs[i];
m->msgs[i].msg_hdr.msg_iovlen = 1;
m->msgs[i].msg_hdr.msg_name = &m->sockaddrs[i];
m->msgs[i].msg_hdr.msg_namelen = sizeof(&m->sockaddrs[i]);
}
#endif
}
int net_udp_recv(NETSOCKET sock, NETADDR *addr, void *data, int maxsize, MMSGS* m)
{
#ifndef FUZZING
char sockaddrbuf[128];
socklen_t fromlen;// = sizeof(sockaddrbuf);
int bytes = 0;
#if defined(CONF_PLATFORM_LINUX)
if(sock.ipv4sock >= 0)
{
if(m->pos >= m->size)
{
m->size = recvmmsg(sock.ipv4sock, m->msgs, VLEN, 0, NULL);
m->pos = 0;
}
}
if(sock.ipv6sock >= 0)
{
if(m->pos >= m->size)
{
m->size = recvmmsg(sock.ipv6sock, m->msgs, VLEN, 0, NULL);
m->pos = 0;
}
}
if(m->pos < m->size)
{
sockaddr_to_netaddr((struct sockaddr *)&(m->sockaddrs[m->pos]), addr);
// TODO: network_stats
//network_stats.recv_bytes += bytes;
//network_stats.recv_packets++;
bytes = m->msgs[m->pos].msg_len;
mem_copy(data, m->bufs[m->pos], bytes);
m->pos++;
return bytes;
}
#else
if(bytes == 0 && sock.ipv4sock >= 0)
{
fromlen = sizeof(struct sockaddr_in);
int fromlen = sizeof(struct sockaddr_in);
bytes = recvfrom(sock.ipv4sock, (char*)data, maxsize, 0, (struct sockaddr *)&sockaddrbuf, &fromlen);
}
if(bytes <= 0 && sock.ipv6sock >= 0)
{
fromlen = sizeof(struct sockaddr_in6);
int fromlen = sizeof(struct sockaddr_in6);
bytes = recvfrom(sock.ipv6sock, (char*)data, maxsize, 0, (struct sockaddr *)&sockaddrbuf, &fromlen);
}
#endif
#if defined(CONF_WEBSOCKETS)
if(bytes <= 0 && sock.web_ipv4sock >= 0)
{
fromlen = sizeof(struct sockaddr);
int fromlen = sizeof(struct sockaddr);
bytes = websocket_recv(sock.web_ipv4sock, data, maxsize, (struct sockaddr_in *)&sockaddrbuf, fromlen);
((struct sockaddr_in *)&sockaddrbuf)->sin_family = AF_WEBSOCKET_INET;
}
@ -1532,7 +1583,7 @@ int net_udp_recv(NETSOCKET sock, NETADDR *addr, void *data, int maxsize)
else if(bytes == 0)
return 0;
return -1; /* error */
#else
#else /* ifdef FUZZING */
addr->type = NETTYPE_IPV4;
addr->port = 11111;
addr->ip[0] = 127;

View file

@ -9,6 +9,11 @@
#define BASE_SYSTEM_H
#include "detect.h"
#ifndef __USE_GNU
#define __USE_GNU
#endif
#include <stddef.h>
#include <stdlib.h>
#include <time.h>
@ -17,6 +22,10 @@
#include <sys/un.h>
#endif
#ifdef CONF_PLATFORM_LINUX
#include <sys/socket.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -732,6 +741,22 @@ NETSOCKET net_udp_create(NETADDR bindaddr);
*/
int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size);
#define VLEN 128
#define PACKETSIZE 1400
typedef struct
{
#ifdef CONF_PLATFORM_LINUX
int pos;
int size;
struct mmsghdr msgs[VLEN];
struct iovec iovecs[VLEN];
char bufs[VLEN][PACKETSIZE];
char sockaddrs[VLEN][128];
#endif
} MMSGS;
void net_init_mmsgs(MMSGS* m);
/*
Function: net_udp_recv
Receives a packet over an UDP socket.
@ -746,7 +771,7 @@ int net_udp_send(NETSOCKET sock, const NETADDR *addr, const void *data, int size
On success it returns the number of bytes received. Returns -1
on error.
*/
int net_udp_recv(NETSOCKET sock, NETADDR *addr, void *data, int maxsize);
int net_udp_recv(NETSOCKET sock, NETADDR *addr, void *data, int maxsize, MMSGS* m);
/*
Function: net_udp_close

View file

@ -56,6 +56,9 @@ int CNetClient::ResetErrorString()
int CNetClient::Recv(CNetChunk *pChunk)
{
MMSGS m;
net_init_mmsgs(&m);
while(1)
{
// check for a chunk
@ -64,7 +67,7 @@ int CNetClient::Recv(CNetChunk *pChunk)
// TODO: empty the recvinfo
NETADDR Addr;
int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE);
int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE, &m);
// no more packets for now
if(Bytes <= 0)

View file

@ -581,6 +581,8 @@ int CNetServer::GetClientSlot(const NETADDR &Addr)
*/
int CNetServer::Recv(CNetChunk *pChunk)
{
MMSGS m;
net_init_mmsgs(&m);
while(1)
{
NETADDR Addr;
@ -590,7 +592,7 @@ int CNetServer::Recv(CNetChunk *pChunk)
return 1;
// TODO: empty the recvinfo
int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE);
int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE, &m);
// no more packets for now
if(Bytes <= 0)