summaryrefslogtreecommitdiffstats
path: root/gst/rtsp/rtspconnection.c
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2005-05-11 12:01:10 +0000
committerWim Taymans <wim.taymans@gmail.com>2005-05-11 12:01:10 +0000
commit63177e073100ce81a14338c464bb1cb83c27c3a7 (patch)
tree469146b7fd30b5f34a9dbce9ec2455f59d8da294 /gst/rtsp/rtspconnection.c
parent91ce2b294e5538313bea3ddf7adaf1373d778384 (diff)
gst/rtsp/: Added README
Original commit message from CVS: * gst/rtsp/README: * gst/rtsp/gstrtspsrc.c: (gst_rtsp_proto_get_type), (gst_rtspsrc_class_init), (gst_rtspsrc_create_stream), (gst_rtspsrc_add_element), (gst_rtspsrc_set_state), (gst_rtspsrc_stream_setup_rtp), (gst_rtspsrc_stream_configure_transport), (find_stream), (gst_rtspsrc_loop), (gst_rtspsrc_open), (gst_rtspsrc_play): * gst/rtsp/rtsp.h: * gst/rtsp/rtspconnection.c: (rtsp_connection_create), (rtsp_connection_send), (read_line), (parse_request_line), (parse_line), (read_body), (rtsp_connection_receive), (rtsp_connection_free): * gst/rtsp/rtspconnection.h: * gst/rtsp/rtspdefs.c: (rtsp_find_method): * gst/rtsp/rtspdefs.h: * gst/rtsp/rtspmessage.c: (rtsp_message_set_body), (rtsp_message_take_body): * gst/rtsp/rtspmessage.h: * gst/rtsp/rtspstream.h: * gst/rtsp/sdpmessage.c: (sdp_parse_line): Added README Some cleanups.
Diffstat (limited to 'gst/rtsp/rtspconnection.c')
-rw-r--r--gst/rtsp/rtspconnection.c196
1 files changed, 156 insertions, 40 deletions
diff --git a/gst/rtsp/rtspconnection.c b/gst/rtsp/rtspconnection.c
index f9a1b420..9f5caa60 100644
--- a/gst/rtsp/rtspconnection.c
+++ b/gst/rtsp/rtspconnection.c
@@ -20,6 +20,7 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
+#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
@@ -94,7 +95,7 @@ rtsp_connection_create (gint fd, RTSPConnection ** conn)
{
RTSPConnection *newconn;
- /* FIXME check fd */
+ /* FIXME check fd, must be connected SOCK_STREAM */
newconn = g_new (RTSPConnection, 1);
@@ -120,30 +121,70 @@ RTSPResult
rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message)
{
GString *str;
+ gint towrite;
+ gchar *data;
if (conn == NULL || message == NULL)
return RTSP_EINVAL;
str = g_string_new ("");
+ /* create request string, add CSeq */
g_string_append_printf (str, "%s %s RTSP/1.0\r\n"
"CSeq: %d\r\n",
rtsp_method_as_text (message->type_data.request.method),
message->type_data.request.uri, conn->cseq);
+ /* append session id if we have one */
if (conn->session_id[0] != '\0') {
rtsp_message_add_header (message, RTSP_HDR_SESSION, conn->session_id);
}
+ /* append headers */
g_hash_table_foreach (message->hdr_fields, (GHFunc) append_header, str);
+ /* append Content-Length and body if needed */
+ if (message->body != NULL && message->body_size > 0) {
+ gchar *len;
- g_string_append (str, "\r\n");
+ len = g_strdup_printf ("%d", message->body_size);
+ append_header (RTSP_HDR_CONTENT_LENGTH, len, str);
+ g_free (len);
+ /* header ends here */
+ g_string_append (str, "\r\n");
+ str = g_string_append_len (str, message->body, message->body_size);
+ } else {
+ /* just end headers */
+ g_string_append (str, "\r\n");
+ }
+
+ /* write request */
+ towrite = str->len;
+ data = str->str;
- write (conn->fd, str->str, str->len);
+ while (towrite > 0) {
+ gint written;
+
+ written = write (conn->fd, data, towrite);
+ if (written < 0) {
+ if (errno != EAGAIN && errno != EINTR)
+ goto write_error;
+ } else {
+ towrite -= written;
+ data += written;
+ }
+ }
g_string_free (str, TRUE);
+ conn->cseq++;
+
return RTSP_OK;
+
+write_error:
+ {
+ g_string_free (str, TRUE);
+ return RTSP_ESYS;
+ }
}
static RTSPResult
@@ -151,29 +192,30 @@ read_line (gint fd, gchar * buffer, guint size)
{
gint idx;
gchar c;
- gint ret;
+ gint r;
idx = 0;
while (TRUE) {
- ret = read (fd, &c, 1);
- if (ret < 1)
- goto error;
-
- if (c == '\n') /* end on \n */
- break;
- if (c == '\r') /* ignore \r */
- continue;
+ r = read (fd, &c, 1);
+ if (r < 1) {
+ if (errno != EAGAIN && errno != EINTR)
+ goto read_error;
+ } else {
+ if (c == '\n') /* end on \n */
+ break;
+ if (c == '\r') /* ignore \r */
+ continue;
- if (idx < size - 1)
- buffer[idx++] = c;
+ if (idx < size - 1)
+ buffer[idx++] = c;
+ }
}
buffer[idx] = '\0';
return RTSP_OK;
-error:
+read_error:
{
- perror ("read");
return RTSP_ESYS;
}
}
@@ -243,6 +285,43 @@ wrong_version:
}
static RTSPResult
+parse_request_line (gchar * buffer, RTSPMessage * msg)
+{
+ gchar versionstr[20];
+ gchar methodstr[20];
+ gchar urlstr[4096];
+ gchar *bptr;
+ RTSPMethod method;
+
+ bptr = buffer;
+
+ read_string (methodstr, sizeof (methodstr), &bptr);
+ method = rtsp_find_method (methodstr);
+ if (method == -1)
+ goto wrong_method;
+
+ read_string (urlstr, sizeof (urlstr), &bptr);
+
+ read_string (versionstr, sizeof (versionstr), &bptr);
+ if (strcmp (versionstr, "RTSP/1.0") != 0)
+ goto wrong_version;
+
+ rtsp_message_init_request (method, urlstr, msg);
+
+ return RTSP_OK;
+
+wrong_method:
+ {
+ return RTSP_EINVAL;
+ }
+wrong_version:
+ {
+ return RTSP_EINVAL;
+ }
+}
+
+/* parsing lines means reading a Key: Value pair */
+static RTSPResult
parse_line (gchar * buffer, RTSPMessage * msg)
{
gchar key[32];
@@ -251,6 +330,7 @@ parse_line (gchar * buffer, RTSPMessage * msg)
bptr = buffer;
+ /* read key */
read_key (key, sizeof (key), &bptr);
if (*bptr != ':')
return RTSP_EINVAL;
@@ -259,7 +339,7 @@ parse_line (gchar * buffer, RTSPMessage * msg)
field = rtsp_find_header_field (key);
if (field == -1) {
- g_warning ("unknown header field '%s'\n", key);
+ g_warning ("ignoring unknown header field '%s'\n", key);
} else {
while (g_ascii_isspace (*bptr))
bptr++;
@@ -276,8 +356,9 @@ read_body (gint fd, glong content_length, RTSPMessage * msg)
gint to_read, r;
if (content_length <= 0) {
- rtsp_message_set_body (msg, NULL, 0);
- return RTSP_OK;
+ body = NULL;
+ content_length = 0;
+ goto done;
}
body = g_malloc (content_length);
@@ -285,14 +366,25 @@ read_body (gint fd, glong content_length, RTSPMessage * msg)
to_read = content_length;
while (to_read > 0) {
r = read (fd, bodyptr, to_read);
-
- to_read -= r;
- bodyptr += r;
+ if (r < 0) {
+ if (errno != EAGAIN && errno != EINTR)
+ goto read_error;
+ } else {
+ to_read -= r;
+ bodyptr += r;
+ }
}
+done:
rtsp_message_set_body (msg, body, content_length);
return RTSP_OK;
+
+read_error:
+ {
+ g_free (body);
+ return RTSP_ESYS;
+ }
}
RTSPResult
@@ -312,30 +404,36 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg)
need_body = TRUE;
+ res = RTSP_OK;
/* parse first line and headers */
- while (TRUE) {
+ while (res == RTSP_OK) {
gchar c;
gint ret;
+ /* read first character, this identifies data messages */
ret = read (conn->fd, &c, 1);
if (ret < 0)
goto read_error;
if (ret < 1)
break;
- /* check for data packet */
+ /* check for data packet, first character is $ */
if (c == '$') {
guint16 size;
- /* read channel */
+ /* data packets are $<1 byte channel><2 bytes length,BE><data bytes> */
+
+ /* read channel, which is the next char */
ret = read (conn->fd, &c, 1);
if (ret < 0)
goto read_error;
if (ret < 1)
goto error;
+ /* now we create a data message */
rtsp_message_init_data ((gint) c, msg);
+ /* next two bytes are the length of the data */
ret = read (conn->fd, &size, 2);
if (ret < 0)
goto read_error;
@@ -344,12 +442,14 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg)
size = GUINT16_FROM_BE (size);
- read_body (conn->fd, size, msg);
+ /* and read the body */
+ res = read_body (conn->fd, size, msg);
need_body = FALSE;
break;
} else {
gint offset = 0;
+ /* we have a regular response */
if (c != '\r') {
buffer[0] = c;
offset = 1;
@@ -358,46 +458,54 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg)
if (c == '\n')
break;
- read_line (conn->fd, buffer + offset, sizeof (buffer) - offset);
+ /* read lines */
+ res = read_line (conn->fd, buffer + offset, sizeof (buffer) - offset);
+ if (res != RTSP_OK)
+ goto read_error;
if (buffer[0] == '\0')
break;
if (line == 0) {
+ /* first line, check for response status */
if (g_str_has_prefix (buffer, "RTSP")) {
- parse_response_status (buffer, msg);
+ res = parse_response_status (buffer, msg);
} else {
- g_warning ("parsing request not implemented\n");
- goto error;
+ res = parse_request_line (buffer, msg);
}
} else {
+ /* else just parse the line */
parse_line (buffer, msg);
}
}
line++;
}
+ /* read the rest of the body if needed */
if (need_body) {
- /* parse body */
- res = rtsp_message_get_header (msg, RTSP_HDR_CONTENT_LENGTH, &hdrval);
- if (res == RTSP_OK) {
+ /* see if there is a Content-Length header */
+ if (rtsp_message_get_header (msg, RTSP_HDR_CONTENT_LENGTH,
+ &hdrval) == RTSP_OK) {
+ /* there is, read the body */
content_length = atol (hdrval);
- read_body (conn->fd, content_length, msg);
+ res = read_body (conn->fd, content_length, msg);
}
- /* save session id */
+ /* save session id in the connection for further use */
{
gchar *session_id;
if (rtsp_message_get_header (msg, RTSP_HDR_SESSION,
&session_id) == RTSP_OK) {
- strncpy (conn->session_id, session_id, sizeof (conn->session_id) - 1);
- conn->session_id[sizeof (conn->session_id) - 1] = '\0';
+ gint maxlen = sizeof (conn->session_id) - 1;
+
+ /* make sure to not overflow */
+ strncpy (conn->session_id, session_id, maxlen);
+ conn->session_id[maxlen] = '\0';
}
}
}
-
- return RTSP_OK;
+ return res;
error:
{
@@ -405,7 +513,6 @@ error:
}
read_error:
{
- perror ("read");
return RTSP_ESYS;
}
}
@@ -430,3 +537,12 @@ sys_error:
return RTSP_ESYS;
}
}
+
+RTSPResult
+rtsp_connection_free (RTSPConnection * conn)
+{
+ if (conn == NULL)
+ return RTSP_EINVAL;
+
+ g_free (conn);
+}