From de5fe64be582c39906644dd4c60f2b032858ecab Mon Sep 17 00:00:00 2001 From: Dennis Felsing Date: Wed, 25 Jul 2018 16:06:00 +0200 Subject: [PATCH] Implement recvmmsg --- src/base/system.c | 63 +++++++++++++++++++++++++--- src/base/system.h | 27 +++++++++++- src/engine/shared/network_client.cpp | 5 ++- src/engine/shared/network_server.cpp | 4 +- 4 files changed, 90 insertions(+), 9 deletions(-) diff --git a/src/base/system.c b/src/base/system.c index 28d098717..5c4a6edc2 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -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; diff --git a/src/base/system.h b/src/base/system.h index 7ee3662a8..289c10244 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -9,6 +9,11 @@ #define BASE_SYSTEM_H #include "detect.h" + +#ifndef __USE_GNU +#define __USE_GNU +#endif + #include #include #include @@ -17,6 +22,10 @@ #include #endif +#ifdef CONF_PLATFORM_LINUX +#include +#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 diff --git a/src/engine/shared/network_client.cpp b/src/engine/shared/network_client.cpp index f955ef5a8..6528c730b 100644 --- a/src/engine/shared/network_client.cpp +++ b/src/engine/shared/network_client.cpp @@ -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) diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index ea8fc15ba..3cd242600 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -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)