udp: add multisend code (sendmmsg)
This commit is contained in:
parent
fd1bc1c5f7
commit
d563dc9127
3 changed files with 144 additions and 0 deletions
12
configure
vendored
12
configure
vendored
|
@ -174,6 +174,18 @@ int test(void)
|
|||
}
|
||||
'
|
||||
|
||||
check_cc_snippet sendmmsg '
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#define TEST test
|
||||
int test(void)
|
||||
{
|
||||
sendmmsg(0, NULL, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
'
|
||||
|
||||
check_cc_snippet libiconv '
|
||||
#include <iconv.h>
|
||||
int test(void)
|
||||
|
|
117
src/udp.c
117
src/udp.c
|
@ -600,3 +600,120 @@ udp_multirecv_read( udp_multirecv_t *um, int fd, int packets,
|
|||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* UDP multi packet send support
|
||||
*/
|
||||
|
||||
#if !defined (CONFIG_SENDMMSG) && defined(__linux__)
|
||||
/* define the syscall - works only for linux */
|
||||
#include <linux/unistd.h>
|
||||
#ifdef __NR_sendmmsg
|
||||
|
||||
int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
|
||||
unsigned int flags);
|
||||
|
||||
int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
|
||||
unsigned int flags)
|
||||
{
|
||||
return syscall(__NR_sendmmsg, sockfd, msgvec, vlen, flags);
|
||||
}
|
||||
|
||||
#define CONFIG_RECVMMSG
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
sendmmsg_i(int sockfd, struct mmsghdr *msgvec,
|
||||
unsigned int vlen, unsigned int flags)
|
||||
{
|
||||
ssize_t r;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < vlen; i++) {
|
||||
r = sendmsg(sockfd, &msgvec->msg_hdr, flags);
|
||||
if (r < 0)
|
||||
return (i > 0) ? i : r;
|
||||
msgvec->msg_len = r;
|
||||
msgvec++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SENDMMSG
|
||||
|
||||
int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
|
||||
unsigned int flags);
|
||||
|
||||
int
|
||||
sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
|
||||
unsigned int flags)
|
||||
{
|
||||
return recvmmsg_i(sockfd, msgvec, vlen, flags);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
udp_multisend_init( udp_multisend_t *um, int packets, int psize,
|
||||
struct iovec **iovec )
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(um);
|
||||
um->um_psize = psize;
|
||||
um->um_packets = packets;
|
||||
um->um_data = malloc(packets * psize);
|
||||
um->um_iovec = malloc(packets * sizeof(struct iovec));
|
||||
um->um_msg = calloc(packets, sizeof(struct mmsghdr));
|
||||
for (i = 0; i < packets; i++) {
|
||||
((struct mmsghdr *)um->um_msg)[i].msg_hdr.msg_iov = &um->um_iovec[i];
|
||||
((struct mmsghdr *)um->um_msg)[i].msg_hdr.msg_iovlen = 1;
|
||||
um->um_iovec[i].iov_base = um->um_data + i * psize;
|
||||
um->um_iovec[i].iov_len = psize;
|
||||
}
|
||||
*iovec = um->um_iovec;
|
||||
}
|
||||
|
||||
void
|
||||
udp_multisend_free( udp_multisend_t *um )
|
||||
{
|
||||
if (um == NULL)
|
||||
return;
|
||||
free(um->um_msg); um->um_msg = NULL;
|
||||
free(um->um_iovec); um->um_iovec = NULL;
|
||||
free(um->um_data); um->um_data = NULL;
|
||||
um->um_psize = 0;
|
||||
um->um_packets = 0;
|
||||
}
|
||||
|
||||
int
|
||||
udp_multisend_send( udp_multisend_t *um, int fd, int packets )
|
||||
{
|
||||
static char use_emul = 0;
|
||||
int n, i;
|
||||
if (um == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (packets > um->um_packets)
|
||||
packets = um->um_packets;
|
||||
for (i = 0; i < packets; i++)
|
||||
((struct mmsghdr *)um->um_msg)[i].msg_len = um->um_iovec[i].iov_len;
|
||||
if (!use_emul) {
|
||||
n = sendmmsg(fd, (struct mmsghdr *)um->um_msg, packets, MSG_DONTWAIT);
|
||||
} else {
|
||||
n = -1;
|
||||
errno = ENOSYS;
|
||||
}
|
||||
if (n < 0 && errno == ENOSYS) {
|
||||
use_emul = 1;
|
||||
n = sendmmsg_i(fd, (struct mmsghdr *)um->um_msg, packets, MSG_DONTWAIT);
|
||||
}
|
||||
if (n > 0) {
|
||||
for (i = 0; i < n; i++)
|
||||
um->um_iovec[i].iov_len = ((struct mmsghdr *)um->um_msg)[i].msg_len;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
|
15
src/udp.h
15
src/udp.h
|
@ -76,5 +76,20 @@ int
|
|||
udp_multirecv_read( udp_multirecv_t *um, int fd, int packets,
|
||||
struct iovec **iovec );
|
||||
|
||||
typedef struct udp_multisend {
|
||||
int um_psize;
|
||||
int um_packets;
|
||||
uint8_t *um_data;
|
||||
struct iovec *um_iovec;
|
||||
struct mmsghdr *um_msg;
|
||||
} udp_multisend_t;
|
||||
|
||||
void
|
||||
udp_multisend_init( udp_multisend_t *um, int packets, int psize,
|
||||
struct iovec **iovec );
|
||||
void
|
||||
udp_multisend_free( udp_multisend_t *um );
|
||||
int
|
||||
udp_multisend_send( udp_multisend_t *um, int fd, int packets );
|
||||
|
||||
#endif /* UDP_H_ */
|
||||
|
|
Loading…
Add table
Reference in a new issue