Forráskód Böngészése

textopsx: new module for text operations

- it collects functions that have no kamailio or ser
  specific dependecies
- moved here: msg_apply_changes() and change_reply_status()
Daniel-Constantin Mierla 15 éve
szülő
commit
a4e0d01788

+ 16 - 0
modules/textopsx/Makefile

@@ -0,0 +1,16 @@
+# $Id$
+#
+# print example module makefile
+#
+# 
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+include ../../Makefile.defs
+auto_gen=
+NAME=textopsx.so
+LIBS=
+
+DEFS+=-DSER_MOD_INTERFACE
+
+include ../../Makefile.modules
+

+ 71 - 0
modules/textopsx/README

@@ -0,0 +1,71 @@
+1. Textopsx Module
+
+Andrei Pelinescu-Onciul
+
+   FhG FOKUS
+
+Daniel-Constantin Mierla
+
+   asipto.com
+   <[email protected]>
+
+   Copyright © 2003 FhG FOKUS
+     __________________________________________________________________
+
+   1.1. Overview
+   1.2. Functions
+
+        1.2.1. msg_apply_changes()
+        1.2.2. change_reply_status(code, reason)
+
+1.1. Overview
+
+   This is a module implementing funtions for text operations over SIP
+   messages in configuration files. It comes to add new features similar
+   to textops module (textops eXtentions).
+
+1.2. Functions
+
+1.2.1.  msg_apply_changes()
+
+   Use this function to apply changes done on SIP request content. Be
+   careful when using this function -- due to special handling of changes
+   done to SIM message buffer so far, using this function might change the
+   behaviour of your config as it was so far -- do test properly your
+   config!
+
+   This function can be used from REQUEST_ROUTE.
+
+   Example 1. msg_apply_changes() usage
+...
+append_hf("My-Header: yes\r\n");
+if(msg_apply_changes())
+{
+    # msg buffer has a new content
+    if(is_present_hf("My-Header"))
+    {
+        # will get here always
+    }
+}
+...
+
+1.2.2.  change_reply_status(code, reason)
+
+   Change the status code and reason phrase of a SIP reply in
+   onreply_route.
+
+   Meaning of the parameters is as follows:
+     * code - Status code.
+     * reason - Reason phrase.
+
+   This function can be used from ONREPLY_ROUTE.
+
+   Example 2. change_reply_status usage
+...
+onreply_route {
+    if (@status == "603") {
+        change_reply_status(404, "Not Found");
+        exit;
+    }
+}
+...

+ 4 - 0
modules/textopsx/doc/Makefile

@@ -0,0 +1,4 @@
+docs = textopsx.xml
+
+docbook_dir=../../../docbook
+include $(docbook_dir)/Makefile.module

+ 76 - 0
modules/textopsx/doc/functions.xml

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<section id="textopsx.functions" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <title>Functions</title>
+
+	<section id="msg_apply_changes">
+		<title>
+		<function moreinfo="none">msg_apply_changes()</function>
+		</title>
+		<para>
+		Use this function to apply changes done on SIP request content. Be
+		careful when using this function -- due to special handling of changes
+		done to SIM message buffer so far, using this function might change
+		the behaviour of your config as it was so far -- do test properly
+		your config!
+		</para>
+   		<para>
+		This function can be used from REQUEST_ROUTE.
+		</para>
+		<example>
+		<title><function>msg_apply_changes()</function> usage</title>
+		<programlisting format="linespecific">
+...
+append_hf("My-Header: yes\r\n");
+if(msg_apply_changes())
+{
+    # msg buffer has a new content
+    if(is_present_hf("My-Header"))
+    {
+        # will get here always
+    }
+}
+...
+</programlisting>
+		</example>
+	</section>
+
+    <section id="change_reply_status">
+	<title>
+	    <function>change_reply_status(code, reason)</function>
+	</title>
+	<para>
+		Change the status code and reason phrase of a SIP reply in onreply_route.
+	</para>
+	<para>Meaning of the parameters is as follows:</para>
+	<itemizedlist>
+	    <listitem>
+		<para><emphasis>code</emphasis> - Status code.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para><emphasis>reason</emphasis> - Reason phrase.
+		</para>
+	    </listitem>
+	</itemizedlist>
+   		<para>
+		This function can be used from ONREPLY_ROUTE.
+		</para>
+	<example>
+	    <title><function>change_reply_status</function> usage</title>
+	    <programlisting>
+...
+onreply_route {
+    if (@status == "603") {
+        change_reply_status(404, "Not Found");
+        exit;
+    }
+}
+...
+	    </programlisting>
+	</example>
+    </section>
+
+</section>

+ 43 - 0
modules/textopsx/doc/textopsx.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<section id="textopsx" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<authorgroup>
+	    <author>
+		<firstname>Andrei</firstname>
+		<surname>Pelinescu-Onciul</surname>
+		<affiliation><orgname>FhG FOKUS</orgname></affiliation>
+		<address>
+		    <email>[email protected]</email>
+		</address>
+	    </author>
+		<author>
+		<firstname>Daniel-Constantin</firstname>
+		<surname>Mierla</surname>
+		<affiliation><orgname>asipto.com</orgname></affiliation>
+		<email>[email protected]</email>
+		</author>
+	</authorgroup>
+	<copyright>
+	    <year>2003</year>
+	    <holder>FhG FOKUS</holder>
+	</copyright>
+    </sectioninfo>
+
+    <title>Textopsx Module</title>
+
+    <section id="textops.overview">
+	<title>Overview</title>
+	<para>
+		This is a module implementing funtions for text operations over
+		SIP messages in configuration files. It comes to add new features
+		similar to textops module (textops eXtentions).
+	</para>
+    </section>
+
+    <xi:include href="functions.xml"/>
+
+</section>
+

+ 226 - 0
modules/textopsx/textopsx.c

@@ -0,0 +1,226 @@
+/**
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../sr_module.h"
+#include "../../dprint.h"
+#include "../../data_lump.h"
+#include "../../msg_translator.h"
+
+
+MODULE_VERSION
+
+static int msg_apply_changes_f(sip_msg_t *msg, char *str1, char *str2);
+
+static int change_reply_status_f(struct sip_msg*, char*, char *);
+static int change_reply_status_fixup(void** param, int param_no);
+
+/* cfg functions */
+static cmd_export_t cmds[] = {
+	{"msg_apply_changes",    (cmd_function)msg_apply_changes_f,     0,
+		0, REQUEST_ROUTE },
+	{"change_reply_status",	 change_reply_status_f,	                2,
+		change_reply_status_fixup, ONREPLY_ROUTE },
+
+	{0,0,0,0,0}
+};
+
+/* module exports structure */
+struct module_exports exports= {
+	"textopsx",
+	cmds, /* cfg functions */
+	0, /* RPC methods */
+	0, /* cfg parameters */
+	0, /* initialization function */
+	0, /* response function */
+	0, /* destroy function */
+	0, /* on_cancel function */
+	0  /* per-child init function */
+};
+
+
+/**
+ *
+ */
+static int msg_apply_changes_f(sip_msg_t *msg, char *str1, char *str2)
+{
+	struct dest_info dst;
+	str obuf;
+	sip_msg_t tmp;
+
+	if(get_route_type()!=REQUEST_ROUTE)
+	{
+		LM_ERR("invalid usage - not in request route\n");
+		return -1;
+	}
+
+	init_dest_info(&dst);
+	dst.proto = PROTO_UDP;
+	obuf.s = build_req_buf_from_sip_req(msg,
+			(unsigned int*)&obuf.len, &dst,
+			BUILD_NO_LOCAL_VIA|BUILD_NO_VIA1_UPDATE);
+	if(obuf.s == NULL)
+	{
+		LM_ERR("couldn't update msg buffer content\n");
+		return -1;
+	}
+	if(obuf.len>=BUF_SIZE)
+	{
+		LM_ERR("new buffer overflow (%d)\n", obuf.len);
+		pkg_free(obuf.s);
+		return -1;
+	}
+	/* temporary copy */
+	memcpy(&tmp, msg, sizeof(sip_msg_t));
+
+	/* reset dst uri and path vector to avoid freeing - restored later */
+	if(msg->dst_uri.s!=NULL)
+	{
+		msg->dst_uri.s = NULL;
+		msg->dst_uri.len = 0;
+	}
+	if(msg->path_vec.s!=NULL)
+	{
+		msg->path_vec.s = NULL;
+		msg->path_vec.len = 0;
+	}
+
+	/* free old msg structure */
+	free_sip_msg(msg);
+	memset(msg, 0, sizeof(sip_msg_t));
+
+	/* restore msg fields */
+	msg->buf                = tmp.buf;
+	msg->id                 = tmp.id;
+	msg->rcv                = tmp.rcv;
+	msg->set_global_address = tmp.set_global_address;
+	msg->set_global_port    = tmp.set_global_port;
+	msg->flags              = tmp.flags;
+	msg->msg_flags          = tmp.msg_flags;
+	msg->force_send_socket  = tmp.force_send_socket;
+	msg->fwd_send_flags     = tmp.fwd_send_flags;
+	msg->rpl_send_flags     = tmp.rpl_send_flags;
+	msg->dst_uri            = tmp.dst_uri;
+	msg->path_vec           = tmp.path_vec;
+
+	memcpy(msg->buf, obuf.s, obuf.len);
+	msg->len = obuf.len;
+	msg->buf[msg->len] = '\0';
+
+	/* free new buffer - copied in the static buffer from old sip_msg_t */
+	pkg_free(obuf.s);
+
+	/* reparse the message */
+	LM_DBG("SIP Request content updated - reparsing\n");
+	if (parse_msg(msg->buf, msg->len, msg)!=0){
+		LM_ERR("parse_msg failed\n");
+		return -1;
+	}
+
+	return 1;
+}
+
+
+/**
+ *
+ */
+static int change_reply_status_fixup(void** param, int param_no)
+{
+	if (param_no == 1) {
+		return fixup_var_int_12(param, param_no);
+	} else if (param_no == 2)
+		return fixup_var_str_12(param, param_no);
+	else
+		return 0;
+}
+
+/**
+ *
+ */
+static int change_reply_status_f(struct sip_msg* msg, char* _code, char* _reason)
+{
+	int	code;
+	str	reason;
+	struct lump	*l;
+	char	*ch;
+
+	if (get_int_fparam(&code, msg, (fparam_t*)_code)
+		|| get_str_fparam(&reason, msg, (fparam_t*)_reason)
+		|| (reason.len == 0)
+	) {
+		LOG(L_ERR, "ERROR: textops: cannot get parameter\n");
+		return -1;
+	}
+
+	if ((code < 100) || (code > 699)) {
+		LOG(L_ERR, "ERROR: textops: wrong status code: %d\n",
+				code);
+		return -1;
+	}
+
+	if (((code < 300) || (msg->REPLY_STATUS < 300))
+		&& (code/100 != msg->REPLY_STATUS/100)
+	) {
+		LOG(L_ERR, "ERROR: textops: the class of provisional or "
+			"positive final replies cannot be changed\n");
+		return -1;
+	}
+
+	/* rewrite the status code directly in the message buffer */
+	msg->first_line.u.reply.statuscode = code;
+	msg->first_line.u.reply.status.s[2] = code % 10 + '0'; code /= 10;
+	msg->first_line.u.reply.status.s[1] = code % 10 + '0'; code /= 10;
+	msg->first_line.u.reply.status.s[0] = code + '0';
+
+	l = del_lump(msg,
+		msg->first_line.u.reply.reason.s - msg->buf,
+		msg->first_line.u.reply.reason.len,
+		0);
+	if (!l) {
+		LOG(L_ERR, "ERROR: textops(): Failed to add del lump\n");
+		return -1;
+	}
+	/* clone the reason phrase, the lumps need to be pkg allocated */
+	ch = (char *)pkg_malloc(reason.len);
+	if (!ch) {
+		LOG(L_ERR, "ERROR: textops: Not enough memory\n");
+		return -1;
+	}
+	memcpy(ch, reason.s, reason.len);
+	if (insert_new_lump_after(l, ch, reason.len, 0)==0){
+		LOG(L_ERR, "ERROR: textops: failed to add new lump: %.*s\n",
+			reason.len, ch);
+		pkg_free(ch);
+		return -1;
+	}
+
+	return 1;
+}
+
+