sdp.c
资源名称:vlc-1.0.5.zip [点击查看]
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:9k
源码类别:
midi
开发平台:
Unix_Linux
- /*****************************************************************************
- * sdp.c : SDP creation helpers
- *****************************************************************************
- * Copyright © 2007 Rémi Denis-Courmont
- * $Id: 47bb16fd9ab3ad1bfab36f80e54a127acf6cd6e0 $
- *
- * This program 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 program 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 General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
- #ifdef HAVE_CONFIG_H
- # include "config.h"
- #endif
- #include <vlc_common.h>
- #include <stddef.h>
- #include <string.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <assert.h>
- #include <vlc_network.h>
- #include <vlc_charset.h>
- #include "stream_output.h"
- #define MAXSDPADDRESS 47
- static
- char *AddressToSDP (const struct sockaddr *addr, socklen_t addrlen, char *buf)
- {
- if (addrlen < offsetof (struct sockaddr, sa_family)
- + sizeof (addr->sa_family))
- return NULL;
- strcpy (buf, "IN IP* ");
- if (vlc_getnameinfo (addr, addrlen, buf + 7, MAXSDPADDRESS - 7, NULL,
- NI_NUMERICHOST))
- return NULL;
- switch (addr->sa_family)
- {
- case AF_INET:
- {
- if (net_SockAddrIsMulticast (addr, addrlen))
- strcat (buf, "/255"); // obsolete in RFC4566, dummy value
- buf[5] = '4';
- break;
- }
- #ifdef AF_INET6
- case AF_INET6:
- {
- char *ptr = strchr (buf, '%');
- if (ptr != NULL)
- *ptr = ' '; // remove scope ID
- buf[5] = '6';
- break;
- }
- #endif
- default:
- return NULL;
- }
- return buf;
- }
- static bool IsSDPString (const char *str)
- {
- if (strchr (str, 'r') != NULL)
- return false;
- if (strchr (str, 'n') != NULL)
- return false;
- if (!IsUTF8 (str))
- return false;
- return true;
- }
- static
- char *sdp_Start (const char *name, const char *description, const char *url,
- const char *email, const char *phone,
- const struct sockaddr *src, size_t srclen,
- const struct sockaddr *addr, size_t addrlen)
- {
- uint64_t now = NTPtime64 ();
- char *sdp;
- char connection[MAXSDPADDRESS], hostname[256],
- sfilter[MAXSDPADDRESS + sizeof ("rna=source-filter: incl * ")];
- const char *preurl = "rnu=", *premail = "rne=", *prephone = "rnp=";
- gethostname (hostname, sizeof (hostname));
- if (name == NULL)
- name = "Unnamed";
- if (description == NULL)
- description = "N/A";
- if (url == NULL)
- preurl = url = "";
- if (email == NULL)
- premail = email = "";
- if (phone == NULL)
- prephone = phone = "";
- if (!IsSDPString (name) || !IsSDPString (description)
- || !IsSDPString (url) || !IsSDPString (email) || !IsSDPString (phone)
- || (AddressToSDP (addr, addrlen, connection) == NULL))
- return NULL;
- strcpy (sfilter, "");
- if (srclen > 0)
- {
- char machine[MAXSDPADDRESS];
- if (AddressToSDP (src, srclen, machine) != NULL)
- sprintf (sfilter, "rna=source-filter: incl IN IP%c * %s",
- machine[5], machine + 7);
- }
- if (asprintf (&sdp, "v=0"
- "rno=- %"PRIu64" %"PRIu64" IN IP%c %s"
- "rns=%s"
- "rni=%s"
- "%s%s" // optional URL
- "%s%s" // optional email
- "%s%s" // optional phone number
- "rnc=%s"
- // bandwidth not specified
- "rnt=0 0" // one dummy time span
- // no repeating
- // no time zone adjustment (silly idea anyway)
- // no encryption key (deprecated)
- "rna=tool:"PACKAGE_STRING
- "rna=recvonly"
- "rna=type:broadcast"
- "rna=charset:UTF-8"
- "%s" // optional source filter
- "rn",
- /* o= */ now, now, connection[5], hostname,
- /* s= */ name,
- /* i= */ description,
- /* u= */ preurl, url,
- /* e= */ premail, email,
- /* p= */ prephone, phone,
- /* c= */ connection,
- /* source-filter */ sfilter) == -1)
- return NULL;
- return sdp;
- }
- static char *
- vsdp_AddAttribute (char **sdp, const char *name, const char *fmt, va_list ap)
- {
- size_t oldlen = strlen (*sdp);
- size_t addlen = sizeof ("a=rn") + strlen (name);
- if (fmt != NULL)
- {
- va_list aq;
- va_copy (aq, ap);
- addlen += 1 + vsnprintf (NULL, 0, fmt, aq);
- va_end (aq);
- }
- char *ret = realloc (*sdp, oldlen + addlen);
- if (ret == NULL)
- return NULL;
- oldlen += sprintf (ret + oldlen, "a=%s", name);
- if (fmt != NULL)
- {
- ret[oldlen++] = ':';
- oldlen += vsprintf (ret + oldlen, fmt, ap);
- }
- strcpy (ret + oldlen, "rn");
- return *sdp = ret;
- }
- char *sdp_AddAttribute (char **sdp, const char *name, const char *fmt, ...)
- {
- char *ret;
- va_list ap;
- va_start (ap, fmt);
- ret = vsdp_AddAttribute (sdp, name, fmt, ap);
- va_end (ap);
- return ret;
- }
- char *sdp_AddMedia (char **sdp,
- const char *type, const char *protocol, int dport,
- unsigned pt, bool bw_indep, unsigned bw,
- const char *ptname, unsigned clock, unsigned chans,
- const char *fmtp)
- {
- char *newsdp, *ptr;
- size_t inlen = strlen (*sdp), outlen = inlen;
- /* Some default values */
- if (type == NULL)
- type = "video";
- if (protocol == NULL)
- protocol = "RTP/AVP";
- assert (pt < 128u);
- outlen += snprintf (NULL, 0,
- "m=%s %u %s %drn"
- "b=TIAS:%urn",
- type, dport, protocol, pt, bw);
- newsdp = realloc (*sdp, outlen + 1);
- if (newsdp == NULL)
- return NULL;
- *sdp = newsdp;
- ptr = newsdp + inlen;
- ptr += sprintf (ptr, "m=%s %u %s %urn",
- type, dport, protocol, pt);
- if (bw > 0)
- ptr += sprintf (ptr, "b=%s:%urn", bw_indep ? "TIAS" : "AS", bw);
- /* RTP payload type map */
- if (ptname != NULL)
- {
- if ((strcmp (type, "audio") == 0) && (chans != 1))
- sdp_AddAttribute (sdp, "rtpmap", "%u %s/%u/%u", pt, ptname, clock,
- chans);
- else
- sdp_AddAttribute (sdp, "rtpmap", "%u %s/%u", pt, ptname, clock);
- }
- /* Format parameters */
- if (fmtp != NULL)
- sdp_AddAttribute (sdp, "fmtp", "%u %s", pt, fmtp);
- return newsdp;
- }
- char *vlc_sdp_Start (vlc_object_t *obj, const char *cfgpref,
- const struct sockaddr *src, size_t srclen,
- const struct sockaddr *addr, size_t addrlen)
- {
- size_t cfglen = strlen (cfgpref);
- if (cfglen > 100)
- return NULL;
- char varname[cfglen + sizeof ("description")], *subvar = varname + cfglen;
- strcpy (varname, cfgpref);
- strcpy (subvar, "name");
- char *name = var_GetNonEmptyString (obj, varname);
- strcpy (subvar, "description");
- char *description = var_GetNonEmptyString (obj, varname);
- strcpy (subvar, "url");
- char *url = var_GetNonEmptyString (obj, varname);
- strcpy (subvar, "email");
- char *email = var_GetNonEmptyString (obj, varname);
- strcpy (subvar, "phone");
- char *phone = var_GetNonEmptyString (obj, varname);
- char *sdp = sdp_Start (name, description, url, email, phone,
- src, srclen, addr, addrlen);
- free (name);
- free (description);
- free (url);
- free (email);
- free (phone);
- if (sdp == NULL)
- return NULL;
- /* Totally non-standard */
- strcpy (subvar, "group");
- char *group = var_GetNonEmptyString (obj, varname);
- if (group != NULL)
- {
- sdp_AddAttribute (&sdp, "x-plgroup", "%s", group);
- free (group);
- }
- return sdp;
- }