Browse code

phonenum: new module to do lookup on phone numbers

- relies on libphonenumber to get the attributes associated with the
phone number

Daniel-Constantin Mierla authored on 16/10/2017 08:54:44
Showing 10 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+#
2
+# WARNING: do not run this directly, it should be run by the master Makefile
3
+
4
+include ../../Makefile.defs
5
+auto_gen=
6
+NAME=phonenum.so
7
+
8
+CXX=g++
9
+LD=g++
10
+LIB_DIR = /opt/local/lib
11
+
12
+LIBS= -L${LIB_DIR} cphonenumber.o -lphonenumber
13
+
14
+DEFS+= -I/opt/local/include -DKAMAILIO_MOD_INTERFACE
15
+
16
+CXXFLAGS=$(CFLAGS:-Wno-deprecated option=)
17
+CXXFLAGS+=-Wno-write-strings -Wno-deprecated -Wno-unused-function -Wno-sign-compare -Wno-strict-aliasing
18
+
19
+include ../../Makefile.modules
20
+
21
+cphonenumber.o: cphonenumber.cpp cphonenumber.h
22
+	@echo "Compiling $<"
23
+	$(CXX) $(CXXFLAGS) $(CFLAGS) $(C_DEFS) $(DEFS) -c $< -o $@
24
+
25
+phonenum.so: cphonenumber.o
0 26
new file mode 100644
... ...
@@ -0,0 +1,138 @@
1
+PHONENUM Module
2
+
3
+Daniel-Constantin Mierla
4
+
5
+   asipto.com
6
+
7
+Edited by
8
+
9
+Daniel-Constantin Mierla
10
+
11
+   <miconda@gmail.com>
12
+
13
+   Copyright � 2017 Daniel-Constantin Mierla (asipto.com)
14
+     __________________________________________________________________
15
+
16
+   Table of Contents
17
+
18
+   1. Admin Guide
19
+
20
+        1. Overview
21
+        2. Dependencies
22
+
23
+              2.1. Kamailio Modules
24
+              2.2. External Libraries or Applications
25
+
26
+        3. Parameters
27
+
28
+              3.1. smode (int)
29
+
30
+        4. Functions
31
+
32
+              4.1. phonenum_match(num, pvc)
33
+
34
+        5. Pseudo Variables
35
+
36
+   List of Examples
37
+
38
+   1.1. Set smode parameter
39
+   1.2. phonenum_match usage
40
+
41
+Chapter 1. Admin Guide
42
+
43
+   Table of Contents
44
+
45
+   1. Overview
46
+   2. Dependencies
47
+
48
+        2.1. Kamailio Modules
49
+        2.2. External Libraries or Applications
50
+
51
+   3. Parameters
52
+
53
+        3.1. smode (int)
54
+
55
+   4. Functions
56
+
57
+        4.1. phonenum_match(num, pvc)
58
+
59
+   5. Pseudo Variables
60
+
61
+1. Overview
62
+
63
+   This module allows real-time queries against the libphonenumber to be
64
+   performed from the config script. With that it is possible to get
65
+   normalize and get details about a phone number.
66
+
67
+   More details about libphonenumber can be found at
68
+   https://github.com/googlei18n/libphonenumber.
69
+
70
+   This module exports a new class of pseudo-variables - $phn(pvc=>key) -
71
+   to enable access to the results of a query to the database.
72
+
73
+   Many queries can be done and store results in different containers to
74
+   be able to use in parallel.
75
+
76
+2. Dependencies
77
+
78
+   2.1. Kamailio Modules
79
+   2.2. External Libraries or Applications
80
+
81
+2.1. Kamailio Modules
82
+
83
+   The following modules must be loaded before this module:
84
+     * none.
85
+
86
+2.2. External Libraries or Applications
87
+
88
+   The following libraries or applications must be installed before
89
+   running Kamailio with this module loaded:
90
+     * libphonenumber - the phone number library.
91
+
92
+3. Parameters
93
+
94
+   3.1. smode (int)
95
+
96
+3.1. smode (int)
97
+
98
+   Phone number search mode.
99
+
100
+   Default value is "0".
101
+
102
+   Example 1.1. Set smode parameter
103
+...
104
+modparam("phonenum", "smode", 0)
105
+...
106
+
107
+4. Functions
108
+
109
+   4.1. phonenum_match(num, pvc)
110
+
111
+4.1. phonenum_match(num, pvc)
112
+
113
+   Match num against the libphonenumber and set the attributes inside the
114
+   pvc container. The function has to be called before accessing a key
115
+   via: $phn(pvc=>key).
116
+
117
+   The parameters can be static strings or strings with variables.
118
+
119
+   It can be used from ANY_ROUTE.
120
+
121
+   Example 1.2. phonenum_match usage
122
+...
123
+if(phonenum_match("1-484-555-8888", "src"))
124
+    xlog("number normalized to: $phn(src=>num)\n");
125
+...
126
+
127
+5. Pseudo Variables
128
+
129
+     * $phn(pvc=>key) - pvc is an identifier for this query result; it is
130
+       designated by the second parameter of phonenum_match(). The key can
131
+       be one of the following:
132
+          + number - normalized phone number
133
+          + country - country for phone number
134
+          + region - region for phone number
135
+          + operator - operator for phone number
136
+
137
+   Exported pseudo-variables are documented at
138
+   https://www.kamailio.org/wiki/.
0 139
new file mode 100644
... ...
@@ -0,0 +1,179 @@
1
+/**
2
+ *
3
+ * Copyright (C) 2017 Daniel-Constantin Mierla (asipto.com)
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * This file is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ *
13
+ * This file is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
20
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21
+ *
22
+ */
23
+
24
+#include <phonenumbers/geocoding/phonenumber_offline_geocoder.h>
25
+#include <phonenumbers/phonenumberutil.h>
26
+#include <unicode/locid.h>
27
+#include <string.h>
28
+#include <cstring>
29
+#include <string>
30
+#include "cphonenumber.h"
31
+
32
+using namespace i18n::phonenumbers;
33
+using icu::Locale;
34
+using std::string;
35
+
36
+const PhoneNumberUtil& _phoneUtil(*PhoneNumberUtil::GetInstance());
37
+static PhoneNumberOfflineGeocoder *_phoneGeoCoder = new PhoneNumberOfflineGeocoder();
38
+
39
+const char* telnum_linetype(PhoneNumberUtil::PhoneNumberType ltype)
40
+{
41
+	switch(ltype) {
42
+      case PhoneNumberUtil::FIXED_LINE:
43
+	  	return "fixed-line";
44
+      case PhoneNumberUtil::MOBILE:
45
+	  	return "mobile";
46
+      // In some regions (e.g. the USA), it is impossible to distinguish between
47
+      // fixed-line and mobile numbers by looking at the phone number itself.
48
+      case PhoneNumberUtil::FIXED_LINE_OR_MOBILE:
49
+	  	return "fixed-line-or-mobile";
50
+      // Freephone lines
51
+      case PhoneNumberUtil::TOLL_FREE:
52
+	  	return "toll-free";
53
+      case PhoneNumberUtil::PREMIUM_RATE:
54
+	  	return "premium-rate";
55
+      // The cost of this call is shared between the caller and the recipient, and
56
+      // is hence typically less than PREMIUM_RATE calls. See
57
+      // http://en.wikipedia.org/wiki/Shared_Cost_Service for more information.
58
+      case PhoneNumberUtil::SHARED_COST:
59
+	  	return "shared-cost";
60
+      // Voice over IP numbers. This includes TSoIP (Telephony Service over IP).
61
+      case PhoneNumberUtil::VOIP:
62
+	  	return "voip";
63
+      // A personal number is associated with a particular person, and may be
64
+      // routed to either a MOBILE or FIXED_LINE number. Some more information can
65
+      // be found here: http://en.wikipedia.org/wiki/Personal_Numbers
66
+      case PhoneNumberUtil::PERSONAL_NUMBER:
67
+	  	return "personal-number";
68
+      case PhoneNumberUtil::PAGER:
69
+	  	return "pager";
70
+      // Used for "Universal Access Numbers" or "Company Numbers". They may be
71
+      // further routed to specific offices, but allow one number to be used for a
72
+      // company.
73
+      case PhoneNumberUtil::UAN:
74
+	  	return "uan";
75
+      // Used for "Voice Mail Access Numbers".
76
+      case PhoneNumberUtil::VOICEMAIL:
77
+	  	return "voicemail";
78
+      // A phone number is of type UNKNOWN when it does not fit any of the known
79
+      // patterns for a specific region.
80
+      case PhoneNumberUtil::UNKNOWN:
81
+	  	return "unknown";
82
+    }
83
+	return "unknown";
84
+}
85
+int telnum_possible(char* number, char* region)
86
+{
87
+	string numStr(number);
88
+	string regionStr(region);
89
+
90
+	bool isPossible = _phoneUtil.IsPossibleNumberForString(numStr, regionStr);
91
+	return (isPossible ? 1 : 0);
92
+}
93
+
94
+char* telnum_cc(char* number)
95
+{
96
+	string numStr(number);
97
+	string defaultRegion("ZZ");
98
+	PhoneNumber parsedNumber;
99
+
100
+	PhoneNumberUtil::ErrorType error = _phoneUtil.Parse(numStr, defaultRegion, &parsedNumber);
101
+	if (error != PhoneNumberUtil::NO_PARSING_ERROR) {
102
+		return NULL;
103
+	}
104
+	string regionCode;
105
+	_phoneUtil.GetRegionCodeForNumber(parsedNumber, &regionCode);
106
+	return strdup(regionCode.c_str());
107
+}
108
+
109
+telnum_t* telnum_parse(char* number, char* region)
110
+{
111
+	string numStr(number);
112
+	string regionStr(region);
113
+
114
+	PhoneNumber parsedNumber;
115
+	PhoneNumberUtil::ErrorType error = _phoneUtil.Parse(numStr, regionStr, &parsedNumber);
116
+	telnum_t* res = telnum_new(number);
117
+	if(res==NULL) {
118
+		return NULL;
119
+	}
120
+	if (error != PhoneNumberUtil::NO_PARSING_ERROR) {
121
+		string error = "Parsing number failed";
122
+		res->error = strdup(error.c_str());
123
+		return res;
124
+	}
125
+	if (!_phoneUtil.IsValidNumber(parsedNumber)) {
126
+		string error = "Invalid number";
127
+		res->error = strdup(error.c_str());
128
+		return res;
129
+	}
130
+	res->valid = 1;
131
+	string formattedNumber;
132
+	_phoneUtil.Format(parsedNumber, PhoneNumberUtil::E164, &formattedNumber);
133
+	res->normalized = strdup(formattedNumber.c_str());
134
+	string descNumber = _phoneGeoCoder->GetDescriptionForNumber(parsedNumber, Locale("en"));
135
+	res->ndesc = strdup(descNumber.c_str());
136
+	res->ltype = strdup(telnum_linetype(_phoneUtil.GetNumberType(parsedNumber)));
137
+	res->cctel = _phoneUtil.GetCountryCodeForRegion(regionStr);
138
+
139
+	return res;
140
+}
141
+
142
+telnum_t* telnum_new(char* number)
143
+{
144
+	telnum_t* tn = (telnum_t*)malloc(sizeof(telnum_t));
145
+	if(tn==NULL) {
146
+		return NULL;
147
+	}
148
+	tn->valid = 0;
149
+	tn->cctel = 0;
150
+	tn->number = strdup(number);
151
+	tn->normalized = NULL;
152
+	tn->ltype = NULL;
153
+	tn->ndesc = NULL;
154
+	tn->error = NULL;
155
+	return tn;
156
+}
157
+
158
+void telnum_free(telnum_t* tn)
159
+{
160
+	if(tn==NULL) {
161
+		return;
162
+	}
163
+	if (tn->number) {
164
+		free(tn->number);
165
+	}
166
+	if (tn->normalized) {
167
+		free(tn->normalized);
168
+	}
169
+	if (tn->error) {
170
+		free(tn->error);
171
+	}
172
+	if (tn->ltype) {
173
+		free(tn->ltype);
174
+	}
175
+	if (tn->ndesc) {
176
+		free(tn->ndesc);
177
+	}
178
+	free(tn);
179
+}
0 180
new file mode 100644
... ...
@@ -0,0 +1,56 @@
1
+/**
2
+ *
3
+ * Copyright (C) 2017 Daniel-Constantin Mierla (asipto.com)
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * This file is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ *
13
+ * This file is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
20
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21
+ *
22
+ */
23
+
24
+#ifndef _CPHONENUMBER_H_
25
+#define _CPHONENUMBER_H_
26
+
27
+#ifdef __cplusplus
28
+extern "C" {
29
+#endif
30
+
31
+// Phone number details
32
+typedef struct telnum {
33
+  char* number;
34
+  char* normalized;
35
+  char* ltype;
36
+  char* ndesc;
37
+  char* error;
38
+  int cctel;
39
+  int valid;
40
+} telnum_t;
41
+
42
+telnum_t* telnum_new(char*);
43
+void telnum_free(telnum_t*);
44
+
45
+// test if number is possible
46
+int telnum_possible(char* number, char* region);
47
+// parse a number
48
+telnum_t* telnum_parse(char* number, char* region);
49
+// get country code for number
50
+char* telnum_cc(char* number);
51
+
52
+#ifdef __cplusplus
53
+}
54
+#endif
55
+
56
+#endif
0 57
new file mode 100644
... ...
@@ -0,0 +1,4 @@
1
+docs = phonenum.xml
2
+
3
+docbook_dir = ../../../../doc/docbook
4
+include $(docbook_dir)/Makefile.module
0 5
new file mode 100644
... ...
@@ -0,0 +1,36 @@
1
+<?xml version="1.0" encoding='ISO-8859-1'?>
2
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4
+
5
+<!-- Include general documentation entities -->
6
+<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
7
+%docentities;
8
+
9
+]>
10
+
11
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
12
+    <bookinfo>
13
+	<title>PHONENUM Module</title>
14
+	<productname class="trade">&kamailioname;</productname>
15
+	<authorgroup>
16
+	    <author>
17
+		<firstname>Daniel-Constantin</firstname>
18
+		<surname>Mierla</surname>
19
+		<affiliation><orgname>asipto.com</orgname></affiliation>
20
+	    </author>
21
+	    <editor>
22
+		<firstname>Daniel-Constantin</firstname>
23
+		<surname>Mierla</surname>
24
+		    <email>miconda@gmail.com</email>
25
+	    </editor>
26
+	</authorgroup>
27
+	<copyright>
28
+	    <year>2017</year>
29
+	    <holder>Daniel-Constantin Mierla (asipto.com)</holder>
30
+	</copyright>
31
+    </bookinfo>
32
+    <toc></toc>
33
+
34
+	<xi:include href="phonenum_admin.xml"/>
35
+
36
+</book>
0 37
new file mode 100644
... ...
@@ -0,0 +1,154 @@
1
+<?xml version="1.0" encoding='ISO-8859-1'?>
2
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4
+
5
+<!-- Include general documentation entities -->
6
+<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
7
+%docentities;
8
+
9
+]>
10
+
11
+<!-- Module User's Guide -->
12
+
13
+<chapter>
14
+
15
+    <title>&adminguide;</title>
16
+
17
+    <section>
18
+	<title>Overview</title>
19
+	<para>
20
+		This module allows real-time queries against the libphonenumber
21
+		to be performed from the config script. With that it is possible
22
+		to get normalize and get details about a phone number.
23
+	</para>
24
+	<para>
25
+		More details about libphonenumber can be found at
26
+		<ulink url="https://github.com/googlei18n/libphonenumber">
27
+			https://github.com/googlei18n/libphonenumber</ulink>.
28
+	</para>
29
+	<para>
30
+		This module exports a new class of pseudo-variables -
31
+		$phn(pvc=&gt;key) - to enable access to the results of a query to the
32
+		database.
33
+	</para>
34
+	<para>
35
+		Many queries can be done and store results in different containers to
36
+		be able to use in parallel.
37
+	</para>
38
+    </section>
39
+    <section>
40
+	<title>Dependencies</title>
41
+	<section>
42
+	    <title>&kamailio; Modules</title>
43
+	    <para>
44
+		The following modules must be loaded before this module:
45
+	    	<itemizedlist>
46
+		    <listitem>
47
+			<para>
48
+			    <emphasis>none</emphasis>.
49
+			</para>
50
+		    </listitem>
51
+	    	</itemizedlist>
52
+	    </para>
53
+	</section>
54
+	<section>
55
+	    <title>External Libraries or Applications</title>
56
+	    <para>
57
+		The following libraries or applications must be installed before running
58
+		&kamailio; with this module loaded:
59
+	    	<itemizedlist>
60
+		    <listitem>
61
+			<para>
62
+			    <emphasis>libphonenumber</emphasis> - the phone number library.
63
+			</para>
64
+		    </listitem>
65
+	    	</itemizedlist>
66
+	    </para>
67
+	</section>
68
+    </section>
69
+    <section>
70
+	<title>Parameters</title>
71
+	<section>
72
+	    <title><varname>smode</varname> (int)</title>
73
+	    <para>
74
+		Phone number search mode.
75
+	    </para>
76
+	    <para>
77
+		<emphasis>
78
+		    Default value is <quote>0</quote>.
79
+		</emphasis>
80
+	    </para>
81
+	    <example>
82
+		<title>Set <varname>smode</varname> parameter</title>
83
+		<programlisting format="linespecific">
84
+...
85
+modparam("phonenum", "smode", 0)
86
+...
87
+</programlisting>
88
+	    </example>
89
+	</section>
90
+
91
+	</section>
92
+
93
+    <section>
94
+	<title>Functions</title>
95
+ 	<section>
96
+	    <title>
97
+		<function moreinfo="none">phonenum_match(num, pvc)</function>
98
+	    </title>
99
+	    <para>
100
+			Match num against the libphonenumber and set the attributes inside
101
+			the pvc container. The function has to be called before accessing
102
+			a key via: $phn(pvc=&gt;key).
103
+	    </para>
104
+	    <para>
105
+	    	The parameters can be static strings or strings with variables.
106
+	    </para>
107
+	    <para>
108
+	    	It can be used from ANY_ROUTE.
109
+	    </para>
110
+		<example>
111
+		<title><function>phonenum_match</function> usage</title>
112
+		<programlisting format="linespecific">
113
+...
114
+if(phonenum_match("1-484-555-8888", "src"))
115
+    xlog("number normalized to: $phn(src=&gt;num)\n");
116
+...
117
+</programlisting>
118
+	    </example>
119
+	</section>
120
+
121
+    </section>
122
+
123
+	<section>
124
+		<title>Pseudo Variables</title>
125
+		<itemizedlist>
126
+			<listitem><para>
127
+				<emphasis>$phn(pvc=&gt;key)</emphasis> - <emphasis>pvc</emphasis>
128
+				is an identifier for this query result; it is designated by
129
+				the second parameter of phonenum_match().
130
+				The <emphasis>key</emphasis> can be one of the following:
131
+				</para>
132
+			<itemizedlist>
133
+				<listitem><para>
134
+					<emphasis>number</emphasis> - normalized phone number
135
+				</para></listitem>
136
+				<listitem><para>
137
+					<emphasis>country</emphasis> - country for phone number
138
+				</para></listitem>
139
+				<listitem><para>
140
+					<emphasis>region</emphasis> - region for phone number
141
+				</para></listitem>
142
+				<listitem><para>
143
+					<emphasis>operator</emphasis> - operator for phone number
144
+				</para></listitem>
145
+			</itemizedlist>
146
+			</listitem>
147
+		</itemizedlist>
148
+		<para>
149
+		Exported pseudo-variables are documented at &kamwikilink;.
150
+		</para>
151
+	</section>
152
+
153
+</chapter>
154
+
0 155
new file mode 100644
... ...
@@ -0,0 +1,150 @@
1
+/**
2
+ *
3
+ * Copyright (C) 2017 Daniel-Constantin Mierla (asipto.com)
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * This file is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ *
13
+ * This file is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
20
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21
+ *
22
+ */
23
+
24
+#include <stdio.h>
25
+#include <unistd.h>
26
+#include <stdlib.h>
27
+#include <string.h>
28
+
29
+#include "../../core/sr_module.h"
30
+#include "../../core/dprint.h"
31
+#include "../../core/ut.h"
32
+#include "../../core/pvar.h"
33
+#include "../../core/kemi.h"
34
+#include "../../core/mod_fix.h"
35
+
36
+#include "phonenum_pv.h"
37
+
38
+MODULE_VERSION
39
+
40
+static int phonenum_smode = 0;
41
+
42
+static int  mod_init(void);
43
+static void mod_destroy(void);
44
+
45
+static int w_phonenum_match(struct sip_msg* msg, char* str1, char* str2);
46
+static int phonenum_match(sip_msg_t *msg, str *tomatch, str *pvclass);
47
+
48
+static pv_export_t mod_pvs[] = {
49
+	{ {"phn", sizeof("phn")-1}, PVT_OTHER, pv_get_phonenum, 0,
50
+		pv_parse_phonenum_name, 0, 0, 0 },
51
+	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
52
+};
53
+
54
+
55
+static cmd_export_t cmds[]={
56
+	{"phonenum_match", (cmd_function)w_phonenum_match, 2, fixup_spve_spve,
57
+		0, ANY_ROUTE},
58
+	{0, 0, 0, 0, 0, 0}
59
+};
60
+
61
+static param_export_t params[]={
62
+	{"smode", PARAM_INT, &phonenum_smode},
63
+	{0, 0, 0}
64
+};
65
+
66
+struct module_exports exports = {
67
+	"phonenum",
68
+	DEFAULT_DLFLAGS, /* dlopen flags */
69
+	cmds,
70
+	params,
71
+	0,
72
+	0,              /* exported MI functions */
73
+	mod_pvs,        /* exported pseudo-variables */
74
+	0,              /* extra processes */
75
+	mod_init,       /* module initialization function */
76
+	0,              /* response function */
77
+	mod_destroy,    /* destroy function */
78
+	0               /* per child init function */
79
+};
80
+
81
+
82
+/**
83
+ * init module function
84
+ */
85
+static int mod_init(void)
86
+{
87
+
88
+	if(phonenum_init_pv(phonenum_smode)!=0)
89
+	{
90
+		LM_ERR("cannot do init\n");
91
+		return -1;
92
+	}
93
+	return 0;
94
+}
95
+
96
+/**
97
+ * destroy module function
98
+ */
99
+static void mod_destroy(void)
100
+{
101
+	phonenum_destroy_pv();
102
+}
103
+
104
+
105
+static int phonenum_match(sip_msg_t *msg, str *tomatch, str *pvclass)
106
+{
107
+	phonenum_pv_reset(pvclass);
108
+
109
+	return phonenum_update_pv(tomatch, pvclass);
110
+}
111
+
112
+static int w_phonenum_match(sip_msg_t* msg, char* target, char* pvname)
113
+{
114
+	str tomatch = STR_NULL;
115
+	str pvclass = STR_NULL;
116
+
117
+	if(msg==NULL) {
118
+		LM_ERR("received null msg\n");
119
+		return -1;
120
+	}
121
+
122
+	if(fixup_get_svalue(msg, (gparam_t*)target, &tomatch)<0) {
123
+		LM_ERR("cannot get the address\n");
124
+		return -1;
125
+	}
126
+	if(fixup_get_svalue(msg, (gparam_t*)pvname, &pvclass)<0) {
127
+		LM_ERR("cannot get the pv class\n");
128
+		return -1;
129
+	}
130
+
131
+	return phonenum_match(msg, &tomatch, &pvclass);
132
+}
133
+
134
+/**
135
+ *
136
+ */
137
+static sr_kemi_t sr_kemi_phonenum_exports[] = {
138
+    { str_init("phonenum"), str_init("match"),
139
+        SR_KEMIP_INT, phonenum_match,
140
+        { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
141
+            SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
142
+    },
143
+
144
+    { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
145
+};
146
+
147
+int mod_register(char *path, int *dlflags, void *p1, void *p2) {
148
+    sr_kemi_modules_add(sr_kemi_phonenum_exports);
149
+    return 0;
150
+}
0 151
new file mode 100644
... ...
@@ -0,0 +1,299 @@
1
+/**
2
+ *
3
+ * Copyright (C) 2017 Daniel-Constantin Mierla (asipto.com)
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * This file is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ *
13
+ * This file is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
20
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21
+ *
22
+ */
23
+
24
+
25
+#include <assert.h>
26
+#include <ctype.h>
27
+#include <string.h>
28
+#include <stdlib.h>
29
+#include <time.h>
30
+
31
+#include "../../core/dprint.h"
32
+#include "../../core/hashes.h"
33
+#include "../../core/pvar.h"
34
+
35
+#include "cphonenumber.h"
36
+#include "phonenum_pv.h"
37
+
38
+typedef struct _sr_phonenum_record {
39
+	telnum_t *record;
40
+	char *number;
41
+	char *country;
42
+	char *region;
43
+	char *operator;
44
+	char tomatch[256];
45
+	int flags;
46
+} sr_phonenum_record_t;
47
+
48
+typedef struct _sr_phonenum_item {
49
+	str pvclass;
50
+	unsigned int hashid;
51
+	sr_phonenum_record_t r;
52
+	struct _sr_phonenum_item *next;
53
+} sr_phonenum_item_t;
54
+
55
+typedef struct _phonenum_pv {
56
+	sr_phonenum_item_t *item;
57
+	int type;
58
+} phonenum_pv_t;
59
+
60
+
61
+static sr_phonenum_item_t *_sr_phonenum_list = NULL;
62
+
63
+sr_phonenum_record_t *sr_phonenum_get_record(str *name)
64
+{
65
+	sr_phonenum_item_t *it = NULL;
66
+	unsigned int hashid = 0;
67
+
68
+	hashid =  get_hash1_raw(name->s, name->len);
69
+
70
+	it = _sr_phonenum_list;
71
+	while(it!=NULL)
72
+	{
73
+		if(it->hashid==hashid && it->pvclass.len == name->len
74
+				&& strncmp(it->pvclass.s, name->s, name->len)==0)
75
+			return &it->r;
76
+		it = it->next;
77
+	}
78
+	return NULL;
79
+}
80
+
81
+sr_phonenum_item_t *sr_phonenum_add_item(str *name)
82
+{
83
+	sr_phonenum_item_t *it = NULL;
84
+	unsigned int hashid = 0;
85
+
86
+	hashid =  get_hash1_raw(name->s, name->len);
87
+
88
+	it = _sr_phonenum_list;
89
+	while(it!=NULL)
90
+	{
91
+		if(it->hashid==hashid && it->pvclass.len == name->len
92
+				&& strncmp(it->pvclass.s, name->s, name->len)==0)
93
+			return it;
94
+		it = it->next;
95
+	}
96
+	/* add new */
97
+	it = (sr_phonenum_item_t*)pkg_malloc(sizeof(sr_phonenum_item_t));
98
+	if(it==NULL)
99
+	{
100
+		LM_ERR("no more pkg\n");
101
+		return NULL;
102
+	}
103
+	memset(it, 0, sizeof(sr_phonenum_item_t));
104
+	it->pvclass.s = (char*)pkg_malloc(name->len+1);
105
+	if(it->pvclass.s==NULL)
106
+	{
107
+		LM_ERR("no more pkg.\n");
108
+		pkg_free(it);
109
+		return NULL;
110
+	}
111
+	memcpy(it->pvclass.s, name->s, name->len);
112
+	it->pvclass.s[name->len] = '\0';
113
+	it->pvclass.len = name->len;
114
+	it->hashid = hashid;
115
+	it->next = _sr_phonenum_list;
116
+	_sr_phonenum_list = it;
117
+	return it;
118
+}
119
+
120
+
121
+int pv_parse_phonenum_name(pv_spec_p sp, str *in)
122
+{
123
+	phonenum_pv_t *gpv=NULL;
124
+	char *p;
125
+	str pvc;
126
+	str pvs;
127
+	if(sp==NULL || in==NULL || in->len<=0)
128
+		return -1;
129
+
130
+	gpv = (phonenum_pv_t*)pkg_malloc(sizeof(phonenum_pv_t));
131
+	if(gpv==NULL)
132
+		return -1;
133
+
134
+	memset(gpv, 0, sizeof(phonenum_pv_t));
135
+
136
+	p = in->s;
137
+
138
+	while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
139
+		p++;
140
+	if(p>in->s+in->len || *p=='\0')
141
+		goto error;
142
+	pvc.s = p;
143
+	while(p < in->s + in->len)
144
+	{
145
+		if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
146
+			break;
147
+		p++;
148
+	}
149
+	if(p>in->s+in->len || *p=='\0')
150
+		goto error;
151
+	pvc.len = p - pvc.s;
152
+	if(*p!='=')
153
+	{
154
+		while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
155
+			p++;
156
+		if(p>in->s+in->len || *p=='\0' || *p!='=')
157
+			goto error;
158
+	}
159
+	p++;
160
+	if(*p!='>')
161
+		goto error;
162
+	p++;
163
+
164
+	pvs.len = in->len - (int)(p - in->s);
165
+	pvs.s = p;
166
+	LM_DBG("phonenum [%.*s] - key [%.*s]\n", pvc.len, pvc.s,
167
+			pvs.len, pvs.s);
168
+
169
+	gpv->item = sr_phonenum_add_item(&pvc);
170
+	if(gpv->item==NULL)
171
+		goto error;
172
+
173
+	switch(pvs.len)
174
+	{
175
+		case 6:
176
+			if(strncmp(pvs.s, "number", 6)==0)
177
+				gpv->type = 0;
178
+			else if(strncmp(pvs.s, "region", 6)==0)
179
+				gpv->type = 2;
180
+			else goto error;
181
+		break;
182
+		case 7:
183
+			if(strncmp(pvs.s, "country", 7)==0)
184
+				gpv->type = 1;
185
+			else goto error;
186
+		break;
187
+		case 8:
188
+			if(strncmp(pvs.s, "operator", 8)==0)
189
+				gpv->type = 3;
190
+			else goto error;
191
+		break;
192
+		default:
193
+			goto error;
194
+	}
195
+	sp->pvp.pvn.u.dname = (void*)gpv;
196
+	sp->pvp.pvn.type = PV_NAME_OTHER;
197
+
198
+	return 0;
199
+
200
+error:
201
+	if(gpv!=NULL)
202
+		pkg_free(gpv);
203
+
204
+	LM_ERR("error at PV phonenum name: %.*s\n", in->len, in->s);
205
+	return -1;
206
+}
207
+
208
+int pv_phonenum_get_strzval(struct sip_msg *msg, pv_param_t *param,
209
+		pv_value_t *res, char *sval)
210
+{
211
+	str s;
212
+	if(sval==NULL)
213
+		return pv_get_null(msg, param, res);
214
+
215
+	s.s = sval;
216
+	s.len = strlen(s.s);
217
+	return pv_get_strval(msg, param, res, &s);
218
+}
219
+
220
+int pv_get_phonenum(struct sip_msg *msg, pv_param_t *param,
221
+		pv_value_t *res)
222
+{
223
+	phonenum_pv_t *gpv;
224
+
225
+	if(msg==NULL || param==NULL)
226
+		return -1;
227
+
228
+	gpv = (phonenum_pv_t*)param->pvn.u.dname;
229
+	if(gpv==NULL)
230
+		return -1;
231
+	if(gpv->item==NULL)
232
+		return pv_get_null(msg, param, res);
233
+
234
+	switch(gpv->type)
235
+	{
236
+		case 1: /* country */
237
+			return pv_get_null(msg, param, res);
238
+		case 2: /* region */
239
+			return pv_get_null(msg, param, res);
240
+		case 3: /* operator */
241
+			return pv_get_null(msg, param, res);
242
+		default: /* number */
243
+			return pv_get_null(msg, param, res);
244
+	}
245
+}
246
+
247
+int phonenum_init_pv(int smode)
248
+{
249
+	return 0;
250
+}
251
+
252
+void phonenum_destroy_list(void)
253
+{
254
+}
255
+
256
+void phonenum_destroy_pv(void)
257
+{
258
+}
259
+
260
+void phonenum_pv_reset(str *name)
261
+{
262
+	sr_phonenum_record_t *gr = NULL;
263
+
264
+	gr = sr_phonenum_get_record(name);
265
+
266
+	if(gr==NULL)
267
+		return;
268
+	memset(gr, 0, sizeof(sr_phonenum_record_t));
269
+}
270
+
271
+int phonenum_update_pv(str *tomatch, str *name)
272
+{
273
+	sr_phonenum_record_t *gr = NULL;
274
+
275
+	if(tomatch->len>255)
276
+	{
277
+		LM_DBG("target too long (max 255): %s\n", tomatch->s);
278
+		return -3;
279
+	}
280
+
281
+	gr = sr_phonenum_get_record(name);
282
+	if(gr==NULL)
283
+	{
284
+		LM_DBG("container not found: %s\n", tomatch->s);
285
+		return - 4;
286
+	}
287
+
288
+	strncpy(gr->tomatch, tomatch->s, tomatch->len);
289
+	gr->tomatch[tomatch->len] = '\0';
290
+	LM_DBG("attempt to match: %s\n", gr->tomatch);
291
+	if (gr->record == NULL)
292
+	{
293
+		LM_DBG("no match for: %s\n", gr->tomatch);
294
+		return -2;
295
+	}
296
+	LM_DBG("phonenum PV updated for: %s\n", gr->tomatch);
297
+
298
+	return 1;
299
+}
0 300
new file mode 100644
... ...
@@ -0,0 +1,39 @@
1
+/**
2
+ *
3
+ * Copyright (C) 2017 Daniel-Constantin Mierla (asipto.com)
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * This file is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ *
13
+ * This file is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
20
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21
+ *
22
+ */
23
+
24
+#ifndef _PHONENUM_PV_H_
25
+#define _PHONENUM_PV_H_
26
+
27
+#include "../../core/pvar.h"
28
+
29
+int pv_parse_phonenum_name(pv_spec_p sp, str *in);
30
+int pv_get_phonenum(struct sip_msg *msg, pv_param_t *param,
31
+		pv_value_t *res);
32
+
33
+int phonenum_init_pv(int smode);
34
+void phonenum_destroy_pv(void);
35
+void phonenum_pv_reset(str *pvclass);
36
+int phonenum_update_pv(str *tomatch, str *pvclass);
37
+
38
+#endif
39
+