-
Notifications
You must be signed in to change notification settings - Fork 564
/
README
767 lines (620 loc) · 26.7 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
CGRateS Module
__________________________________________________________
Table of Contents
1. Admin Guide
1.1. Overview
1.2. Authorization
1.3. Accounting
1.4. Other Commands
1.5. CGRateS Failover
1.6. CGRateS Compatibility
1.7. Dependencies
1.7.1. OpenSIPS Modules
1.7.2. External Libraries or Applications
1.8. Exported Parameters
1.8.1. cgrates_engine (string)
1.8.2. bind_ip (string)
1.8.3. max_async_connections (integer)
1.8.4. retry_timeout (integer)
1.8.5. compat_mode (integer)
1.9. Exported Functions
1.9.1. cgrates_acc([flags[, account[, destination[,
session]]]])
1.9.2. cgrates_auth([account[, destination[,
session]]])
1.9.3. cgrates_cmd(command[, session])
1.10. Exported Pseudo-Variables
1.10.1. $cgr(name) / $(cgr(name)[session])
1.10.2. $cgr_opt(name) / $(cgr_opt(name)[session])
1.10.3. $cgr_ret(name)
1.11. Exported Asynchronous Functions
1.11.1. cgrates_auth([account[, destination[,
session]]])
1.11.2. cgrates_cmd(command[, session])
2. Contributors
2.1. By Commit Statistics
2.2. By Commit Activity
3. Documentation
3.1. Contributors
List of Tables
2.1. Top contributors by DevScore^(1), authored commits^(2) and
lines added/removed^(3)
2.2. Most recently active contributors^(1) to this module
List of Examples
1.1. Set cgrates_engine parameter
1.2. Set bind_ip parameter
1.3. Set max_async_connections parameter
1.4. Set retry_timeout parameter
1.5. Set compat_mode parameter
1.6. cgrates_acc() usage
1.7. cgrates_auth() usage
1.8. cgrates_auth() usage with attributes parsing
1.9. cgrates_cmd() usage
1.10. $cgr(name) simple usage
1.11. $cgr(name) multiple sessions usage
1.12. $cgr_opt(name) usage
1.13. $cgr_ret(name) usage
1.14. async cgrates_auth usage
1.15. async cgrates_cmd compat_mode usage
1.16. async cgrates_cmd new usage
Chapter 1. Admin Guide
1.1. Overview
CGRateS is an open-source rating engine used for carrier-grade,
multi-tenant, real-time billing. It is able to do both postpaid
and prepaid rating for multiple concurrent sessions
with different balance units (eg: Monetary, SMS, Internet
Traffic). CGRateS can also export accurate CDRs in various
formats.
This module can be used to communicate with the CGRates engine
in order to do call authorization and accounting for billing
purposes. The OpenSIPS module does not do any billing by
itself, but provides an interface to communicate with the
CGRateS engine using efficient JSON-RPC APIs in both
synchronous and asynchronous ways. For each command the user
can provide a set of parameters that will be forwarded to the
CGRateS engine, using the $cgr() variable. You can find usage
examples in the following sections.
The module also has support for multiple parallel billing
sessions to CGRateS. This can be useful in scenarios that
involve complex billing logic, such as double billing (both
customer and carrier billing), or multi-leg calls
(serial/parallel forking). Each billing session is independent
and has a specific tag that can be use throughout the call
lifetime.
The module can be used to implement the following features:
1.2. Authorization
The authorization is used to check if an account is allowed to
start a new call and it has enough credit to call to that
destination. This is done using the cgrates_auth() command,
which returns the number of seconds a call is allowed to run in
the $cgr_ret pseudo-variable.
Usage example:
...
if (cgrates_auth("$fU", "$rU"))
xlog("Call is allowed to run $cgr_ret seconds\n"
);
}
...
1.3. Accounting
The accounting mode is used to start and stop a CGRateS
session. This can be used for both prepaid and postpaid
billing. The cgrates_acc() function starts the CGRateS session
when the call is answered (the 200 OK message is received) and
ends it when the call is ended (a BYE message is received).
This is done automatically using the dialog module.
Note that it is important to first authorize the call (using
the cgrates_auth() command) before starting accounting. If you
do not do this and the user is not authorized to call, the
dialog will be immediately closed, resulting in a 0-duration
call. If the call is allowed to go on, the dialog lifetime will
be set to the duration indicated by the CGRateS engine.
Therefore, the dialog will be automatically ended if the call
would have been longer.
After the call is ended (by a BYE message), the CGRateS session
is also ended. At this point, you can generate a CDR. To do
this, you have to set the cdr flag to the cgrates_acc()
command. CDRs can also be generated for missed calls by using
the missed flag.
Usage example:
...
if (!cgrates_auth("$fU", "$rU")) {
sl_send_reply("403", "Forbidden");
exit;
}
xlog("Call is allowed to run $cgr_ret seconds\n");
# do accounting for this call
cgrates_acc("cdr", "$fU", "$rU");
...
Note that when using the cdr flag, CDRs are exported by the
CGRateS engine in various formats, not by OpenSIPS. Check the
CGRateS documentation for more information.
1.4. Other Commands
You can use the cgrates_cmd() to send arbitrary commands to the
CGRateS engine, and use the $cgr_ret pseudo-variable to
retrieve the response.
The following example simulates the cgrates_auth() CGRateS
call:
...
$cgr_opt(Tenant) = $fd; # or $cgr(Tenant) = $fd; /* in c
ompat mode */
$cgr(Account) = $fU;
$cgr(OriginID) = $ci;
$cgr(SetupTime) = "" + $Ts;
$cgr(RequestType) = "*prepaid";
$cgr(Destination) = $rU;
cgrates_cmd("SessionSv1.AuthorizeEvent");
xlog("Call is allowed to run $cgr_ret(MaxUsage) seconds\
n");
...
1.5. CGRateS Failover
Multiple CGRateS engines can be provisioned to use in a
failover manner: in case one engine is down, the next one is
used. Currently there is no load balancing logic between the
servers, but this is a feature one of the CGRateS component
does starting with newer versions.
Each CGRateS engine has assigned up to max_async_connections
connections, plus one used for synchronous commands. If a
connection fails (due to network issues, or server issues), it
is marked as closed and a new one is tried. If all connections
to that engine are down, then the entire engine is marked as
disabled, and a new engine is queried. After an engine is down
for more than retry_timeout seconds, OpenSIPS tries to connect
once again to that server. If it succeeds, that server is
enabled. Otherwise, the other engines are used, until none is
available and the command fails.
1.6. CGRateS Compatibility
The module supports two different versions of CGRateS: the
compat_mode one, which works with pre-rc8 releases, and a new
one which works with the post-rc8 releases. The difference
between the two versions consist in the way the requests and
responses to and from CGRateS are built. In the
non-compat_mode/new version, a new variable, $cgr_opt(), is
available, and can be used to tune the request options. This
variable should not be used in compat_mode mode to avoid
abiguities, but if it is used, it behaves exactly as $cgr(). By
default compat_mode is disabled.
1.7. Dependencies
1.7.1. OpenSIPS Modules
The following modules must be loaded before this module:
* dialog -- in case CGRateS accounting is used.
1.7.2. External Libraries or Applications
The following libraries or applications must be installed
before running OpenSIPS with this module loaded:
* libjson
1.8. Exported Parameters
1.8.1. cgrates_engine (string)
This parameter is used to specify a CGRateS engine connection.
The format is IP[:port]. The port is optional, and if missing,
2014 is used.
This parameter can have multiple values, for each server used
for failover. At least one server should be provisioned.
Default value is “None”.
Example 1.1. Set cgrates_engine parameter
...
modparam("cgrates", "cgrates_engine", "127.0.0.1")
modparam("cgrates", "cgrates_engine", "127.0.0.1:2013")
...
1.8.2. bind_ip (string)
IP used to bind the socket that communicates with the CGRateS
engines. This is useful to set when the engine is runing in a
local, secure LAN, and you want to use that network to
communicate with your servers. The parameter is optional.
Default value is “not set - any IP is used”.
Example 1.2. Set bind_ip parameter
...
modparam("cgrates", "bind_ip", "10.0.0.100")
...
1.8.3. max_async_connections (integer)
The maximum number of simultaneous asynchronous connections to
a CGRateS engine.
Default value is “10”.
Example 1.3. Set max_async_connections parameter
...
modparam("cgrates", "max_async_connections", 20)
...
1.8.4. retry_timeout (integer)
The number of seconds after which a disabled connection/engine
is retried.
Default value is “60”.
Example 1.4. Set retry_timeout parameter
...
modparam("cgrates", "retry_timeout", 120)
...
1.8.5. compat_mode (integer)
Indicates whether OpenSIPS should use the old (compat_mode)
CGRateS version API (pre-rc8).
Default value is “false (0)”.
Example 1.5. Set compat_mode parameter
...
modparam("cgrates", "compat_mode", 1)
...
1.9. Exported Functions
1.9.1. cgrates_acc([flags[, account[, destination[, session]]]])
cgrates_acc() starts an accounting session on the CGRateS
engine for the current dialog. It also ends the session when
the dialog is ended. This function requires a dialog, so in
case create_dialog() was not previously used, it will
internally call that function.
Note that the cgrates_acc() function does not send any message
to the CGRateS engine when it is called, but only when the call
is answered and the CGRateS session should be started (a 200 OK
message is received).
When called in REQUEST_ROUTE or FAILURE_ROUTE, accounting for
this session is done for all the branches created. When called
in BRANCH_ROUTE or ONREPLY_ROUTE, acccounting is done only if
that branch is successful (terminates with a 2xx reply code).
The cgrates_acc() function should only be called on initial
INVITEs. For more infirmation check Section 1.3, “Accounting”.
Meaning of the parameters is as follows:
* flags (string, optional) - indicates whether OpenSIPS
should generate a CDR at the end of the call. If the
parameter is missing, no CDR is generated - the session is
only passed through CGRateS. The following values can be
used, separated by '|':
+ cdr - also generate a CDR;
+ missed - generate a CDR even for missed calls; this
flag only makes sense if the cdr flag is used;
* account (string, optional) - the account that will be
charged in CGrateS. If not specified, the user in the From
header is used.
* destination (string, optional) - the dialled number. If not
present the request URI user is used.
* session (string, optional) - the tag of the session that
will be started if the branch/call completes with success.
This parameter indicates what set of data from the $cgr()
variable should be considered. If missing, the default set
is used.
The function can return the following values:
* 1 - successful call - the CGRateS accouting was
successfully setup for the call.
* -1 - OpenSIPS returned an internal error (i.e. the dialog
cannot be created, or the server is out of memory).
* -2 - the SIP message is invalid: either it has missing
headers, or it is not an initial INVITE.
This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
BRANCH_ROUTE and LOCAL_ROUTE.
Example 1.6. cgrates_acc() usage
...
if (!has_totag()) {
...
if (cgrates_auth($fU, $rU))
cgrates_acc("cdr|missed", $fU, $rU);
...
}
...
1.9.2. cgrates_auth([account[, destination[, session]]])
cgrates_auth() does call authorization through using the
CGRateS engine.
Meaning of the parameters is as follows:
* account (string, optional) - the account that will be
checked in CGrateS. If not specified, the user in the From
header is used.
* destination (string, optional) - the dialled number. If not
present the request URI user is used.
* session (string, optional) - the tag of the session that
will be started if the branch/call completes with success.
This parameter indicates what set of data from the $cgr()
variable should be considered. If missing, the default set
is used.
The function can return the following values:
* 1 - successful call - the CGRateS account is allowed to
make the call.
* -1 - OpenSIPS returned an internal error (i.e. server is
out of memory).
* -2 - the CGRateS engine returned error.
* -3 - No suitable CGRateS server found. message type (not an
initial INVITE).
* -4 - the SIP message is invalid: either it has missing
headers, or it is not an initial INVITE.
* -5 - CGRateS returned an invalid message.
This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
BRANCH_ROUTE and LOCAL_ROUTE.
Example 1.7. cgrates_auth() usage
...
if (!has_totag()) {
...
if (!cgrates_auth($fU, $rU)) {
sl_send_reply(403, "Forbidden");
exit;
}
...
}
...
Example 1.8. cgrates_auth() usage with attributes parsing
...
if (!has_totag()) {
...
$cgr_opt(GetAttributes) = 1;
if (!cgrates_auth($fU, $rU)) {
sl_send_reply(403, "Forbidden");
exit;
}
# move attributes from AttributesDigest variable
to plain AVPs
$var(idx) = 0;
while ($(cgr_ret(AttributesDigest){s.select,$var
(idx),,}) != NULL) {
$avp($(cgr_ret(AttributesDigest){s.selec
t,$var(idx),,}{s.select,0,:}))
= $(cgr_ret(AttributesDigest){s.
select,$var(idx),,}{s.select,1,:});
$var(idx) = $var(idx) + 1;
}
...
}
...
1.9.3. cgrates_cmd(command[, session])
cgrates_cmd() can send arbitrary commands to the CGRateS
engine.
Meaning of the parameters is as follows:
* command (string) - the command sent to the CGRateS engine.
* session (string, optional) - the tag of the session that
will be started if the branch/call completes with success.
This parameter indicates what set of data from the $cgr()
variable should be considered. If missing, the default set
is used.
The function can return the following values:
* 1 - successful call - the CGRateS account is allowed to
make the call.
* -1 - OpenSIPS returned an internal error (i.e. server is
out of memory).
* -2 - the CGRateS engine returned error.
* -3 - No suitable CGRateS server found. message type (not an
initial INVITE).
This function can be used from any route.
Example 1.9. cgrates_cmd() usage
...
# cgrates_auth($fU, $rU); simulation
$cgr_opt(Tenant) = $fd;
$cgr(Account) = $fU;
$cgr(OriginID) = $ci;
$cgr(SetupTime) = "" + $Ts;
$cgr(RequestType) = "*prepaid";
$cgr(Destination) = $rU;
cgrates_cmd("SessionSv1.AuthorizeEvent");
xlog("Call is allowed to run $cgr_ret seconds\n");
...
1.10. Exported Pseudo-Variables
1.10.1. $cgr(name) / $(cgr(name)[session])
Pseudo-variable used to set different parameters for the
CGRateS command. Each name-value pair will be encoded as a
string - value attribute in the JSON message sent to CGRateS.
The name-values pairs are stored in the transaction (if tm
module is loaded). Therefore the values are accessible in the
reply.
When the cgrates_acc() function is called, all the name-value
pairs are moved in the dialog. Therefore the values will be
accessible along the dialog's lifetime.
This variable consists of serveral sets of name-value pairs.
Each set corresponds to a session. The variable can be indexed
by a session tag. The sets are completely indepdendent from one
another. if the session tag does not exist, the default (no
name) one is used.
When assigned with the := operator, the value is treated as a
JSON, rather than a string/integer. However, the evaluation of
the JSON is late, therefore when the CGRateS request is built,
if the module is unable to parse the JSON, the value is sent as
a string.
Example 1.10. $cgr(name) simple usage
...
if (!has_totag()) {
...
$cgr_opt(Tenant) = $fd; # set the From domain as
a tenant
$cgr(RequestType) = "*prepaid"; # do prepaid acc
ounting
$cgr(AttributeIDs) := '["+5551234"]'; # treat as
array
if (!cgrates_auth("$fU", "$rU")) {
sl_send_reply("403", "Forbidden");
exit;
}
}
...
Example 1.11. $cgr(name) multiple sessions usage
...
if (!has_totag()) {
...
# first session - authorize the user
$cgr_opt(Tenant) = $fd; # set the From domain as
a tenant
$cgr(RequestType) = "*prepaid"; # do prepaid acc
ounting
if (!cgrates_auth("$fU", "$rU")) {
sl_send_reply("403", "Forbidden");
exit;
}
# second session - authorize the carrier
$(cgr_opt(Tenant)[carrier]) = $td;
$(cgr(RequestType)[carrier]) = "*postpaid";
if (!cgrates_auth("$tU", "$fU", "carrier")) {
# use a different carrier
return;
}
# if everything is successful start accounting o
n both
cgrates_acc("cdr", "$fU", "rU");
cgrates_acc("cdr", "$tU", "$fU", "carrier");
}
...
1.10.2. $cgr_opt(name) / $(cgr_opt(name)[session])
Used to tune the request parameter of a CGRateS request when
used in non-compat_mode.
Note: for all request options integer values act as boolean
values: 0 disables the feature and 1(or different than 0 value)
enables it. String variables are passed just as they are set.
Possible values at the time the documentation was written:
* Tenant - tune CGRateS Tenant.
* GetAttributes - requests the account attributes from the
CGRateS DB.
* GetMaxUsage - request the maximum time the call is allowed
to run.
* GetSuppliers - request an array with all the suppliers for
that can terminate that call.
Example 1.12. $cgr_opt(name) usage
...
$cgr_opt(Tenant) = "cgrates.org";
$cgr_opt(GetMaxUsage) = 1; # also retrieve the max usage
if (!cgrates_auth("$fU", "$rU")) {
# call rejected
}
...
1.10.3. $cgr_ret(name)
Returns the reply message of a CGRateS command in script, or
when used in the non-compat mode, one of the objects within the
reply.
Example 1.13. $cgr_ret(name) usage
...
cgrates_auth("$fU", "$rU");
# in compat mode
xlog("Call is allowed to run $cgr_ret seconds\n");
# in non-compat mode
xlog("Call is allowed to run $cgr_ret(MaxUsage) seconds\
n");
...
1.11. Exported Asynchronous Functions
1.11.1. cgrates_auth([account[, destination[, session]]])
Does the CGRateS authorization call in an asynchronous way.
Script execution is suspended until the CGRateS engine sends
the reply back.
Meaning of the parameters is as follows:
* account - the account that will be checked in CGRateS. This
parameter is optional, and if not specified, the user in
the From header is used.
* destination - the dialled number. Optional parameter, if
not present the request URI user is used.
* session - the tag of the session that will be started if
the branch/call completes with success. This parameter
indicates what set of data from the $cgr() variable should
be considered. If missing, the default set is used.
The function can return the following values:
* 1 - successful call - the CGRateS account is allowed to
make the call.
* -1 - OpenSIPS returned an internal error (i.e. server is
out of memory).
* -2 - the CGRateS engine returned error.
* -3 - No suitable CGRateS server found. message type (not an
initial INVITE).
* -4 - the SIP message is invalid: either it has missing
headers, or it is not an initial INVITE.
* -5 - CGRateS returned an invalid message.
Example 1.14. async cgrates_auth usage
route {
...
async(cgrates_auth("$fU", "$rU"), auth_reply);
}
route [auth_reply]
{
if ($rc < 0) {
xlog("Call not authorized: code=$cgr_ret!\n");
send_reply("403", "Forbidden");
exit;
}
...
}
1.11.2. cgrates_cmd(command[, session])
Can run an arbitrary CGRateS command in an asynchronous way.
The execution is suspended until the CGRateS engine sends the
reply back.
Meaning of the parameters is as follows:
* command - the command sent to the CGRateS engine. This is a
mandatory parameter.
* session - the tag of the session that will be started if
the branch/call completes with success. This parameter
indicates what set of data from the $cgr() variable should
be considered. If missing, the default set is used.
The function can return the following values:
* 1 - successful call - the CGRateS account is allowed to
make the call.
* -1 - OpenSIPS returned an internal error (i.e. server is
out of memory).
* -2 - the CGRateS engine returned error.
* -3 - No suitable CGRateS server found. message type (not an
initial INVITE).
Example 1.15. async cgrates_cmd compat_mode usage
route {
...
$cgr(Tenant) = $fd;
$cgr(Account) = $fU;
$cgr(OriginID) = $ci;
$cgr(SetupTime) = "" + $Ts;
$cgr(RequestType) = "*prepaid";
$cgr(Destination) = $rU;
async(cgrates_cmd("SMGenericV1.GetMaxUsage"), auth_reply);
}
route [auth_reply]
{
if ($rc < 0) {
xlog("Call not authorized: code=$cgr_ret!\n");
send_reply("403", "Forbidden");
exit;
}
...
}
Example 1.16. async cgrates_cmd new usage
route {
...
$cgr_opt(Tenant) = $fd;
$cgr(Account) = $fU;
$cgr(OriginID) = $ci;
$cgr(SetupTime) = "" + $Ts;
$cgr(RequestType) = "*prepaid";
$cgr(Destination) = $rU;
async(cgrates_cmd("SessionSv1.AuthorizeEventWithDigest"), auth_r
eply);
}
route [auth_reply]
{
if ($rc < 0) {
xlog("Call not authorized: MaxUsage=$cgr_ret(MaxUsage)!\
n");
send_reply("403", "Forbidden");
exit;
}
...
}
Chapter 2. Contributors
2.1. By Commit Statistics
Table 2.1. Top contributors by DevScore^(1), authored
commits^(2) and lines added/removed^(3)
Name DevScore Commits Lines ++ Lines --
1. Razvan Crainea (@razvancrainea) 183 93 7234 1850
2. Vlad Patrascu (@rvlad-patrascu) 13 9 115 172
3. Liviu Chircu (@liviuchircu) 9 7 32 48
4. Bogdan-Andrei Iancu (@bogdan-iancu) 6 4 20 21
5. Maksym Sobolyev (@sobomax) 4 2 9 9
6. wuhanck 3 1 3 3
7. Bradley Jokinen 2 1 6 0
8. Razvan 2 1 4 0
(1) DevScore = author_commits + author_lines_added /
(project_lines_added / project_commits) + author_lines_deleted
/ (project_lines_deleted / project_commits)
(2) including any documentation-related commits, excluding
merge commits. Regarding imported patches/code, we do our best
to count the work on behalf of the proper owner, as per the
"fix_authors" and "mod_renames" arrays in
opensips/doc/build-contrib.sh. If you identify any
patches/commits which do not get properly attributed to you,
please submit a pull request which extends "fix_authors" and/or
"mod_renames".
(3) ignoring whitespace edits, renamed files and auto-generated
files
2.2. By Commit Activity
Table 2.2. Most recently active contributors^(1) to this module
Name Commit Activity
1. Razvan Crainea (@razvancrainea) Dec 2016 - Nov 2021
2. Maksym Sobolyev (@sobomax) Jul 2017 - Jan 2021
3. Bogdan-Andrei Iancu (@bogdan-iancu) Mar 2017 - Mar 2020
4. Vlad Patrascu (@rvlad-patrascu) May 2017 - Nov 2019
5. Liviu Chircu (@liviuchircu) Nov 2017 - Nov 2019
6. Razvan Dec 2018 - Dec 2018
7. wuhanck Apr 2018 - Apr 2018
8. Bradley Jokinen Jul 2017 - Jul 2017
(1) including any documentation-related commits, excluding
merge commits
Chapter 3. Documentation
3.1. Contributors
Last edited by: Razvan Crainea (@razvancrainea), Liviu Chircu
(@liviuchircu), Vlad Patrascu (@rvlad-patrascu).
Documentation Copyrights:
Copyright © 2017 Răzvan Crainea