New try at recvmmsg with some improvements

This commit is contained in:
Dennis Felsing 2018-07-25 16:06:00 +02:00 committed by def
parent a3b07dbf9c
commit 9febf58f37
6 changed files with 98 additions and 9 deletions

View file

@ -1522,29 +1522,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;
}
@ -1560,7 +1611,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
@ -747,6 +756,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.
@ -761,7 +786,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

@ -2031,6 +2031,13 @@ int CServer::Run()
int64 t = time_get();
int x = (TickStartTime(m_CurrentGameTick+1) - t) * 1000000 / time_freq() + 1;
if(x > 3000)
{
// at least sleep 3 ms, reduce number of syscalls in stress situations
thread_sleep(3);
x = (TickStartTime(m_CurrentGameTick+1) - t) * 1000000 / time_freq() + 1;
}
if(x > 0)
{
net_socket_read_wait(m_NetServer.Socket(), x);

View file

@ -301,6 +301,7 @@ class CNetServer
};
NETSOCKET m_Socket;
MMSGS m_MMSGS;
class CNetBan *m_pNetBan;
CSlot m_aSlots[NET_MAX_CLIENTS];
int m_MaxClients;
@ -423,6 +424,7 @@ class CNetClient
CNetRecvUnpacker m_RecvUnpacker;
public:
NETSOCKET m_Socket;
MMSGS m_MMSGS;
// openness
bool Open(NETADDR BindAddr, int Flags);
int Close();

View file

@ -17,6 +17,8 @@ bool CNetClient::Open(NETADDR BindAddr, int Flags)
// init
m_Socket = Socket;
m_Connection.Init(m_Socket, false);
net_init_mmsgs(&m_MMSGS);
return true;
}
@ -64,7 +66,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_MMSGS);
// no more packets for now
if(Bytes <= 0)

View file

@ -80,6 +80,8 @@ bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int Ma
for(int i = 0; i < NET_MAX_CLIENTS; i++)
m_aSlots[i].m_Connection.Init(m_Socket, true);
net_init_mmsgs(&m_MMSGS);
return true;
}
@ -598,7 +600,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_MMSGS);
// no more packets for now
if(Bytes <= 0)