Featured image of post kamailio kemix 模块

kamailio kemix 模块

背景

kemix模块是kamailio提供另外一种可不通过.cfg文件来写主路由的方式,可以使用脚本语言来写主路由, 目前支持的脚本语言有JavaScript,Lua,Python2,Python3,Ruby,Squirrel

此模块不同于APP_相关的其他模块,APP_相关的模块是在.cfg的路由中调用相关脚本来执行命令, 而kemix模块是在.cfg中加载模块,然后在脚本中写主路由。

官方文档地址: kemi, 官方基础脚本示例: base-kemi

本次测试的脚本语言是:JavaScript

本次测试的版本为:

kamailio 5.8.5

编译安装

因为本次测试的是JavaScript, 所以在编译kamailio时,把modules.lstexclude_modules去掉app_jsdt.so

app_jsdt依赖外部库为libm, 请提前安装。

脚本示例

kamailio-basic-kemi.cfg

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
#!KAMAILIO
#
# Kamailio SIP Server v5.0 - default configuration script
#     - web: https://www.kamailio.org
#     - git: http://sip-router.org
#
# Direct your questions about this file to: <sr-users@lists.kamailio.org>
#
# Refer to the Core CookBook at https://www.kamailio.org/wikidocs/
# for an explanation of possible statements, functions and parameters.
#
# Several features can be enabled using '#!define WITH_FEATURE' directives:
#
# *** To run in debug mode:
#     - define WITH_DEBUG
#
# *** To enable mysql:
#     - define WITH_MYSQL
#
# *** To enable authentication execute:
#     - enable mysql
#     - define WITH_AUTH
#     - add users using 'kamctl'
#
# *** To enable IP authentication execute:
#     - enable mysql
#     - enable authentication
#     - define WITH_IPAUTH
#     - add IP addresses with group id '1' to 'address' table
#
# *** To enable persistent user location execute:
#     - enable mysql
#     - define WITH_USRLOCDB
#
# *** To enable nat traversal execute:
#     - define WITH_NAT
#     - install RTPProxy: http://www.rtpproxy.org
#     - start RTPProxy:
#        rtpproxy -l _your_public_ip_ -s udp:localhost:7722
#     - option for NAT SIP OPTIONS keepalives: WITH_NATSIPPING
#
# *** To use RTPEngine (instead of RTPProxy) for nat traversal execute:
#!define WITH_RTPENGINE
#     - install RTPEngine: https://github.com/sipwise/rtpengine
#     - start RTPEngine:
#        rtpengine --listen-ng=127.0.0.1:2223 ...
#
# *** To enable TLS support execute:
#     - adjust CFGDIR/tls.cfg as needed
#     - define WITH_TLS
#
# *** To enhance accounting execute:
#     - enable mysql
#     - define WITH_ACCDB
#     - add following columns to database
#!ifdef ACCDB_COMMENT
  ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';
  ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';
  ALTER TABLE acc ADD COLUMN src_ip varchar(64) NOT NULL default '';
  ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';
  ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';
  ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';
  ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';
  ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';
  ALTER TABLE missed_calls ADD COLUMN src_ip varchar(64) NOT NULL default '';
  ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';
  ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';
  ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';
#!endif

#!define WITH_MYSQL
#!define WITH_USRLOCDB
#!define WITH_NAT
#!define WITH_ANTIFLOOD
#!define WITH_ACCDB
#!define WITH_CFGJSDT 

####### Include Local Config If Exists #########
import_file "kamailio-local.cfg"

####### Defined Values #########

# *** Value defines - IDs used later in config
#!ifdef WITH_MYSQL
# - database URL - used to connect to database server by modules such
#       as: auth_db, acc, usrloc, a.s.o.
#!ifndef DBURL
#!define DBURL "mysql://kamauser:kamailiorw@172.16.4.111:3306/kamailio_5_8_5"
#!endif
#!endif
#!define MULTIDOMAIN 0

# - flags
#   FLT_ - per transaction (message) flags
#	FLB_ - per branch flags
#!define FLT_ACC 1
#!define FLT_ACCMISSED 2
#!define FLT_ACCFAILED 3
#!define FLT_NATS 5

#!define FLB_NATB 6
#!define FLB_NATSIPPING 7

####### Global Parameters #########

### LOG Levels: 3=DBG, 2=INFO, 1=NOTICE, 0=WARN, -1=ERR
#!ifdef WITH_DEBUG
debug=4
log_stderror=yes
#!else
debug=2
log_stderror=no
#!endif

memdbg=5
memlog=5

#!ifdef WITH_CFGLUA
log_prefix="LUA {$rm}: "
#!define KEMIENGINE "lua"
#!define KEMIMODULE "app_lua"
#!define KEMILOAD "/usr/local/etc/kamailio/kamailio-basic-kemi-lua.lua"
#!endif

#!ifdef WITH_CFGPYTHON
log_prefix="PY2 {$rm}: "
#!define KEMIENGINE "python"
#!define KEMIMODULE "app_python"
#!define KEMILOAD "/usr/local/etc/kamailio/kamailio-basic-kemi-python.py"
#!endif

#!ifdef WITH_CFGPYTHON3
log_prefix="PY3 {$rm}: "
#!define KEMIENGINE "python"
#!define KEMIMODULE "app_python3"
#!define KEMILOAD "/usr/local/etc/kamailio/kamailio-basic-kemi-python.py"
#!endif

#!ifdef WITH_CFGPYTHON3S
log_prefix="PY8 {$rm}: "
#!define KEMIENGINE "python"
#!define KEMIMODULE "app_python3s"
#!define KEMILOAD "/usr/local/etc/kamailio/kamailio-basic-kemi-python3s.py"
#!endif

#!ifdef WITH_CFGJSDT
log_prefix="JSC {$rm}: "
#!define KEMIENGINE "jsdt"
#!define KEMIMODULE "app_jsdt"
#!define KEMILOAD "/usr/local/etc/kamailio/kamailio-basic-kemi-jsdt.js"
#!endif

#!ifdef WITH_CFGSQLANG
log_prefix="SQL {$rm}: "
#!define KEMIENGINE "sqlang"
#!define KEMIMODULE "app_sqlang"
#!define KEMILOAD "/usr/local/etc/kamailio/kamailio-basic-kemi-sqlang.sq"
#!endif

#!ifdef WITH_CFGRUBY
log_prefix="RUB {$rm}: "
#!define KEMIENGINE "ruby"
#!define KEMIMODULE "app_ruby"
#!define KEMILOAD "/usr/local/etc/kamailio/kamailio-basic-kemi-ruby.rb"
#!endif

#!ifndef KEMIENGINE
log_prefix="NAT {$rm}: "
#!endif

latency_cfg_log=2
latency_log=2
latency_limit_action=100000
latency_limit_db=200000
log_facility=LOG_LOCAL0

fork=yes
children=2

/* uncomment the next line to disable TCP (default on) */
#disable_tcp=yes

/* uncomment the next line to disable the auto discovery of local aliases
 * based on reverse DNS on IPs (default on) */
#auto_aliases=no

/* add local domain aliases */
#alias="sip.mydomain.com"

/* uncomment and configure the following line if you want Kamailio to
 * bind on a specific interface/port/proto (default bind on all available) */
#listen=udp:10.0.0.10:5060

listen=udp:172.16.4.111:5461
listen=tcp:172.16.4.111:5461
listen=udp:172.16.4.111:5464
listen=udp:172.16.4.111:5465

/* port to listen to
 * - can be specified more than once if needed to listen on many ports */
#port=5060

#!ifdef WITH_TLS
enable_tls=yes
#!endif

# life time of TCP connection when there is no traffic
# - a bit higher than registration expires to cope with UA behind NAT
tcp_connection_lifetime=3605

####### Modules Section ########

/* set paths to location of modules (to sources or installation folders) */
# mpath="/usr/local/lib/kamailio/modules/"

#!ifdef WITH_MYSQL
loadmodule "db_mysql.so"
#!endif

loadmodule "jsonrpcs.so"
loadmodule "kex.so"
loadmodule "corex.so"
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "cfg_rpc.so"
loadmodule "acc.so"
loadmodule "kemix.so"

#!ifdef WITH_AUTH
loadmodule "auth.so"
loadmodule "auth_db.so"
#!ifdef WITH_IPAUTH
loadmodule "permissions.so"
#!endif
#!endif

#!ifdef WITH_NAT
loadmodule "nathelper.so"
#!ifdef WITH_RTPENGINE
loadmodule "rtpengine.so"
#!else
loadmodule "rtpproxy.so"
#!endif
#!endif

#!ifdef WITH_TLS
loadmodule "tls.so"
#!endif

#!ifdef WITH_DEBUG
loadmodule "debugger.so"
#!endif

#!ifdef WITH_ANTIFLOOD
loadmodule "htable.so"
loadmodule "pike.so"
#!endif

#!ifdef KEMIENGINE
loadmodule KEMIMODULE
#!endif

# ----------------- setting module-specific parameters ---------------

# ----- jsonrpcs params -----
modparam("jsonrpcs", "pretty_format", 1)
/* set the path to RPC fifo control file */
# modparam("jsonrpcs", "fifo_name", "/run/kamailio/kamailio_rpc.fifo")
/* set the path to RPC unix socket control file */
# modparam("jsonrpcs", "dgram_socket", "/run/kamailio/kamailio_rpc.sock")

# ----- ctl params -----
#modparam("ctl", "binrpc", "unix:/run/kamailio/kamailio_ctl")

# ----- tm params -----
# auto-discard branches from previous serial forking leg
modparam("tm", "failure_reply_mode", 3)
# default retransmission timeout: 30sec
modparam("tm", "fr_timer", 30000)
# default invite retransmission timeout after 1xx: 120sec
modparam("tm", "fr_inv_timer", 120000)


# ----- rr params -----
# add value to ;lr param to cope with most of the UAs
modparam("rr", "enable_full_lr", 1)
# do not append from tag to the RR (no need for this script)
modparam("rr", "append_fromtag", 0)


# ----- registrar params -----
modparam("registrar", "method_filtering", 1)
/* uncomment the next line to disable parallel forking via location */
# modparam("registrar", "append_branches", 0)
/* uncomment the next line not to allow more than 10 contacts per AOR */
#modparam("registrar", "max_contacts", 10)
# max value for expires of registrations
modparam("registrar", "max_expires", 3600)
# set it to 1 to enable GRUU
modparam("registrar", "gruu_enabled", 0)


# ----- acc params -----
/* what special events should be accounted ? */
modparam("acc", "early_media", 0)
modparam("acc", "report_ack", 0)
modparam("acc", "report_cancels", 0)
/* by default we do not adjust the direct of the sequential requests.
 * if you enable this parameter, be sure the enable "append_fromtag"
 * in "rr" module */
modparam("acc", "detect_direction", 0)
/* account triggers (flags) */
modparam("acc", "log_flag", FLT_ACC)
modparam("acc", "log_missed_flag", FLT_ACCMISSED)
modparam("acc", "log_extra",
	"src_user=$fU;src_domain=$fd;src_ip=$si;"
	"dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
modparam("acc", "failed_transaction_flag", FLT_ACCFAILED)
/* enhanced DB accounting */
#!ifdef WITH_ACCDB
modparam("acc", "db_flag", FLT_ACC)
modparam("acc", "db_missed_flag", FLT_ACCMISSED)
modparam("acc", "db_url", DBURL)
modparam("acc", "db_extra",
	"src_user=$fU;src_domain=$fd;src_ip=$si;"
	"dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
#!endif


# ----- usrloc params -----
/* enable DB persistency for location entries */
modparam("usrloc", "preload", "location")
#!ifdef WITH_USRLOCDB
modparam("usrloc", "db_url", DBURL)
modparam("usrloc", "db_mode", 2)
modparam("usrloc", "use_domain", MULTIDOMAIN)
#!endif


# ----- auth_db params -----
#!ifdef WITH_AUTH
modparam("auth_db", "db_url", DBURL)
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
modparam("auth_db", "load_credentials", "")
modparam("auth_db", "use_domain", MULTIDOMAIN)

# ----- permissions params -----
#!ifdef WITH_IPAUTH
modparam("permissions", "db_url", DBURL)
modparam("permissions", "db_mode", 1)
#!endif

#!endif


#!ifdef WITH_NAT
#!ifdef WITH_RTPENGINE
# ----- rtpengine params -----
modparam("rtpengine", "rtpengine_sock", "udp:172.16.4.111:2222")
#!else
# ----- rtpproxy params -----
modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722")
#!endif

# ----- nathelper params -----
modparam("nathelper", "natping_interval", 30)
modparam("nathelper", "ping_nated_only", 1)
modparam("nathelper", "sipping_bflag", FLB_NATSIPPING)
modparam("nathelper", "sipping_from", "sip:pinger@kamailio.org")

# params needed for NAT traversal in other modules
modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")
modparam("usrloc", "nat_bflag", FLB_NATB)
#!endif


#!ifdef WITH_TLS
# ----- tls params -----
modparam("tls", "config", "/usr/local/etc/kamailio/tls.cfg")
#!endif

#!ifdef WITH_DEBUG
# ----- debugger params -----
modparam("debugger", "cfgtrace", 1)
#!endif

#!ifdef WITH_ANTIFLOOD
# ----- pike params -----
modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 16)
modparam("pike", "remove_latency", 4)

# ----- htable params -----
# ip ban htable with autoexpire after 5 minutes
modparam("htable", "htable", "ipban=>size=8;autoexpire=300;")
#!endif

#!ifdef KEMIENGINE
modparam(KEMIMODULE, "load", KEMILOAD)
cfgengine KEMIENGINE
#!else
cfgengine "native"
include_file "/usr/local/etc/kamailio/kamailio-basic-kemi-native.cfg"
#!endif

kamailio-basic-kemi-jsdt.js

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
// Kamailio - equivalent of routing blocks in JavaScript
//
// KSR - the new dynamic object exporting Kamailio functions
// sr - the old static object exporting Kamailio functions
//

// global variables corresponding to defined values (e.g., flags) in kamailio.cfg
var FLT_ACC=1
var FLT_ACCMISSED=2
var FLT_ACCFAILED=3
var FLT_NATS=5

var FLB_NATB=6
var FLB_NATSIPPING=7

// SIP request routing
// equivalent of request_route{}
function ksr_request_route()
{
	// KSR.sl.sl_send_reply(100, "Intelligent trying");
	// KSR.info("===== request - from kamailio javascript script\n");

	// per request initial checks
	ksr_route_reqinit();

	// NAT detection
	ksr_route_natdetect();

	// CANCEL processing
	if (KSR.is_CANCEL()) {
		if(KSR.tm.t_check_trans()>0) {
			ksr_route_relay();
		}
		return;
	}

	// handle retransmissions
	if (!KSR.is_ACK()) {
		if (KSR.tmx.t_precheck_trans()>0) {
			KSR.tm.t_check_trans();
			return;
		}
		if (KSR.tm.t_check_trans()==0) { return; }
	}

	// handle requests within SIP dialogs
	ksr_route_withindlg();

	// -- only initial requests (no To tag)

	// authentication
	// ksr_route_auth();

	// record routing for dialog forming requests (in case they are routed)
	// - remove preloaded route headers
	KSR.hdr.remove("Route");
	if (KSR.is_method_in("IS")) {
		KSR.rr.record_route();
	}

	// account only INVITEs
	if (KSR.is_INVITE()) {
		KSR.setflag(FLT_ACC); // do accounting
	}

	// dispatch requests to foreign domains
	ksr_route_sipout();

	// -- requests for my local domains

	// handle registrations
	ksr_route_registrar();

	if (KSR.corex.has_ruri_user() < 0) {
		// request with no Username in RURI
		KSR.sl.sl_send_reply(484, "Address Incomplete");
		return;
	}

	// user location service
	ksr_route_location();

	return;
}

// wrapper around tm relay function
function ksr_route_relay()
{
	// enable additional event routes for forwarded requests
	// - serial forking, RTP relaying handling, a.s.o.
	if (KSR.is_method_in("IBSU")) {
		if (KSR.tm.t_is_set("branch_route")<0) {
			KSR.tm.t_on_branch("ksr_branch_manage");
		}
	}
	if (KSR.is_method_in("ISU")) {
		if (KSR.tm.t_is_set("onreply_route")<0) {
			KSR.tm.t_on_reply("ksr_onreply_manage");
		}
	}

	if (KSR.is_INVITE()) {
		if (KSR.tm.t_is_set("failure_route")<0) {
			KSR.tm.t_on_failure("ksr_failure_manage");
		}
	}

	if (KSR.tm.t_relay()<0) {
		KSR.sl.sl_reply_error();
	}
	KSR.x.exit();
}


// Per SIP request initial checks
function ksr_route_reqinit()
{
	if (!KSR.is_myself_srcip()) {
		var srcip = KSR.kx.get_srcip();
		if (KSR.htable.sht_match_name("ipban", "eq", srcip) > 0) {
			// ip is already blocked
			KSR.dbg("request from blocked IP - " + KSR.kx.get_method()
					+ " from " + KSR.kx.get_furi() + " (IP:"
					+ srcip + ":" + KSR.kx.get_srcport() + ")\n");
			KSR.x.exit();
		}
		if (KSR.pike.pike_check_req()<0) {
			KSR.err("ALERT: pike blocking " + KSR.kx.get_method()
					+ " from " + KSR.kx.get_furi() + " (IP:"
					+ srcip + ":" + KSR.kx.get_srcport() + ")\n");
			KSR.htable.sht_seti("ipban", srcip, 1);
			KSR.x.exit();
		}
	}
	if (KSR.corex.has_user_agent()>0) {
		var UA = KSR.kx.gete_ua();
		if (UA.indexOf("friendly")>=0 || UA.indexOf("scanner")>=0
				|| UA.indexOf("sipcli")>=0 || UA.indexOf("sipvicious")>=0
				|| UA.indexOf("VaxSIPUserAgent")>=0 || UA.indexOf("pplsip")>= 0) {
			KSR.sl.sl_send_reply(200, "OK");
			KSR.x.exit();
		}
	}

	if (KSR.maxfwd.process_maxfwd(10) < 0) {
		KSR.sl.sl_send_reply(483, "Too Many Hops");
		KSR.x.exit();
	}

	if (KSR.is_OPTIONS()
			&& KSR.is_myself_ruri()
			&& KSR.corex.has_ruri_user() < 0) {
		KSR.sl.sl_send_reply(200, "Keepalive");
		KSR.x.exit();
	}

	if (KSR.sanity.sanity_check(17895, 7)<0) {
		KSR.err("Malformed SIP message from "
				+ KSR.kx.get_srcip() + ":" + KSR.kx.get_srcport() + "\n");
		KSR.x.exit();
	}
}


// Handle requests within SIP dialogs
function ksr_route_withindlg()
{
	if (KSR.siputils.has_totag()<0) { return; }

	// sequential request within a dialog should
	// take the path determined by record-routing
	if (KSR.rr.loose_route()>0) {
		ksr_route_dlguri();
		if (KSR.is_BYE()) {
			KSR.setflag(FLT_ACC); // do accounting ...
			KSR.setflag(FLT_ACCFAILED); // ... even if the transaction fails
		} else if (KSR.is_ACK()) {
			// ACK is forwarded statelessly
			ksr_route_natmanage();
		} else if (KSR.is_NOTIFY()) {
			// Add Record-Route for in-dialog NOTIFY as per RFC 6665.
			KSR.rr.record_route();
		}
		ksr_route_relay();
		KSR.x.exit();
	}
	if (KSR.is_ACK()) {
		if (KSR.tm.t_check_trans() >0) {
			// no loose-route, but stateful ACK;
			// must be an ACK after a 487
			// or e.g. 404 from upstream server
			ksr_route_relay();
			KSR.x.exit();
		} else {
			// ACK without matching transaction ... ignore and discard
			KSR.x.exit();
		}
	}
	KSR.sl.sl_send_reply(404, "Not here");
	KSR.x.exit();
}

// Handle SIP registrations
function ksr_route_registrar()
{
	if (!KSR.is_REGISTER()) { return; }
	if (KSR.isflagset(FLT_NATS)) {
		KSR.setbflag(FLB_NATB);
		// do SIP NAT pinging
		KSR.setbflag(FLB_NATSIPPING);
	}
	if (KSR.registrar.save("location", 0)<0) {
		KSR.sl.sl_reply_error();
	}
	KSR.x.exit();
}

// User location service
function ksr_route_location()
{
	var rc = KSR.registrar.lookup("location");
	if (rc<0) {
		KSR.tm.t_newtran();
		if (rc==-1 || rc==-3) {
			KSR.sl.send_reply(404, "Not Found");
			KSR.x.exit();
		} else if (rc==-2) {
			KSR.sl.send_reply(405, "Method Not Allowed");
			KSR.x.exit();
		}
	}

	// when routing via usrloc, log the missed calls also
	if (KSR.is_INVITE()) {
		KSR.setflag(FLT_ACCMISSED);
	}

	ksr_route_relay();
	KSR.x.exit();
}


// IP authorization and user authentication
function ksr_route_auth()
{
	if (!KSR.is_REGISTER()) {
		if (KSR.permissions.allow_source_address(1)>0) {
			// source IP allowed
			return;
		}
	}

	if (KSR.is_REGISTER() || KSR.is_myself_furi()) {
		// authenticate requests
		if (KSR.auth_db.auth_check(KSR.kx.gete_fhost(), "subscriber", 1)<0) {
			KSR.auth.auth_challenge(KSR.kx.gete_fhost(), 0);
			KSR.x.exit();
		}
		// user authenticated - remove auth header
		if (!KSR.is_method_in("RP")) {
			KSR.auth.consume_credentials();
		}
	}

	// if caller is not local subscriber, then check if it calls
	// a local destination, otherwise deny, not an open relay here
	if ((!KSR.is_myself_furi())
			&& (!KSR.is_myself_ruri())) {
		KSR.sl.sl_send_reply(403, "Not relaying");
		KSR.x.exit();
	}

	return;
}

// Caller NAT detection
function ksr_route_natdetect()
{
	KSR.force_rport();
	if (KSR.nathelper.nat_uac_test(19)>0) {
		if (KSR.is_REGISTER()) {
			KSR.nathelper.fix_nated_register();
		} else if (KSR.siputils.is_first_hop()>0) {
			KSR.nathelper.set_contact_alias();
		}
		KSR.setflag(FLT_NATS);
	}
	return;
}

// RTPProxy control
function ksr_route_natmanage()
{
	if (KSR.siputils.is_request()>0) {
		if (KSR.siputils.has_totag()>0) {
			if (KSR.rr.check_route_param("nat=yes")>0) {
				KSR.setbflag(FLB_NATB);
			}
		}
	}
	if (! (KSR.isflagset(FLT_NATS) || KSR.isbflagset(FLB_NATB))) {
		return;
	}

	KSR.rtpproxy.rtpproxy_manage("co");

	if (KSR.siputils.is_request()>0) {
		if (! KSR.siputils.has_totag()) {
			if (KSR.tmx.t_is_branch_route()>0) {
				KSR.rr.add_rr_param(";nat=yes");
			}
		}
	}
	if (KSR.siputils.is_reply()>0) {
		if (KSR.isbflagset(FLB_NATB)) {
			KSR.nathelper.set_contact_alias();
		}
	}
	return;
}

// URI update for dialog requests
function ksr_route_dlguri()
{
	if (! KSR.isdsturiset()) {
		KSR.nathelper.handle_ruri_alias();
	}
	return;
}

// Routing to foreign domains
function ksr_route_sipout()
{
	if (KSR.is_myself_ruri()) { return; }

	KSR.hdr.append_hf("P-Hint: outbound\r\n");
	ksr_route_relay();
	KSR.x.exit();
}

// Manage outgoing branches
// equivalent of branch_route[...]{}
function ksr_branch_manage()
{
	KSR.dbg("new branch [" + KSR.tm.t_get_branch_index()
				+ "] to " + KSR.kx.get_ruri() + "\n");
	ksr_route_natmanage();
	return;
}

// Manage incoming replies
// equivalent of onreply_route[...]{}
function ksr_onreply_manage()
{
	KSR.dbg("incoming reply\n");
	var scode = KSR.kx.gets_status();
	if (scode>100 && scode<=299) {
		ksr_route_natmanage();
	}
	return;
}

// Manage failure routing cases
// equivalent of failure_route[...]{}
function ksr_failure_manage()
{
	ksr_route_natmanage();

	if (KSR.tm.t_is_canceled()>0) {
		return;
	}
	return;
}

// SIP response handling
// equivalent of reply_route{}
function ksr_reply_route()
{
	KSR.info("===== response - from kamailio JS script\n");
	return;
}

测试

  1. 运行kamailio
1
kamailio -f /usr/local/etc/kamailio/kamailio-basic-kemi.cfg -m 216 -M 128 -DD -E -e
  1. 软电话注册

使用MicroSIP注册, 注册地址为172.16.4.111, 端口为5461, 用户名和密码为1003/1234

可以看到注册成功:

1
2
3
1(1574) INFO: JSC {REGISTER}: <core> [core/receive.c:532]: receive_msg(): request-route executed in: 488 usec
2(1575) INFO: JSC {REGISTER}: <core> [core/receive.c:532]: receive_msg(): request-route executed in: 493 usec
1(1574) INFO: JSC {OPTIONS}: <core> [core/kemi.c:107]: sr_kemi_core_info(): ===== response - from kamailio JS script

总结

  1. .js相对原生的.cfg脚本,#!ifdef xxx不再起作用,在.js内不想执行某个模块,只能把该函数注释掉。
  2. .js内大部分功能都是通过KSR对象来调用kamailio模块。
  3. kemi模式相对于原生的.cfg, 功能更加强大, 但是也更复杂。 这是官方测试的结果: kemi-Performances, 官方对比了原生.cfg,lua,python, 可以看到性能上有些差别,但是不太大。
本博客已稳定运行
发表了58篇文章 · 总计99.35k字
本站总访问量 次 · 您是本站第 位访问者
粤ICP备2025368587号-1| 使用 Hugo 构建
主题 StackJimmy 设计