I hope you can hear me.
First of all, thank you for having me this year in Fosdum.
My name is Saber Katelari.
I'm a core developer at IDCS.com.
And today I'll be showing you how you can build your own enum as your server using CG
Rates.
Firstly, something about our company.
It's located in Bavaria, Germany with backhouses in Romania and Albania.
We have over 17 years of experience in architecture and server-side solutions in voice-over IP environments.
We have platform implementations covering both wholesale and retail businesses categories.
And by now we are responsible to understand real-time processing and constraints and serious
life system outages.
Something about CG Rates.
It's a real-time enterprise building suite, more like a framework since it can do many
things.
It's pluggable into any existing infrastructure.
It's non-intrusive into existing setups.
So it means it does not force you to make decisions.
It's all dependent on your system admin if you want to take into consideration what CG
Rates gives you or if you just want to ignore it.
We are an open-source software since born in 2010.
First sources published in 2012.
Full sources are available in GitHub, 100% in Go.
We always mention Go because when CG Rates first started, Go was also in its first weekly
releases.
And this means that we were one of the first implementers of Go.
And it also means that everyone that we also paved the way for other people coming after
us.
We have no add-ons in private repositories and we take into consideration community contributions
also.
About Engine.
Engine is performance-oriented.
It has this built-in advanced caching system with transactional list record use and time
TTL expiring records.
It's asynchronous, processing with micro threads.
If you know about Go, you probably know more about this.
Also including API load balancer.
We have three branches, V010, master and 1.0.
V010 is our most conservative branch.
Master is where we have our most recent developments.
And also 1.0, we call it like the pinnacle that CG Rates can do, but it's still in early
developments.
We have a test-driven development environment with over 10,000 tests as part of our testing
suite.
Here we can mention unit tests, integration tests, and also call tests for switches.
It has a building modular architecture which is cloud-ready.
It has microservices with a rich set of RPC APIs because everything in CG Rates is API-related.
And it's easy to enhance by rewriting specific components.
So for example, if you want to rewrite the engine in some other code, you can easily do
so.
Some features for about CG Rates.
You can do online offline charging system.
You can have multi-tenancy from day one.
This is more for wide labeling platforms.
You can have multiple databases supported.
We have multiple databases supported to mention some MySQL, Microsoft SQL, SQL Lite, Mongo
Rates, Postgres, and also our internal database, which is compatible with everything we do.
This is also a pretty challenging job to do for a relatively small team that we are.
You can have real-time configuration reloads.
So you can reload your configurations without having to shut down the engine and open it
again.
You can have rating engine with derived charging and in-number rating.
You can have account balances and management with bundles and Dynaprepate.
With Dynaprepate, you can create accounts on the fly and have it give some restricted
permissions or limited permissions to your system.
You can have sessions or event charging with balance reservation and refunds.
This is prepaid logic.
Stereo-shaken authentication, which is more for North America.
CDR logging with support for interim records and rating cues.
This is when you have your CDR sitting in a black box and have it communicate with your
switch and have your CDR straight at the end of a matter of milliseconds without using
any databases from the CDR side.
You can have high-number of interfaces for event readers and exporters to mention some
MQP, SQS, SQL, CSVs, XMLs and a couple more.
You can have fraud detection with automatic mitigation, LCR with quality-based bundles,
quality-based stats and bundles, call statistics with pattern monitoring.
So you can find your ASR and your ACD live from your CDR rates.
And also in combination with your proxy, you can find your average call cost and your total
call cost.
You can have dynamic pricing imports with templates.
This is since all suppliers have different formats and CDR scan is compatible with most
of them.
You can use it with diameter, with radius if you need some authentication, Wi-Fi authorization.
With DNS if you need enamel CR routing, which is also the topic for today.
And you can also have a basic SIP server where it can do redirecting with your CDRs.
You can have it redirect traffic from your switch to your CDRs with some routing and
IP addresses.
Well, else we have resource allocation and controller.
This is some virtual channeling for your customers.
You can have your API server with Gop Json, HDB Json support, built-in high availability
with dynamic partitioning support, API capturing analysis service.
This is something like an internal grant for CDR rates.
Clustering through remote, replication for internal cache and database.
Data versioning with automatic migration.
This is when you need to move between releases in the same branch.
You can do so with data migration.
You can have and we also do, we also are agile in developing new features.
So if you have some feature or some idea that you want to bring us, you are more than welcome
to do so.
This is an internal schema or diagram that we have for CDRs.
It basically shows how CDRs has its components and interfaces and how they communicate with
each other.
On your left side you can see all our interfaces.
You might notice that we don't have open SIPs over there because open SIPs has its own
native module which is faster and better than anything we can do since it's native to open
SIPs.
And if we take one example, for example DNS agent which is on your left, you can see
that it communicates with sessions which is our main subsystem and through there it can
communicate with every component or all components at all or one component.
It's all dependent on what you want to do with CDRs.
For some use cases, again online offline charging, you can have a highly configurable rating
bundle with voice, data, SMS, MS, monetary or anything else.
In 1.0 you can really charge anything else.
You can have there concurrent sessions with concurrent sessions handling and also a centralized
CDR server.
And this all together is what others call online offline charging system.
Another use case which you can do is a dynamic routing system where you can use the dedicated
subsystem for various routing strategies.
There we can mention load balancing, the difference in our load balancers is that we cannot use
setups but only real calls since we get that information out of CDRs.
Also you can have LRN support via attributes, bundle support routing systems, quality based
stats monitoring with thresholds and also load balancer which I mentioned.
Now to get to the INOM LCR server that the topic is for.
Firstly we need to know about DNS, probably most of you know but DNS is something like
an internet address book where you query for something and you get information back specific
to that what you question for.
Depending on your answer the answer is categorized in some record types.
There's a couple but we only work with these three, A-Type, SRV type and NEP type records.
We work only with this because that's what most people need and nobody has really asked
for anything more than this.
To shortly describe them A-Type records convert domain addresses into IPv4 addresses, SRV
records for network servicing.
You can find priority, weight, port, targets from your SIP addresses and most importantly
in NEPTR records which convert INOM addresses, INOMs into IP addresses.
But what is INOM?
INOM is basically a standard to translate telephone numbers into your eyes.
Here's an example how you can do that.
Firstly you need an E164 number.
You can convert your number into an E164 number by firstly removing any leading zero before
it and also adding your country code after it and with a plus at the end.
Then to convert this INOM 164 number into an INOM number you have to remove the leading
plus, reverse all the digits, add a dot between each digit and then add a suffix.
This suffix, the one you have in this example is from RFC standards but in C-Drates we don't
really care what you put in your suffix.
In my example even I even replaced this ARPA later with the account string that I will
use.
For DNS agent I also mentioned earlier it's an interface, it's like a middleware where
your DNS client communicates with DNS agent and then sends that information, that request
to the DNS server and then from there maybe you can see from the schema.
From there you can go into sessions and any component it can take any component and then
give that information back to the DNS client.
In terms of capability you can have as many listeners as you want.
Also to mention in DNS agent we also implemented our DNS server and DNS service and listeners
and for listeners you can have as many listeners as you want and they can all be opened at
the same time. You can have UDP, TCP and TLS protocols and this means it is highly configurable
and concurrent.
Again for query types we support ASRV and NAPTR.
For configuration this is in your configuration files. You need to open a new field, name
it DNS agent, also this is JSON, everything is JSON in configuration.
Name a new field DNS agent, enable it, by enabling it you allow it to receive and to
send API calls.
Then you name listeners where again you can see that it's a list so you can have as many
listeners as you want.
You name your address by giving it an IP and a port.
In my case I use an empty IP since if it's sent by default in CJA we put what's in defaults
and in this case in default is just localhost.
For port I put 2053.
If left empty again this will be filled by the default which is 53.
And for that address I need to attach it a network.
On this case I use the UDP protocol and again if left empty again it will be on UDP by default.
After that I want to also be open to TCP listeners.
That's why I create the same address but this time I changed the protocol.
This doesn't mean that either one or the other will work.
It means that both of them will work at the same time.
There's something messed up over there.
They should be on the same line for the last one.
The address for TLS since I cannot have TLS and TCP on the same address I can put it
in a different port for this example.
And after you finish with listeners you go to connect your DNS agent with sessions and
you do that by using session cons.
You can have either localhost, internal or some configurable other connection which is
done by you.
I use in this case localhost since I want to track the network, the packets going through
sessions and DNS agent.
You can switch it with internal if you want to have a faster connection or if you do not
need this debugging, this packet tracing.
Just on that same DNS agent field you put request processors.
To short explain request processors do the logic of what's going to happen after a query
is done to your server.
In this case you can have many request processors.
In this case I'm only showing one.
And this is what happens with it.
First we define an ID for it which has to be different from other request processors.
It doesn't matter what you put inside, it just has to be different.
So in this case I'm describing what I do in this process which is NAPTR list cost route.
After that you define filters.
Because I want to find the list cost route to find a Cp address for my query.
I first need to be sure that the query type is in NAPTR and that the leading country code
starts with 32.
This is just an example.
You can have any filter that you want.
The first filter asks the query type from the request if it's a full NAPTR string.
And if that's true it goes to the second filter which finds if there's a prefix starting
in that query name that starts with 32.
And before it does that it converts that in number into E164.
And that's done with filters.
If those are true it goes to the next one which are the flags.
In my case I want to create an event each time this query is being made.
So I put there meta event which calls an API for sessions process event.
Each time this query is true.
And I also put routes authorized because I want to get the max usage when the query is
done.
And I also put routes because I want to do list cost routing with it.
Next I put log there because I want to get some logs out of the query when the query
is done.
So I want to get the request and the reply from the query.
And after that I put request fields.
The request fields are what you want to populate when the query is being done.
In this case I want to populate account, destination, set up time, type of record and usage.
I want to populate this because I want to put them in my event later and the event needs
to use them.
How I populate them?
I populate account with the query name by stripping away the first E164 and what's before
it.
So it leaves me behind with only the 1001 account which I will show later.
This way I populate account with 1001.
In destination I put the query name fully converted into E164.
In set up time I put now for the current time of the query, type of record voice and usage
of one minute.
For the reply fields I want to put what I want to reply to the DNS with.
So I want to reply with order of 100, reference 10, flags U and service E2U plus CIP.
In the most important part the regular expression which I find through route parameters.
I didn't show here but I created a routing profile before and I put there two information
in two routes and that information are the CIP addresses which are different.
One of them is of highly cost and the other one is least cost, is lesser cost.
And since I have that meta routes flag over there, those routes will be sorted using least
cost.
And since I have reply I want to find that reply the routing parameters for that first
index of the route.
And the first index is always depending on the sorting route and make it least cost,
the first index is going to be the least cost route.
And under the reply you can see the reply.
I find in the structure routing profile I go to run ID meta row, meta is in this case
asterisk of iteration 0 of that ID.
I go to routes of iteration 0 again and then I find the value of routing parameters which
is the CIP address that it finds.
And then I populate it to that regular expression.
After that I just also put the replacement dot at the end.
For the client, for the client I'm using dig, in this case I'm couring localhost on port
2053, the type of regular this NAPTR.
And you can see the N number that I put there.
You can see the 1001 account at the end.
For the reply I captured this using ngrep.
You can see the API that gets called sessions process event.
In the flags they are the exact same that I put in my request processes.
The tenant gets automatically taken by default configs which is cj.org, the ID is some random
number.
Time is the current time of the query.
And in the event you can see they are exactly what I asked for in my request processes again,
if you can see.
And that's just the request for the reply site.
I can see the reply from that API where I find the max usage of 60 seconds.
If you remember I put one minute of the request.
You can see that it's also 60 billion nanoseconds.
This cj also works in nanoseconds.
Also I have the reply on the routes profile site.
You can see that it found the routes account for 1001.
You can see the sorting that it used.
It's LC for list cost.
And also it shows all the routes that it found sorted by it.
And you can see routes with ID route 2.
You can see the Cp address ending with 12 and the cost that it would take of 60 units.
And the second ID which is more costly with the Cp address of 11.
And here we get the reply back from DNS agent after it's done.
You can see that it found a regular expression with 12 at the end which was 60 cost units
if you saw from earlier.
And also as another use case you can have a fail fallback.
So for example you can have multiple answers over here.
In my case I would just have to make another request process.
And in this case I put just one instead of zero over there and it gets the second list
cost that it finds from routes.
By that you can just get the second answer also.
And that's about it.
Any questions?
I'm guessing not.
If you have any questions you can also ask them at our Google groups.
Oh sorry.
Yeah.
Going back to the request and the response.
I saw you had a, in the request you were getting an account ID.
How are you figuring out the account of the person asking according to DNS?
Well it depends on what you want to do.
In my case I just put that in my request on the DNS client over there.
You can see at the end it's in that 1001.
So I give it myself that account ID.
Okay so you're giving each customer a phone top level domain name.
Whatever you want.
Any other questions?
Okay.
Thank you.