Call forwarder is a US/CA Number Portability server with custom in-memory database engine.
The main feature is high-speed mapping 10-digit phone number into 10-digit routing number.
In addition, it support inverse operation of listing all numbers that maps into specified routing number prefix.
- Compile proxygen using
proxygen/proxygen/build.sh
script - Install
proxygen/proxygen/_build/deps/{bin,lib,include}
intocallfwd/deps/{bin,lib,include}
- Install
proxygen/proxygen/_build/{bin,lib,include}
intocallfwd/deps/{bin,lib,include}
- Build
callfwd
binary usingcmake
- Install
callfwd
binary andconf/
to the target machine (checkbuild-centos.sh
as example) - Read and modify
/etc/callfwd.{flags,env}
as needed - Start service and autoupdate timers using
sudo systemctl start callfwd.service
- Use devtoolset-9 and tbb 2019, set environment variables as in Dockerfile
- When building proxygen, compile gflags glog and boost 1.75 from sources and install them into
_build/deps
- Folly's check for SIMD support is broken, modify its
CMakeLists.txt
to always use SIMD
- if (${IS_X86_64_ARCH} STREQUAL "-1")
+ #if (${IS_X86_64_ARCH} STREQUAL "-1")
+ if (FALSE)
- Modify
proxygen/build.sh
to use static boost libraries (copy line from fuzzing section)
@@ -208,9 +208,9 @@ function setup_folly() {
MAYBE_USE_STATIC_DEPS=""
MAYBE_USE_STATIC_BOOST=""
MAYBE_BUILD_SHARED_LIBS=""
+ MAYBE_USE_STATIC_BOOST="-DBOOST_LINK_STATIC=ON"
- After copying
proxygen
artifacts intodeps
modifyproxygen-config.cmake
and removefind_depedency(mvfst)
line
The main binary is expected to run through systemd
service unit.
The service unit is paired with unix datagram socket used for passing commands into daemon without restarting it.
You should use callfwdctl
script communicate with daemon. It supports the following subcommands:
reload
- reload US/CA phone mapping from.txt
or.tar.gz
fileverify
- check if loaded mapping in memory matches file on diskdump
- write loaded mapping from memory to diskacl
- reload ACL rules from filestatus
- show information about loaded database
After starting, callfwd
will listen HTTP and SIP ports and respond with 503
until both US and CA mappings are loaded.
The following commands should be useful to troubeshoot callfwd
behaviour:
sudo systemctl status callfwd.{service,socket} callfwd-acl.{service,timer} callfwd-reload.{service,timer}
sudo journalctl -xfu callfwd.service
callfwdctl status
All request are logged to file specified by --access_log
flag. Both HTTP and SIP requests logged into the same stream with Apache-style format:
46.242.10.41:2623 - - [21/Jan/2021:09:44:28 +0000] "INVITE sip:[email protected]:5060;user=phone" 401 0
46.242.10.41:2582 - - [21/Jan/2021:09:44:53 +0000] "POST /target" 200 210
You can send HUP
signal to the daemon after rotation to reopen stream:
sudo systemctl kill --signal HUP callfwd.service
callfwd
registers two HTTP endpoints:
/target
(GET
,POST
) - map a batch of phone numbers into routing numbers/reverse
(GET
) - map a batch of routing prefixes into phone numbers
Both requests supports two output formats: csv
and json
. By default csv
format is used.
To use json
you need to ask it explicitly using Accept
header.
For example: curl -H "Accept: application/json"
or http --json
.
Note that maximum length of a POST
body is controlled by --max_query_length
flag.
GET /target?phone[]=9899999992&phone[]=9899999995 HTTP/1.1
Accept: */*
HTTP/1.1 200 OK
Content-Type: text/plain
9899999992,9895010081
9899999995,9894590000
POST /target HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Accept: */*
phone[]=9899999992&phone[]=9899999995
HTTP/1.1 200 OK
Content-Type: text/plain
9899999992,9895010081
9899999995,9894590000
GET /reverse?prefix[]=9895&prefix[]=9894 HTTP/1.1
Accept: */*
HTTP/1.1 200 OK
Content-Type: text/plain
9892001376,9895010012
9892001559,9895010012
9892001846,9895010012
...
9898376038,9894929997
9898376039,9894929997
9898390500,9894929997
GET /target?phone[]=9899999992&phone[]=9899999995 HTTP/1.1
Accept: application/json, */*;q=0.5
HTTP/1.1 200 OK
Content-Type: application/json
[
{"pn": "9899999992", "rn": "9895010081"},
{"pn": "9899999995", "rn": "9894590000"},
]
callfwd
registers two SIP endpoints:
INVITE
- return302 Moved
and addrn
parameter intoContact
fieldOPTIONS
- always returns200
Note that if requested phone not found in DB rn
parameter will contain a copy of original number.
If you wan't to follow RFC4694 and skip rn
parameter in that case use --rfc4694
flag.
Access to the SIP handler is limited by ACL rules:
- If client IP is not listed in ACL
401 Unauthorized
returned - If client exceeds maximum number of calls per second
429 Too Many Requests
returned
All phone numbers must be 10-digit US or Canada numbers.
It's allowed to use 1
and +1
prefixes, -
delimiters and ()
brackets.
All other numbers are treated as international and will not be checked in DB.
2020/12/23 12:09:11.582212 204.9.202.155:4319 -> 204.9.202.153:5060
INVITE sip:[email protected]:5060;user=phone SIP/2.0
Via: SIP/2.0/UDP 204.9.202.155:4319;branch=z9h64bK1953406209
From: <sip:[email protected]:4319;user=phone>;tag=339948729
To: <sip:[email protected]:5060;user=phone>
Call-ID: s0-9bca09cc-0fd4fc38-7f21bd45-2d08fdc6
CSeq: 2311677411 INVITE
Max-Forwards: 70
Contact: <sip:[email protected]:4319;transport=udp>
Content-Type: application/sdp
Content-Length: 0
2020/12/23 12:09:11.582339 204.9.202.153:5060 -> 204.9.202.155:4319
SIP/2.0 302 Moved Temporarily
Via: SIP/2.0/UDP 204.9.202.155:4319;branch=z9h64bK1953406209
From: <sip:[email protected]:4319;user=phone>;tag=339948729
To: <sip:[email protected]:5060;user=phone>;tag=13bd22f6
Call-ID: s0-9bca09cc-0fd4fc38-7f21bd45-2d08fdc6
CSeq: 2311677411 INVITE
Contact: <sip:+12018660805;rn=+12018209999;[email protected]:5060>
Location-Info: N
Content-Length: 0