Skip to content

Commit

Permalink
WIP: Implement request route as library functions
Browse files Browse the repository at this point in the history
* This takes the KEMI lua example file and moves its request route
  function to a library. Some functions are tested, most still need
  tests.
  • Loading branch information
Sebastian Damm committed May 14, 2018
1 parent ae47249 commit d20cd0e
Show file tree
Hide file tree
Showing 22 changed files with 1,036 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Compiled Lua sources
luac.out

# Luacov files
luacov.stats.out
luacov.report.out.index
luacov.report.out

# luarocks build files
*.src.rock
*.zip
Expand Down Expand Up @@ -39,3 +44,5 @@ luac.out
*.x86_64
*.hex

# I still use Textmate, ignore its working files
._*
18 changes: 18 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
SHELL=/bin/bash
LUA_VERSION=5.1
TARGET=/usr/local/share/lua/$(LUA_VERSION)/
LIBRARY_NAME=kamailio


install: tests
@echo
@mkdir -p $(TARGET) || die "Can't create directory $(TARGET)"
@install -d $(TARGET)/$(LIBRARY_NAME) || die "Can't create directory $(TARGET)/$(LIBRARY_NAME)"
@install -m 644 src/kamailio/* $(TARGET)/$(LIBRARY_NAME)
@echo "Library successfully installed."
@echo "You have to install src/kamailio-basic-kemi-lua.lua manually to the desired directory"
@echo "and instruct your example Kamailio Kemi config file to use it."

tests:
which busted || die "No busted installed. Please install busted so we can run unit tests!"
busted spec/[[:alpha:]]*_spec.lua
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,21 @@
# lua-kamailio
A library to replace the monolithic Kemi example file, making it testable

## State of the project

This project is currently in an early alpha stage. It was created as a proof of concept for Kamailioworld 2018 showing how to develop Kamailio routing logic the test driven way.

It aims to replace the example KEMI lua file. The original can be found here: [Kamailio KEMI example config](https://github.com/kamailio/kamailio/blob/master/misc/examples/kemi/kamailio-basic-kemi-lua.lua)

Currently, only `ksr_request_route()` and all functions called by it have been replaced. The other functions are just a copy from the example file.

## Installation

To install the library, simply type:
```make install```

You may have to fix some permissions first. On Debian, this should work, if you are in group `staff`.

After the installation of the library, please install the file `src/kamailio-basic-kemi-lua.lua` to the desired location. Then change the appropriate modparam for `app_lua` to point to the installed file.

Now restart your Kamailio.
9 changes: 9 additions & 0 deletions spec/actions_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'busted.runner'()

local actions = require "kamailio/actions"

describe("Check Foo -> ", function()
it("Some Test", function()
pending("There are tests missing.")
end)
end)
9 changes: 9 additions & 0 deletions spec/core_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'busted.runner'()

local core = require "kamailio/core"

describe("Check Foo -> ", function()
it("Some Test", function()
pending("There are tests missing.")
end)
end)
83 changes: 83 additions & 0 deletions spec/headers_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
require 'busted.runner'()

local function init_mock(options)
-- mock global variable 'KSR'
local ksr_mock = {
pv = {
get = function(key)
if key == "$rU" then
if options.rU ~= nil then return options.rU else return "01234567" end
end
end,
sets = function(k, v) end,
},
hdr = {
append = function(header) end,
}
}
_G["KSR"] = mock(ksr_mock)

local message_mock = {
is_invite = function() return options.is_invite end
}
_G["message"] = mock(message_mock)
end

local headers = require "kamailio/headers"

describe("Check and enable CLIR ->", function()
it("Caller dials *31021112345", function()
-- Initialize the mock
init_mock{ rU = "*31021112345", is_invite = true }
-- Call the function
headers.suppress_cid_if_needed()
-- Now check if everything is as expected
assert.spy(KSR.pv.sets).was.called_with("$rU", "021112345")
assert.spy(KSR.hdr.append).was.called_with("Privacy: id\r\n")
end)
it("Caller dials *31*021112345", function()
-- Initialize the mock
init_mock{ rU = "*31*021112345", is_invite = true }
-- Call the function
headers.suppress_cid_if_needed()
-- Now check if everything is as expected
assert.spy(KSR.pv.sets).was.called_with("$rU", "021112345")
assert.spy(KSR.hdr.append).was.called_with("Privacy: id\r\n")
end)
it("Caller dials *31#021112345", function()
-- Initialize the mock
init_mock{ rU = "*31#021112345", is_invite = true }
-- Call the function
headers.suppress_cid_if_needed()
-- Now check if everything is as expected
assert.spy(KSR.pv.sets).was.called_with("$rU", "021112345")
assert.spy(KSR.hdr.append).was.called_with("Privacy: id\r\n")
end)
it("Caller dials *31%23021112345", function()
-- Initialize the mock
init_mock{ rU = "*31%23021112345", is_invite = true }
-- Call the function
headers.suppress_cid_if_needed()
-- Now check if everything is as expected
assert.spy(KSR.pv.sets).was.called_with("$rU", "021112345")
assert.spy(KSR.hdr.append).was.called_with("Privacy: id\r\n")
end)
it("Caller dials +4921112345", function()
-- Initialize the mock
init_mock{ rU = "+4921112345", is_invite = true }
-- Call the function
headers.suppress_cid_if_needed()
-- Now check if everything is as expected
assert.spy(KSR.pv.sets).was.called(0)
assert.spy(KSR.hdr.append).was.called(0)
end)
it("Caller dials *31+4921112345, non-INVITE", function()
-- Initialize the mock
init_mock{ rU = "*31+4921112345" }
-- Call the function
headers.suppress_cid_if_needed()
-- Now check if everything is as expected
assert.spy(KSR.pv.sets).was.called_with("$rU", "+4921112345")
assert.spy(KSR.hdr.append).was.called(0)
end)
end)
21 changes: 21 additions & 0 deletions spec/init_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'busted.runner'()

local kamailio = require "kamailio"

describe("Check authorization -> ", function()
it("REGISTER is allowed by permissions", function()
pending("There are tests missing.")
end)
it("REGISTER is not authenticated", function()
pending("There are tests missing.")
end)
it("REGISTER is authenticated", function()
pending("We should check for remove_credentials, too.")
end)
it("INVITE is authenticated", function()
pending("There are tests missing.")
end)
it("Request is neither from local domain nor to local domain", function()
pending("There are tests missing.")
end)
end)
45 changes: 45 additions & 0 deletions spec/message_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require 'busted.runner'()

local function init_mock(options)
-- mock global variable 'KSR'
local ksr_mock = {
pv = {
get = function(key)
if key == "$rU" then
if options.rU ~= nil then return options.rU else return "01234567" end
elseif key == "$ua" then return options.ua end
end,
sets = function(k, v) end,
is_null = function(key)
if key == "$ua" then
if options.ua then return false else return true end
end
end,
},
hdr = {
append = function(header) end,
}
}
_G["KSR"] = mock(ksr_mock)
end


local message = require "kamailio/message"

describe("Check for bad user agent ->", function()
it("UA is friendly-scanner", function()
init_mock{ ua = "friendly-scanner" }
ua_check = message.is_from_bad_user_agent()
assert.are.equal(1, ua_check)
end)
it("UA is sipcli-1.1.8", function()
init_mock{ ua = "sipcli-1.1.8" }
ua_check = message.is_from_bad_user_agent()
assert.are.equal(1, ua_check)
end)
it("UA is Asterisk 15.1.1", function()
init_mock{ ua = "Asterisk 15.1.1" }
ua_check = message.is_from_bad_user_agent()
assert.are.equal(nil, ua_check)
end)
end)
81 changes: 81 additions & 0 deletions spec/nathandling_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
require 'busted.runner'()

local function init_mock(options)
-- mock global variable 'KSR'
local ksr_mock = {
pv = {
get = function(key)
if key == "$rU" then
if options.rU ~= nil then return options.rU else return "01234567" end
end
end,
sets = function(k, v) end,
},
hdr = {
append = function(header) end,
},
nathelper = {
nat_uac_test = function(flags) return options.is_nated end,
fix_nated_register = function() end,
set_contact_alias = function() end,
},
setflag = function(flag) end,
}
_G["KSR"] = mock(ksr_mock)

local message_mock = {
is_register = function() return options.is_register end,
is_first_hop = function() return options.is_first_hop end
}
_G["message"] = mock(message_mock)
end

local nathandling = require "kamailio/nathandling"

describe("Check for caller NAT -> ", function()
it("Detect NAT REGISTER", function()
init_mock{ is_register = true, is_nated = 1 }
nated = nathandling.detect_caller_nat()
assert.are.equal(1, nated)
assert.spy(KSR.nathelper.nat_uac_test).was.called_with(19)
assert.spy(KSR.nathelper.fix_nated_register).was.called()
assert.spy(KSR.nathelper.set_contact_alias).was.called(0)
assert.spy(KSR.setflag).was.called()
end)
it("Detect non-NAT REGISTER", function()
init_mock{ is_register = true, is_nated = 0 }
nated = nathandling.detect_caller_nat()
assert.are.equal(nil, nated)
assert.spy(KSR.nathelper.nat_uac_test).was.called_with(19)
assert.spy(KSR.nathelper.fix_nated_register).was.called(0)
assert.spy(KSR.nathelper.set_contact_alias).was.called(0)
assert.spy(KSR.setflag).was.called(0)
end)
it("Detect NAT INVITE, first hop", function()
init_mock{ is_register = false, is_nated = 1, is_first_hop = true }
nated = nathandling.detect_caller_nat()
assert.are.equal(1, nated)
assert.spy(KSR.nathelper.nat_uac_test).was.called_with(19)
assert.spy(KSR.nathelper.fix_nated_register).was.called(0)
assert.spy(KSR.nathelper.set_contact_alias).was.called()
assert.spy(KSR.setflag).was.called()
end)
it("Detect NAT INVITE, not first hop", function()
init_mock{ is_register = false, is_nated = 1, is_first_hop = false }
nated = nathandling.detect_caller_nat()
assert.are.equal(1, nated)
assert.spy(KSR.nathelper.nat_uac_test).was.called_with(19)
assert.spy(KSR.nathelper.fix_nated_register).was.called(0)
assert.spy(KSR.nathelper.set_contact_alias).was.called(0)
assert.spy(KSR.setflag).was.called()
end)
it("Detect non-NAT INVITE, first hop", function()
init_mock{ is_register = false, is_nated = 0, is_first_hop = true }
nated = nathandling.detect_caller_nat()
assert.are.equal(nil, nated)
assert.spy(KSR.nathelper.nat_uac_test).was.called_with(19)
assert.spy(KSR.nathelper.fix_nated_register).was.called(0)
assert.spy(KSR.nathelper.set_contact_alias).was.called(0)
assert.spy(KSR.setflag).was.called(0)
end)
end)
9 changes: 9 additions & 0 deletions spec/security_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'busted.runner'()

local security = require "kamailio/security"

describe("Check Foo -> ", function()
it("Some Test", function()
pending("There are tests missing.")
end)
end)
9 changes: 9 additions & 0 deletions spec/traffic_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'busted.runner'()

local traffic = require "kamailio/traffic"

describe("Check Foo -> ", function()
it("Some Test", function()
pending("There are tests missing.")
end)
end)
Loading

0 comments on commit d20cd0e

Please sign in to comment.