[OpenSIPS-Users] Cant get CPL to work for inbound calls

Кисляков Степан Викторович Stepan.Kislyakov at kaspi.kz
Wed Jun 10 11:48:50 UTC 2026


I have it working now in some way.

So the problem was that when you create opensips tables using opensip-cli it create cpl table like that:
-- public.cpl определение



-- Drop table



--DROP TABLE public.cpl;



CREATE TABLE public.cpl (

       id serial4 NOT NULL,

       username varchar(64) NOT NULL,

       "domain" varchar(64) DEFAULT ''::character varying NOT NULL,

       cpl_xml text NULL,

       cpl_bin text NULL,

       CONSTRAINT cpl_account_idx UNIQUE (username, domain),

       CONSTRAINT cpl_pkey PRIMARY KEY (id)

);

But cpl_bin should be type BYTEA.

So I just drop the table, and create a new one:
-- public.cpl определение



-- Drop table



--DROP TABLE public.cpl;



CREATE TABLE public.cpl (

       id serial4 NOT NULL,

       username varchar(64) NOT NULL,

       "domain" varchar(64) DEFAULT ''::character varying NOT NULL,

       cpl_xml text NULL,

       cpl_bin BYTEA NULL,

       CONSTRAINT cpl_account_idx UNIQUE (username, domain),

       CONSTRAINT cpl_pkey PRIMARY KEY (id)

);


After that I upload the same XML and it works!
I just don’t understand, how to use cpl_xml column as a script without a binary file?
Can you suggest something to me?



Best regards,
Stepan
VOIP dep.

From: Кисляков Степан Викторович
Sent: Wednesday, June 10, 2026 11:36 AM
To: 'Stas Kobzar' <staskobzar at gmail.com>; OpenSIPS users mailling list <users at lists.opensips.org>
Subject: RE: [OpenSIPS-Users] Cant get CPL to work for inbound calls

Hi!,
Thanks for the point.
"db_table" really helped.
But anyway I have the same problem.
I’ve enabled debug and here is the log if I add xml using LOAD command:



NOTICE:Local user is 305 - doing CPL route. newUri
DBG:cpl_c:get_dest_user: trying to get user from new_uri
DBG:cpl_c:get_dest_user: trying to get user from R_uri
DBG:cpl_c:get_user_script: fetching script for user <305>
DBG:db_postgres:db_postgres_val2str: PQescapeStringConn: in: 6 chars, out: 6 chars
DBG:db_postgres:db_postgres_submit_query: 0x7f3562f21008 PQsendQuery(select cpl_bin from cpl where username='305')
DBG:core:db_new_result: allocate 48 bytes for result set at 0x7f3562f25400
DBG:db_postgres:db_postgres_store_result: 0x7f3562f21008 PQresultStatus(PGRES_TUPLES_OK) PQgetResult(0x5621bd4443e0)
DBG:db_postgres:db_postgres_get_columns: 1 columns returned from the query
DBG:core:db_allocate_columns: allocate 28 bytes for result columns at 0x7f3562f25468
DBG:db_postgres:db_postgres_get_columns: RES_NAMES(0x7f3562f25470)[0]=[cpl_bin]
DBG:db_postgres:db_postgres_get_columns: use DB_STRING result type
DBG:db_postgres:db_postgres_convert_rows: allocate for 1 columns 8 bytes in row buffer at 0x7f3562f254c0
DBG:core:db_allocate_rows: allocate 48 bytes for result rows and values at 0x7f3562f25500
DBG:db_postgres:db_postgres_convert_rows: PQgetvalue(0x7f3562f21008,0,0)=[\x0101000000060201000000060d0101000020000000167369703a3430353230354031302e34372e35342e32001301000000061201000000060d000100000000167369703a3430353230334031302e34372e35342e3200]
DBG:db_postgres:db_postgres_convert_rows: allocated 174 bytes for row_buf[0] at 0x7f3562f25568
DBG:db_postgres:db_postgres_convert_rows: [0][0] Column[cpl_bin]=[\x0101000000060201000000060d0101000020000000167369703a3430353230354031302e34372e35342e32001301000000061201000000060d000100000000167369703a3430353230334031302e34372e35342e3200]
DBG:db_postgres:db_postgres_str2val: converting STRING [\x0101000000060201000000060d0101000020000000167369703a3430353230354031302e34372e35342e32001301000000061201000000060d000100000000167369703a3430353230334031302e34372e35342e3200]
DBG:db_postgres:db_postgres_convert_rows: freeing row buffer at 0x7f3562f254c0
DBG:db_postgres:free_query: PQclear(0x5621bd4443e0) result set
DBG:cpl_c:get_user_script: we got the script len=0
DBG:core:db_free_columns: freeing result columns at 0x7f3562f25468
DBG:core:db_free_rows: freeing 1 rows
DBG:core:db_free_row: freeing row values at 0x7f3562f25510
DBG:core:db_free_row: free VAL_STRING[0] '\x0101000000060201000000060d0101000020000000167369703a3430353230354031302e34372e35342e32001301000000061201000000060d000100000000167369703a3430353230334031302e34372e35342e3200' at 0x7f3562f25568
DBG:core:db_free_rows: freeing rows at 0x7f3562f25500
DBG:core:db_free_result: freeing result set at 0x7f3562f25400

Maybe I miss some small details?
Like “you should always add xml script using LOAD command.”
or “you should remove all spaces when you upload xml script to database!”
Is there any specific xml rules that  I need to be aware of?
I’m reading RFC and module doc’s but don’t understand what I’m doing wrong.



Best regards,
Stepan
VOIP dep.

From: Stas Kobzar <staskobzar at gmail.com>
Sent: Monday, June 8, 2026 3:07 PM
To: Кисляков Степан Викторович <Stepan.Kislyakov at kaspi.kz>; OpenSIPS users mailling list <users at lists.opensips.org>
Subject: Re: [OpenSIPS-Users] Cant get CPL to work for inbound calls

Hi,

I think the parameter should be "db_table".
It looks like there is a typo in the docs in the example.

You can also increase log level to debug and try to get more info from logs

Best regards,


On Mon, Jun 8, 2026 at 3:36 AM Кисляков Степан Викторович via Users <users at lists.opensips.org<mailto:users at lists.opensips.org>> wrote:
Hi!
Could you please help me get this working?
I’m using OpenSIPS v3.6.
I need to set up something like a hunt list: when user 300 is called and is busy or unavailable, the call should be routed to 301 and 302 (just an example).
To achieve this, I’m trying to use the CPL_C module.

This is my config in opensips.cfg:
modparam("cpl_c", "db_url", "postgres://alfauser:somepass123@127.0.0.1/opensips<http://alfauser:somepass123@127.0.0.1/opensips>")
#modparam("cpl_c", "cpl_table", "cpl")
modparam("cpl_c", "cpl_dtd_file", "/etc/opensips/cpl.dtd")
modparam("cpl_c","log_dir","/var/log/opensips")
modparam("cpl_c","username_column","username")
modparam("cpl_c","domain_column","domain")
modparam("cpl_c","cpl_xml_column","cpl_xml")
modparam("cpl_c","cpl_bin_column","cpl_bin")
modparam("cpl_c","log_dir","/var/log/opensips/cpl")
modparam("cpl_c","case_sensitive",0)

I don’t know why, but if I set modparam("cpl_c", "cpl_table", "cpl") – I get error that “cpl_table command is not found in cpl_c module”.
Anyway if I run:  opensips-cli -x mi LOAD_CPL sip:300 at local.lcl /usr/share/opensips/cpl_scripts/300.xml
I get "OK"
I can see a new row in the database, and it looks correct. The cpl_bin and cpl_xml columns contain binary data.
However, when I run:
opensips-cli -x mi GET_CPL sip:300 at local.lcl
I get an empty response:

{
    "script": ""
}

I’ve tried to write very simple script to database in cpl_xml column:
<?xml version="1.0" encoding="UTF-8"?>
<cpl>
  <incoming >
    <location url="sip:301 at local.lcl" >
      <proxy >
        <noanswer >
          <location url=" sip:302 at local.lcl " />
        </noanswer>
      </proxy>
    </location>
  </incoming>
</cpl>

When I run opensips-cli -x mi GET_CPL sip:300 at local.lcl
I still get the same empty response.
I don’t know how to make this work.
I would be very grateful for any advice.



Best regards,
Stepan
VOIP dep.

_______________________________________________
Users mailing list
Users at lists.opensips.org<mailto:Users at lists.opensips.org>
http://lists.opensips.org/cgi-bin/mailman/listinfo/users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.opensips.org/pipermail/users/attachments/20260610/3d2da095/attachment-0001.html>


More information about the Users mailing list