X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Frtp.c;h=ee99286a276e272fc76e1d584cb45da996c4c45b;hb=1f1e1106101bc913dd3f2f4ef3789a4cad16bf93;hp=c0797c6cd26e6df19b2646c3388b2109b7b0f74f;hpb=be0a4188843b2cb1ab4b68a7bd08d78e178a5a21;p=vlc diff --git a/modules/demux/rtp.c b/modules/demux/rtp.c index c0797c6cd2..ee99286a27 100644 --- a/modules/demux/rtp.c +++ b/modules/demux/rtp.c @@ -31,16 +31,29 @@ #include #include #include +#ifdef HAVE_POLL +# include +#endif #include #include #include "rtp.h" +#include #define RTP_CACHING_TEXT N_("RTP de-jitter buffer length (msec)") #define RTP_CACHING_LONGTEXT N_( \ "How long to wait for late RTP packets (and delay the performance)." ) +#define SRTP_KEY_TEXT N_("SRTP key (hexadecimal)") +#define SRTP_KEY_LONGTEXT N_( \ + "RTP packets will be authenticated and deciphered "\ + "with this Secure RTP master shared secret key.") + +#define SRTP_SALT_TEXT N_("SRTP salt (hexadecimal)") +#define SRTP_SALT_LONGTEXT N_( \ + "Secure RTP requires a (non-secret) master salt value.") + #define RTP_MAX_SRC_TEXT N_("Maximum RTP sources") #define RTP_MAX_SRC_LONGTEXT N_( \ "How many distinct active RTP sources are allowed at a time." ) @@ -76,6 +89,10 @@ vlc_module_begin (); add_integer ("rtp-caching", 1000, NULL, RTP_CACHING_TEXT, RTP_CACHING_LONGTEXT, true); change_integer_range (0, 65535); + add_string ("srtp-key", "", NULL, + SRTP_KEY_TEXT, SRTP_KEY_LONGTEXT, false); + add_string ("srtp-salt", "", NULL, + SRTP_SALT_TEXT, SRTP_SALT_LONGTEXT, false); add_integer ("rtp-max-src", 1, NULL, RTP_MAX_SRC_TEXT, RTP_MAX_SRC_LONGTEXT, true); change_integer_range (1, 255); @@ -88,6 +105,9 @@ vlc_module_begin (); RTP_MAX_MISORDER_LONGTEXT, true); change_integer_range (0, 32767); + add_shortcut ("dccp"); + /*add_shortcut ("sctp");*/ + add_shortcut ("rtptcp"); /* "tcp" is already taken :( */ add_shortcut ("rtp"); add_shortcut ("udplite"); vlc_module_end (); @@ -124,6 +144,12 @@ static int Open (vlc_object_t *obj) demux_t *demux = (demux_t *)obj; int tp; /* transport protocol */ + if (!strcmp (demux->psz_access, "dccp")) + tp = IPPROTO_DCCP; + else + if (!strcmp (demux->psz_access, "rtptcp")) + tp = IPPROTO_TCP; + else if (!strcmp (demux->psz_access, "rtp")) tp = IPPROTO_UDP; else @@ -150,7 +176,40 @@ static int Open (vlc_object_t *obj) dport = 5004; /* avt-profile-1 port */ /* Try to connect */ - int fd = net_OpenDgram (obj, dhost, dport, shost, sport, AF_UNSPEC, tp); + int fd = -1, rtcp_fd = -1; + + switch (tp) + { + case IPPROTO_UDP: + case IPPROTO_UDPLITE: + fd = net_OpenDgram (obj, dhost, (dport + 1) & ~1, + shost, (sport + 1) & ~1, AF_UNSPEC, tp); + if (fd == -1) + break; + rtcp_fd = net_OpenDgram (obj, dhost, dport | 1, shost, + sport ? (sport | 1) : 0, AF_UNSPEC, tp); + break; + + case IPPROTO_DCCP: +#ifndef SOCK_DCCP /* provisional API (FIXME) */ +# ifdef __linux__ +# define SOCK_DCCP 6 +# endif +#endif +#ifdef SOCK_DCCP + var_Create (obj, "dccp-service", VLC_VAR_STRING); + var_SetString (obj, "dccp-service", "RTPV"); /* FIXME: RTPA? */ + fd = net_Connect (obj, shost, (sport + 1) & ~1, SOCK_DCCP, tp); +#else + msg_Err (obj, "DCCP support not included"); +#endif + break; + + case IPPROTO_TCP: + fd = net_Connect (obj, shost, (sport + 1) & ~1, SOCK_STREAM, tp); + break; + } + free (tmp); if (fd == -1) return VLC_EGENERIC; @@ -159,14 +218,23 @@ static int Open (vlc_object_t *obj) /* Initializes demux */ demux_sys_t *p_sys = malloc (sizeof (*p_sys)); if (p_sys == NULL) - goto error; + { + net_Close (fd); + if (rtcp_fd != -1) + net_Close (rtcp_fd); + return VLC_EGENERIC; + } + p_sys->srtp = NULL; + p_sys->fd = fd; + p_sys->rtcp_fd = rtcp_fd; p_sys->caching = var_CreateGetInteger (obj, "rtp-caching"); p_sys->max_src = var_CreateGetInteger (obj, "rtp-max-src"); p_sys->timeout = var_CreateGetInteger (obj, "rtp-timeout"); p_sys->max_dropout = var_CreateGetInteger (obj, "rtp-max-dropout"); p_sys->max_misorder = var_CreateGetInteger (obj, "rtp-max-misorder"); p_sys->autodetect = true; + p_sys->framed_rtp = (tp == IPPROTO_TCP); demux->pf_demux = Demux; demux->pf_control = Control; @@ -176,12 +244,32 @@ static int Open (vlc_object_t *obj) if (p_sys->session == NULL) goto error; - p_sys->fd = fd; + char *key = var_CreateGetNonEmptyString (demux, "srtp-key"); + if (key) + { + p_sys->srtp = srtp_create (SRTP_ENCR_AES_CM, SRTP_AUTH_HMAC_SHA1, 10, + SRTP_PRF_AES_CM, SRTP_RCC_MODE1); + if (p_sys->srtp == NULL) + { + free (key); + goto error; + } + + char *salt = var_CreateGetNonEmptyString (demux, "srtp-salt"); + errno = srtp_setkeystring (p_sys->srtp, key, salt ? salt : ""); + free (salt); + free (key); + if (errno) + { + msg_Err (obj, "bad SRTP key/salt combination (%m)"); + goto error; + } + } + return VLC_SUCCESS; error: - net_Close (fd); - free (p_sys); + Close (obj); return VLC_EGENERIC; } @@ -194,7 +282,12 @@ static void Close (vlc_object_t *obj) demux_t *demux = (demux_t *)obj; demux_sys_t *p_sys = demux->p_sys; - rtp_session_destroy (demux, p_sys->session); + if (p_sys->srtp) + srtp_destroy (p_sys->srtp); + if (p_sys->session) + rtp_session_destroy (demux, p_sys->session); + if (p_sys->rtcp_fd != -1) + net_Close (p_sys->rtcp_fd); net_Close (p_sys->fd); free (p_sys); } @@ -265,22 +358,79 @@ static int Control (demux_t *demux, int i_query, va_list args) /** - * Gets a datagram from the network + * Checks if a file descriptor is hung up. + */ +static bool fd_dead (int fd) +{ + struct pollfd ufd = { .fd = fd, }; + + return (poll (&ufd, 1, 0) == 1) && (ufd.revents & POLLHUP); +} + + +/** + * Gets a datagram from the network, or NULL in case of fatal error. */ static block_t *rtp_dgram_recv (demux_t *demux, int fd) { block_t *block = block_Alloc (0xffff); + ssize_t len; - ssize_t len = net_Read (VLC_OBJECT (demux), fd, NULL, - block->p_buffer, block->i_buffer, false); - if (len == -1) + do { - block_Release (block); - return NULL; + len = net_Read (VLC_OBJECT (demux), fd, NULL, + block->p_buffer, block->i_buffer, false); + if (((len <= 0) && fd_dead (fd)) + || !vlc_object_alive (demux)) + { + block_Release (block); + return NULL; + } } + while (len == -1); + return block_Realloc (block, 0, len); } +/** + * Gets a framed RTP packet, or NULL in case of fatal error. + */ +static block_t *rtp_stream_recv (demux_t *demux, int fd) +{ + ssize_t len = 0; + uint8_t hdr[2]; /* frame header */ + + /* Receives the RTP frame header */ + do + { + ssize_t val = net_Read (VLC_OBJECT (demux), fd, NULL, + hdr + len, 2 - len, false); + if (val <= 0) + return NULL; + len += val; + } + while (len < 2); + + block_t *block = block_Alloc (GetWBE (hdr)); + + /* Receives the RTP packet */ + for (ssize_t i = 0; i < len;) + { + ssize_t val; + + val = net_Read (VLC_OBJECT (demux), fd, NULL, + block->p_buffer + i, block->i_buffer - i, false); + if (val <= 0) + { + block_Release (block); + return NULL; + } + i += val; + } + + return block; +} + /* * Generic packet handlers @@ -468,9 +618,11 @@ static int Demux (demux_t *demux) demux_sys_t *p_sys = demux->p_sys; block_t *block; - block = rtp_dgram_recv (demux, p_sys->fd); + block = p_sys->framed_rtp + ? rtp_stream_recv (demux, p_sys->fd) + : rtp_dgram_recv (demux, p_sys->fd); if (!block) - return 1; + return 0; if (block->i_buffer < 2) goto drop; @@ -479,6 +631,17 @@ static int Demux (demux_t *demux) if (ptype >= 72 && ptype <= 76) goto drop; /* Muxed RTCP, ignore for now */ + if (p_sys->srtp) + { + size_t len = block->i_buffer; + if (srtp_recv (p_sys->srtp, block->p_buffer, &len)) + { + msg_Dbg (demux, "SRTP authentication/decryption failed"); + goto drop; + } + block->i_buffer = len; + } + /* Not using SDP, we need to guess the payload format used */ /* see http://www.iana.org/assignments/rtp-parameters */ if (p_sys->autodetect) @@ -520,7 +683,7 @@ static int Demux (demux_t *demux) msg_Dbg (demux, "detected MPEG Audio"); pt.init = mpa_init; pt.decode = mpa_decode; - pt.frequency = 44100; + pt.frequency = 90000; break; case 32: