I have trouble reading RTP packets from a multicast socket which is opened using the following function:
int
open_multicast_socket
(const char *group_address,
uint16_t port)
{
assert(group_address != NULL);
int
s;
if (-1 != (s = socket(
AF_INET, SOCK_DGRAM, 0
)))
{
int
reuse = 1;
if (-1 != setsockopt(
s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse
))
{
struct sockaddr_in
sock_addr;
bzero(&sock_addr, sizeof sock_addr);
if (1 == inet_pton(
AF_INET, group_address, &sock_addr.sin_addr
))
{
sock_addr.sin_family = AF_INET;
sock_addr.sin_port = htons(port);
if (0 == bind(
s, (struct sockaddr*)&sock_addr, sizeof sock_addr
))
{
struct ip_mreq
mreq = {
.imr_multiaddr.s_addr = inet_addr(group_address),
.imr_interface.s_addr = htonl(INADDR_ANY)
};
if (0 == setsockopt(
s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof mreq
))
{
//fcntl(s, F_SETFL, O_NONBLOCK);
return s;
} // setsockopt
else
{
perror("setsockopt");
close(s);
}
} // bind
else
{
perror("bind");
close(s);
}
} // inet_pton
else
{
perror("inet_pton");
close(s);
}
} // setsockopt
else
{
perror("setsockopt");
close(s);
}
} // socket
else
{
perror("socket");
}
return -1;
}
If I read RTP header plus payload in one read
operation, I get the entire
packet. However, if I attempt to receive the RTP header first, then - a custom
header in the payload - the 2nd read
always gets a next RTP header instead,
discarding all attached data. Because payload length may vary, the only way to
receive a whole packet, it seems, is to guess its max possible size.
I tried to get a number of available bytes before reading:
ioctl(sock, FIONREAD, &nbytes);
but it always returns 0.
Polling on the socket always fails, as if no data is available at all.
When non-blocking is enabled (i.e. fcntl(sock, F_SETFL, O_NONBLOCK);
) - read
always fails (-1), so does recv(sock, buf, buf_len, MSG_DONTWAIT)
.
So is there a way to properly parse RTP packets via consequensive non-blocking
read
calls?
Non-blocking is essential, because it should be possible to check whether a connection was lost and re-open the socket if necessary.