I'm trying to build a very simple and basic STCP one-to-many server for testing purposes, but for some reason, the socket seems to be able to receive only one message. After receiving one message, each subsequent call to recvmsg
returns -1 with the errno
being EFAULT
. This makes absolutely no sense to me, so maybe you can tell me what I'm not seeing here. EFAULT
is supposed to be returned when
EFAULT
The receive buffer pointer(s) point outside the process's address space.
which is definitely not the case.
#include <ctype.h>
#include <cstring>
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, char** argv) {
struct sockaddr_in bind_address;
bind_address.sin_family = AF_INET;
bind_address.sin_port = htons(51338);
bind_address.sin_addr.s_addr = INADDR_ANY;
int sock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
if (sock == -1) {
perror("Error while creating socket");
return 1;
}
int rv = bind(sock, (struct sockaddr*)(&bind_address), sizeof(bind_address));
if (rv != 0 ) {
perror("Error while binding socket");
return 1;
}
rv = listen(sock, 1);
if (rv != 0 ) {
perror("Error while listening");
return 1;
}
struct iovec iov[1];
iov[0].iov_base = malloc(1500);
iov[0].iov_len = 1500;
struct sockaddr_in sin = {};
char control[1000] = { 0 };
struct msghdr mhdr;
mhdr.msg_iov = iov;
mhdr.msg_iovlen = sizeof(iov);
mhdr.msg_name = &sin;
mhdr.msg_namelen = sizeof(sin);
mhdr.msg_control = &control;
mhdr.msg_controllen = sizeof(control);
while (true) {
std::memset(iov[0].iov_base, 0, iov[0].iov_len);
std::memset(&sin, 0, sizeof(sin));
int recv_bytes = recvmsg(sock, &mhdr, 0);
if (recv_bytes == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
continue;
} else {
perror("Err");
}
break;
}
std::cout << "Received message: " << std::endl;
std::cout << (char*)iov[0].iov_base << std::endl;
}
return 0;
}
The error is most likely because the first call to recvmsg()
overwrites some data on the stack, causing one of the pointers inside mhdr
to be invalid. And this is probably because of this line:
mhdr.msg_iovlen = sizeof(iov);
This should not contain the size of the array iov
in bytes, but just the number of elements in that array, so:
mhdr.msg_iovlen = sizeof(iov) / sizeof(*iov); // which equals 1 in this case