posops: new module with functions working with the position in message buffer
authorDaniel-Constantin Mierla <miconda@gmail.com>
Wed, 15 Sep 2021 12:54:59 +0000 (14:54 +0200)
committerDaniel-Constantin Mierla <miconda@gmail.com>
Wed, 15 Sep 2021 12:54:59 +0000 (14:54 +0200)
- add/remove content at a specific position in the sip message buffer

src/modules/posops/Makefile [new file with mode: 0644]
src/modules/posops/README [new file with mode: 0644]
src/modules/posops/doc/Makefile [new file with mode: 0644]
src/modules/posops/doc/posops.xml [new file with mode: 0644]
src/modules/posops/doc/posops_admin.xml [new file with mode: 0644]
src/modules/posops/posops_mod.c [new file with mode: 0644]

diff --git a/src/modules/posops/Makefile b/src/modules/posops/Makefile
new file mode 100644 (file)
index 0000000..c358a3c
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# posops module makefile
+#
+#
+# WARNING: do not run this directly, it should be run by the main Makefile
+
+include ../../Makefile.defs
+auto_gen=
+NAME=posops.so
+LIBS=
+
+include ../../Makefile.modules
+
diff --git a/src/modules/posops/README b/src/modules/posops/README
new file mode 100644 (file)
index 0000000..9c86186
--- /dev/null
@@ -0,0 +1,137 @@
+POSOPS Module
+
+Daniel-Constantin Mierla
+
+   asipto.com
+   <miconda@gmail.com>
+
+Edited by
+
+Daniel-Constantin Mierla
+
+   <miconda@gmail.com>
+
+   Copyright © 2021 http://www.asipto.com
+     __________________________________________________________________
+
+   Table of Contents
+
+   1. Admin Guide
+
+        1. Overview
+        2. Dependencies
+
+              2.1. Kamailio Modules
+              2.2. External Libraries or Applications
+
+        3. Functions
+
+              3.1. pos_append(idx, val)
+              3.2. pos_insert(idx, val)
+              3.3. pos_rm(idx, len)
+
+   List of Examples
+
+   1.1. pos_append() usage
+   1.2. pos_insert() usage
+   1.3. pos_rm() usage
+
+Chapter 1. Admin Guide
+
+   Table of Contents
+
+   1. Overview
+   2. Dependencies
+
+        2.1. Kamailio Modules
+        2.2. External Libraries or Applications
+
+   3. Functions
+
+        3.1. pos_append(idx, val)
+        3.2. pos_insert(idx, val)
+        3.3. pos_rm(idx, len)
+
+1. Overview
+
+   The module exports utility functions to work with position inside the
+   SIP message buffer.
+
+   Among them are function to add or remove content at a specific
+   position.
+
+2. Dependencies
+
+   2.1. Kamailio Modules
+   2.2. External Libraries or Applications
+
+2.1. Kamailio Modules
+
+   The following modules must be installed (but not loaded) to use this
+   module:
+     * none.
+
+2.2. External Libraries or Applications
+
+   The following libraries or applications must be installed before
+   running Kamailio with this module loaded:
+     * none.
+
+3. Functions
+
+   3.1. pos_append(idx, val)
+   3.2. pos_insert(idx, val)
+   3.3. pos_rm(idx, len)
+
+3.1. pos_append(idx, val)
+
+   Append the value val after the position idx in the SIP message buffer.
+
+   The idx can be an integer value or a variable holding an integer. If
+   the value is negative, the position is counted from the end of the
+   buffer.
+
+   The val can be a static string or variables.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.1. pos_append() usage
+...
+pos_append("100", "kamailio-$si");
+...
+
+3.2. pos_insert(idx, val)
+
+   Insert the value val at the position idx in the SIP message buffer.
+
+   The idx can be an integer value or a variable holding an integer. If
+   the value is negative, the position is counted from the end of the
+   buffer.
+
+   The val can be a static string or variables.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.2. pos_insert() usage
+...
+pos_insert("100", "kamailio-$si");
+...
+
+3.3. pos_rm(idx, len)
+
+   Remove len characters starting at the position idx in the SIP message
+   buffer.
+
+   The idx can be an integer value or a variable holding an integer. If
+   the value is negative, the position is counted from the end of the
+   buffer.
+
+   The idx can be a positive integer value or a variable holding a
+   positive integer.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.3. pos_rm() usage
+...
+pos_insert("100", "10");
+...
diff --git a/src/modules/posops/doc/Makefile b/src/modules/posops/doc/Makefile
new file mode 100644 (file)
index 0000000..d5d3168
--- /dev/null
@@ -0,0 +1,4 @@
+docs = posops.xml
+
+docbook_dir = ../../../../doc/docbook
+include $(docbook_dir)/Makefile.module
diff --git a/src/modules/posops/doc/posops.xml b/src/modules/posops/doc/posops.xml
new file mode 100644 (file)
index 0000000..97ed12e
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
+%docentities;
+
+]>
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+    <bookinfo>
+       <title>POSOPS Module</title>
+       <productname class="trade">&kamailioname;</productname>
+       <authorgroup>
+           <author>
+               <firstname>Daniel-Constantin</firstname>
+               <surname>Mierla</surname>
+               <affiliation><orgname>asipto.com</orgname></affiliation>
+               <email>miconda@gmail.com</email>
+               <address>
+               <otheraddr>
+               <ulink url="http://www.asipto.com">http://www.asipto.com</ulink>
+               </otheraddr>
+               </address>
+           </author>
+           <editor>
+               <firstname>Daniel-Constantin</firstname>
+               <surname>Mierla</surname>
+               <email>miconda@gmail.com</email>
+           </editor>
+       </authorgroup>
+       <copyright>
+           <year>2021</year>
+           <holder>http://www.asipto.com</holder>
+       </copyright>
+    </bookinfo>
+    <toc></toc>
+
+    <xi:include href="posops_admin.xml"/>
+
+</book>
diff --git a/src/modules/posops/doc/posops_admin.xml b/src/modules/posops/doc/posops_admin.xml
new file mode 100644 (file)
index 0000000..6869e7f
--- /dev/null
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
+%docentities;
+
+]>
+<!-- Module User's Guide -->
+
+<chapter>
+
+       <title>&adminguide;</title>
+
+       <section>
+       <title>Overview</title>
+       <para>
+               The module exports utility functions to work with position inside the
+               SIP message buffer.
+       </para>
+       <para>
+               Among them are function to add or remove content at a specific position.
+       </para>
+       </section>
+       <section>
+       <title>Dependencies</title>
+       <section>
+               <title>&kamailio; Modules</title>
+               <para>
+               The following modules must be installed (but not loaded) to use this module:
+                       <itemizedlist>
+                       <listitem>
+                       <para>
+                               <emphasis>none</emphasis>.
+                       </para>
+                       </listitem>
+                       </itemizedlist>
+               </para>
+       </section>
+       <section>
+               <title>External Libraries or Applications</title>
+               <para>
+               The following libraries or applications must be installed before running
+               &kamailio; with this module loaded:
+                       <itemizedlist>
+                       <listitem>
+                       <para>
+                               <emphasis>none</emphasis>.
+                       </para>
+                       </listitem>
+                       </itemizedlist>
+               </para>
+       </section>
+       </section>
+
+       <section>
+       <title>Functions</title>
+               <section id="posops.f.pos_append">
+                       <title>
+                               <function moreinfo="none">pos_append(idx, val)</function>
+                       </title>
+                       <para>
+                       Append the value val after the position idx in the SIP message buffer.
+                       </para>
+                       <para>
+                       The idx can be an integer value or a variable holding an integer. If
+                       the value is negative, the position is counted from the end of the buffer.
+                       </para>
+                       <para>
+                       The val can be a static string or variables.
+                       </para>
+                       <para>
+                       This function can be used from ANY_ROUTE.
+                       </para>
+                       <example>
+                               <title><function>pos_append()</function> usage</title>
+                               <programlisting format="linespecific">
+...
+pos_append("100", "kamailio-$si");
+...
+                               </programlisting>
+                       </example>
+               </section>
+               <section id="posops.f.pos_insert">
+                       <title>
+                               <function moreinfo="none">pos_insert(idx, val)</function>
+                       </title>
+                       <para>
+                       Insert the value val at the position idx in the SIP message buffer.
+                       </para>
+                       <para>
+                       The idx can be an integer value or a variable holding an integer. If
+                       the value is negative, the position is counted from the end of the buffer.
+                       </para>
+                       <para>
+                       The val can be a static string or variables.
+                       </para>
+                       <para>
+                       This function can be used from ANY_ROUTE.
+                       </para>
+                       <example>
+                               <title><function>pos_insert()</function> usage</title>
+                               <programlisting format="linespecific">
+...
+pos_insert("100", "kamailio-$si");
+...
+                               </programlisting>
+                       </example>
+               </section>
+               <section id="posops.f.pos_rm">
+                       <title>
+                               <function moreinfo="none">pos_rm(idx, len)</function>
+                       </title>
+                       <para>
+                       Remove len characters starting at the position idx in the SIP message buffer.
+                       </para>
+                       <para>
+                       The idx can be an integer value or a variable holding an integer. If
+                       the value is negative, the position is counted from the end of the buffer.
+                       </para>
+                       <para>
+                       The idx can be a positive integer value or a variable holding a positive
+                       integer.
+                       </para>
+                       <para>
+                       This function can be used from ANY_ROUTE.
+                       </para>
+                       <example>
+                               <title><function>pos_rm()</function> usage</title>
+                               <programlisting format="linespecific">
+...
+pos_insert("100", "10");
+...
+                               </programlisting>
+                       </example>
+               </section>
+       </section>
+
+</chapter>
+
diff --git a/src/modules/posops/posops_mod.c b/src/modules/posops/posops_mod.c
new file mode 100644 (file)
index 0000000..834846a
--- /dev/null
@@ -0,0 +1,305 @@
+/**
+ * Copyright (C) 2021 Daniel-Constantin Mierla (asipto.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * This file 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 file 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../core/sr_module.h"
+#include "../../core/dprint.h"
+#include "../../core/mod_fix.h"
+#include "../../core/data_lump.h"
+#include "../../core/kemi.h"
+
+
+MODULE_VERSION
+
+static int mod_init(void);
+static int child_init(int);
+static void mod_destroy(void);
+
+static int w_posops_pos_append(sip_msg_t* msg, char* p1idx, char* p2val);
+static int w_posops_pos_insert(sip_msg_t* msg, char* p1idx, char* p2val);
+static int w_posops_pos_rm(sip_msg_t* msg, char* p1idx, char* p2len);
+
+typedef struct posops_data {
+       int ret;
+       int idx;
+} pospos_data_t;
+
+/* clang-format off */
+static cmd_export_t cmds[]={
+       {"pos_append", (cmd_function)w_posops_pos_append, 2, fixup_igp_spve,
+               fixup_free_igp_spve, ANY_ROUTE},
+       {"pos_insert", (cmd_function)w_posops_pos_insert, 2, fixup_igp_spve,
+               fixup_free_igp_spve, ANY_ROUTE},
+       {"pos_rm", (cmd_function)w_posops_pos_rm, 2, fixup_igp_igp,
+               fixup_free_igp_igp, ANY_ROUTE},
+
+       {0, 0, 0, 0, 0, 0}
+};
+
+static param_export_t params[]={
+
+       {0, 0, 0}
+};
+
+struct module_exports exports = {
+       "posops",
+       DEFAULT_DLFLAGS, /* dlopen flags */
+       cmds,
+       params,
+       0,              /* exported RPC methods */
+       0,              /* exported pseudo-variables */
+       0,              /* response function */
+       mod_init,       /* module initialization function */
+       child_init,     /* per child init function */
+       mod_destroy     /* destroy function */
+};
+/* clang-format on */
+
+
+/**
+ * init module function
+ */
+static int mod_init(void)
+{
+       return 0;
+}
+
+/**
+ * @brief Initialize async module children
+ */
+static int child_init(int rank)
+{
+       return 0;
+}
+
+/**
+ * destroy module function
+ */
+static void mod_destroy(void)
+{
+       return;
+}
+
+/**
+ *
+ */
+static int ki_posops_pos_append(sip_msg_t *msg, int idx, str *val)
+{
+       int offset;
+       sr_lump_t *anchor = NULL;
+
+       if(val==NULL || val->s==NULL || val->len<=0) {
+               LM_ERR("invalid val parameter\n");
+               return -1;
+       }
+
+       if(idx<0) {
+               offset = msg->len + idx + 1;
+       } else {
+               offset = idx;
+       }
+       if(offset>msg->len) {
+               LM_ERR("offset invalid: %d (msg-len: %d)\n", offset, msg->len);
+               return -1;
+       }
+
+       anchor = anchor_lump(msg, offset, 0, 0);
+       if (insert_new_lump_after(anchor, val->s, val->len, 0) == 0) {
+               LM_ERR("unable to add lump\n");
+               return -1;
+       }
+
+       return 1;
+}
+
+/**
+ *
+ */
+static int w_posops_pos_append(sip_msg_t* msg, char* p1idx, char* p2val)
+{
+       int idx = 0;
+       str val = STR_NULL;
+
+       if(fixup_get_ivalue(msg, (gparam_t*)p1idx, &idx)!=0) {
+               LM_ERR("unable to get idx parameter\n");
+               return -1;
+       }
+
+       if(fixup_get_svalue(msg, (gparam_t*)p2val, &val)!=0) {
+               LM_ERR("unable to get val parameter\n");
+               return -1;
+       }
+
+       return ki_posops_pos_append(msg, idx, &val);
+}
+
+/**
+ *
+ */
+static int ki_posops_pos_insert(sip_msg_t *msg, int idx, str *val)
+{
+       int offset;
+       sr_lump_t *anchor = NULL;
+
+       if(val==NULL || val->s==NULL || val->len<=0) {
+               LM_ERR("invalid val parameter\n");
+               return -1;
+       }
+
+       if(idx<0) {
+               offset = msg->len + idx + 1;
+       } else {
+               offset = idx;
+       }
+       if(offset>msg->len) {
+               LM_ERR("offset invalid: %d (msg-len: %d)\n", offset, msg->len);
+               return -1;
+       }
+
+       anchor = anchor_lump(msg, offset, 0, 0);
+       if (insert_new_lump_before(anchor, val->s, val->len, 0) == 0) {
+               LM_ERR("unable to add lump\n");
+               return -1;
+       }
+
+       return 1;
+}
+
+/**
+ *
+ */
+static int w_posops_pos_insert(sip_msg_t* msg, char* p1idx, char* p2val)
+{
+       int idx = 0;
+       str val = STR_NULL;
+
+       if(fixup_get_ivalue(msg, (gparam_t*)p1idx, &idx)!=0) {
+               LM_ERR("unable to get idx parameter\n");
+               return -1;
+       }
+
+       if(fixup_get_svalue(msg, (gparam_t*)p2val, &val)!=0) {
+               LM_ERR("unable to get val parameter\n");
+               return -1;
+       }
+
+       return ki_posops_pos_insert(msg, idx, &val);
+}
+
+
+/**
+ *
+ */
+static int ki_posops_pos_rm(sip_msg_t *msg, int idx, int len)
+{
+       int offset;
+       sr_lump_t *anchor = NULL;
+
+       if(len<=0) {
+               LM_ERR("length invalid: %d (msg-len: %d)\n", len, msg->len);
+               return -1;
+       }
+       if(idx<0) {
+               offset = msg->len + idx + 1;
+       } else {
+               offset = idx;
+       }
+       if(offset>msg->len) {
+               LM_ERR("offset invalid: %d (msg-len: %d)\n", offset, msg->len);
+               return -1;
+       }
+       if(offset==msg->len) {
+               LM_WARN("offset at the end of message: %d (msg-len: %d)\n",
+                               offset, msg->len);
+               return 1;
+       }
+       if(offset + len > msg->len) {
+               LM_WARN("offset + len over the end of message: %d + %d (msg-len: %d)\n",
+                               offset, len, msg->len);
+               return -1;
+       }
+       anchor=del_lump(msg, offset, len, 0);
+       if (anchor==0) {
+               LM_ERR("cannot remove - offset: %d - len: %d - msg-len: %d\n",
+                               offset, len, msg->len);
+               return -1;
+       }
+       return 1;
+}
+
+/**
+ *
+ */
+static int w_posops_pos_rm(sip_msg_t* msg, char* p1idx, char* p2len)
+{
+       int idx = 0;
+       int len = 0;
+
+       if(fixup_get_ivalue(msg, (gparam_t*)p1idx, &idx)!=0) {
+               LM_ERR("unable to get idx parameter\n");
+               return -1;
+       }
+       if(fixup_get_ivalue(msg, (gparam_t*)p2len, &len)!=0) {
+               LM_ERR("unable to get len parameter\n");
+               return -1;
+       }
+
+       return ki_posops_pos_rm(msg, idx, len);
+}
+
+/**
+ *
+ */
+/* clang-format off */
+static sr_kemi_t sr_kemi_posops_exports[] = {
+       { str_init("posops"), str_init("pos_append"),
+               SR_KEMIP_INT, ki_posops_pos_append,
+               { SR_KEMIP_INT, SR_KEMIP_STR, SR_KEMIP_NONE,
+                       SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+       },
+       { str_init("posops"), str_init("pos_insert"),
+               SR_KEMIP_INT, ki_posops_pos_insert,
+               { SR_KEMIP_INT, SR_KEMIP_STR, SR_KEMIP_NONE,
+                       SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+       },
+       { str_init("posops"), str_init("pos_rm"),
+               SR_KEMIP_INT, ki_posops_pos_rm,
+               { SR_KEMIP_INT, SR_KEMIP_INT, SR_KEMIP_NONE,
+                       SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+       },
+
+       { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
+};
+/* clang-format on */
+
+/**
+ *
+ */
+int mod_register(char *path, int *dlflags, void *p1, void *p2)
+{
+       sr_kemi_modules_add(sr_kemi_posops_exports);
+       return 0;
+}