aboutsummaryrefslogtreecommitdiffstats
path: root/packet-rtsp.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>1999-07-07 00:34:58 +0000
committerGuy Harris <guy@alum.mit.edu>1999-07-07 00:34:58 +0000
commitb547681d563bdaeece9f62ae43da5ab2ae93d953 (patch)
treec073c6e4a3438a5dcc8ccfe3ec9c26b292fadb63 /packet-rtsp.c
parentbec7c4afe520dde06fdf82050ec9ac058f7335bd (diff)
Add support for RTSP (RFC 2326) over TCP, and SDP (RFC 2327) inside
RTSP, from Jason Lango <jal@netapp.com>. svn path=/trunk/; revision=340
Diffstat (limited to 'packet-rtsp.c')
-rw-r--r--packet-rtsp.c241
1 files changed, 241 insertions, 0 deletions
diff --git a/packet-rtsp.c b/packet-rtsp.c
new file mode 100644
index 0000000000..785d17b39a
--- /dev/null
+++ b/packet-rtsp.c
@@ -0,0 +1,241 @@
+/* packet-rtsp.c
+ * Routines for RTSP packet disassembly
+ *
+ * Jason Lango <jal@netapp.com>
+ * Liberally copied from packet-http.c, by Guy Harris <guy@netapp.com>
+ *
+ * $Id: packet-rtsp.c,v 1.1 1999/07/07 00:34:56 guy Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ */
+
+#include "config.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include "packet.h"
+
+static int is_rtsp_request_or_reply(const u_char *data, int linelen);
+
+static int
+is_content_sdp(const u_char *line, int linelen)
+{
+ const char *hdr = "Content-Type:";
+ size_t hdrlen = strlen(hdr);
+ const char *type = "application/sdp";
+ size_t typelen = strlen(type);
+
+ if (linelen < hdrlen || strncasecmp(hdr, line, hdrlen))
+ return 0;
+
+ line += hdrlen;
+ linelen -= hdrlen;
+ while (linelen > 0 && (*line == ' ' || *line == '\t')) {
+ line++;
+ linelen--;
+ }
+
+ if (linelen < typelen || strncasecmp(type, line, typelen))
+ return 0;
+
+ line += typelen;
+ linelen -= typelen;
+ if (linelen > 0 && !isspace(*line))
+ return 0;
+
+ return 1;
+}
+
+void dissect_rtsp(const u_char *pd, int offset, frame_data *fd,
+ proto_tree *tree)
+{
+ proto_tree *rtsp_tree;
+ proto_item *ti;
+ const u_char *data, *dataend;
+ const u_char *linep, *lineend, *eol;
+ int linelen;
+ u_char c;
+ int is_sdp = 0;
+
+ data = &pd[offset];
+ dataend = data + END_OF_FRAME;
+
+ if (check_col(fd, COL_PROTOCOL))
+ col_add_str(fd, COL_PROTOCOL, "RTSP");
+ if (check_col(fd, COL_INFO)) {
+ /*
+ * Put the first line from the buffer into the summary,
+ * if it's an RTSP request or reply.
+ * Otherwise, just call it a continuation.
+ */
+ lineend = find_line_end(data, dataend, &eol);
+ linelen = lineend - data;
+ if (is_rtsp_request_or_reply(data, linelen))
+ col_add_str(fd, COL_INFO, format_text(data, linelen));
+ else
+ col_add_str(fd, COL_INFO, "Continuation");
+ }
+
+ rtsp_tree = NULL;
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, offset, END_OF_FRAME,
+ "Real Time Streaming Protocol");
+ rtsp_tree = proto_tree_new();
+ proto_item_add_subtree(ti, rtsp_tree, ETT_RTSP);
+ }
+
+ while (data < dataend) {
+ /*
+ * Find the end of the line.
+ */
+ lineend = find_line_end(data, dataend, &eol);
+ linelen = lineend - data;
+
+ /*
+ * OK, does it look like an RTSP request or
+ * response?
+ */
+ if (is_rtsp_request_or_reply(data, linelen))
+ goto is_rtsp;
+
+ /*
+ * No. Does it look like a blank line (as would
+ * appear at the end of an RTSP request)?
+ */
+ if (linelen == 1) {
+ if (*data == '\n')
+ goto is_rtsp;
+ }
+ if (linelen == 2) {
+ if (strncmp(data, "\r\n", 2) == 0 ||
+ strncmp(data, "\n\r", 2) == 0)
+ goto is_rtsp;
+ }
+
+ /*
+ * No. Does it look like a MIME header?
+ */
+ linep = data;
+ while (linep < lineend) {
+ c = *linep++;
+ if (!isprint(c))
+ break; /* not printable, not a MIME header */
+ switch (c) {
+
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '@':
+ case ',':
+ case ';':
+ case '\\':
+ case '"':
+ case '/':
+ case '[':
+ case ']':
+ case '?':
+ case '=':
+ case '{':
+ case '}':
+ /*
+ * It's a tspecial, so it's not
+ * part of a token, so it's not
+ * a field name for the beginning
+ * of a MIME header.
+ */
+ goto not_rtsp;
+
+ case ':':
+ /*
+ * This ends the token; we consider
+ * this to be a MIME header.
+ */
+ if (is_content_sdp(data, linelen))
+ is_sdp = 1;
+ goto is_rtsp;
+ }
+ }
+
+ not_rtsp:
+ /*
+ * We don't consider this part of an RTSP request or
+ * reply, so we don't display it.
+ */
+ break;
+
+ is_rtsp:
+ /*
+ * Put this line.
+ */
+ if (rtsp_tree) {
+ proto_tree_add_item(rtsp_tree, offset, linelen, "%s",
+ format_text(data, linelen));
+ }
+ offset += linelen;
+ data = lineend;
+ }
+
+ if (is_sdp) {
+ dissect_sdp(pd, offset, fd, tree);
+ if (check_col(fd, COL_PROTOCOL))
+ col_add_str(fd, COL_PROTOCOL, "RTSP/SDP");
+ }
+ else if (rtsp_tree && data < dataend) {
+ proto_tree_add_item(rtsp_tree, offset, END_OF_FRAME,
+ "Data (%d bytes)", END_OF_FRAME);
+ }
+}
+
+const char *rtsp_methods[] = {
+ "DESCRIBE", "ANNOUNCE", "GET_PARAMETER", "OPTIONS",
+ "PAUSE", "PLAY", "RECORD", "REDIRECT", "SETUP",
+ "SET_PARAMETER", "TEARDOWN"
+};
+const int rtsp_nmethods = sizeof(rtsp_methods) / sizeof(*rtsp_methods);
+
+static int
+is_rtsp_request_or_reply(const u_char *data, int linelen)
+{
+ int ii;
+ size_t len;
+
+ /* Reply */
+ if (linelen >= 5 && !strncasecmp("RTSP/", data, 5))
+ return TRUE;
+
+ /* Request Methods */
+ for (ii = 0; ii < rtsp_nmethods; ii++) {
+ len = strlen(rtsp_methods[ii]);
+ if (linelen >= len && !strncasecmp(rtsp_methods[ii], data, len))
+ return TRUE;
+ }
+
+ return FALSE;
+}