rtsp: Do not split headers which should not be split.
From RFC 2068 section 4.2: "Multiple message-header fields with the same field-name may be present in a message if and only if the entire field-value for that header field is defined as a comma-separated list [i.e., #(values)]." This means that we should not split other headers which may contain a comma, e.g., Range and Date.
This commit is contained in:
parent
08d3fe8561
commit
607209f121
@ -1606,8 +1606,15 @@ parse_line (guint8 * buffer, GstRTSPMessage * msg)
|
|||||||
if (*value == ' ')
|
if (*value == ' ')
|
||||||
value++;
|
value++;
|
||||||
|
|
||||||
|
/* for headers which may not appear multiple times, and thus may not
|
||||||
|
* contain multiple values on the same line, we can short-circuit the loop
|
||||||
|
* below and the entire value results in just one key:value pair*/
|
||||||
|
if (!gst_rtsp_header_allow_multiple (field))
|
||||||
|
next_value = value + strlen (value);
|
||||||
|
else
|
||||||
|
next_value = value;
|
||||||
|
|
||||||
/* find the next value, taking special care of quotes and comments */
|
/* find the next value, taking special care of quotes and comments */
|
||||||
next_value = value;
|
|
||||||
while (*next_value != '\0') {
|
while (*next_value != '\0') {
|
||||||
if ((quoted || comment != 0) && *next_value == '\\' &&
|
if ((quoted || comment != 0) && *next_value == '\\' &&
|
||||||
next_value[1] != '\0')
|
next_value[1] != '\0')
|
||||||
|
@ -66,6 +66,12 @@ extern int h_errno;
|
|||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct rtsp_header
|
||||||
|
{
|
||||||
|
const gchar *name;
|
||||||
|
gboolean multiple;
|
||||||
|
};
|
||||||
|
|
||||||
static const gchar *rtsp_results[] = {
|
static const gchar *rtsp_results[] = {
|
||||||
"OK",
|
"OK",
|
||||||
/* errors */
|
/* errors */
|
||||||
@ -106,96 +112,101 @@ static const gchar *rtsp_methods[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static const gchar *rtsp_headers[] = {
|
static struct rtsp_header rtsp_headers[] = {
|
||||||
"Accept", /* Accept R opt. entity */
|
{"Accept", TRUE},
|
||||||
"Accept-Encoding", /* Accept-Encoding R opt. entity */
|
{"Accept-Encoding", TRUE},
|
||||||
"Accept-Language", /* Accept-Language R opt. all */
|
{"Accept-Language", TRUE},
|
||||||
"Allow", /* Allow r opt. all */
|
{"Allow", TRUE},
|
||||||
"Authorization", /* Authorization R opt. all */
|
{"Authorization", FALSE},
|
||||||
"Bandwidth", /* Bandwidth R opt. all */
|
{"Bandwidth", FALSE},
|
||||||
"Blocksize", /* Blocksize R opt. all but OPTIONS, TEARDOWN */
|
{"Blocksize", FALSE},
|
||||||
"Cache-Control", /* Cache-Control g opt. SETUP */
|
{"Cache-Control", TRUE},
|
||||||
"Conference", /* Conference R opt. SETUP */
|
{"Conference", FALSE},
|
||||||
"Connection", /* Connection g req. all */
|
{"Connection", TRUE},
|
||||||
"Content-Base", /* Content-Base e opt. entity */
|
{"Content-Base", FALSE},
|
||||||
"Content-Encoding", /* Content-Encoding e req. SET_PARAMETER, DESCRIBE, ANNOUNCE */
|
{"Content-Encoding", TRUE},
|
||||||
"Content-Language", /* Content-Language e req. DESCRIBE, ANNOUNCE */
|
{"Content-Language", TRUE},
|
||||||
"Content-Length", /* Content-Length e req. SET_PARAMETER, ANNOUNCE, entity */
|
{"Content-Length", FALSE},
|
||||||
"Content-Location", /* Content-Location e opt. entity */
|
{"Content-Location", FALSE},
|
||||||
"Content-Type", /* Content-Type e req. SET_PARAMETER, ANNOUNCE, entity */
|
{"Content-Type", FALSE},
|
||||||
"CSeq", /* CSeq g req. all */
|
{"CSeq", FALSE},
|
||||||
"Date", /* Date g opt. all */
|
{"Date", FALSE},
|
||||||
"Expires", /* Expires e opt. DESCRIBE, ANNOUNCE */
|
{"Expires", FALSE},
|
||||||
"From", /* From R opt. all */
|
{"From", FALSE},
|
||||||
"If-Modified-Since", /* If-Modified-Since R opt. DESCRIBE, SETUP */
|
{"If-Modified-Since", FALSE},
|
||||||
"Last-Modified", /* Last-Modified e opt. entity */
|
{"Last-Modified", FALSE},
|
||||||
"Proxy-Authenticate", /* Proxy-Authenticate */
|
{"Proxy-Authenticate", TRUE},
|
||||||
"Proxy-Require", /* Proxy-Require R req. all */
|
{"Proxy-Require", TRUE},
|
||||||
"Public", /* Public r opt. all */
|
{"Public", TRUE},
|
||||||
"Range", /* Range Rr opt. PLAY, PAUSE, RECORD */
|
{"Range", FALSE},
|
||||||
"Referer", /* Referer R opt. all */
|
{"Referer", FALSE},
|
||||||
"Require", /* Require R req. all */
|
{"Require", TRUE},
|
||||||
"Retry-After", /* Retry-After r opt. all */
|
{"Retry-After", FALSE},
|
||||||
"RTP-Info", /* RTP-Info r req. PLAY */
|
{"RTP-Info", TRUE},
|
||||||
"Scale", /* Scale Rr opt. PLAY, RECORD */
|
{"Scale", FALSE},
|
||||||
"Session", /* Session Rr req. all but SETUP, OPTIONS */
|
{"Session", FALSE},
|
||||||
"Server", /* Server r opt. all */
|
{"Server", FALSE},
|
||||||
"Speed", /* Speed Rr opt. PLAY */
|
{"Speed", FALSE},
|
||||||
"Transport", /* Transport Rr req. SETUP */
|
{"Transport", FALSE},
|
||||||
"Unsupported", /* Unsupported r req. all */
|
{"Unsupported", FALSE},
|
||||||
"User-Agent", /* User-Agent R opt. all */
|
{"User-Agent", FALSE},
|
||||||
"Via", /* Via g opt. all */
|
{"Via", TRUE},
|
||||||
"WWW-Authenticate", /* WWW-Authenticate r opt. all */
|
{"WWW-Authenticate", TRUE},
|
||||||
|
|
||||||
/* Real extensions */
|
/* Real extensions */
|
||||||
"ClientChallenge", /* ClientChallenge */
|
{"ClientChallenge", FALSE},
|
||||||
"RealChallenge1", /* RealChallenge1 */
|
{"RealChallenge1", FALSE},
|
||||||
"RealChallenge2", /* RealChallenge2 */
|
{"RealChallenge2", FALSE},
|
||||||
"RealChallenge3", /* RealChallenge3 */
|
{"RealChallenge3", FALSE},
|
||||||
"Subscribe", /* Subscribe */
|
{"Subscribe", FALSE},
|
||||||
"Alert", /* Alert */
|
{"Alert", FALSE},
|
||||||
"ClientID", /* ClientID */
|
{"ClientID", FALSE},
|
||||||
"CompanyID", /* CompanyID */
|
{"CompanyID", FALSE},
|
||||||
"GUID", /* GUID */
|
{"GUID", FALSE},
|
||||||
"RegionData", /* RegionData */
|
{"RegionData", FALSE},
|
||||||
"SupportsMaximumASMBandwidth", /* SupportsMaximumASMBandwidth */
|
{"SupportsMaximumASMBandwidth", FALSE},
|
||||||
"Language", /* Language */
|
{"Language", FALSE},
|
||||||
"PlayerStarttime", /* PlayerStarttime */
|
{"PlayerStarttime", FALSE},
|
||||||
|
|
||||||
"Location", /* Location */
|
/* Since 0.10.16 */
|
||||||
"ETag", /* ETag */
|
{"Location", FALSE},
|
||||||
"If-Match", /* If-Match */
|
|
||||||
|
|
||||||
/* WM extensions [MS-RTSP] */
|
/* Since 0.10.23 */
|
||||||
"Accept-Charset", /* Accept-Charset */
|
{"ETag", FALSE},
|
||||||
"Supported", /* Supported */
|
{"If-Match", TRUE},
|
||||||
"Vary", /* Vary */
|
|
||||||
"X-Accelerate-Streaming", /* X-Accelerate-Streaming */
|
|
||||||
"X-Accept-Authentication", /* X-Accept-Authentication */
|
|
||||||
"X-Accept-Proxy-Authentication", /* X-Accept-Proxy-Authentication */
|
|
||||||
"X-Broadcast-Id", /* X-Broadcast-Id */
|
|
||||||
"X-Burst-Streaming", /* X-Burst-Streaming */
|
|
||||||
"X-Notice", /* X-Notice */
|
|
||||||
"X-Player-Lag-Time", /* X-Player-Lag-Time */
|
|
||||||
"X-Playlist", /* X-Playlist */
|
|
||||||
"X-Playlist-Change-Notice", /* X-Playlist-Change-Notice */
|
|
||||||
"X-Playlist-Gen-Id", /* X-Playlist-Gen-Id */
|
|
||||||
"X-Playlist-Seek-Id", /* X-Playlist-Seek-Id */
|
|
||||||
"X-Proxy-Client-Agent", /* X-Proxy-Client-Agent */
|
|
||||||
"X-Proxy-Client-Verb", /* X-Proxy-Client-Verb */
|
|
||||||
"X-Receding-PlaylistChange", /* X-Receding-PlaylistChange */
|
|
||||||
"X-RTP-Info", /* X-RTP-Info */
|
|
||||||
"X-StartupProfile", /* X-StartupProfile */
|
|
||||||
|
|
||||||
"Timestamp", /* Timestamp */
|
/* WM extensions [MS-RTSP] Since 0.10.23 */
|
||||||
|
{"Accept-Charset", TRUE},
|
||||||
|
{"Supported", TRUE},
|
||||||
|
{"Vary", TRUE},
|
||||||
|
{"X-Accelerate-Streaming", FALSE},
|
||||||
|
{"X-Accept-Authentication", FALSE},
|
||||||
|
{"X-Accept-Proxy-Authentication", FALSE},
|
||||||
|
{"X-Broadcast-Id", FALSE},
|
||||||
|
{"X-Burst-Streaming", FALSE},
|
||||||
|
{"X-Notice", FALSE},
|
||||||
|
{"X-Player-Lag-Time", FALSE},
|
||||||
|
{"X-Playlist", FALSE},
|
||||||
|
{"X-Playlist-Change-Notice", FALSE},
|
||||||
|
{"X-Playlist-Gen-Id", FALSE},
|
||||||
|
{"X-Playlist-Seek-Id", FALSE},
|
||||||
|
{"X-Proxy-Client-Agent", FALSE},
|
||||||
|
{"X-Proxy-Client-Verb", FALSE},
|
||||||
|
{"X-Receding-PlaylistChange", FALSE},
|
||||||
|
{"X-RTP-Info", FALSE},
|
||||||
|
{"X-StartupProfile", FALSE},
|
||||||
|
|
||||||
"Authentication-Info", /* Authentication-Info */
|
/* Since 0.10.24 */
|
||||||
"Host", /* Host */
|
{"Timestamp", FALSE},
|
||||||
"Pragma", /* Pragma */
|
|
||||||
"X-Server-IP-Address", /* X-Server-IP-Address */
|
|
||||||
"X-Sessioncookie", /* X-Sessioncookie */
|
|
||||||
|
|
||||||
NULL
|
/* Since 0.10.25 */
|
||||||
|
{"Authentication-Info", FALSE},
|
||||||
|
{"Host", FALSE},
|
||||||
|
{"Pragma", TRUE},
|
||||||
|
{"X-Server-IP-Address", FALSE},
|
||||||
|
{"X-Sessioncookie", FALSE},
|
||||||
|
|
||||||
|
{NULL, FALSE}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEF_STATUS(c, t) \
|
#define DEF_STATUS(c, t) \
|
||||||
@ -368,7 +379,7 @@ gst_rtsp_header_as_text (GstRTSPHeaderField field)
|
|||||||
if (field == GST_RTSP_HDR_INVALID)
|
if (field == GST_RTSP_HDR_INVALID)
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
return rtsp_headers[field - 1];
|
return rtsp_headers[field - 1].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -404,8 +415,8 @@ gst_rtsp_find_header_field (const gchar * header)
|
|||||||
{
|
{
|
||||||
gint idx;
|
gint idx;
|
||||||
|
|
||||||
for (idx = 0; rtsp_headers[idx]; idx++) {
|
for (idx = 0; rtsp_headers[idx].name; idx++) {
|
||||||
if (g_ascii_strcasecmp (rtsp_headers[idx], header) == 0) {
|
if (g_ascii_strcasecmp (rtsp_headers[idx].name, header) == 0) {
|
||||||
return idx + 1;
|
return idx + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -480,3 +491,22 @@ gst_rtsp_options_as_text (GstRTSPMethod options)
|
|||||||
|
|
||||||
return g_string_free (str, FALSE);
|
return g_string_free (str, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_rtsp_header_allow_multiple:
|
||||||
|
* @field: a #GstRTSPHeaderField
|
||||||
|
*
|
||||||
|
* Check whether @field may appear multiple times in a message.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if multiple headers are allowed.
|
||||||
|
*
|
||||||
|
* Since: 0.10.25
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_rtsp_header_allow_multiple (GstRTSPHeaderField field)
|
||||||
|
{
|
||||||
|
if (field == GST_RTSP_HDR_INVALID)
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
return rtsp_headers[field - 1].multiple;
|
||||||
|
}
|
||||||
|
@ -389,6 +389,8 @@ gchar* gst_rtsp_options_as_text (GstRTSPMethod options);
|
|||||||
GstRTSPHeaderField gst_rtsp_find_header_field (const gchar *header);
|
GstRTSPHeaderField gst_rtsp_find_header_field (const gchar *header);
|
||||||
GstRTSPMethod gst_rtsp_find_method (const gchar *method);
|
GstRTSPMethod gst_rtsp_find_method (const gchar *method);
|
||||||
|
|
||||||
|
gboolean gst_rtsp_header_allow_multiple (GstRTSPHeaderField field);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_RTSP_DEFS_H__ */
|
#endif /* __GST_RTSP_DEFS_H__ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user