Exactly a year ago, our former colleagues turned to us with a proposal to take part in modifying the operator's VoIP engine. The task was reduced to a complete rework of the personal account, ensuring the scaling of the system, creating a billing system, LCR, monitoring user expenses, controlling the duration of calls, analytics on calls. The story ended sadly, because The expanded functionality of the system we have laid down allegedly did not correspond to the TZ, which was not formalized on paper and is only in the heads of the managers of the operator. Due to the fact that managers did not want to pay for the developed functionality, which the customer really liked, we broke off the relationship. We did not have the NDA and we did not have a contract, so after consulting with colleagues we decided to put part of the developments into free access. I think this will be a series of articles. And let's start with the basic things and architecture.
Every administrator who has dealt with IP telephony at least once in his life knows that IP telephony services can be provided to the final subscriber in several ways:
Companies with offices in several countries or who wish to have a presence in another country can buy, for the convenience of their clients, a phone number in the UK, for example, and handle incoming calls in Moscow. At the same time, the operator who provided them with such a number may not be engaged in the delivery of calls to the UK. Some countries, such as the Republic of Belarus, do not provide numbers to non-residents.
So, we proceed from the following initial requirements:
A small remark: the described configuration is universal, but is more suitable for services with a customer-oriented direction, such as call centers, in cases where customer personalization is necessary and the client is tied to one manager or a group of managers. Most of the described mechanisms are universal and can be effectively used in other configurations.
Quite a few requirements, so where to start? Asterisk will accept and make calls, Application Server will be responsible for preparing calls in python, we will store all working data in MariaDB, and most of the logic will be implemented in the form of procedures. This will allow us to maximally distance the logic of asterisk from unnecessary rules in the dialplan and provide scalability along with configuration unification.
We will determine our traffic. We need a presence say in Cyprus, America, the UK and Russia. From the point of view of Russian traffic, it is more profitable to work through Russian telecom operators. For example Vestkol, IPPort and others. Russian (Moscow) operators also provide telephone numbers in codes 495 and 499 at a fairly reasonable price. We can provide a presence in Cyprus, in America and the United Kingdom by purchasing numbers from Zadarma, Multilel or someone else. Since international calls from Russian operators are quite expensive, you can buy traffic from foreign operators for example VoiceBuy or VoxBeam.
When connecting to the operator in the option "login / password" calls to our PBX will come from the IP address of the server of the operator on which the registration takes place. However, in the case of outgoing calls, the server address may be different.
When connecting to an operator via a SIP trunk, incoming calls can come from several servers from the operator's pool, and outgoing calls are made using a single DNS name, which in most cases contains several IP addresses. As we have already defined, the operator may be able to replace CallerID for an outgoing call, which can be regulated by a tariff plan or contract. Replacing CallerID (number substitution) in Russia for outgoing calls is prohibited. With foreign operators, the situation is much simpler and the replacement of CallerID is fully supported.
Most of the data and tables published in this article are extracts from the core of the real database, with the exception of phone numbers and IP addresses
Due to the fact that we have multicurrency communication operators, the link to the currency table should be in the table of communication operators. A little later we will consider the possibility of multi-currency recalculation of tariffs of operators.
CREATE TABLE `currency` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `iso` CHAR(3) NOT NULL DEFAULT '' COLLATE 'utf8mb4_unicode_ci', `name_en` VARCHAR(200) NOT NULL DEFAULT '' COLLATE 'utf8mb4_unicode_ci', `name_ru` VARCHAR(200) NOT NULL DEFAULT '' COLLATE 'utf8mb4_unicode_ci', `numcode` INT(3) UNSIGNED ZEROFILL NULL DEFAULT NULL COMMENT 'numcode for country', PRIMARY KEY (`id`), UNIQUE INDEX `iso` (`iso`) ) COMMENT=' , iso ' COLLATE='utf8mb4_unicode_ci' ENGINE=InnoDB AUTO_INCREMENT=1 ;
id | iso | name_en | name_ru | numcode |
---|---|---|---|---|
96 | RUB | Russian ruble | Russian ruble | 643 |
122 | USD | US Dollar | U.S. dollar | 840 |
156 | EUR | Euro | Euro | 978 |
CREATE TABLE `providers` ( `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, `providername` VARCHAR(50) NULL DEFAULT '0' COLLATE 'utf8mb4_unicode_ci', `currency_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', `noncli_prefix` VARCHAR(10) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci', `cli_prefix` VARCHAR(10) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci', `premcli_prefix` VARCHAR(10) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci', `cli_allowed` ENUM('Y','N') NOT NULL DEFAULT 'N' COLLATE 'utf8mb4_unicode_ci', `dynamic_calls` CHAR(1) NULL DEFAULT 'N' COLLATE 'utf8mb4_unicode_ci', `append_plus` TINYINT(1) NOT NULL DEFAULT '1', `dynamic_calls_caller_id` VARCHAR(30) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`id`), INDEX `FK_providers_currency` (`currency_id`), CONSTRAINT `FK_providers_currency` FOREIGN KEY (`currency_id`) REFERENCES `currency` (`id`) ) COMMENT=' ' COLLATE='utf8mb4_unicode_ci' ENGINE=InnoDB AUTO_INCREMENT=1 ;
id | providername | currency_id | noncli_prefix | cli_prefix | premcli_prefix | cli_allowed | dynamic_calls | append_plus | dynamic_calls_caller_id |
---|---|---|---|---|---|---|---|---|---|
3 | Zadarma | 96 | N | N | one | ||||
four | Multitel | 122 | N | N | one | ||||
7 | Westcall | 96 | Y | N | 0 | 74951815283 | |||
eight | Voxbeam | 122 | 0011103 | 0011101 | 0011102 | Y | Y | one | |
eleven | Voicebuy | 122 | 9991 | 9992 | 9993 | Y | Y | one | |
sixteen | IPport | 96 | N | N | one |
So. Operators.
Usually, foreign operators have 2-3 tariffs for which they deliver traffic to the called subscriber. You can read about the differences between CLI and NonCLI techniques here .
To select a tariff plan, the prefix ( noncli_prefix, cli_prefix, premcli_prefix ) is usually used , indicated before the called number in the process of forming the call line.
Description of fields:
In the case of WestCall and other operators providing a connection via a SIP trunk, you buy a pool of numbers and, when making calls, you can change the outgoing number to any number from this pool. IPPort, like other operators, when using the login / password scheme with a single purchased number, does not allow changing the outgoing number. Operators VoxBeam and VoiceBuy are used for outgoing calls for any directions and allow you to change the outgoing number to any other. The truth is there is one thing! And it lies in the fact that the end telecom operators delivering the call to the called subscriber can reject the call or change the caller's number to their own if the calling number corresponds to the internal number of the country or area. Those. for example, when calling from Russia to Ukraine (Kiev), we change CallerID to a Ukrainian number in Kiev and the telecom operator through which the call is being made can simply call the call, because it does not comply with the internal call processing policy "A call through an external incoming international trunk cannot contain internal numbers". Operators Zadarma and Multitel will be used as number providers and we will not send outgoing traffic through them, although we could have done so if we wanted to.
An important aspect of call processing is security. Quite often there are situations when an incorrectly configured IP telephony server allows other calls to pass through. To ensure the security of the circuits that process incoming and outgoing calls, in addition to separating operators into different contexts, it is worth creating a database of IP addresses of telecom operators providing us with communication services. Firstly, it will allow you to configure the export of addresses in the firewall and remove unnecessary attempts to “ring out” through us, and secondly, it will provide more complete information about how to connect to telecom operators.
CREATE TABLE `providers_ips` ( `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, `provider_id` INT(11) UNSIGNED NOT NULL DEFAULT '0', `ipaddress` INT(11) UNSIGNED NOT NULL DEFAULT '2130706433', `domainname` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci', `direction` ENUM('IN','OUT','IN/OUT') NOT NULL DEFAULT 'IN' COLLATE 'utf8mb4_unicode_ci', `proto` ENUM('SIP','IAX2','H323') NOT NULL DEFAULT 'SIP' COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`id`), INDEX `FK_providers_ips_providers` (`provider_id`), CONSTRAINT `FK_providers_ips_providers` FOREIGN KEY (`provider_id`) REFERENCES `providers` (`id`) ) COMMENT=' . direction / ' COLLATE='utf8mb4_unicode_ci' ENGINE=InnoDB AUTO_INCREMENT=1 ;
id | provider_id | ipaddress | domainname | direction | proto |
---|---|---|---|---|---|
one | eight | 2130706433 | sbc.voxbeam.com | Out | Sip |
2 | eight | 1607694320 | 95.211.119.240 | IN | Sip |
7 | 3 | 2130706433 | sip.zadarma.com | Out | Sip |
sixteen | 3 | 3106773121 | proxy-1.fr.zadarma.com | IN | Sip |
17 | 3 | 3106773122 | proxy-2.fr.zadarma.com | IN | Sip |
31 | sixteen | 1506852360 | 89.208.190.8 | IN | Sip |
33 | sixteen | 1506852357 | 89.208.190.5 | IN | Sip |
34 | sixteen | 1506852354 | sip.n1.ipport.net | Out | Sip |
35 | eleven | 2991415097 | sip.voicebuy.com | Out | Sip |
42 | four | 3514573416 | 209.124.34.104 | Out | Sip |
44 | 7 | 3277775106 | 195.94.225.2 | IN / OUT | Sip |
51 | four | 3514573417 | 209.124.34.105 | IN | Sip |
52 | four | 3514573446 | 209.124.34.134 | IN | Sip |
Description of fields:
Thus, a bunch of operator and addresses will look like this.
id | providername | proto | aa | direction |
---|---|---|---|---|
sixteen | IPport | Sip | 89.208.190.5 [89.208.190.5] | IN |
sixteen | IPport | Sip | sip.n1.ipport.net [89.208.190.2] | Out |
sixteen | IPport | Sip | 89.208.190.8 [89.208.190.8] | IN |
four | Multitel | Sip | 80.97.55.105 [80.97.55.105] | IN |
four | Multitel | Sip | 209.124.34.104 [209.124.34.104] | Out |
four | Multitel | Sip | 41.218.96.199 [41.218.96.199] | IN |
eleven | Voicebuy | Sip | sip.voicebuy.com [178.77.95.57] | Out |
eight | Voxbeam | Sip | sbc.voxbeam.com [127.0.0.1] | Out |
eight | Voxbeam | Sip | 95.211.119.240 [95.211.119.240] | IN |
7 | Westcall | Sip | 195.94.225.2 [195.94.225.2] | IN / OUT |
3 | Zadarma | Sip | proxy-1.fr.zadarma.com [185.45.152.129] | IN |
3 | Zadarma | Sip | proxy-3.ri.zadarma.com [195.122.19.11] | IN |
3 | Zadarma | Sip | siplv.zadarma.com [195.122.19.17] | IN |
3 | Zadarma | Sip | proxy-8.fr.zadarma.com [185.45.152.136] | IN |
3 | Zadarma | Sip | sip.zadarma.com [127.0.0.1] | Out |
3 | Zadarma | Sip | siplv1.zadarma.com [195.122.19.17] | IN |
3 | Zadarma | Sip | mediarelay-1.zadarma.com [185.45.152.162] | IN |
What is it for ?
Let's try to get a call string for the number 74957777777.
SELECT CONCAT_WS('/', pips.proto, pips.domainname, CONCAT(IF(p.append_plus IS TRUE,'+',''), IFNULL(p.cli_prefix,''),74957777777)) AS dial_string FROM providers_ips AS pips LEFT JOIN providers AS p ON p.id=pips.provider_id WHERE pips.direction IN ('OUT', 'IN/OUT')
dial_string |
---|
Sip / sip.zadarma.com/74957777777 |
Sip / westcall / 74957777777 |
Sip / sbc.voxbeam.com/001110174957777777 |
Sip / sip.voicebuy.com/999274957777777 |
SIP / sip.n1.ipport.net / + 74957777777 |
As we see, we received ready data for dialing, which need to be transferred to the Dial application of the Asterisk server. Let's stop on this for now.
To bind the numbers leased from the carrier, we need to specify a list of servers on which these numbers will be serviced.
CREATE TABLE `servers` ( `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, `servername` VARCHAR(50) NULL DEFAULT '0' COLLATE 'utf8mb4_unicode_ci', `location` INT(11) NOT NULL DEFAULT '0' COMMENT 'country code where server is located', `ipaddress` INT(11) NOT NULL DEFAULT '2130706433' COMMENT 'localhost by default', `comment` VARCHAR(50) NULL DEFAULT '0' COLLATE 'utf8mb4_unicode_ci', `sip` VARCHAR(50) NULL DEFAULT NULL COMMENT 'SIP URI' COLLATE 'utf8mb4_unicode_ci', `iax2` VARCHAR(50) NULL DEFAULT NULL COMMENT 'IAX2 address and user binding if rsa keys used' COLLATE 'utf8mb4_unicode_ci', `iax2control` VARCHAR(50) NULL DEFAULT NULL COMMENT 'IAX2 address and control user binding for pair and route control' COLLATE 'utf8mb4_unicode_ci', `protocol` ENUM('SIP','IAX2') NOT NULL DEFAULT 'SIP' COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`id`) ) COMMENT=' ' COLLATE='utf8mb4_unicode_ci' ENGINE=InnoDB AUTO_INCREMENT=1 ;
id | servername | location | ipaddress | comment | sip | iax2 | iax2control | protocol |
---|---|---|---|---|---|---|---|---|
0 | undefined | 0 | 2130706433 | 0 | Sip | |||
one | asterisk-macomnet | 189 | 3557129729 | 0 | SIP / 212.5.126.1 | IAX2 / macomnet @ macomnet | IAX2 / macomnetcontrol @ macomnet | IAX2 |
2 | asterisk-msm | 189 | 1506807809 | 0 | SIP / 89.208.16.1 | IAX2 / msm @ msm | IAX2 / msmcontrol @ msm | IAX2 |
five | asterisk-corbina | 189 | 1399234817 | 0 | SIP / 83.102.161.1 | IAX2 / corbina @ corbina | IAX2 / corbinacontrol @ corbina | IAX2 |
Description of fields:
What is this table for and why is it so strange? For the inter-server connection of asterisk servers, it is most convenient to use the IAX protocol. There are several reasons:
[macomnet] type=user username=macomnet auth=rsa inkeys=asterisk-corbina:asterisk-msm context=incoming_dialer encryption=yes qualify=yes disallow=all allow=gsm allow=ulaw [msm] type=peer host=89.208.16.1 username=msm auth=rsa outkey=asterisk-macomnet encryption=yes qualify=yes disallow=all allow=gsm allow=ulaw trunk=yes [corbina] type=peer host=83.102.161.1 username=corbina auth=rsa outkey=asterisk-macomnet encryption=yes qualify=yes disallow=all allow=gsm allow=ulaw trunk=yes
With the servers initially figured out. Now you need to bind the rented numbers to a specific server. This is necessary for correct call routing.
CREATE TABLE numbers_pool
(id
INT (11) UNSIGNED NOT NULL AUTO_INCREMENT,number
VARCHAR (50) NULL DEFAULT '0' COMMENT 'The rented number' COLLATE 'is utf8mb4_unicode_ci',provider_id
INT (11) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Attaching a number to the operator',server_id
INT (11) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Attaching a number to the server',enabled
BIT (1) NOT NULL DEFAULT b'1 'COMMENT' Enabling / disabling number ',direction
ENUM ('IN', 'OUT', 'IN / OUT') NULL DEFAULT 'IN' COMMENT 'The default call direction is' COLLATE 'utf8mb4_unicode_ci',virtualflag
BIT (1) NOT NULL DEFAULT b'1 'COMMENT' Virtual or real number ',echotest
TINYINT (1) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Testing the number 0/1 - off / on',
PRIMARY KEY ( id
)
UNIQUE INDEX number
( number
),
INDEX FK_number_assignment_copy_providers
( provider_id
),
INDEX FK_number_assignment_servers
( server_id
),
INDEX number btree
( number
)
CONSTRAINT FK_provider
FOREIGN KEY ( provider_id
) REFERENCES providers
( id
),
CONSTRAINT FK_server
FOREIGN KEY ( server_id
) REFERENCES servers
( id
)
)
COLLATE = 'utf8mb4_unicode_ci'
ENGINE = InnoDB
AUTO_INCREMENT = 1
;
id | number | provider_id | server_id | enabled | direction | virtualflag | echotest |
---|---|---|---|---|---|---|---|
125 | 37167859001 | four | one | one | IN | one | 0 |
126 | 37167859002 | four | one | one | IN | one | 0 |
278 | 4971122954000 | four | one | 0 | IN | one | 0 |
279 | 74951815000 | 7 | one | one | IN / OUT | 0 | 0 |
280 | 74951815001 | 7 | one | one | IN / OUT | 0 | 0 |
281 | 74951815002 | 7 | one | one | IN / OUT | 0 | 0 |
426 | 74951339501 | 3 | 2 | 0 | IN / OUT | one | 0 |
427 | 74951339502 | 3 | one | 0 | IN / OUT | one | 0 |
515 | 74957952301 | sixteen | one | one | IN / OUT | 0 | 0 |
516 | 74957952302 | sixteen | 2 | one | IN / OUT | 0 | 0 |
529 | 442038070121 | eleven | one | one | IN | one | 0 |
531 | 442038070123 | eleven | one | one | IN | one | 0 |
Description of fields:
At the time of developing the system, the number of leased numbers was about 400, the number of servers was 4. To test call routing, they even added a Multiphone from Megaphone. When using "real" numbers associated with the login / password, it is necessary to ensure the implementation of the call through the correct dialpyr. Since asterisk cannot know through which dialpere a call should be routed, it is necessary to create a table of connections.
CREATE TABLE `gates` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `numbers_pool_id` INT(11) UNSIGNED NOT NULL DEFAULT '0', `serverid` INT(11) UNSIGNED NOT NULL DEFAULT '0', `gatename` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci', `gatenumber` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci', `cid_support` ENUM('Y','N') NULL DEFAULT 'Y' COLLATE 'utf8mb4_unicode_ci', `contextname` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci', `comment` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`id`), UNIQUE INDEX `name_number` (`gatename`, `gatenumber`), INDEX `FK_gates_servers` (`serverid`), INDEX `FK_gates_numbers_pool` (`numbers_pool_id`), CONSTRAINT `FK_gates_numbers_pool` FOREIGN KEY (`numbers_pool_id`) REFERENCES `numbers_pool` (`id`), CONSTRAINT `FK_gates_servers` FOREIGN KEY (`serverid`) REFERENCES `servers` (`id`) ) COMMENT='List of gates on servers' COLLATE='utf8mb4_unicode_ci' ENGINE=InnoDB AUTO_INCREMENT=1 ;
id | numbers_pool_id | serverid | gatename | gatenumber | cid_support | contextname | comment |
---|---|---|---|---|---|---|---|
one | 516 | one | sip_peer_msm_2302 | 74957952302 | Y | sip_msm_74957952302 | |
2 | 515 | one | sip_peer_msm_2301 | 74957952301 | Y | sip_msm_74957952301 | |
eight | 279 | one | westcall | 74951815000 | Y | westcall | |
9 | 280 | one | westcall | 74951815001 | Y | westcall | |
ten | 281 | one | westcall | 74951815002 | Y | westcall |
Description of fields:
At this point, the setting of the base for service calls is almost complete. I deliberately do not consider now the work of the tariffiser and call control systems, as this is a very big topic that should be put in a separate article.
Due to the fact that the main call processing and call routing logic is removed from Asterisk to the Application Server, and the procedures are in MariaDB, it is necessary to provide mechanisms for debugging and controlling the operation of the procedures. To do this, you can use the following scheme.
To store debug information, create an additional debug database and create a debug_records table there .
CREATE TABLE `debug_records` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `logtime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `procedure_name` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_unicode_ci', `debug_text` TEXT NOT NULL COLLATE 'utf8mb4_unicode_ci', PRIMARY KEY (`id`) ) COLLATE='utf8mb4_unicode_ci' ENGINE=InnoDB AUTO_INCREMENT=1 ;
To write to this data table, create a debug procedure.
CREATE DEFINER=`root`@`localhost` PROCEDURE `debug`( IN `ProcedureName` VARCHAR(50), IN `DebugText` TEXT ) LANGUAGE SQL NOT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER COMMENT 'Save debug info to log' BEGIN DECLARE DebugEnabled TINYINT DEFAULT False; SET DebugEnabled=True; IF DebugEnabled THEN INSERT INTO debug_records (procedure_name,debug_text) VALUES (ProcedureName,DebugText); COMMIT; END IF; END
Now debugging and control of the procedure at the development stage becomes a pleasure. At the beginning of each procedure, we define two variables, the first is the name of the procedure, the second is the flag defining whether debugging is enabled or not. And then in various places where the procedure may behave incorrectly - we first add an entry to the debug log.
CREATE DEFINER=`root`@`localhost` PROCEDURE `usp_gettypeofcall`( IN `IncomingPhoneNumber` VARCHAR(30), IN `TargetGateNumber` VARCHAR(30), IN `CHANID` VARCHAR(60), IN `SYSTEMNAME` VARCHAR(30) ) LANGUAGE SQL NOT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER COMMENT ' ' BEGIN DECLARE ProcedureName VARCHAR(50) DEFAULT 'usp_gettypeofcall'; DECLARE ProcedureDebug TINYINT DEFAULT True; IF ProcedureDebug THEN CALL debug.debug(ProcedureName,CONCAT_WS(' ','Call from ',IncomingPhoneNumber,'to',TargetGateNumber,'at server',SYSTEMNAME,'with channelid',CHANID)); END IF; END
I draw your attention to the fact that the use of this logic is not recommended !!! in production mode at high loads, since the output of debugging information can greatly reduce the speed.
Let us proceed to setting up the Asterisk server. The standard procedure for handling calls that fall into a public context, in most existing configurations, is as follows.
[public] exten => 74951815000,1,NoOp(Incoming Call to ${EXTEN}) same => n,Dial(SIP/1000,60) same => n,Hangup()
handling outgoing calls from the dialout context looks like this
[dialout] exten => _X.,1,NoOp(Outgoing Call to ${EXTEN}) same => n,Dial(SIP/dialpeer_name/${EXTEN},60) same => n,Hangup() [dialout] exten => _X.,1,NoOp(Outgoing Call to ${EXTEN}) same => n,Dial(SIP/sip.n1.ipport.net/${EXTEN},60) same => n,Hangup() [dialout] exten => _X.,1,NoOp(Outgoing Call to ${EXTEN}) same => n,Dial(SIP/${EXTEN}@sip.n1.ipport.net,60) same => n,Hangup()
In general, who is as accustomed and as you like. As we see with such an organization of outgoing calls, there is practically no information about the status of the call. We modified Dialplan call processing and added service functions to it.
[service] ; GetIP subroutine exten => getip,1,Set(TESTAT=${CUT(SIP_HEADER(From),@,2)}) same => n,GotoIf($["${TESTAT}" != ""]?hasat) same => n,Set(FROM_IP=${CUT(CUT(SIP_HEADER(From),>,1),:,2)}) same => n,Goto(gotip) same => 20(hasat),Set(FROM_IP=${CUT(CUT(CUT(SIP_HEADER(From),@,2),>,1),:,1)}) same => n(gotip),NoOp(Incoming Server IP is ${FROM_IP}) same => n,Return() exten => set_handler,1,Set(CHANNEL(hangup_handler_push)=service,outbound_handler,1) same => n,AGI(/usr/local/etc/asterisk_scripts/create_channel_record.py) same => n,Return() ; Set Hangup handler for channel exten => outbound_handler,1,NoOp(Hungup handler python started) same => n,AGI(/usr/local/etc/asterisk_scripts/hangup.py) same => n,HangupCauseClear() same => n,Return() exten => no_more_paths,1,NoOp(No more dial paths) same => n,Hangup() [predial] exten => s,1,NoOp(PreDial handler python started) same => n,AGI(/usr/local/etc/asterisk_scripts/predial.py) same => n,Return() [public] exten => _X.,1,GoSub(service,getip,1) same => n,AGI(/usr/local/etc/asterisk_scripts/incoming.py) exten => _+X.,1,GoSub(service,getip,1) same => n,AGI(/usr/local/etc/asterisk_scripts/incoming.py) [users_context] exten => _X.,1,NoOp() same => n,AGI(/usr/local/etc/asterisk_scripts/make_a_route.py) [make_a_call] exten => h,1,NoOp(Hangup) exten => _.,1,NoOp(${EXTEN}) same => n,SET(__LoopCount=1) same => n(try),AGI(/usr/local/etc/asterisk_scripts/incoming_dialer.py) same => n,Dial(${DIALSTRING},60,b(service^set_handler^1)U(predial)) same => n,SET(__LoopCount=${IF($[${HANGUPCAUSE}=17]?10:${LoopCount})}) same => n,Set(__LoopCount=${INC(LoopCount)}) same => n,NoOp(Current LoopCount ${LoopCount}) same => n,GotoIf($["${LoopCount}" < 10]?try) same => n,Hangup() [redirect] exten => h,1,NoOp(Hangup) exten => _.,1,NoOp(${ForwardPath}) same => n,Dial(${ForwardPath}/${EXTEN},60,b(service^set_handler^1)) same => n,Hangup()
The [service] context contains service functions such as:
The [predial] context is invoked before the callers are connected when they successfully pick up the handset on the called side.
All external calls fall into the [public] context.
All calls that need to be redirected from server to server fall into the [redirect] context.
The context [users_context] is the main context of users for preparing routes for calls.
The context [make_a_call] is the main context when making an outgoing call.
Let us consider in more detail the procedure for processing an incoming call:
[users_context] [make_a_call] .
:
Asterisk . , Asterisk, , RSA IAX . .
AGI Python Application . AGI . , AGI HTTP Application Server uwsgi . , , CURL .
© Aborche 2017
Source: https://habr.com/ru/post/319352/
All Articles