diff options
author | Peter Kjellerstedt <pkj@axis.com> | 2007-06-01 13:07:11 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2007-06-01 13:07:11 +0000 |
commit | f12fb76f70cbc7ecb088fa9ca00b33b3079c9d8e (patch) | |
tree | c051ea88aa8b4d42eaf9ea6169f75cd983ef2084 /gst | |
parent | 89ae9b40f9c32d3e8aac4c7c9aafb83d64fa2497 (diff) |
gst/rtsp/: Improves version checking, allowing an RTSP server to reply with "505
Original commit message from CVS:
Patch by: Peter Kjellerstedt <pkj at axis com>
* gst/rtsp/rtspconnection.c: (rtsp_connection_create),
(rtsp_connection_connect), (add_date_header),
(rtsp_connection_send), (parse_response_status),
(parse_request_line), (parse_line), (rtsp_connection_receive):
* gst/rtsp/rtspdefs.c: (rtsp_version_as_text):
* gst/rtsp/rtspdefs.h:
* gst/rtsp/rtspmessage.c: (key_value_foreach),
(rtsp_message_init_request), (rtsp_message_init_response),
(rtsp_message_remove_header), (rtsp_message_append_headers),
(rtsp_message_dump):
* gst/rtsp/rtspmessage.h:
Improves version checking, allowing an RTSP server to reply with "505
RTSP Version not supported.
Adds a Date header to all messages.
Replies with RTSP_EPARSE rather than RTSP_EINVALID in cases where we
want to be able to send a response even if something in the request was
invalid. EINVAL is only used when passing wrong arguments to functions.
Do not handle an invalid method in parse_request_line(). Defer this to
the caller so it can respond with "405 Method Not Allowed".
Improves parsing of the timeout parameter to the Session header,
allowing whitespace after the semicolon.
Avoids a compiler warning due to variables shadowing a function argument.
Diffstat (limited to 'gst')
-rw-r--r-- | gst/rtsp/rtspconnection.c | 147 | ||||
-rw-r--r-- | gst/rtsp/rtspdefs.c | 12 | ||||
-rw-r--r-- | gst/rtsp/rtspdefs.h | 6 | ||||
-rw-r--r-- | gst/rtsp/rtspmessage.c | 14 | ||||
-rw-r--r-- | gst/rtsp/rtspmessage.h | 2 |
5 files changed, 116 insertions, 65 deletions
diff --git a/gst/rtsp/rtspconnection.c b/gst/rtsp/rtspconnection.c index e20de231..50948f6c 100644 --- a/gst/rtsp/rtspconnection.c +++ b/gst/rtsp/rtspconnection.c @@ -122,7 +122,7 @@ rtsp_connection_create (RTSPUrl * url, RTSPConnection ** conn) g_return_val_if_fail (conn != NULL, RTSP_EINVAL); - newconn = g_new (RTSPConnection, 1); + newconn = g_new0 (RTSPConnection, 1); #ifdef G_OS_WIN32 /* This should work on UNIX too. PF_UNIX sockets replaced with pipe */ @@ -140,8 +140,6 @@ rtsp_connection_create (RTSPUrl * url, RTSPConnection ** conn) newconn->url = url; newconn->fd = -1; - newconn->cseq = 0; - newconn->session_id[0] = 0; newconn->timer = g_timer_new (); newconn->auth_method = RTSP_AUTH_NONE; @@ -164,7 +162,7 @@ RTSPResult rtsp_connection_connect (RTSPConnection * conn, GTimeVal * timeout) { gint fd; - struct sockaddr_in sin; + struct sockaddr_in sa_in; struct hostent *hostinfo; char **addrs; gchar *ip; @@ -201,10 +199,10 @@ rtsp_connection_connect (RTSPConnection * conn, GTimeVal * timeout) /* get the port from the url */ rtsp_url_get_port (url, &port); - memset (&sin, 0, sizeof (sin)); - sin.sin_family = AF_INET; /* network socket */ - sin.sin_port = htons (port); /* on port */ - sin.sin_addr.s_addr = inet_addr (ip); /* on host ip */ + memset (&sa_in, 0, sizeof (sa_in)); + sa_in.sin_family = AF_INET; /* network socket */ + sa_in.sin_port = htons (port); /* on port */ + sa_in.sin_addr.s_addr = inet_addr (ip); /* on host ip */ fd = socket (AF_INET, SOCK_STREAM, 0); if (fd == -1) @@ -214,7 +212,7 @@ rtsp_connection_connect (RTSPConnection * conn, GTimeVal * timeout) fcntl (fd, F_SETFL, O_NONBLOCK); /* we are going to connect ASYNC now */ - ret = connect (fd, (struct sockaddr *) &sin, sizeof (sin)); + ret = connect (fd, (struct sockaddr *) &sa_in, sizeof (sa_in)); if (ret == 0) goto done; if (errno != EINPROGRESS) @@ -295,6 +293,19 @@ add_auth_header (RTSPConnection * conn, RTSPMessage * message) } } +static void +add_date_header (RTSPMessage * message) +{ + GTimeVal tv; + gchar date_string[100]; + + g_get_current_time (&tv); + strftime (date_string, sizeof (date_string), "%a, %d %b %Y %H:%M:%S GMT", + gmtime (&tv.tv_sec)); + + rtsp_message_add_header (message, RTSP_HDR_DATE, date_string); +} + RTSPResult rtsp_connection_write (RTSPConnection * conn, const guint8 * data, guint size, GTimeVal * timeout) @@ -389,7 +400,7 @@ RTSPResult rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message, GTimeVal * timeout) { - GString *str = NULL; + GString *str; RTSPResult res; #ifdef G_OS_WIN32 @@ -455,6 +466,9 @@ rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message, /* append headers and body */ if (message->type != RTSP_MESSAGE_DATA) { + /* add date header */ + add_date_header (message); + /* append headers */ rtsp_message_append_headers (message, str); @@ -576,6 +590,7 @@ read_key (gchar * dest, gint size, gchar ** src) static RTSPResult parse_response_status (gchar * buffer, RTSPMessage * msg) { + RTSPResult res; gchar versionstr[20]; gchar codestr[4]; gint code; @@ -584,28 +599,34 @@ parse_response_status (gchar * buffer, RTSPMessage * msg) bptr = buffer; read_string (versionstr, sizeof (versionstr), &bptr); - if (strcmp (versionstr, "RTSP/1.0") != 0) - goto wrong_version; - read_string (codestr, sizeof (codestr), &bptr); code = atoi (codestr); while (g_ascii_isspace (*bptr)) bptr++; - rtsp_message_init_response (msg, code, bptr, NULL); + if (strcmp (versionstr, "RTSP/1.0") == 0) + RTSP_CHECK (rtsp_message_init_response (msg, code, bptr, NULL), + parse_error); + else if (strncmp (versionstr, "RTSP/", 5) == 0) { + RTSP_CHECK (rtsp_message_init_response (msg, code, bptr, NULL), + parse_error); + msg->type_data.response.version = RTSP_VERSION_INVALID; + } else + goto parse_error; return RTSP_OK; -wrong_version: +parse_error: { - return RTSP_EINVAL; + return RTSP_EPARSE; } } static RTSPResult parse_request_line (gchar * buffer, RTSPMessage * msg) { + RTSPResult res = RTSP_OK; gchar versionstr[20]; gchar methodstr[20]; gchar urlstr[4096]; @@ -616,27 +637,30 @@ parse_request_line (gchar * buffer, RTSPMessage * msg) read_string (methodstr, sizeof (methodstr), &bptr); method = rtsp_find_method (methodstr); - if (method == RTSP_INVALID) - goto wrong_method; read_string (urlstr, sizeof (urlstr), &bptr); + if (*urlstr == '\0') + res = RTSP_EPARSE; read_string (versionstr, sizeof (versionstr), &bptr); - if (strcmp (versionstr, "RTSP/1.0") != 0) - goto wrong_version; - rtsp_message_init_request (msg, method, urlstr); + if (*bptr != '\0') + res = RTSP_EPARSE; - return RTSP_OK; - -wrong_method: - { - return RTSP_EINVAL; - } -wrong_version: - { - return RTSP_EINVAL; + if (strcmp (versionstr, "RTSP/1.0") == 0) { + if (rtsp_message_init_request (msg, method, urlstr) != RTSP_OK) + res = RTSP_EPARSE; + } else if (strncmp (versionstr, "RTSP/", 5) == 0) { + if (rtsp_message_init_request (msg, method, urlstr) != RTSP_OK) + res = RTSP_EPARSE; + msg->type_data.request.version = RTSP_VERSION_INVALID; + } else { + rtsp_message_init_request (msg, method, urlstr); + msg->type_data.request.version = RTSP_VERSION_INVALID; + res = RTSP_EPARSE; } + + return res; } /* parsing lines means reading a Key: Value pair */ @@ -667,7 +691,7 @@ parse_line (gchar * buffer, RTSPMessage * msg) no_column: { - return RTSP_EINVAL; + return RTSP_EPARSE; } } @@ -821,7 +845,6 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg, { gchar buffer[4096]; gint line; - gchar *hdrval; glong content_length; RTSPResult res; gboolean need_body; @@ -899,6 +922,9 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg, /* read the rest of the body if needed */ if (need_body) { + gchar *session_id; + gchar *hdrval; + /* see if there is a Content-Length header */ if (rtsp_message_get_header (msg, RTSP_HDR_CONTENT_LENGTH, &hdrval, 0) == RTSP_OK) { @@ -908,38 +934,37 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg, } /* save session id in the connection for further use */ - { - gchar *session_id; - - if (rtsp_message_get_header (msg, RTSP_HDR_SESSION, - &session_id, 0) == RTSP_OK) { - gint sesslen, maxlen, i; - - /* default session timeout */ - conn->timeout = 60; - - sesslen = strlen (session_id); - maxlen = sizeof (conn->session_id) - 1; - /* the sessionid can have attributes marked with ; - * Make sure we strip them */ - for (i = 0; i < sesslen; i++) { - if (session_id[i] == ';') { - maxlen = i; - /* parse timeout */ - if (g_str_has_prefix (&session_id[i], ";timeout=")) { - gint timeout; - - /* if we parsed something valid, configure */ - if ((timeout = atoi (&session_id[i + 9])) > 0) - conn->timeout = timeout; - } + if (rtsp_message_get_header (msg, RTSP_HDR_SESSION, + &session_id, 0) == RTSP_OK) { + gint maxlen, i; + + /* default session timeout */ + conn->timeout = 60; + + maxlen = sizeof (conn->session_id) - 1; + /* the sessionid can have attributes marked with ; + * Make sure we strip them */ + for (i = 0; session_id[i] != '\0'; i++) { + if (session_id[i] == ';') { + maxlen = i; + /* parse timeout */ + do { + i++; + } while (g_ascii_isspace (session_id[i])); + if (g_str_has_prefix (&session_id[i], "timeout=")) { + gint to; + + /* if we parsed something valid, configure */ + if ((to = atoi (&session_id[i + 9])) > 0) + conn->timeout = to; } + break; } - - /* make sure to not overflow */ - strncpy (conn->session_id, session_id, maxlen); - conn->session_id[maxlen] = '\0'; } + + /* make sure to not overflow */ + strncpy (conn->session_id, session_id, maxlen); + conn->session_id[maxlen] = '\0'; } } return res; diff --git a/gst/rtsp/rtspdefs.c b/gst/rtsp/rtspdefs.c index 2c3f7b73..8f11a5d9 100644 --- a/gst/rtsp/rtspdefs.c +++ b/gst/rtsp/rtspdefs.c @@ -255,6 +255,18 @@ rtsp_method_as_text (RTSPMethod method) } const gchar * +rtsp_version_as_text (RTSPVersion version) +{ + switch (version) { + case RTSP_VERSION_1_0: + return "1.0"; + + default: + return "0.0"; + } +} + +const gchar * rtsp_header_as_text (RTSPHeaderField field) { if (field == RTSP_HDR_INVALID) diff --git a/gst/rtsp/rtspdefs.h b/gst/rtsp/rtspdefs.h index 8a2182db..2045c1fc 100644 --- a/gst/rtsp/rtspdefs.h +++ b/gst/rtsp/rtspdefs.h @@ -90,6 +90,11 @@ typedef enum { } RTSPState; typedef enum { + RTSP_VERSION_INVALID = 0x00, + RTSP_VERSION_1_0 = 0x10, +} RTSPVersion; + +typedef enum { RTSP_INVALID = 0, RTSP_DESCRIBE = (1 << 0), RTSP_ANNOUNCE = (1 << 1), @@ -232,6 +237,7 @@ typedef enum { gchar* rtsp_strresult (RTSPResult result); const gchar* rtsp_method_as_text (RTSPMethod method); +const gchar* rtsp_version_as_text (RTSPVersion version); const gchar* rtsp_header_as_text (RTSPHeaderField field); const gchar* rtsp_status_as_text (RTSPStatusCode code); diff --git a/gst/rtsp/rtspmessage.c b/gst/rtsp/rtspmessage.c index 2cb12bf3..5dd2faab 100644 --- a/gst/rtsp/rtspmessage.c +++ b/gst/rtsp/rtspmessage.c @@ -118,6 +118,7 @@ rtsp_message_init_request (RTSPMessage * msg, RTSPMethod method, msg->type = RTSP_MESSAGE_REQUEST; msg->type_data.request.method = method; msg->type_data.request.uri = g_strdup (uri); + msg->type_data.request.version = RTSP_VERSION_1_0; msg->hdr_fields = g_array_new (FALSE, FALSE, sizeof (RTSPKeyValue)); return RTSP_OK; @@ -152,6 +153,7 @@ rtsp_message_init_response (RTSPMessage * msg, RTSPStatusCode code, msg->type = RTSP_MESSAGE_RESPONSE; msg->type_data.response.code = code; msg->type_data.response.reason = g_strdup (reason); + msg->type_data.response.version = RTSP_VERSION_1_0; msg->hdr_fields = g_array_new (FALSE, FALSE, sizeof (RTSPKeyValue)); if (request) { @@ -424,9 +426,11 @@ rtsp_message_dump (RTSPMessage * msg) case RTSP_MESSAGE_REQUEST: g_print ("RTSP request message %p\n", msg); g_print (" request line:\n"); - g_print (" method: '%s'\n", + g_print (" method: '%s'\n", rtsp_method_as_text (msg->type_data.request.method)); - g_print (" uri: '%s'\n", msg->type_data.request.uri); + g_print (" uri: '%s'\n", msg->type_data.request.uri); + g_print (" version: '%s'\n", + rtsp_version_as_text (msg->type_data.request.version)); g_print (" headers:\n"); key_value_foreach (msg->hdr_fields, dump_key_value, NULL); g_print (" body:\n"); @@ -436,8 +440,10 @@ rtsp_message_dump (RTSPMessage * msg) case RTSP_MESSAGE_RESPONSE: g_print ("RTSP response message %p\n", msg); g_print (" status line:\n"); - g_print (" code: '%d'\n", msg->type_data.response.code); - g_print (" reason: '%s'\n", msg->type_data.response.reason); + g_print (" code: '%d'\n", msg->type_data.response.code); + g_print (" reason: '%s'\n", msg->type_data.response.reason); + g_print (" version: '%s'\n", + rtsp_version_as_text (msg->type_data.response.version)); g_print (" headers:\n"); key_value_foreach (msg->hdr_fields, dump_key_value, NULL); rtsp_message_get_body (msg, &data, &size); diff --git a/gst/rtsp/rtspmessage.h b/gst/rtsp/rtspmessage.h index 2c099f17..15d173c3 100644 --- a/gst/rtsp/rtspmessage.h +++ b/gst/rtsp/rtspmessage.h @@ -65,10 +65,12 @@ typedef struct _RTSPMessage struct { RTSPMethod method; gchar *uri; + RTSPVersion version; } request; struct { RTSPStatusCode code; gchar *reason; + RTSPVersion version; } response; struct { guint8 channel; |