summaryrefslogtreecommitdiffstats
path: root/src/parser/sip_body.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser/sip_body.cpp')
-rw-r--r--src/parser/sip_body.cpp326
1 files changed, 326 insertions, 0 deletions
diff --git a/src/parser/sip_body.cpp b/src/parser/sip_body.cpp
new file mode 100644
index 0000000..cc95f85
--- /dev/null
+++ b/src/parser/sip_body.cpp
@@ -0,0 +1,326 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
+
+ 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 "sip_body.h"
+
+#include <list>
+#include <cassert>
+#include <cstdlib>
+#include "log.h"
+#include "protocol.h"
+#include "sip_message.h"
+#include "util.h"
+#include "audits/memman.h"
+#include "audio/rtp_telephone_event.h"
+
+////////////////////////////////////
+// class t_sip_body
+////////////////////////////////////
+
+t_sip_body::t_sip_body() {
+ invalid = false;
+}
+
+bool t_sip_body::local_ip_check(void) const {
+ return true;
+}
+
+size_t t_sip_body::get_encoded_size(void) const {
+ return encode().size();
+}
+
+////////////////////////////////////
+// class t_sip_xml_body
+////////////////////////////////////
+
+void t_sip_body_xml::create_xml_doc(const string &xml_version, const string &charset) {
+ clear_xml_doc();
+
+ // XML doc
+ xml_doc = xmlNewDoc(BAD_CAST xml_version.c_str());
+ MEMMAN_NEW(xml_doc);
+ xml_doc->encoding = xmlCharStrdup(charset.c_str());
+}
+
+void t_sip_body_xml::clear_xml_doc(void) {
+ if (xml_doc) {
+ MEMMAN_DELETE(xml_doc);
+ xmlFreeDoc(xml_doc);
+ xml_doc = NULL;
+ }
+}
+
+void t_sip_body_xml::copy_xml_doc(t_sip_body_xml *to_body) const {
+ if (to_body->xml_doc) {
+ to_body->clear_xml_doc();
+ }
+
+ if (xml_doc) {
+ to_body->xml_doc = xmlCopyDoc(xml_doc, 1);
+ if (!to_body->xml_doc) {
+ log_file->write_report("Failed to copy xml document.",
+ "t_sip_body_xml::copy",
+ LOG_NORMAL, LOG_CRITICAL);
+ } else {
+ MEMMAN_NEW(to_body->xml_doc);
+ }
+ }
+}
+
+t_sip_body_xml::t_sip_body_xml() : t_sip_body(),
+ xml_doc(NULL)
+{}
+
+t_sip_body_xml::~t_sip_body_xml() {
+ clear_xml_doc();
+}
+
+string t_sip_body_xml::encode(void) const {
+ if (!xml_doc) {
+ t_sip_body_xml *self = const_cast<t_sip_body_xml *>(this);
+ self->create_xml_doc();
+ }
+ assert(xml_doc);
+
+ xmlChar *buf;
+ int buf_size;
+
+ xmlDocDumpMemory(xml_doc, &buf, &buf_size);
+ string result((char*)buf);
+ xmlFree(buf);
+
+ return result;
+}
+
+bool t_sip_body_xml::parse(const string &s) {
+ assert(xml_doc == NULL);
+
+ xml_doc = xmlReadMemory(s.c_str(), s.size(), "noname.xml", NULL,
+ XML_PARSE_NOBLANKS | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
+ if (!xml_doc) {
+ log_file->write_report("Failed to parse xml document.",
+ "t_sip_body_xml::parse",
+ LOG_NORMAL, LOG_WARNING);
+ } else {
+ MEMMAN_NEW(xml_doc);
+ }
+
+ return (xml_doc != NULL);
+}
+
+////////////////////////////////////
+// class t_sip_body_opaque
+////////////////////////////////////
+
+t_sip_body_opaque::t_sip_body_opaque() : t_sip_body()
+{}
+
+t_sip_body_opaque::t_sip_body_opaque(string s) :
+ t_sip_body(),
+ opaque(s)
+{}
+
+string t_sip_body_opaque::encode(void) const {
+ return opaque;
+}
+
+t_sip_body *t_sip_body_opaque::copy(void) const {
+ t_sip_body_opaque *sb = new t_sip_body_opaque(*this);
+ MEMMAN_NEW(sb);
+ return sb;
+}
+
+t_body_type t_sip_body_opaque::get_type(void) const {
+ return BODY_OPAQUE;
+}
+
+t_media t_sip_body_opaque::get_media(void) const {
+ return t_media("application", "octet-stream");
+}
+
+size_t t_sip_body_opaque::get_encoded_size(void) const {
+ return opaque.size();
+}
+
+////////////////////////////////////
+// class t_sip_body_sipfrag
+////////////////////////////////////
+
+t_sip_body_sipfrag::t_sip_body_sipfrag(t_sip_message *m) : t_sip_body() {
+ sipfrag = m->copy();
+}
+
+t_sip_body_sipfrag::~t_sip_body_sipfrag() {
+ MEMMAN_DELETE(sipfrag);
+ delete sipfrag;
+}
+
+string t_sip_body_sipfrag::encode(void) const {
+ return sipfrag->encode(false);
+}
+
+t_sip_body *t_sip_body_sipfrag::copy(void) const {
+ t_sip_body_sipfrag *sb = new t_sip_body_sipfrag(sipfrag);
+ MEMMAN_NEW(sb);
+ return sb;
+}
+
+t_body_type t_sip_body_sipfrag::get_type(void) const {
+ return BODY_SIPFRAG;
+}
+
+t_media t_sip_body_sipfrag::get_media(void) const {
+ return t_media("message", "sipfrag");
+}
+
+////////////////////////////////////
+// class t_sip_body_dtmf_relay
+////////////////////////////////////
+
+t_sip_body_dtmf_relay::t_sip_body_dtmf_relay() : t_sip_body() {
+ signal = '0';
+ duration = 250;
+}
+
+t_sip_body_dtmf_relay::t_sip_body_dtmf_relay(char _signal, uint16 _duration) :
+ signal(_signal), duration(_duration)
+{}
+
+string t_sip_body_dtmf_relay::encode(void) const {
+ string s = "Signal=";
+ s += signal;
+ s += CRLF;
+
+ s += "Duration=";
+ s += int2str(duration);
+ s += CRLF;
+
+ return s;
+}
+
+t_sip_body *t_sip_body_dtmf_relay::copy(void) const {
+ t_sip_body_dtmf_relay *sb = new t_sip_body_dtmf_relay(*this);
+ MEMMAN_NEW(sb);
+ return sb;
+}
+
+t_body_type t_sip_body_dtmf_relay::get_type(void) const {
+ return BODY_DTMF_RELAY;
+}
+
+t_media t_sip_body_dtmf_relay::get_media(void) const {
+ return t_media("application", "dtmf-relay");
+}
+
+bool t_sip_body_dtmf_relay::parse(const string &s) {
+ signal = 0;
+ duration = 250;
+
+ bool valid = false;
+ vector<string> lines = split_linebreak(s);
+
+ for (vector<string>::iterator i = lines.begin(); i != lines.end(); i++) {
+ string line = trim(*i);
+ if (line.empty()) continue;
+
+ vector<string> l = split_on_first(line, '=');
+ if (l.size() != 2) continue;
+
+ string parameter = tolower(trim(l[0]));
+ string value = tolower(trim(l[1]));
+
+ if (value.empty()) continue;
+
+ if (parameter == "signal") {
+ if (!VALID_DTMF_SYM(value[0])) return false;
+ signal = value[0];
+ valid = true;
+ } else if (parameter == "duration") {
+ duration = atoi(value.c_str());
+ if (duration == 0) return false;
+ }
+ }
+
+ return valid;
+}
+
+////////////////////////////////////
+// class t_sip_body_plain_text
+////////////////////////////////////
+
+t_sip_body_plain_text::t_sip_body_plain_text() :
+ t_sip_body()
+{}
+
+t_sip_body_plain_text::t_sip_body_plain_text(const string &_text) :
+ t_sip_body(),
+ text(_text)
+{}
+
+string t_sip_body_plain_text::encode(void) const {
+ return text;
+}
+
+t_sip_body *t_sip_body_plain_text::copy(void) const {
+ t_sip_body *sb = new t_sip_body_plain_text(*this);
+ MEMMAN_NEW(sb);
+ return sb;
+}
+
+t_body_type t_sip_body_plain_text::get_type(void) const {
+ return BODY_PLAIN_TEXT;
+}
+
+t_media t_sip_body_plain_text::get_media(void) const {
+ return t_media("text", "plain");
+}
+
+size_t t_sip_body_plain_text::get_encoded_size(void) const {
+ return text.size();
+}
+
+////////////////////////////////////
+// class t_sip_body_html_text
+////////////////////////////////////
+
+t_sip_body_html_text::t_sip_body_html_text(const string &_text) :
+ t_sip_body(),
+ text(_text)
+{}
+
+string t_sip_body_html_text::encode(void) const {
+ return text;
+}
+
+t_sip_body *t_sip_body_html_text::copy(void) const {
+ t_sip_body *sb = new t_sip_body_html_text(*this);
+ MEMMAN_NEW(sb);
+ return sb;
+}
+
+t_body_type t_sip_body_html_text::get_type(void) const {
+ return BODY_HTML_TEXT;
+}
+
+t_media t_sip_body_html_text::get_media(void) const {
+ return t_media("text", "html");
+}
+
+size_t t_sip_body_html_text::get_encoded_size(void) const {
+ return text.size();
+}