You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
4.4 KiB
164 lines
4.4 KiB
/**
|
|
* @file input.c
|
|
* @brief RTP packet input
|
|
*/
|
|
/*****************************************************************************
|
|
* Copyright © 2008 Rémi Denis-Courmont
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation; either version 2.1
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
****************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <limits.h>
|
|
#include <errno.h>
|
|
#ifdef HAVE_POLL_H
|
|
# include <poll.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_UIO_H
|
|
# include <sys/uio.h>
|
|
#endif
|
|
#ifdef _WIN32
|
|
# include <winsock2.h>
|
|
#endif
|
|
|
|
#include <vlc_common.h>
|
|
#include <vlc_threads.h>
|
|
#include <vlc_poll.h>
|
|
#include <vlc_demux.h>
|
|
#include <vlc_block.h>
|
|
#include "vlc_dtls.h"
|
|
|
|
#include "rtp.h"
|
|
#ifdef HAVE_SRTP
|
|
# include "srtp.h"
|
|
#endif
|
|
#include "input.h"
|
|
|
|
#define DEFAULT_MRU (1500u - (20 + 8))
|
|
|
|
/**
|
|
* Processes a packet received from the RTP socket.
|
|
*/
|
|
static void rtp_process (struct vlc_logger *logger, rtp_input_sys_t *sys,
|
|
rtp_session_t *session, block_t *block)
|
|
{
|
|
if (block->i_buffer < 2)
|
|
goto drop;
|
|
const uint8_t ptype = rtp_ptype (block);
|
|
if (ptype >= 72 && ptype <= 76)
|
|
goto drop; /* Muxed RTCP, ignore for now FIXME */
|
|
|
|
#ifdef HAVE_SRTP
|
|
if (sys->srtp != NULL)
|
|
{
|
|
size_t len = block->i_buffer;
|
|
if (srtp_recv (sys->srtp, block->p_buffer, &len))
|
|
{
|
|
vlc_debug (logger, "SRTP authentication/decryption failed");
|
|
goto drop;
|
|
}
|
|
block->i_buffer = len;
|
|
}
|
|
#endif
|
|
|
|
rtp_queue (logger, session, block);
|
|
return;
|
|
drop:
|
|
block_Release (block);
|
|
}
|
|
|
|
static int rtp_timeout (vlc_tick_t deadline)
|
|
{
|
|
if (deadline == VLC_TICK_INVALID)
|
|
return -1; /* infinite */
|
|
|
|
vlc_tick_t t = vlc_tick_now ();
|
|
if (t >= deadline)
|
|
return 0;
|
|
|
|
t = (deadline - t) / (CLOCK_FREQ / INT64_C(1000));
|
|
if (unlikely(t > INT_MAX))
|
|
return INT_MAX;
|
|
return t;
|
|
}
|
|
|
|
/**
|
|
* RTP/RTCP session thread for datagram sockets
|
|
*/
|
|
void *rtp_dgram_thread (void *opaque)
|
|
{
|
|
rtp_sys_t *sys = opaque;
|
|
vlc_tick_t deadline = VLC_TICK_INVALID;
|
|
struct vlc_dtls *rtp_sock = sys->input_sys.rtp_sock;
|
|
|
|
vlc_thread_set_name("vlc-rtp");
|
|
|
|
for (;;)
|
|
{
|
|
struct pollfd ufd[1];
|
|
|
|
ufd[0].events = POLLIN;
|
|
ufd[0].fd = vlc_dtls_GetPollFD(rtp_sock, &ufd[0].events);
|
|
|
|
int n = poll (ufd, 1, rtp_timeout (deadline));
|
|
if (n == -1)
|
|
continue;
|
|
|
|
int canc = vlc_savecancel ();
|
|
if (n == 0)
|
|
goto dequeue;
|
|
|
|
if (ufd[0].revents)
|
|
{
|
|
block_t *block = block_Alloc(DEFAULT_MRU);
|
|
if (unlikely(block == NULL))
|
|
break; /* we are totallly screwed */
|
|
|
|
bool truncated;
|
|
ssize_t len = vlc_dtls_Recv(rtp_sock, block->p_buffer,
|
|
block->i_buffer, &truncated);
|
|
if (len >= 0) {
|
|
if (truncated) {
|
|
vlc_error (sys->logger, "packet truncated (MRU was %zu)",
|
|
block->i_buffer);
|
|
block->i_flags |= BLOCK_FLAG_CORRUPTED;
|
|
}
|
|
else
|
|
block->i_buffer = len;
|
|
|
|
rtp_process (sys->logger, &sys->input_sys, sys->session, block);
|
|
}
|
|
else
|
|
{
|
|
if (errno == EPIPE)
|
|
break; /* connection terminated */
|
|
vlc_warning (sys->logger, "RTP network error: %s",
|
|
vlc_strerror_c(errno));
|
|
block_Release (block);
|
|
}
|
|
|
|
n--;
|
|
}
|
|
|
|
dequeue:
|
|
if (!rtp_dequeue (sys->logger, sys->session, vlc_tick_now(), &deadline))
|
|
deadline = VLC_TICK_INVALID;
|
|
vlc_restorecancel (canc);
|
|
}
|
|
return NULL;
|
|
}
|
|
|