diff --git a/.gitignore b/.gitignore index 6559bcf3a..9181381ee 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ dean* data/vagrant/.vagrant data/vagrant/vagrant_ansible_inventory_default data/tutorials/fs_evsock/freeswitch/etc/freeswitch/ +data/tutorials_test/fs_evsock/freeswitch/etc/freeswitch/ vendor *.test glide.lock diff --git a/data/tutorials/kamevapi/cgrates/etc/cgrates/cgrates.json b/data/tutorials/kamevapi/cgrates/etc/cgrates/cgrates.json index 7cb209405..f15bac3b7 100644 --- a/data/tutorials/kamevapi/cgrates/etc/cgrates/cgrates.json +++ b/data/tutorials/kamevapi/cgrates/etc/cgrates/cgrates.json @@ -83,7 +83,7 @@ ], "store_session_costs": true, "debit_interval": "5s", - "channel_sync_interval":"7s", // default: "5m" for test please use "7s" + "channel_sync_interval":"5m", }, diff --git a/data/tutorials/osips/opensips/etc/opensips/opensips.cfg b/data/tutorials/osips/opensips/etc/opensips/opensips.cfg index 678466d38..794255abe 100644 --- a/data/tutorials/osips/opensips/etc/opensips/opensips.cfg +++ b/data/tutorials/osips/opensips/etc/opensips/opensips.cfg @@ -203,6 +203,8 @@ route{ $cgr_opt(GetAttributes) = 1; $cgr_opt(GetSuppliers) = 1; $cgr_opt(AuthorizeResources) = 1; + $cgr_opt(AllocateResources) = 1; + $cgr_opt(ReleaseResources) = 1; $cgr_opt(ProcessThresholds) = 1; $cgr_opt(ProcessStatQueues) = 1; $cgr(RequestType) = "*prepaid"; diff --git a/data/tutorials/osips_native/opensips/etc/opensips/opensips.cfg b/data/tutorials/osips_native/opensips/etc/opensips/opensips.cfg index 01fafb284..4c439a88c 100644 --- a/data/tutorials/osips_native/opensips/etc/opensips/opensips.cfg +++ b/data/tutorials/osips_native/opensips/etc/opensips/opensips.cfg @@ -119,7 +119,7 @@ route{ if ( !loose_route() ) { # we do record-routing for all our traffic, so we should not # receive any sequential requests without Route hdr. - send_reply(404,"Not here"); + send_reply(404, "Not here"); exit; } @@ -164,7 +164,7 @@ route{ xlog("L_ERR", "Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]"); if (!is_method("ACK")) - send_reply(403,"Preload Route denied"); + send_reply(403, "Preload Route denied"); exit; } diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/README b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/README new file mode 100755 index 000000000..0f57ad6c2 --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/README @@ -0,0 +1,15 @@ +The included Asterisk configuration files are intended to be an example +implementation for a fictitious company, Super Awesome Company. + +It can serve as a handy reference for understanding a simple Asterisk +configuration in an approximate real-world environment. + +If you intend to use this configuration as a template for your own, then +you will need to change many values in the various configuration files to +match your own devices, network, SIP ITSP accounts and more. + +For further documentation on this configuration see the Asterisk wiki: +https://wiki.asterisk.org/wiki/display/AST/Reference+Use+Cases+for+Asterisk. + +Please report bugs or errors in configuration on the Asterisk issue tracker: +https://wiki.asterisk.org/wiki/display/AST/Asterisk+Issue+Guidelines diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/ari.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/ari.conf new file mode 100755 index 000000000..f78a801e7 --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/ari.conf @@ -0,0 +1,8 @@ +[general] +enabled = yes +allowed_origins = http://cgrates.org + +[cgrates] +type = user +read_only = no +password = CGRateS.org \ No newline at end of file diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/asterisk.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/asterisk.conf new file mode 100755 index 000000000..cb2ba8367 --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/asterisk.conf @@ -0,0 +1,12 @@ +[directories] +astetcdir => /usr/share/cgrates/tutorials_test/asterisk_ari/asterisk/etc/asterisk +astspooldir => /tmp/cgr_asterisk_ari/asterisk/spool +astlogdir => /tmp/cgr_asterisk_ari/asterisk/log +astrundir => /tmp/cgr_asterisk_ari/asterisk/run +astdbdir => /tmp/cgr_asterisk_ari/asterisk/lib + +[options] +runuser = asterisk ; The user to run as. The default is root. +rungroup = asterisk ; The group to run as. The default is root + + diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/cdr.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/cdr.conf new file mode 100755 index 000000000..e8749e37d --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/cdr.conf @@ -0,0 +1,7 @@ +[general] +enable=yes + +[custom] +; We log the unique ID as it can be useful for troubleshooting any issues +; that arise. +loguniqueid=yes diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/cdr_custom.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/cdr_custom.conf new file mode 100755 index 000000000..12ad24fe4 --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/cdr_custom.conf @@ -0,0 +1,4 @@ +[mappings] +; Our CDR log will be written to /var/log/asterisk/cdr-custom/Master.csv +; with the following schema. +Master.csv => ${CSV_QUOTE(${CDR(clid)})},${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})},${CSV_QUOTE(${CDR(dcontext)})},${CSV_QUOTE(${CDR(channel)})},${CSV_QUOTE(${CDR(dstchannel)})},${CSV_QUOTE(${CDR(lastapp)})},${CSV_QUOTE(${CDR(lastdata)})},${CSV_QUOTE(${CDR(start)})},${CSV_QUOTE(${CDR(answer)})},${CSV_QUOTE(${CDR(end)})},${CSV_QUOTE(${CDR(duration)})},${CSV_QUOTE(${CDR(billsec)})},${CSV_QUOTE(${CDR(disposition)})},${CSV_QUOTE(${CDR(amaflags)})},${CSV_QUOTE(${CDR(accountcode)})},${CSV_QUOTE(${CDR(uniqueid)})},${CSV_QUOTE(${CDR(userfield)})},${CDR(sequence)} diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/confbridge.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/confbridge.conf new file mode 100755 index 000000000..3a44e686a --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/confbridge.conf @@ -0,0 +1 @@ +; All conferences use default settings. This config must be present to load the confbridge application diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/extensions.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/extensions.conf new file mode 100755 index 000000000..7c3c8da6c --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/extensions.conf @@ -0,0 +1,8 @@ +[internal] + exten => _1XXX,1,NoOp() + same => n,Set(CGRMaxSessionTime=0); use it to disconnect automatically the call if CGRateS is not active + same => n,DumpChan() + same => n,Stasis(cgrates_auth,cgr_reqtype=*prepaid,cgr_supplier=supplier1,cgr_subsystems=*accounts*attributes*resources*stats*suppliers*thresholds) + same => n,Dial(PJSIP/${EXTEN},30,L(${CGRMaxSessionTime})) + same => n,Hangup() + diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/http.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/http.conf new file mode 100644 index 000000000..9d1f51885 --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/http.conf @@ -0,0 +1,4 @@ +[general] +enabled = yes +bindaddr = 0.0.0.0 +bindport = 8088 \ No newline at end of file diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/indications.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/indications.conf new file mode 100755 index 000000000..115cddd0b --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/indications.conf @@ -0,0 +1,19 @@ +[general] +country = us ; We are in Waldo, Al, USA so the US is our default. + +[us] +description = United States / North America +ringcadence = 2000,4000 +dial = 350+440 +busy = 480+620/500,0/500 +ring = 440+480/2000,0/4000 +congestion = 480+620/250,0/250 +callwaiting = 440/300,0/10000 +dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440 +record = 1400/500,0/15000 +info = !950/330,!1400/330,!1800/330,0 +stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440 + +; Additional country configurations can be found in the Asterisk source +; at /configs/samples/indications.conf.sample + diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/logger.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/logger.conf new file mode 100755 index 000000000..8b0a1c19d --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/logger.conf @@ -0,0 +1,9 @@ +[general] + +[logfiles] + +console = verbose,notice,warning,error + +;messages = notice,warning,error +;full = verbose,notice,warning,error,debug +;security = security diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/manager.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/manager.conf new file mode 100755 index 000000000..bb9cc219a --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/manager.conf @@ -0,0 +1,155 @@ +; +; AMI - The Asterisk Manager Interface +; +; Third party application call management support and PBX event supervision +; +; Use the "manager show commands" at the CLI to list available manager commands +; and their authorization levels. +; +; "manager show command " will show a help text. +; +; ---------------------------- SECURITY NOTE ------------------------------- +; Note that you should not enable the AMI on a public IP address. If needed, +; block this TCP port with iptables (or another FW software) and reach it +; with IPsec, SSH, or SSL vpn tunnel. You can also make the manager +; interface available over http/https if Asterisk's http server is enabled in +; http.conf and if both "enabled" and "webenabled" are set to yes in +; this file. Both default to no. httptimeout provides the maximum +; timeout in seconds before a web based session is discarded. The +; default is 60 seconds. +; +[general] +enabled = yes +;webenabled = yes + +port = 5038 +bindaddr = 0.0.0.0 + +; Parameters that control AMI over TLS. ("enabled" must be set too). +; You can open a connection to this socket with e.g. +; +; openssl s_client -connect my_host:5039 +; +;tlsenable=no ; set to YES to enable it +;tlsbindaddr=0.0.0.0:5039 ; address and port to bind to, default to bindaddr and port 5039 +;tlscertfile=/tmp/asterisk.pem ; path to the certificate. +;tlsprivatekey=/tmp/private.pem ; path to the private key, if no private given, + ; if no tlsprivatekey is given, default is to search + ; tlscertfile for private key. +;tlscipher= ; string specifying which SSL ciphers to use or not use +; +;allowmultiplelogin = yes ; IF set to no, rejects manager logins that are already in use. +; ; The default is yes. +; +;displayconnects = yes +; +; Add a Unix epoch timestamp to events (not action responses) +; +;timestampevents = yes + +;brokeneventsaction = yes ; Restore previous behavior that caused the events + ; action to not return a response in certain + ; circumstances. Defaults to 'no'. + +; +; Display certain channel variables every time a channel-oriented +; event is emitted: +; +;channelvars = var1,var2,var3 + +; debug = on ; enable some debugging info in AMI messages (default off). + ; Also accessible through the "manager debug" CLI command. + +; authtimeout specifies the maximum number of seconds a client has to +; authenticate. If the client does not authenticate beofre this timeout +; expires, the client will be disconnected. (default: 30 seconds) + +;authtimeout = 30 + +; authlimit specifies the maximum number of unauthenticated sessions that will +; be allowed to connect at any given time. + +;authlimit = 50 + +;httptimeout = 60 +; a) httptimeout sets the Max-Age of the http cookie +; b) httptimeout is the amount of time the webserver waits +; on a action=waitevent request (actually its httptimeout-10) +; c) httptimeout is also the amount of time the webserver keeps +; a http session alive after completing a successful action + + +;[mark] +;secret = mysecret +;deny=0.0.0.0/0.0.0.0 +;permit=209.16.236.73/255.255.255.0 +;acl=named_acl_example ; use a named ACL from acl.conf +; +; +;setvar=PBXACCOUNT=edvina +; The setvar option defines channel variables that will be set when this account +; originates a call. You can define multiple setvar= commands for one manager +; user. +; +;eventfilter=Event: Newchannel +;eventfilter=Channel: (PJ)?SIP/(james|jim|john)- +;eventfilter=!Channel: DAHDI/ +; The eventfilter option is used to whitelist or blacklist events per user. +; A filter consists of an (unanchored) regular expression that is run on the +; entire event data. If the first character of the filter is an exclamation +; mark (!), the filter is appended to the blacklist instead of the whitelist. +; After first checking the read access below, the regular expression filters +; are processed as follows: +; - If no filters are configured all events are reported as normal. +; - If there are white filters only: implied black all filter processed first, +; then white filters. +; - If there are black filters only: implied white all filter processed first, +; then black filters. +; - If there are both white and black filters: implied black all filter processed +; first, then white filters, and lastly black filters. + +; +; If the device connected via this user accepts input slowly, +; the timeout for writes to it can be increased to keep it +; from being disconnected (value is in milliseconds) +; +; writetimeout = 100 +; +;displayconnects = yes ; Display on CLI user login/logoff +; +; Authorization for various classes +; +; Read authorization permits you to receive asynchronous events, in general. +; Write authorization permits you to send commands and get back responses. The +; following classes exist: +; +; all - All event classes below (including any we may have missed). +; system - General information about the system and ability to run system +; management commands, such as Shutdown, Restart, and Reload. +; call - Information about channels and ability to set information in a +; running channel. +; log - Logging information. Read-only. (Defined but not yet used.) +; verbose - Verbose information. Read-only. (Defined but not yet used.) +; agent - Information about queues and agents and ability to add queue +; members to a queue. +; user - Permission to send and receive UserEvent. +; config - Ability to read and write configuration files. +; command - Permission to run CLI commands. Write-only. +; dtmf - Receive DTMF events. Read-only. +; reporting - Ability to get information about the system. +; cdr - Output of cdr_manager, if loaded. Read-only. +; dialplan - Receive NewExten and VarSet events. Read-only. +; originate - Permission to originate new calls. Write-only. +; agi - Output AGI commands executed. Input AGI command to execute. +; cc - Call Completion events. Read-only. +; aoc - Permission to send Advice Of Charge messages and receive Advice +; - Of Charge events. +; test - Ability to read TestEvent notifications sent to the Asterisk Test +; Suite. Note that this is only enabled when the TEST_FRAMEWORK +; compiler flag is defined. +; security - Security Events. Read-only. +; message - Permissions to send out of call messages. Write-only +; +;read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan +;write = system,call,agent,user,config,command,reporting,originate,message + diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/modules.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/modules.conf new file mode 100755 index 000000000..38df4bcac --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/modules.conf @@ -0,0 +1,136 @@ +[modules] +autoload = no + +; This is a minimal module load. We are loading only the modules required for +; the Asterisk features used in the Super Awesome Company configuration. + +; Applications + +load = app_bridgewait.so +load = app_dial.so +load = app_playback.so +load = app_stack.so +load = app_verbose.so +load = app_voicemail.so +load = app_directory.so +load = app_confbridge.so +load = app_queue.so +load = app_dumpchan.so + +; Bridging + +load = bridge_builtin_features.so +load = bridge_builtin_interval_features.so +load = bridge_holding.so +load = bridge_native_rtp.so +load = bridge_simple.so +load = bridge_softmix.so + +; Call Detail Records + +load = cdr_custom.so + +; Channel Drivers + +load = chan_bridge_media.so +load = chan_pjsip.so + +; Codecs + +load = codec_gsm.so +load = codec_resample.so +load = codec_ulaw.so +load = codec_g722.so + +; Formats + +load = format_gsm.so +load = format_pcm.so +load = format_wav_gsm.so +load = format_wav.so + +; Functions + +load = func_callerid.so +load = func_cdr.so +load = func_pjsip_endpoint.so +load = func_sorcery.so +load = func_devstate.so +load = func_strings.so + +; Core/PBX + +load = pbx_config.so + +; Resources + +load = res_musiconhold.so +load = res_pjproject.so +load = res_pjsip_acl.so +load = res_pjsip_authenticator_digest.so +load = res_pjsip_caller_id.so +load = res_pjsip_dialog_info_body_generator.so +load = res_pjsip_diversion.so +load = res_pjsip_dtmf_info.so +load = res_pjsip_endpoint_identifier_anonymous.so +load = res_pjsip_endpoint_identifier_ip.so +load = res_pjsip_endpoint_identifier_user.so +load = res_pjsip_exten_state.so +load = res_pjsip_header_funcs.so +load = res_pjsip_logger.so +load = res_pjsip_messaging.so +load = res_pjsip_multihomed.so +load = res_pjsip_mwi_body_generator.so +load = res_pjsip_mwi.so +load = res_pjsip_nat.so +load = res_pjsip_notify.so +load = res_pjsip_one_touch_record_info.so +load = res_pjsip_outbound_authenticator_digest.so +load = res_pjsip_outbound_publish.so +load = res_pjsip_outbound_registration.so +load = res_pjsip_path.so +load = res_pjsip_pidf_body_generator.so +load = res_pjsip_pidf_digium_body_supplement.so +load = res_pjsip_pidf_eyebeam_body_supplement.so +load = res_pjsip_publish_asterisk.so +load = res_pjsip_pubsub.so +load = res_pjsip_refer.so +load = res_pjsip_registrar_expire.so +load = res_pjsip_registrar.so +load = res_pjsip_rfc3326.so +load = res_pjsip_sdp_rtp.so +load = res_pjsip_send_to_voicemail.so +load = res_pjsip_session.so +load = res_pjsip.so +load = res_pjsip_t38.so +load = res_pjsip_transport_websocket.so +load = res_pjsip_xpidf_body_generator.so +load = res_rtp_asterisk.so +load = res_sorcery_astdb.so +load = res_sorcery_config.so +load = res_sorcery_memory.so +load = res_sorcery_realtime.so +load = res_timing_timerfd.so + +;ARI +load => app_stasis.so +load => res_http_websocket.so +load => res_stasis.so +load => res_stasis_answer.so +load => res_stasis_device_state.so +load => res_stasis_playback.so +load => res_stasis_recording.so +load => res_stasis_snoop.so +load => res_ari.so +load => res_ari_applications.so +load => res_ari_asterisk.so +load => res_ari_bridges.so +load => res_ari_channels.so +load => res_ari_device_states.so +load => res_ari_endpoints.so +load => res_ari_events.so +load => res_ari_mailboxes.so +load => res_ari_model.so +load => res_ari_playbacks.so +load => res_ari_recordings.so +load => res_ari_sounds.so \ No newline at end of file diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/musiconhold.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/musiconhold.conf new file mode 100755 index 000000000..bc3ba2129 --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/musiconhold.conf @@ -0,0 +1,5 @@ +[general] + +[default] +mode = files +directory = moh diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/pjsip.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/pjsip.conf new file mode 100755 index 000000000..a1d439b61 --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/pjsip.conf @@ -0,0 +1,147 @@ +[testcalls] +type=transport +protocol=udp +bind=0.0.0.0:5080 + +[1001] +type = endpoint +transport = testcalls +context = internal +disallow = all +allow = ulaw +allow = alaw +aors = 1001 +auth = 1001 + +[1001] +type = aor +max_contacts = 5 + +[1001] +type=auth +auth_type=userpass +username=1001 +password=CGRateS.org + +[1002] +type = endpoint +transport = testcalls +context = internal +disallow = all +allow = ulaw +allow = alaw +aors = 1002 +auth = 1002 + +[1002] +type = aor +max_contacts = 5 +qualify_frequency = 0 + +[1002] +type=auth +auth_type=userpass +username=1002 +password=CGRateS.org + +[1003] +type = endpoint +transport = testcalls +context = internal +aors = 1003 +auth = 1003 +disallow = all +allow = ulaw +allow = alaw + +[1003] +type = aor +max_contacts = 5 + +[1003] +type=auth +auth_type=userpass +username=1003 +password=CGRateS.org + +[1004] +type = endpoint +transport = testcalls +context = internal +aors = 1004 +auth = 1004 +disallow = all +allow = ulaw +allow = alaw + +[1004] +type = aor +max_contacts = 5 + +[1004] +type=auth +auth_type=userpass +username=1004 +password=CGRateS.org + +[1005] +type = endpoint +transport = testcalls +context = internal +aors = 1005 +auth = 1005 +disallow = all +allow = ulaw +allow = alaw + +[1005] +type = aor +max_contacts = 5 + +[1005] +type=auth +auth_type=userpass +username=1005 +password=CGRateS.org + +[1006] +type = endpoint +transport = testcalls +context = internal +aors = 1006 +auth = 1006 +disallow = all +allow = ulaw +allow = alaw + +[1006] +type = aor +max_contacts = 5 + +[1006] +type=auth +auth_type=userpass +username=1006 +password=CGRateS.org + + +[1007] +type = endpoint +transport = testcalls +context = internal +aors = 1007 +auth = 1007 +disallow = all +allow = ulaw +allow = alaw + +[1007] +type = aor +max_contacts = 5 + +[1007] +type=auth +auth_type=userpass +username=1007 +password=CGRateS.org + diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/queues.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/queues.conf new file mode 100755 index 000000000..8aaa0b4d1 --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/queues.conf @@ -0,0 +1,19 @@ +[general] +monitor-type = MixMonitor + +;========================Sales Queue == +; Calls all sales persons in a ring-all fashion +[sales] +strategy=ringall +member => PJSIP/1109 ; Terry Jules - Director of Sales +member => PJSIP/1105 ; Garnet Claude - Sales Associate +member => PJSIP/1112 ; Franny Ocean - Sales Associate + +;===================== Customer Advocate Queue == +; Calls all customer advocates in a ring-all fashion +[customer_advocate] +strategy=ringall +member => PJSIP/1101 ; Maria Berny - Director of Customer Experience +member => PJSIP/1115 ; Dusty Williams - Customer Advocate +member => PJSIP/1102 ; Tommy Briar - Customer Advocate + diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/voicemail.conf b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/voicemail.conf new file mode 100755 index 000000000..8ef72d447 --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/asterisk/voicemail.conf @@ -0,0 +1,23 @@ +[general] +format = wav49|gsm|wav + +[default] + + +[example] +; Voicemail context for all internal users in the example.com domain. +1101 = 0717,Maria Berny +1102 = 7085,Tommie Briar +1103 = 1809,Penelope Bronte +1104 = 0039,Richard Casey +1105 = 6618,Garnet Claude +1106 = 9805,Aaron Courtney +1107 = 7484,Lindsey Freddie +1108 = 7788,Colby Hildred +1109 = 5750,Terry Jules +1110 = 3702,Hollis Justy +1111 = 1878,Temple Morgan +1112 = 5497,Franny Ocean +1113 = 1637,Laverne Roberts +1114 = 3717,Sal Smith +1115 = 3088,Dusty Williams diff --git a/data/tutorials_test/asterisk_ari/asterisk/etc/init.d/asterisk b/data/tutorials_test/asterisk_ari/asterisk/etc/init.d/asterisk new file mode 100755 index 000000000..611d5ca3e --- /dev/null +++ b/data/tutorials_test/asterisk_ari/asterisk/etc/init.d/asterisk @@ -0,0 +1,175 @@ +#! /bin/sh +# $Id$ +# +# Mon Jun 04 2007 IƱaki Baz Castillo +# - Eliminated SAFE_ASTERISK since it doesn't work as LSB script (it could require a independent "safe_asterisk" init script). +# - Load and use the standar "/lib/lsb/init-functions". +# - Added "--oknodo" to "start-stop-daemon" for compatibility with LSB: +# http://www.linux-foundation.org/spec/refspecs/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html +# +# Thu Nov 17 2005 Gregory Boehnlein +# - Reversed behavior of LD_ASSUME_KERNEL=2.4.1 +# - Added detailed failure messages +# +# Sun Jul 18 2004 Gregory Boehnlein +# - Added test for safe_asterisk +# - Changed "stop gracefully" to "stop now" +# - Added support for -U and -G command line options +# - Modified "reload" to call asterisk -rx 'reload' + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +NAME=asterisk +DESC="Asterisk PBX" +TUTDIR=/usr/share/cgrates/tutorials_test/asterisk_ari/asterisk +TMP_DIR=/tmp/cgr_asterisk_ari/asterisk +# Full path to asterisk binary +DAEMON=/usr/sbin/asterisk +ASTVARRUNDIR=$TMP_DIR/run +LOGDIR=$TMP_DIR/log +DBDIR=$TMP_DIR/lib +CDRDIR=$LOGDIR/cdr-custom +SPOOLDIR=$TMP_DIR/spool +ALTCONF=$TUTDIR/etc/asterisk/asterisk.conf +TRUE=/bin/true +AST_USER="asterisk" +AST_GROUP="asterisk" +VERBOSITY=1 + + +### BEGIN INIT INFO +# Provides: asterisk +# Required-Start: $network $syslog $named $local_fs $remote_fs +# Required-Stop: $network $syslog $named $local_fs $remote_fs +# Should-Start: dahdi misdn lcr wanrouter mysql postgresql +# Should-Stop: dahdi misdn lcr wanrouter mysql postgresql +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Asterisk PBX +# Description: the Asterisk Open Source PBX +### END INIT INFO + +set -e + +if ! [ -x $DAEMON ] ; then + echo "ERROR: $DAEMON not found" + exit 0 +fi + +if ! [ -d $ASTETCDIR ] ; then + echo "ERROR: $ASTETCDIR directory not found" + exit 0 +fi + +if [ ! -d $LOGDIR ]; then + mkdir -p $LOGDIR + chown -R $AST_USER:$AST_GROUP $LOGDIR +fi + + +if [ ! -d $CDRDIR ]; then + mkdir -p $CDRDIR + chown -R $AST_USER:$AST_GROUP $CDRDIR +fi + +if [ ! -d $SPOOLDIR ]; then + mkdir -p $SPOOLDIR + chown -R $AST_USER:$AST_GROUP $SPOOLDIR +fi + +if [ ! -d $DBDIR ]; then + mkdir -p $DBDIR + chown -R $AST_USER:$AST_GROUP $DBDIR +fi + +# Use the LSB standard functions for services management +. /lib/lsb/init-functions + +# Allow configuration overrides in /etc/default/asterisk +CONFIG0=`readlink $0 || :` # readlink returns 1 when something isn't a symlink +if [ "$CONFIG0" = "" ]; then + CONFIGFILE=/etc/default/`basename $0` +else + CONFIGFILE=/etc/default/`basename $CONFIG0` +fi +[ -r $CONFIGFILE ] && . $CONFIGFILE + +case "$1" in + start) + # Check if Asterisk is already running. If it is, then bug out, because + # starting up Asterisk when Asterisk is already running is very bad. + VERSION=`${DAEMON} -rx 'core show version' 2>/dev/null || ${TRUE}` + if [ "`echo $VERSION | cut -c 1-8`" = "Asterisk" ]; then + echo "Asterisk is already running. $0 will exit now." + exit 0 + fi + + log_begin_msg "Starting $DESC: $NAME" + if [ ! -d $ASTVARRUNDIR ]; then + mkdir -p $ASTVARRUNDIR + fi + if [ $AST_USER ] ; then + ASTARGS="$ASTARGS -U $AST_USER" + chown $AST_USER $ASTVARRUNDIR + fi + if [ $AST_GROUP ] ; then + ASTARGS="$ASTARGS -G $AST_GROUP" + chgrp $AST_GROUP $ASTVARRUNDIR + fi + if [ $ALTCONF ]; then + ASTARGS="$ASTARGS -C $ALTCONF" + fi + if [ "x$COREDUMP" = "xyes" ]; then + ASTARGS="$ASTARGS -g" + fi + if [ "0$MAXLOAD" -gt "0" ]; then + ASTARGS="$ASTARGS -L $MAXLOAD" + fi + if [ "0$MAXCALLS" -gt "0" ]; then + ASTARGS="$ASTARGS -M $MAXCALLS" + fi + if [ "0$VERBOSITY" -gt "0" ]; then + for i in `seq 1 $VERBOSITY`; do + ASTARGS="$ASTARGS -v" + done + # -v implies -f, so we override that implicit specification here + ASTARGS="$ASTARGS -F" + fi + if [ "x$INTERNALTIMING" = "xyes" ]; then + ASTARGS="$ASTARGS -I" + fi + if [ "x$TEMPRECORDINGLOCATION" = "xyes" -o "x$TMPRECORDINGLOCATION" = "xyes" ]; then + ASTARGS="$ASTARGS -t" + fi + if test "x$COLOR" = "xno" ; then + ASTARGS="$ASTARGS -n" + fi + # "start-stop-daemon --oknodo" returns 0 even if Asterisk was already running (as LSB expects): + echo "$DAEMON -- $ASTARGS" + start-stop-daemon --start --oknodo --exec $DAEMON -- $ASTARGS + log_end_msg $? + ;; + stop) + log_begin_msg "Stopping $DESC: $NAME" + # "start-stop-daemon --oknodo" returns 0 even if Asterisk was already stopped (as LSB expects): + start-stop-daemon --stop --oknodo --exec $DAEMON + log_end_msg $? + ;; + reload) + echo "Reloading $DESC configuration files." + $DAEMON -rx 'module reload' > /dev/null 2> /dev/null + ;; + restart|force-reload) + $0 stop + sleep 2 # It needs some time to really be stopped. + $0 start + # "restart|force-reload" starts Asterisk and returns 0 even if Asterisk was stopped (as LSB expects). + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|reload|force-reload|status}" >&2 + exit 1 + ;; +esac diff --git a/data/tutorials_test/asterisk_ari/cgrates/etc/cgrates/cgrates.json b/data/tutorials_test/asterisk_ari/cgrates/etc/cgrates/cgrates.json new file mode 100644 index 000000000..6878cc3a6 --- /dev/null +++ b/data/tutorials_test/asterisk_ari/cgrates/etc/cgrates/cgrates.json @@ -0,0 +1,145 @@ +{ + +// Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +// Copyright (C) ITsysCOM GmbH + +"general": { + "log_level": 7, + "node_id":"CGRAsterisk", + "reply_timeout": "5s", +}, + + +"listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080", +}, + + +"stor_db": { + "db_password": "CGRateS.org", +}, + + +"scheduler": { + "enabled": true, +}, + + +"rals": { + "enabled": true, + "thresholds_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], +}, + + +"cdrs": { + "enabled": true, + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "chargers_conns": [ + {"address": "*internal"} + ], + "sessions_cost_retries": 5, +}, + + +"chargers": { + "enabled": true, + "attributes_conns": [ + {"address": "*internal"} + ], +}, + + +"sessions": { + "enabled": true, + "rals_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "cdrs_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "resources_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "suppliers_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "attributes_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "thresholds_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "chargers_conns": [ + {"address": "*internal"} + ], + "store_session_costs": true, + "debit_interval": "5s", + "channel_sync_interval":"7s", +}, + + +"asterisk_agent": { + "enabled": true, + "asterisk_conns":[ + {"address": "127.0.0.1:8088", "user": "cgrates", + "password": "CGRateS.org", "connect_attempts": 3,"reconnects": 10} + ], + "sessions_conns": [ + {"address": "*internal"}, + ], + "create_cdr": true, +}, + + +"attributes": { + "enabled": true, + "string_indexed_fields": ["Account"], +}, + + +"resources": { + "enabled": true, + "string_indexed_fields": ["Account"], +}, + + +"stats": { + "enabled": true, + "string_indexed_fields": ["Account","RunID","Destination"], +}, + + +"thresholds": { + "enabled": true, + "string_indexed_fields": ["Account"], +}, + + +"suppliers": { + "enabled": true, + "rals_conns": [ + {"address": "*internal"}, + ], + "resources_conns": [ + {"address": "*internal"}, + ], + "stats_conns": [ + {"address": "*internal"}, + ], + "string_indexed_fields": ["Account"], +}, + + +} diff --git a/data/tutorials_test/asterisk_ari/cgrates/etc/init.d/cgrates b/data/tutorials_test/asterisk_ari/cgrates/etc/init.d/cgrates new file mode 100755 index 000000000..85cc228af --- /dev/null +++ b/data/tutorials_test/asterisk_ari/cgrates/etc/init.d/cgrates @@ -0,0 +1,184 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: cgrates +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: CGRateS real-time charging system +# Description: Control CGRateS - carrier grade real-time charging system +### END INIT INFO + +# Author: DanB +# +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="CGRateS real-time online/offline Charging System" +NAME=cgrates +DAEMON=/usr/bin/cgr-engine +USER=cgrates +GROUP=cgrates +DAEMON_OPTS="" +TUTFOLDER=/usr/share/cgrates/tutorials_test/asterisk_ari/cgrates +TMP_DIR=/tmp/cgr_astevents/cgrates +SCRIPTNAME=$TUTFOLDER/etc/init.d/$NAME +RUNDIR=$TMP_DIR/run +PIDFILE=$RUNDIR/cgr-engine.pid +STACKTRACE=$RUNDIR/$NAME.strace +ENABLE=true +DAEMON_OPTS="-config_path=$TUTFOLDER/etc/cgrates" +CDREDIR=$TMP_DIR/cdre +CDRCINDIR=$TMP_DIR/cdrc/in +CDRCOUTDIR=$TMP_DIR/cdrc/out + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +if [ "$ENABLE" != "true" ]; then + echo "$DESC not yet configured. Edit $DEFAULTS first." + exit 0 +fi + +# Install the run folder +if [ ! -d $RUNDIR ]; then + mkdir -p $RUNDIR + touch $STACKTRACE + chown -R $USER:$GROUP $RUNDIR +fi +# Install the cdrc folder +if [ ! -d $CDRCINDIR ]; then + mkdir -p $CDRCINDIR + chown $USER:$GROUP $CDRCINDIR + mkdir -p $CDRCOUTDIR + chown $USER:$GROUP $CDRCOUTDIR +fi +# Install the cdre folder +if [ ! -d $CDREDIR ]; then + mkdir -p $CDREDIR + chown $USER:$GROUP $CDREDIR +fi + +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + echo "\n### Started at:" `date`>>$STACKTRACE + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test\ + || return 1 + start-stop-daemon --start --quiet --chuid $USER:$GROUP --make-pidfile --pidfile $PIDFILE --background\ + --startas /bin/bash -- -c "exec $DAEMON $DAEMON_OPTS >> $STACKTRACE 2>&1" \ + || return 2 +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + # Wait for children to finish too if this is a daemon that forks + # and if the daemon is only ever run from this initscript. + # If the above conditions are not satisfied then add some other code + # that waits for the process to drop all resources that could be + # needed by services started subsequently. A last resort is to + # sleep for some time. + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON + [ "$?" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f $PIDFILE + return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + # + # If the daemon can reload its configuration without + # restarting (for example, when it is sent a SIGHUP), + # then implement that here. + # + start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME + return 0 +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + #reload|force-reload) + # + # If do_reload() is not implemented then leave this commented out + # and leave 'force-reload' as an alias for 'restart'. + # + #log_daemon_msg "Reloading $DESC" "$NAME" + #do_reload + #log_end_msg $? + #;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff --git a/data/tutorials_test/fs_evsock/README.md b/data/tutorials_test/fs_evsock/README.md new file mode 100644 index 000000000..15a9598f5 --- /dev/null +++ b/data/tutorials_test/fs_evsock/README.md @@ -0,0 +1,17 @@ +Tutorial FS_JSON +================ + +Scenario: +--------- + +- FreeSWITCH with minimal custom configuration. + + - Added following users (with configs in *etc/freeswitch/directory/default*): 1001-prepaid, 1002-postpaid, 1003-pseudoprepaid, 1004-rated, 1006-prepaid, 1007-prepaid. + - Have added inside default dialplan CGR own extensions just before routing towards users (*etc/freeswitch/dialplan/default.xml*). + +- **CGRateS** with following components: + + - CGR-SM started as prepaid controller, with debits taking place at 5s intervals. + - CGR-Mediator component attaching costs to the raw CDRs from FreeSWITCH_ inside CGR StorDB. + - CGR-CDRE exporting mediated CDRs from CGR StorDB (export path: */tmp*). + - CGR-CDRStats component building up stats in 5 different queues. diff --git a/data/tutorials_test/fs_evsock/cgrates/etc/cgrates/cgrates.json b/data/tutorials_test/fs_evsock/cgrates/etc/cgrates/cgrates.json new file mode 100644 index 000000000..c044b42bf --- /dev/null +++ b/data/tutorials_test/fs_evsock/cgrates/etc/cgrates/cgrates.json @@ -0,0 +1,142 @@ +{ + +// Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +// Copyright (C) ITsysCOM GmbH + +"general": { + "log_level": 7, + "node_id":"CGRFreeswitch", +}, + + +"listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080", +}, + + +"stor_db": { + "db_password": "CGRateS.org", +}, + + +"scheduler": { + "enabled": true, +}, + + +"rals": { + "enabled": true, + "thresholds_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], +}, + + +"cdrs": { + "enabled": true, + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "chargers_conns": [ + {"address": "*internal"} + ], + "sessions_cost_retries": 5, +}, + + +"chargers": { + "enabled": true, + "attributes_conns": [ + {"address": "*internal"} + ], +}, + + +"sessions": { + "enabled": true, + "rals_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "cdrs_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "resources_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "suppliers_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "attributes_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "thresholds_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "chargers_conns": [ + {"address": "*internal"} + ], + "store_session_costs": true, + "debit_interval": "5s", + "channel_sync_interval":"7s", +}, + + +"freeswitch_agent": { + "enabled": true, + "event_socket_conns":[ + {"address": "127.0.0.1:8021", "password": "ClueCon", "reconnects": -1,"alias":""} + ], + "sessions_conns": [ + {"address": "*internal"}, + ], +}, + + +"attributes": { + "enabled": true, + "string_indexed_fields": ["Account"], +}, + + +"resources": { + "enabled": true, + "string_indexed_fields": ["Account"], +}, + + +"stats": { + "enabled": true, + "string_indexed_fields": ["Account","RunID","Destination"], +}, + + +"thresholds": { + "enabled": true, + "string_indexed_fields": ["Account"], +}, + + +"suppliers": { + "enabled": true, + "rals_conns": [ + {"address": "*internal"}, + ], + "resources_conns": [ + {"address": "*internal"}, + ], + "stats_conns": [ + {"address": "*internal"}, + ], + "string_indexed_fields": ["Account"], +}, + + +} diff --git a/data/tutorials_test/fs_evsock/cgrates/etc/init.d/cgrates b/data/tutorials_test/fs_evsock/cgrates/etc/init.d/cgrates new file mode 100755 index 000000000..94c7e9c36 --- /dev/null +++ b/data/tutorials_test/fs_evsock/cgrates/etc/init.d/cgrates @@ -0,0 +1,184 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: cgrates +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: CGRateS real-time charging system +# Description: Control CGRateS - carrier grade real-time charging system +### END INIT INFO + +# Author: DanB +# +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="CGRateS real-time charging system" +NAME=cgrates +DAEMON=/usr/bin/cgr-engine +USER=cgrates +GROUP=cgrates +DAEMON_OPTS="" +TUTFOLDER=/usr/share/cgrates/tutorials_test/fs_evsock/cgrates +TMP_DIR=/tmp/cgr_fsevsock/cgrates +SCRIPTNAME=$TUTFOLDER/etc/init.d/$NAME +RUNDIR=$TMP_DIR/run +PIDFILE=$RUNDIR/cgr-engine.pid +STACKTRACE=$RUNDIR/$NAME.strace +ENABLE=true +DAEMON_OPTS="-config_path=$TUTFOLDER/etc/cgrates" +CDREDIR=$TMP_DIR/cdre +CDRCINDIR=$TMP_DIR/cdrc/in +CDRCOUTDIR=$TMP_DIR/cdrc/out + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +if [ "$ENABLE" != "true" ]; then + echo "$DESC not yet configured. Edit $DEFAULTS first." + exit 0 +fi + +# Install the run folder +if [ ! -d $RUNDIR ]; then + mkdir -p $RUNDIR + touch $STACKTRACE + chown -R $USER:$GROUP $RUNDIR +fi +# Install the cdrc folder +if [ ! -d $CDRCINDIR ]; then + mkdir -p $CDRCINDIR + chown $USER:$GROUP $CDRCINDIR + mkdir -p $CDRCOUTDIR + chown $USER:$GROUP $CDRCOUTDIR +fi +# Install the cdre folder +if [ ! -d $CDREDIR ]; then + mkdir -p $CDREDIR + chown $USER:$GROUP $CDREDIR +fi + +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + echo "\n### Started at:" `date`>>$STACKTRACE + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test\ + || return 1 + start-stop-daemon --start --quiet --chuid $USER:$GROUP --make-pidfile --pidfile $PIDFILE --background\ + --startas /bin/bash -- -c "exec $DAEMON $DAEMON_OPTS >> $STACKTRACE 2>&1" \ + || return 2 +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + # Wait for children to finish too if this is a daemon that forks + # and if the daemon is only ever run from this initscript. + # If the above conditions are not satisfied then add some other code + # that waits for the process to drop all resources that could be + # needed by services started subsequently. A last resort is to + # sleep for some time. + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON + [ "$?" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f $PIDFILE + return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + # + # If the daemon can reload its configuration without + # restarting (for example, when it is sent a SIGHUP), + # then implement that here. + # + start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME + return 0 +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + #reload|force-reload) + # + # If do_reload() is not implemented then leave this commented out + # and leave 'force-reload' as an alias for 'restart'. + # + #log_daemon_msg "Reloading $DESC" "$NAME" + #do_reload + #log_end_msg $? + #;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff --git a/data/tutorials_test/fs_evsock/freeswitch/etc/freeswitch_conf.tar.gz b/data/tutorials_test/fs_evsock/freeswitch/etc/freeswitch_conf.tar.gz new file mode 100644 index 000000000..28ba3a0fb Binary files /dev/null and b/data/tutorials_test/fs_evsock/freeswitch/etc/freeswitch_conf.tar.gz differ diff --git a/data/tutorials_test/fs_evsock/freeswitch/etc/init.d/freeswitch b/data/tutorials_test/fs_evsock/freeswitch/etc/init.d/freeswitch new file mode 100755 index 000000000..b7f958e97 --- /dev/null +++ b/data/tutorials_test/fs_evsock/freeswitch/etc/init.d/freeswitch @@ -0,0 +1,145 @@ +#!/bin/sh +### -*- mode:shell-script; indent-tabs-mode:nil; sh-basic-offset:2 -*- +### BEGIN INIT INFO +# Provides: freeswitch +# Required-Start: $network $remote_fs $local_fs +# Required-Stop: $network $remote_fs $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: FreeSWITCH Softswitch +# Description: FreeSWITCH Softswitch +### END INIT INFO + +# Author: Travis Cross + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC=freeswitch +NAME=freeswitch +DAEMON=/usr/bin/freeswitch +USER=freeswitch +GROUP=freeswitch +TUTDIR=/usr/share/cgrates/tutorials_test/fs_evsock/freeswitch +SCRIPTNAME=$TUTDIR/etc/init.d/$NAME +TMP_DIR=/tmp/cgr_fsevsock/freeswitch +CONFDIR=$TUTDIR/etc/$NAME +RUNDIR=$TMP_DIR/run +LOGDIR=$TMP_DIR/log +PIDFILE=$RUNDIR/$NAME.pid +WORKDIR=$TMP_DIR/lib +DBDIR=$WORKDIR/db/ +DAEMON_ARGS="-rp -conf $CONFDIR -db $DBDIR -log $LOGDIR -u $USER -g $GROUP -nonat -nc" + + +[ -x $DAEMON ] || exit 0 +. /lib/init/vars.sh +. /lib/lsb/init-functions + +if [ ! -d $RUNDIR ]; then + mkdir -p $RUNDIR + chown -R $USER:$GROUP $RUNDIR + chmod -R ug=rwX,o= $RUNDIR +fi + +if [ ! -d $LOGDIR ]; then + mkdir -p $LOGDIR + chown -R $USER:$GROUP $LOGDIR +fi + +if [ ! -d $DBDIR ]; then + mkdir -p $DBDIR + chown -R $USER:$GROUP $DBDIR +fi + +do_start() { + if ! [ -f $CONFDIR/freeswitch.xml ]; then + echo "$NAME is not configured so not starting.">&2 + echo "Please review /usr/share/doc/$NAME/README.Debian">&2 + return 3 + fi + echo $DAEMON_ARGS + start-stop-daemon --start --quiet \ + --pidfile $PIDFILE --exec $DAEMON --name $NAME --user $USER \ + --test > /dev/null \ + || return 1 + ulimit -s 240 + start-stop-daemon --start --quiet \ + --pidfile $PIDFILE --exec $DAEMON --name $NAME --user $USER \ + --chdir $WORKDIR -- $DAEMON_ARGS $DAEMON_OPTS \ + || return 2 + return 0 +} + +stop_fs() { + start-stop-daemon --stop --quiet \ + --pidfile $PIDFILE --name $NAME --user $USER \ + --retry=TERM/30/KILL/5 +} + +stop_fs_children() { + start-stop-daemon --stop --quiet \ + --exec $DAEMON \ + --oknodo --retry=0/30/KILL/5 +} + +do_stop() { + stop_fs + RETVAL="$?" + [ "$RETVAL" -eq 2 ] && return 2 + stop_fs_children + [ "$?" -eq 2 ] && return 2 + rm -f $PIDFILE + return "$RETVAL" +} + +do_reload() { + start-stop-daemon --stop --quiet \ + --pidfile $PIDFILE --name $NAME --user $USER \ + --signal HUP +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + reload|force-reload) + log_daemon_msg "Reloading $DESC" "$NAME" + do_reload + log_end_msg $? + ;; + restart) + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1|*) log_end_msg 1 ;; + esac + ;; + *) log_end_msg 1 ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +exit 0 diff --git a/data/tutorials_test/kamevapi/cgrates/etc/cgrates/cgrates.json b/data/tutorials_test/kamevapi/cgrates/etc/cgrates/cgrates.json new file mode 100644 index 000000000..a9f955719 --- /dev/null +++ b/data/tutorials_test/kamevapi/cgrates/etc/cgrates/cgrates.json @@ -0,0 +1,141 @@ +{ + +// Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +// Copyright (C) ITsysCOM GmbH + +"general": { + "log_level": 7, + "node_id":"CGRKamailio", + "reply_timeout": "5s", +}, + + +"listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080", +}, + + +"stor_db": { + "db_password": "CGRateS.org", +}, + + +"scheduler": { + "enabled": true, +}, + + +"rals": { + "enabled": true, + "thresholds_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], +}, + + +"cdrs": { + "enabled": true, + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "sessions_cost_retries": 5, +}, + + +"chargers": { + "enabled": true, + "attributes_conns": [ + {"address": "*internal"} + ], +}, + + +"sessions": { + "enabled": true, + "rals_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "cdrs_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "resources_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "suppliers_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "attributes_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "thresholds_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "chargers_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"}, + ], + "store_session_costs": true, + "debit_interval": "5s", + "channel_sync_interval":"7s", +}, + + +"kamailio_agent": { + "enabled": true, + "evapi_conns":[ + {"address": "127.0.0.1:8448", "reconnects": 5} + ], + "sessions_conns": [ + {"address": "*internal"}, + ], + "create_cdr": true, +}, + + +"attributes": { + "enabled": true, + "string_indexed_fields": ["Account"], +}, + + +"resources": { + "enabled": true, + "string_indexed_fields": ["Account"], +}, + + +"stats": { + "enabled": true, + "string_indexed_fields": ["Account","RunID","Destination"], +}, + + +"thresholds": { + "enabled": true, + "string_indexed_fields": ["Account"], +}, + + +"suppliers": { + "enabled": true, + "rals_conns": [ + {"address": "*internal"}, + ], + "resources_conns": [ + {"address": "*internal"}, + ], + "stats_conns": [ + {"address": "*internal"}, + ], + "string_indexed_fields": ["Account"], +}, + + +} diff --git a/data/tutorials/osips_native/cgrates/etc/init.d/.fuse_hidden0000001700000001 b/data/tutorials_test/kamevapi/cgrates/etc/init.d/cgrates similarity index 95% rename from data/tutorials/osips_native/cgrates/etc/init.d/.fuse_hidden0000001700000001 rename to data/tutorials_test/kamevapi/cgrates/etc/init.d/cgrates index 84ccd75d8..dc8c52376 100755 --- a/data/tutorials/osips_native/cgrates/etc/init.d/.fuse_hidden0000001700000001 +++ b/data/tutorials_test/kamevapi/cgrates/etc/init.d/cgrates @@ -21,14 +21,14 @@ DAEMON=/usr/bin/cgr-engine USER=cgrates GROUP=cgrates DAEMON_OPTS="" -TUTFOLDER=/usr/share/cgrates/tutorials/fs_evsock/cgrates -TMP_DIR=/tmp/cgr_evsock/cgrates +TUTFOLDER=/usr/share/cgrates/tutorials_test/kamevapi/cgrates +TMP_DIR=/tmp/cgr_kamevapi/cgrates SCRIPTNAME=$TUTFOLDER/etc/init.d/$NAME RUNDIR=$TMP_DIR/run PIDFILE=$RUNDIR/cgr-engine.pid STACKTRACE=$RUNDIR/$NAME.strace ENABLE=true -DAEMON_OPTS="-config_path=/usr/share/cgrates/tutorials/fs_evsock/cgrates/etc/cgrates" +DAEMON_OPTS="-config_path=$TUTFOLDER/etc/cgrates" CDREDIR=$TMP_DIR/cdre # Exit if the package is not installed @@ -56,7 +56,7 @@ fi # Install the cdre folder if [ ! -d $CDREDIR ]; then mkdir -p $CDREDIR - chown $USER:$GROUP $CDREDIR + chown -R $USER:$GROUP $CDREDIR fi # diff --git a/data/tutorials_test/kamevapi/kamailio/etc/init.d/kamailio b/data/tutorials_test/kamevapi/kamailio/etc/init.d/kamailio new file mode 100755 index 000000000..e5e3bf7d4 --- /dev/null +++ b/data/tutorials_test/kamevapi/kamailio/etc/init.d/kamailio @@ -0,0 +1,166 @@ +#! /bin/sh +# +### BEGIN INIT INFO +# Provides: kamailio +# Required-Start: $syslog $network $local_fs $remote_fs $time +# Should-Start: $named slapd mysql postgresql snmpd radiusd +# Should-Stop: $named slapd mysql postgresql snmpd radiusd +# Required-Stop: $syslog $network $local_fs $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start the Kamailio SIP proxy server +# Description: Start the Kamailio SIP proxy server +### END INIT INFO + +. /lib/lsb/init-functions + +PATH=/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/sbin/kamailio +NAME=kamailio +DESC="Kamailio SIP Server" +TUTDIR=/usr/share/cgrates/tutorials_test/kamevapi/ +TMP_DIR=/tmp/cgr_kamevapi/kamailio +HOMEDIR=$TMP_DIR/run/ +PIDFILE=$HOMEDIR/$NAME.pid +CFGFILE=$TUTDIR/kamailio/etc/kamailio/kamailio.cfg +USER=kamailio +GROUP=kamailio +# Amount of shared and private memory to allocate +# for the running Kamailio server (in Mb) +SHM_MEMORY=64 +PKG_MEMORY=8 +DUMP_CORE=no + +if [ ! -d $HOMEDIR ]; then + mkdir -p $HOMEDIR + chown -R $USER:$GROUP $HOMEDIR + chmod -R ug=rwX,o= $HOMEDIR +fi + +if [ ! -d $LOGDIR ]; then + mkdir -p $LOGDIR + chown -R $USER:$GROUP $LOGDIR +fi + +# Do not start kamailio if fork=no is set in the config file +# otherwise the boot process will just stop +check_fork () +{ + if grep -q "^[[:space:]]*fork[[:space:]]*=[[:space:]]*no.*" $CFGFILE; then + log_failure_msg "Not starting $DESC: fork=no specified in config file; run /etc/init.d/kamailio debug instead" + exit 0 + fi +} + +check_kamailio_config () +{ + # Check if kamailio configuration is valid before starting the server + set +e + out=$($DAEMON -f $CFGFILE -M $PKG_MEMORY -c 2>&1 > /dev/null) + retcode=$? + set -e + if [ "$retcode" != '0' ]; then + log_failure_msg "Not starting $DESC: invalid configuration file!" + log_failure_msg + log_failure_msg "$out" + log_failure_msg + exit 1 + fi +} + +create_radius_seqfile () +{ + # Create a radius sequence file to be used by the radius client if + # radius accounting is enabled. This is needed to avoid any issue + # with the file not being writable if kamailio first starts as user + # root because DUMP_CORE is enabled and creates this file as user + # root and then later it switches back to user kamailio and cannot + # write to the file. If the file exists before kamailio starts, it + # won't change it's ownership and will be writable for both root + # and kamailio, no matter what options are chosen at install time + RADIUS_SEQ_FILE=/var/run/kamailio/kamailio_radius.seq + if [ -d /var/run/kamailio ]; then + chown ${USER}:${GROUP} /var/run/kamailio + + if [ ! -f $RADIUS_SEQ_FILE ]; then + touch $RADIUS_SEQ_FILE + fi + + chown ${USER}:${GROUP} $RADIUS_SEQ_FILE + chmod 660 $RADIUS_SEQ_FILE + fi +} + +test -f $DAEMON || exit 0 + +# Load startup options if available + + +set -e + +SHM_MEMORY=$((`echo $SHM_MEMORY | sed -e 's/[^0-9]//g'`)) +PKG_MEMORY=$((`echo $PKG_MEMORY | sed -e 's/[^0-9]//g'`)) +[ -z "$USER" ] && USER=kamailio +[ -z "$GROUP" ] && GROUP=kamailio +[ $SHM_MEMORY -le 0 ] && SHM_MEMORY=64 +[ $PKG_MEMORY -le 0 ] && PKG_MEMORY=4 + +if test "$DUMP_CORE" = "yes" ; then + # set proper ulimit + ulimit -c unlimited + + # directory for the core dump files + # COREDIR=/home/corefiles + # [ -d $COREDIR ] || mkdir $COREDIR + # chmod 777 $COREDIR + # echo "$COREDIR/core.%e.sig%s.%p" > /proc/sys/kernel/core_pattern +fi + +# /var/run can be a tmpfs +if [ ! -d $HOMEDIR ]; then + mkdir -p $HOMEDIR +fi + +OPTIONS="-f $CFGFILE -P $PIDFILE -m $SHM_MEMORY -M $PKG_MEMORY -u $USER -g $GROUP" + +case "$1" in + start|debug) + check_kamailio_config + create_radius_seqfile + + if [ "$1" != "debug" ]; then + check_fork + fi + + log_daemon_msg "Starting $DESC: $NAME" + start-stop-daemon --start --quiet --pidfile $PIDFILE \ + --exec $DAEMON -- $OPTIONS || log_failure_msg " already running" + log_end_msg 0 + ;; + stop) + log_daemon_msg "Stopping $DESC: $NAME" + start-stop-daemon --oknodo --stop --quiet --pidfile $PIDFILE \ + --exec $DAEMON + log_end_msg 0 + ;; + restart|force-reload) + check_kamailio_config + create_radius_seqfile + + $0 stop + sleep 1 + $0 start + ;; + status) + log_daemon_msg "Status of $DESC: " + + status_of_proc -p"$PIDFILE" $NAME $NAME + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|force-reload|status|debug}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/data/tutorials_test/kamevapi/kamailio/etc/kamailio/kamailio-cgrates.cfg b/data/tutorials_test/kamevapi/kamailio/etc/kamailio/kamailio-cgrates.cfg new file mode 100644 index 000000000..836d2c902 --- /dev/null +++ b/data/tutorials_test/kamevapi/kamailio/etc/kamailio/kamailio-cgrates.cfg @@ -0,0 +1,192 @@ +# Kamailio-CGRateS related route blocks + + +# Called on new connection over evapi, should normally be the case of CGRateS engine +event_route[evapi:connection-new] { + $sht(cgrconn=>cgr) = $evapi(srcaddr) + ":" + $evapi(srcport); # Detect presence of at least one connection +} + + +# Called when the connection with CGRateS closes +event_route[evapi:connection-closed] { + $var(connClosed) = $evapi(srcaddr) + ":" + $evapi(srcport); + if $sht(cgrconn=>cgr) == $var(connClosed) { + $sht(cgrconn=>cgr) = $null; + } +} + + +# Message received from CGRateS, dispatch it to own route +event_route[evapi:message-received] { + json_get_field("$evapi(msg)", "Event", "$var(Event)"); + route($(var(Event){s.rm,"})); # String characters are kept by json_get_field, remove them here +} + + +# Called by Kamailio on new dialog +event_route[dialog:start] { + route(CGR_CALL_START); +} + + +# Called by Kamailio on dialog end +event_route[dialog:end] { + route(CGR_CALL_END); +} + +# Parse the CGRateS attributes from encoded variable into pseudovariables +route[PARSE_CGRATES_ATTRIBUTES] { + # convert encoded attributes into individual Kamailio pseudovariables + $var(idx) = 0; + while !strempty($(var(cgrAttributes){s.select,$var(idx),,})) { + $avp($(var(cgrAttributes){s.select,$var(idx),,}{s.select,0,:})) + = $(var(cgrAttributes){s.select,$var(idx),,}{s.select,1,:}); + $var(idx) = $var(idx) + 1; + } +} + + +# CGRateS request for session disconnect +route[CGR_SESSION_DISCONNECT] { + json_get_field("$evapi(msg)", "HashEntry", "$var(HashEntry)"); + json_get_field("$evapi(msg)", "HashId", "$var(HashId)"); + json_get_field("$evapi(msg)", "Reason", "$var(Reason)"); + jsonrpc_exec('{"jsonrpc":"2.0","id":1, "method":"dlg.end_dlg","params":[$(var(HashEntry){s.rm,"}),$(var(HashId){s.rm,"})]}'); +} + +route[CGR_DLG_LIST] { + if $sht(cgrconn=>cgr) == $null { + sl_send_reply("503","Charging controller unreachable"); + exit; + } + jsonrpc_exec('{"jsonrpc":"2.0","id":1, "method":"dlg.list","params":[]}'); + evapi_relay("{\"event\":\"CGR_DLG_LIST_REPLY\", + \"jsonrpl_body\":$jsonrpl(body)}"); +} + + +# Route to mainly query account password from CGRateS +route[CGRATES_SIMPLEAUTH_REQUEST] { + if $sht(cgrconn=>cgr) == $null { + sl_send_reply("503","Charging controller unreachable"); + exit; + } + evapi_async_relay("{\"event\":\"CGR_AUTH_REQUEST\", + \"tr_index\":\"$T(id_index)\", + \"tr_label\":\"$T(id_label)\", + \"cgr_subsystems\":\"*attributes\", + \"cgr_context\":\"simpleauth\", + \"reply_route\":\"CGR_SIMPLEAUTH_REPLY\", + \"Account\":\"$fU\"}"); +} + + +# Route receiving simpleauth replies, sanitizes them and dispatch back into Kamailio inside CGRATES_SIMPLEAUTH_REPLY +route[CGR_SIMPLEAUTH_REPLY] { + + json_get_field("$evapi(msg)", "TransactionIndex", "$var(TransactionIndex)"); + $var(TransactionIndex) = $(var(TransactionIndex){s.rm,"}); + $var(id_index) = $(var(TransactionIndex){s.int}); + + json_get_field("$evapi(msg)", "TransactionLabel", "$var(TransactionLabel)"); + $var(TransactionLabel) = $(var(TransactionLabel){s.rm,"}); + $var(id_label) = $(var(TransactionLabel){s.int}); + + json_get_field("$evapi(msg)", "Attributes", "$var(cgrAttributes)"); + $var(cgrAttributes) = $(var(cgrAttributes){s.rm,"}); + + json_get_field("$evapi(msg)", "Error", "$var(cgrError)"); + $var(cgrError) = $(var(cgrError){s.rm,"}); + + t_continue("$var(id_index)", "$var(id_label)", "CGRATES_SIMPLEAUTH_REPLY"); # Unpark the transaction + +} + + +# Request session auth information from CGRateS +route[CGRATES_SESSIONAUTH_REQUEST] { + # Auth INVITEs with CGRateS + if $sht(cgrconn=>cgr) == $null { + sl_send_reply("503","Charging controller unreachable"); + exit; + } + evapi_async_relay("{\"event\":\"CGR_AUTH_REQUEST\", + \"tr_index\":\"$T(id_index)\", + \"tr_label\":\"$T(id_label)\", + \"cgr_subsystems\":\"*attributes;*accounts;*suppliers;*resources;*thresholds\", + \"reply_route\":\"CGR_SESSIONAUTH_REPLY\", + \"Account\":\"$fU\", + \"Destination\":\"$rU\", + \"SetupTime\":\"$TS\"}"); +} + + +# Process SESSIONAUTH_reply from CGRateS +route[CGR_SESSIONAUTH_REPLY] { + json_get_field("$evapi(msg)", "TransactionIndex", "$var(TransactionIndex)"); + $var(TransactionIndex) = $(var(TransactionIndex){s.rm,"}); + $var(id_index) = $(var(TransactionIndex){s.int}); + + json_get_field("$evapi(msg)", "TransactionLabel", "$var(TransactionLabel)"); + $var(TransactionLabel) = $(var(TransactionLabel){s.rm,"}); + $var(id_label) = $(var(TransactionLabel){s.int}); + + json_get_field("$evapi(msg)", "Attributes", "$var(cgrAttributes)"); + $var(cgrAttributes) = $(var(cgrAttributes){s.rm,"}); + + json_get_field("$evapi(msg)", "ResourceAllocation", "$var(cgrResourceAllocation)"); + $var($var(cgrResourceAllocation)) = $(var(cgrResourceAllocation){s.rm,"}); + + json_get_field("$evapi(msg)", "MaxUsage", "$var(MaxUsage)"); + $var(cgrMaxUsage) = $(var(MaxUsage){s.int}); + + json_get_field("$evapi(msg)", "Suppliers", "$var(cgrSuppliers)"); + $var($var(cgrSuppliers)) = $(var(cgrSuppliers){s.rm,"}); + + json_get_field("$evapi(msg)", "Error", "$var(cgrError)"); + $var(cgrError) = $(var(cgrError){s.rm,"}); + + t_continue("$var(id_index)", "$var(id_label)", "CGRATES_SESSIONAUTH_REPLY"); # Unpark the transaction +} + + +# Inform CGRateS about CALL_START (start prepaid sessions loops) +route[CGR_CALL_START] { + if $sht(cgrconn=>cgr) == $null { + xlog("Charging controller unreachable"); + exit; + } + evapi_relay("{\"event\":\"CGR_CALL_START\", + \"h_entry\":\"$dlg(h_entry)\", + \"h_id\":\"$dlg(h_id)\", + \"cgr_subsystems\":\"*attributes;*accounts;*resources;*thresholds\", + \"OriginID\":\"$dlg_var(cgrOriginID)\", + \"RequestType\":\"$dlg_var(cgrReqType)\", + \"Tenant\":\"$dlg_var(cgrTenant)\", + \"Account\":\"$dlg_var(cgrAccount)\", + \"Destination\":\"$dlg_var(cgrDestination)\", + \"SetupTime\":\"$dlg_var(SetupTime)\", + \"AnswerTime\":\"$TS\"}"); +} + + +# Inform CGRateS about CALL_END (stop debit loops, perform accounting if desired in this way) +route[CGR_CALL_END] { + if $sht(cgrconn=>cgr) == $null { + xlog("Charging controller unreachable"); + exit; + } + $var(callDur) = $TS - $dlg(start_ts); + evapi_relay("{\"event\":\"CGR_CALL_END\", + \"cgr_subsystems\":\"*accounts;*resources\", + \"OriginID\":\"$dlg_var(cgrOriginID)\", + \"RequestType\":\"$dlg_var(cgrReqType)\", + \"Tenant\":\"$dlg_var(cgrTenant)\", + \"Account\":\"$dlg_var(cgrAccount)\", + \"Destination\":\"$dlg_var(cgrDestination)\", + \"AnswerTime\":\"$dlg(start_ts)\", + \"PaypalAccount\":\"$dlg_var(paypalAccount)\", + \"SetupTime\":\"$dlg_var(SetupTime)\", + \"Usage\":\"$var(callDur)\"}"); +} + diff --git a/data/tutorials_test/kamevapi/kamailio/etc/kamailio/kamailio.cfg b/data/tutorials_test/kamevapi/kamailio/etc/kamailio/kamailio.cfg new file mode 100644 index 000000000..85672bced --- /dev/null +++ b/data/tutorials_test/kamevapi/kamailio/etc/kamailio/kamailio.cfg @@ -0,0 +1,439 @@ +#!KAMAILIO + +# Sample demo config for Kamailio-CGRateS communication +# tested against Kamailio 5.1 + +####### Defined Values ######### + +#!define FLT_DIALOG 4 +#!define FLT_NATS 5 +#!define FLB_NATB 6 +#!define FLB_NATSIPPING 7 + +####### Global Parameters ######### + +debug=2 +log_stderror=no + +listen=udp:enp0s3:5060 +listen=udp:127.0.0.1:5080 +listen=udp:127.0.0.1:5060 +listen=udp:enp0s3:5080 + +memdbg=5 +memlog=5 +log_facility=LOG_LOCAL0 +fork=yes +children=4 +tcp_connection_lifetime=3605 +use_dns_cache=no +dns_try_ipv6=no +dns_retr_time=1 +dns_retr_no=1 +dns_servers_no=1 +dns_use_search_list=no + +####### Modules Section ######## + +mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/" + +loadmodule "kex.so" +loadmodule "corex.so" +loadmodule "tm.so" +loadmodule "tmx.so" +loadmodule "sl.so" +loadmodule "rr.so" +loadmodule "pv.so" +loadmodule "maxfwd.so" +loadmodule "usrloc.so" +loadmodule "registrar.so" +loadmodule "textops.so" +loadmodule "siputils.so" +loadmodule "xlog.so" +loadmodule "sanity.so" +loadmodule "nathelper.so" +loadmodule "htable.so" +loadmodule "auth.so" +loadmodule "evapi.so" +loadmodule "json.so" +loadmodule "dialog.so" +loadmodule "jsonrpcs.so" + + + +# ----------------- setting module-specific parameters --------------- + +modparam("evapi", "bind_addr", "127.0.0.1:8448") + +# ----- tm params ----- +modparam("tm", "failure_reply_mode", 3) +modparam("tm", "fr_timer", 30000) +modparam("tm", "fr_inv_timer", 120000) + +# ----- rr params ----- +modparam("rr", "enable_full_lr", 0) +modparam("rr", "append_fromtag", 0) + +# ----- registrar params ----- +modparam("registrar", "method_filtering", 1) +modparam("registrar", "max_expires", 3600) + +# ----- dialog params ----- +modparam("dialog", "dlg_flag", FLT_DIALOG) +modparam("dialog", "send_bye", 1) +modparam("dialog", "timeout_noreset", 1) + +# ----- nathelper params ----- +modparam("nathelper", "natping_interval", 30) +modparam("nathelper", "ping_nated_only", 1) +modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) +modparam("nathelper", "sipping_from", "sip:pinger@kamailio.org") + +# params needed for NAT traversal in other modules +modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)") +modparam("usrloc", "nat_bflag", FLB_NATB) + +# ----- htable params ----- +modparam("htable", "htable", "cgrconn=>size=1;") + +####### Routing Logic ######## + +include_file "kamailio-cgrates.cfg" + + +# Main SIP request routing logic +request_route { + + # per request initial checks + route(REQINIT); + + # NAT detection + route(NATDETECT); + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) { + route(RELAY); + } + exit; + } + + # handle requests within SIP dialogs + route(WITHINDLG); + + ### only initial requests (no To tag) + + # handle retransmissions + if(t_precheck_trans()) { + t_check_trans(); + exit; + } + t_check_trans(); + + # record routing for dialog forming requests (in case they are routed) + # - remove preloaded route headers + remove_hf("Route"); + if (is_method("INVITE|SUBSCRIBE")) + record_route(); + + # Not handling requests towards external domains + if uri != myself { + sl_send_reply("604", "Only local destinations accepted"); + exit; + } + + ### requests for my local domains + + # SIMPLE AUTH methods + if is_method("REGISTER|SUBSCRIBE|PUBLISH") { + route(CGRATES_SIMPLEAUTH_REQUEST); + exit; + } + + if ($rU==$null) { + # request with no Username in RURI + sl_send_reply("484","Address Incomplete"); + exit; + } + + if !is_method("INVITE") { + sl_send_reply("503", "Unsupported method"); + exit; + } + + route(CGRATES_SESSIONAUTH_REQUEST); + exit; +} + + +# Here will land requests after processing them with CGRateS. +route[CGRATES_SIMPLEAUTH_REPLY] { + if $var(cgrError) != "" { + xlog("CGR_PROFILE_ERROR: $var(cgrError)"); + sl_send_reply("503","CGR_ERROR"); + exit; + } + + # parse the CGRateS attributes + route(PARSE_CGRATES_ATTRIBUTES); + + # password based auth + route(AUTH); + + if is_method("REGISTER") { + route(REGISTRAR); + exit; + } + + # other methods going over location + route(LOCATION); + route(RELAY); +} + + +# Here will land requests after processing them with CGRateS. Call RELAY or other routes following this route +route[CGRATES_SESSIONAUTH_REPLY] { + + if $var(cgrError) != "" { + xlog("CGR_AUTH_ERROR: $var(cgrError)"); + sl_send_reply("503","CGR_ERROR"); + exit; + } + + # parse the CGRateS attributes + route(PARSE_CGRATES_ATTRIBUTES); + + # password based auth + route(AUTH); + + # track the dialog so we can set it's timeout and channel variables to store in CDRs + # cannot initialize the dialog sooner due to AUTH + dlg_manage(); + $dlg_var(SetupTime) = $TS; + $dlg_var(cgrOriginID) = $dlg(callid) + ";" + $dlg(from_tag); + $dlg_var(cgrTenant) = "cgrates.org"; + $dlg_var(cgrReqType) = $avp(RequestType); + $dlg_var(cgrAccount) = $fU; + $dlg_var(cgrDestination) = $rU; + $dlg_var(paypalAccount) = $avp(PaypalAccount); + + if $var(cgrMaxUsage) != -1 { + if $var(cgrMaxUsage) == 0 { // Not enough balance, do not allow the call to go through + sl_send_reply("403","Insufficient credit"); + exit; + } else if !dlg_set_timeout("$var(cgrMaxUsage)") { + sl_send_reply("503","CGR_MAX_USAGE_ERROR"); + exit; + } + } + + if $var(cgrSuppliers) != "" { # Enforce the supplier variable to the first one received from CGRateS, here more for demo purposes + $dlg_var(cgrSupplier) = $(var(cgrSuppliers){s.select,0,,}); + } + + # user location service + route(LOCATION); + + # send out + route(RELAY); + +} + + +# Wrapper for relaying requests +route[RELAY] { + # enable additional event routes for forwarded requests + # - serial forking, RTP relaying handling, a.s.o. + if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) { + if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH"); + } + if (is_method("INVITE|SUBSCRIBE|UPDATE")) { + if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY"); + } + if (is_method("INVITE")) { + if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE"); + } + + if (!t_relay()) { + sl_reply_error(); + } + exit; +} + +# Per SIP request initial checks +route[REQINIT] { + if (!mf_process_maxfwd_header("10")) { + sl_send_reply("483","Too Many Hops"); + exit; + } + + if(is_method("OPTIONS") && uri==myself && $rU==$null) { + sl_send_reply("200","Keepalive"); + exit; + } + + if(!sanity_check("1511", "7")) { + xlog("Malformed SIP message from $si:$sp\n"); + exit; + } +} + +# Handle requests within SIP dialogs +route[WITHINDLG] { + if (!has_totag()) return; + + # sequential request withing a dialog should + # take the path determined by record-routing + if (loose_route()) { + route(DLGURI); + if ( is_method("ACK") ) { + # ACK is forwarded statelessy + route(NATMANAGE); + } + else if ( is_method("NOTIFY") ) { + # Add Record-Route for in-dialog NOTIFY as per RFC 6665. + record_route(); + } + route(RELAY); + exit; + } + if ( is_method("ACK") ) { + if ( t_check_trans() ) { + # no loose-route, but stateful ACK; + # must be an ACK after a 487 + # or e.g. 404 from upstream server + route(RELAY); + exit; + } else { + # ACK without matching transaction ... ignore and discard + exit; + } + } + sl_send_reply("404","Not here"); + exit; +} + +# Handle SIP registrations +route[REGISTRAR] { + if(isflagset(FLT_NATS)) { + setbflag(FLB_NATB); + } + if (!save("location")) + sl_reply_error(); + exit; +} + +# User location service +route[LOCATION] { + $avp(oexten) = $rU; + if (!lookup("location")) { + $var(rc) = $rc; + t_newtran(); + switch ($var(rc)) { + case -1: + case -3: + send_reply("404", "Not Found"); + exit; + case -2: + send_reply("405", "Method Not Allowed"); + exit; + } + } +} + + +# user uthentication +route[AUTH] { + if (is_method("REGISTER")) { + if ( strempty($au) || !pv_www_authenticate("$td", "$avp(Password)", "0") ) { + www_challenge("$td", "0"); + exit; + } + } else { # All other methods here + if ( strempty($au) || !pv_proxy_authenticate("$td", "$avp(Password)", "0") ) { + proxy_challenge("$td", "0"); + exit; + } + } + consume_credentials(); + return; +} + + +# Caller NAT detection +route[NATDETECT] { + force_rport(); + if (nat_uac_test("19")) { + if (is_method("REGISTER")) { + fix_nated_register(); + } else { + if(is_first_hop()) + set_contact_alias(); + } + setflag(FLT_NATS); + } + return; +} + +# RTPProxy control and singaling updates for NAT traversal +route[NATMANAGE] { + if (is_request()) { + if(has_totag()) { + if(check_route_param("nat=yes")) { + setbflag(FLB_NATB); + } + } + } + if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) + return; + + if (is_request()) { + if (!has_totag()) { + if(t_is_branch_route()) { + add_rr_param(";nat=yes"); + } + } + } + if (is_reply()) { + if(isbflagset(FLB_NATB)) { + if(is_first_hop()) + set_contact_alias(); + } + } + return; +} + +# URI update for dialog requests +route[DLGURI] { + if(!isdsturiset()) { + handle_ruri_alias(); + } + return; +} + + +# Manage outgoing branches +branch_route[MANAGE_BRANCH] { + route(NATMANAGE); +} + +# Manage incoming replies +onreply_route[MANAGE_REPLY] { + if(status=~"[12][0-9][0-9]") + route(NATMANAGE); +} + +# Manage failure routing cases +failure_route[MANAGE_FAILURE] { + route(NATMANAGE); + + if (t_is_canceled()) { + exit; + } + + if (t_check_status("3[0-9][0-9]")) { + t_reply("404","Not found"); + exit; + } +} + diff --git a/data/tutorials_test/osips/cgrates/etc/cgrates/cgrates.json b/data/tutorials_test/osips/cgrates/etc/cgrates/cgrates.json new file mode 100644 index 000000000..fa3b522bb --- /dev/null +++ b/data/tutorials_test/osips/cgrates/etc/cgrates/cgrates.json @@ -0,0 +1,139 @@ +{ + +// Real-time Charging System for Telecom & ISP environments +// Copyright (C) ITsysCOM GmbH +// + + +"listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080", +}, + + +"stor_db": { + "db_password": "CGRateS.org", +}, + + +"scheduler": { + "enabled": true, +}, + + +"rals": { + "enabled": true, + "thresholds_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "attributes_conns": [ + {"address": "*internal"} + ], +}, + + +"cdrs": { + "enabled": true, + "stats_conns": [ + {"address": "*internal"} + ], + "chargers_conns": [ + {"address": "*internal"} + ], + "sessions_cost_retries": 5, +}, + + +"chargers": { + "enabled": true, + "attributes_conns": [ + {"address": "*internal"} + ], +}, + + +"sessions": { + "enabled": true, + "listen_bijson": "127.0.0.1:2014", // address where to listen for bidirectional JSON-RPC requests + "chargers_conns": [ + {"address": "*internal"} + ], + "rals_conns": [ + {"address": "*internal"} + ], + "cdrs_conns": [ + {"address": "*internal"} + ], + "resources_conns": [ + {"address": "*internal"} + ], + "suppliers_conns": [ + {"address": "*internal"} + ], + "attributes_conns": [ + {"address": "*internal"} + ], + "stats_conns": [ + {"address": "*internal"} + ], + "thresholds_conns": [ + {"address": "*internal"} + ], + "debit_interval": "5s", + "channel_sync_interval":"7s", +}, + + + +"attributes": { + "enabled": true, + "string_indexed_fields": ["Account"], +}, + + +"resources": { + "enabled": true, + "thresholds_conns": [ + {"address": "*internal"} + ], + "string_indexed_fields": ["Account"], + "prefix_indexed_fields": ["Destination"], +}, + + +"stats": { + "enabled": true, + "thresholds_conns": [ + {"address": "*internal"} + ], + "string_indexed_fields": ["Account"], +}, + + +"thresholds": { + "enabled": true, + "string_indexed_fields": ["Account"], +}, + + +"suppliers": { + "enabled": true, + "rals_conns": [ + {"address": "*internal"} + ], + "resources_conns": [ + {"address": "*internal"} + ], + "stats_conns": [ + {"address": "*internal"} + ], + "string_indexed_fields": ["Account"], + "prefix_indexed_fields": ["Destination"], +}, + + +} diff --git a/data/tutorials_test/osips/cgrates/etc/init.d/cgrates b/data/tutorials_test/osips/cgrates/etc/init.d/cgrates new file mode 100755 index 000000000..0e0833e12 --- /dev/null +++ b/data/tutorials_test/osips/cgrates/etc/init.d/cgrates @@ -0,0 +1,175 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: cgrates +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: CGRateS real-time charging system +# Description: Control CGRateS - carrier grade real-time charging system +### END INIT INFO + +# Author: DanB +# +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="CGRateS Online Charging System" +NAME=cgrates +DAEMON=/usr/bin/cgr-engine +USER=cgrates +GROUP=cgrates +DAEMON_OPTS="" +TUTFOLDER=/usr/share/cgrates/tutorials_test/osips/$NAME +TMP_DIR=/tmp/cgr_osipsnative/$NAME +SCRIPTNAME=$TUTFOLDER/etc/init.d/$NAME +RUNDIR=$TMP_DIR/run +PIDFILE=$RUNDIR/cgr-engine.pid +STACKTRACE=$RUNDIR/$NAME.strace +ENABLE=true +DAEMON_OPTS="-config_path=$TUTFOLDER/etc/cgrates" +CDREDIR=$TMP_DIR/cdre + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +if [ "$ENABLE" != "true" ]; then + echo "$DESC not yet configured. Edit $DEFAULTS first." + exit 0 +fi + +# Install the run folder +if [ ! -d $RUNDIR ]; then + mkdir -p $RUNDIR + touch $STACKTRACE + chown -R $USER:$GROUP $RUNDIR +fi +# Install the cdre folder +if [ ! -d $CDREDIR ]; then + mkdir -p $CDREDIR + chown $USER:$GROUP $CDREDIR +fi + +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + echo "\n### Started at:" `date`>>$STACKTRACE + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test\ + || return 1 + start-stop-daemon --start --quiet --chuid $USER:$GROUP --make-pidfile --pidfile $PIDFILE --background\ + --startas /bin/bash -- -c "exec $DAEMON $DAEMON_OPTS >> $STACKTRACE 2>&1" \ + || return 2 +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + # Wait for children to finish too if this is a daemon that forks + # and if the daemon is only ever run from this initscript. + # If the above conditions are not satisfied then add some other code + # that waits for the process to drop all resources that could be + # needed by services started subsequently. A last resort is to + # sleep for some time. + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON + [ "$?" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f $PIDFILE + return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + # + # If the daemon can reload its configuration without + # restarting (for example, when it is sent a SIGHUP), + # then implement that here. + # + start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME + return 0 +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + #reload|force-reload) + # + # If do_reload() is not implemented then leave this commented out + # and leave 'force-reload' as an alias for 'restart'. + # + #log_daemon_msg "Reloading $DESC" "$NAME" + #do_reload + #log_end_msg $? + #;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff --git a/data/tutorials_test/osips/opensips/etc/default/opensips b/data/tutorials_test/osips/opensips/etc/default/opensips new file mode 100755 index 000000000..0671f96a0 --- /dev/null +++ b/data/tutorials_test/osips/opensips/etc/default/opensips @@ -0,0 +1,27 @@ +# +# OpenSIPS startup options +# + +# Set to yes to enable opensips, once configured properly. +RUN_OPENSIPS=yes + +# User to run as +USER=opensips + +# Group to run as +GROUP=opensips + +# Amount of shared memory to allocate for the running OpenSIPS server (in Mb) +S_MEMORY=64 + +# Amount of pkg memory to allocate for the running OpenSIPS server (in Mb) +P_MEMORY=4 + +# Enable the server to leave a core file when it crashes. +# Set this to 'yes' to enable OpenSIPS to leave a core file when it crashes +# or 'no' to disable this feature. This option is case sensitive and only +# accepts 'yes' and 'no' and only in lowercase letters. +# On some systems (e.g. Ubuntu 6.10, Debian 4.0) it is necessary to specify +# a directory for the core files to get a dump. Look into the opensips +# init file for an example configuration. +DUMP_CORE=no diff --git a/data/tutorials_test/osips/opensips/etc/init.d/opensips b/data/tutorials_test/osips/opensips/etc/init.d/opensips new file mode 100755 index 000000000..6e2ad2d1f --- /dev/null +++ b/data/tutorials_test/osips/opensips/etc/init.d/opensips @@ -0,0 +1,199 @@ +#! /bin/sh +# +### BEGIN INIT INFO +# Provides: opensips +# Required-Start: $syslog $network $local_fs $time +# Required-Stop: $syslog $network $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start the OpenSIPS SIP server +# Description: Start the OpenSIPS SIP server +### END INIT INFO +# +# TODO: +# The following fields should be added (and completed): +# Should-Start: postgresql mysql radius +# Should-Stop: postgresql mysql radius + +PATH=/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/sbin/opensips +NAME=opensips +DESC=opensips +TUTDIR=/usr/share/cgrates/tutorials_test/osips/$NAME +SCRIPTNAME=$TUTDIR/etc/init.d/$NAME +TMP_DIR=/tmp/cgr_osipsnative/$NAME +CFGFILE=$TUTDIR/etc/$NAME/opensips.cfg +M4CFGFILE=/etc/opensips/opensips.m4 +M4ARCHIVEDIR=/etc/opensips/archive +HOMEDIR=$TMP_DIR/run/opensips +PIDFILE=$HOMEDIR/$NAME.pid +DEFAULTS=$TUTDIR/etc/default/opensips +RUN_OPENSIPS=no + +if [ ! -d $HOMEDIR ]; then + mkdir -p $HOMEDIR + chown -R $USER:$GROUP $HOMEDIR +fi + +# Do not start opensips if fork=no is set in the config file +# otherwise the boot process will just stop +check_fork () +{ + if grep -q "^[[:space:]]*fork[[:space:]]*=[[:space:]]*no.*" $CFGFILE; then + echo "Not starting $DESC: fork=no specified in config file; run /etc/init.d/opensips debug instead" + exit 1 + fi +} + +check_opensips_config () +{ + # Check if opensips configuration is valid before starting the server + set +e + out=$($DAEMON -c 2>&1 > /dev/null) + retcode=$? + set -e + if [ "$retcode" != '0' ]; then + echo "Not starting $DESC: invalid configuration file!" + echo -e "\n$out\n" + exit 1 + fi +} + +create_radius_seqfile () +{ + # Create a radius sequence file to be used by the radius client if + # radius accounting is enabled. This is needed to avoid any issue + # with the file not being writable if opensips first starts as user + # root because DUMP_CORE is enabled and creates this file as user + # root and then later it switches back to user opensips and cannot + # write to the file. If the file exists before opensips starts, it + # won't change it's ownership and will be writable for both root + # and opensips, no matter what options are chosen at install time + RADIUS_SEQ_FILE=/var/run/opensips/opensips_radius.seq + if [ -d /var/run/opensips ]; then + chown ${USER}:${GROUP} /var/run/opensips + + if [ ! -f $RADIUS_SEQ_FILE ]; then + touch $RADIUS_SEQ_FILE + fi + + chown ${USER}:${GROUP} $RADIUS_SEQ_FILE + chmod 660 $RADIUS_SEQ_FILE + fi +} + +test -f $DAEMON || exit 0 + +# Load startup options if available +if [ -f $DEFAULTS ]; then + . $DEFAULTS || true +fi + +if [ "$RUN_OPENSIPS" != "yes" ]; then + echo "OpenSIPS not yet configured. Edit /etc/default/opensips first." + exit 0 +fi + +set -e + +S_MEMORY=$((`echo $S_MEMORY | sed -e 's/[^0-9]//g'`)) +P_MEMORY=$((`echo $P_MEMORY | sed -e 's/[^0-9]//g'`)) +[ -z "$USER" ] && USER=opensips +[ -z "$GROUP" ] && GROUP=opensips +[ $S_MEMORY -le 0 ] && S_MEMORY=32 +[ $P_MEMORY -le 0 ] && P_MEMORY=32 + +if test "$DUMP_CORE" = "yes" ; then + # set proper ulimit + ulimit -c unlimited + + # directory for the core dump files + # COREDIR=/home/corefiles + # [ -d $COREDIR ] || mkdir $COREDIR + # chmod 777 $COREDIR + # echo "$COREDIR/core.%e.sig%s.%p" > /proc/sys/kernel/core_pattern +fi + +OPTIONS="-f $CFGFILE -P $PIDFILE -m $S_MEMORY -M $P_MEMORY -u $USER -g $GROUP -w $HOMEDIR" + +case "$1" in + start|debug) + check_opensips_config + create_radius_seqfile + + if [ "$1" != "debug" ]; then + check_fork + fi + + # dirs under /var/run can go away on reboots. + mkdir -p "$HOMEDIR" + chmod 775 "$HOMEDIR" + chown "$USER:$GROUP" "$HOMEDIR" >/dev/null 2>&1 || true + + # Generate config from M4 + if [ -f $M4CFGFILE ]; then + m4 -Q $M4CFGFILE >$CFGFILE.tmp + if [ $? != 0 ]; then + echo "Cannot process m4 macro" + rm "$CFGFILE.tmp" + exit 1 + fi + + [ -e $CFGFILE ] || touch $CFGFILE + + # compare configs + if [ `md5sum $CFGFILE|awk '{print $1}'` != `md5sum $CFGFILE.tmp|awk '{print $1}'` ]; then + mkdir -p "$M4ARCHIVEDIR" + mv "$CFGFILE" "$M4ARCHIVEDIR/$NAME.cfg-`date +%Y%m%d_%H%M%S`" + fi + + mv "$CFGFILE.tmp" "$CFGFILE" + chown $USER:$GROUP $CFGFILE + chmod 640 $CFGFILE + fi + + echo -n "Starting $DESC: $NAME" + start-stop-daemon --start --quiet --pidfile $PIDFILE \ + --exec $DAEMON -- $OPTIONS || echo -n " already running" + echo "." + ;; + stop) + echo -n "Stopping $DESC: $NAME" + start-stop-daemon --oknodo --stop --quiet --pidfile $PIDFILE \ + --exec $DAEMON + echo "." + ;; + restart|force-reload) + check_opensips_config + create_radius_seqfile + + echo -n "Restarting $DESC: $NAME" + start-stop-daemon --oknodo --stop --quiet --pidfile \ + $PIDFILE --exec $DAEMON + sleep 1 + start-stop-daemon --start --quiet --pidfile \ + $PIDFILE --exec $DAEMON -- $OPTIONS + echo "." + ;; + status) + echo -n "Status of $DESC: " + if [ ! -r "$PIDFILE" ]; then + echo "$NAME is not running." + exit 3 + fi + if read pid < "$PIDFILE" && ps -p "$pid" > /dev/null 2>&1; then + echo "$NAME is running." + exit 0 + else + echo "$NAME is not running but $PIDFILE exists." + exit 1 + fi + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|force-reload|debug|status}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/data/tutorials_test/osips/opensips/etc/opensips/opensips.cfg b/data/tutorials_test/osips/opensips/etc/opensips/opensips.cfg new file mode 100644 index 000000000..794255abe --- /dev/null +++ b/data/tutorials_test/osips/opensips/etc/opensips/opensips.cfg @@ -0,0 +1,269 @@ +# +# OpenSIPS residential configuration script +# by OpenSIPS Solutions +# +# This script was generated via "make menuconfig", from +# the "Residential" scenario. +# You can enable / disable more features / functionalities by +# re-generating the scenario with different options.# +# +# Please refer to the Core CookBook at: +# http://www.opensips.org/Resources/DocsCookbooks +# for a explanation of possible statements, functions and parameters. +# + + +####### Global Parameters ######### + +log_level=3 +log_stderror=no +log_facility=LOG_LOCAL0 + +udp_workers=4 + +auto_aliases=no + +listen=udp:enp0s3:5060 +listen=udp:127.0.0.1:5080 +listen=udp:127.0.0.1:5060 +listen=udp:enp0s3:5080 + + + +####### Modules Section ######## + +#set module path +mpath="/usr/lib/x86_64-linux-gnu/opensips/modules/" + +#### SIGNALING module +loadmodule "signaling.so" + +#### StateLess module +loadmodule "sl.so" + +#### Transaction Module +loadmodule "tm.so" +modparam("tm", "fr_timeout", 5) +modparam("tm", "fr_inv_timeout", 30) +modparam("tm", "restart_fr_on_each_reply", 0) +modparam("tm", "onreply_avp_mode", 1) + +#### Record Route Module +loadmodule "rr.so" +/* do not append from tag to the RR (no need for this script) */ +modparam("rr", "append_fromtag", 0) + +#### MAX ForWarD module +loadmodule "maxfwd.so" + +#### SIP MSG OPerationS module +loadmodule "sipmsgops.so" + +#### FIFO Management Interface +loadmodule "mi_fifo.so" +modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo") +modparam("mi_fifo", "fifo_mode", 0666) + +#### USeR LOCation module +loadmodule "usrloc.so" +modparam("usrloc", "nat_bflag", "NAT") +modparam("usrloc", "db_mode", 0) + +#### REGISTRAR module +loadmodule "registrar.so" +modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT") + +#### ACCounting module +loadmodule "acc.so" +modparam("acc", "early_media", 0) +modparam("acc", "report_cancels", 0) +modparam("acc", "detect_direction", 0) + +loadmodule "proto_udp.so" + + +#### CGRateS module +loadmodule "dialog.so" +loadmodule "cgrates.so" +modparam("cgrates", "cgrates_engine", "127.0.0.1:2014") + + +####### Routing Logic ######## + +# main request routing logic + +route{ + + if (!mf_process_maxfwd_header(10)) { + send_reply(483,"Too Many Hops"); + exit; + } + + if (has_totag()) { + + # handle hop-by-hop ACK (no routing required) + if ( is_method("ACK") && t_check_trans() ) { + t_relay(); + exit; + } + + # sequential request within a dialog should + # take the path determined by record-routing + if ( !loose_route() ) { + # we do record-routing for all our traffic, so we should not + # receive any sequential requests without Route hdr. + send_reply(404, "Not here"); + exit; + } + + if (is_method("BYE")) { + # do accounting even if the transaction fails + do_accounting("log","failed"); + } + + # route it out to whatever destination was set by loose_route() + # in $du (destination URI). + route(relay); + exit; + } + + # CANCEL processing + if (is_method("CANCEL")) { + if (t_check_trans()) + t_relay(); + exit; + } + + # absorb retransmissions, but do not create transaction + t_check_trans(); + + if ( !(is_method("REGISTER") ) ) { + + if (is_myself("$fd")) { + + } else { + # if caller is not local, then called number must be local + + if (!is_myself("$rd")) { + send_reply(403,"Relay Forbidden"); + exit; + } + } + + } + + # preloaded route checking + if (loose_route()) { + xlog("L_ERR", + "Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]"); + if (!is_method("ACK")) + send_reply(403, "Preload Route denied"); + exit; + } + + # record routing + if (!is_method("REGISTER|MESSAGE")) + record_route(); + + if (!is_myself("$rd")) { + append_hf("P-hint: outbound\r\n"); + + route(relay); + } + + # requests for my domain + + if (is_method("PUBLISH|SUBSCRIBE")) { + send_reply(503, "Service Unavailable"); + exit; + } + + if (is_method("REGISTER")) { + + if (!save("location")) + sl_reply_error(); + + exit; + } + + if ($rU==NULL) { + # request with no Username in RURI + send_reply(484,"Address Incomplete"); + exit; + } + + # do lookup with method filtering + if (!lookup("location","m")) { + t_reply(404, "Not Found"); + exit; + } + + # check auth with CGRateS + $cgr_opt(GetMaxUsage) = 1; # also retrieve the max usage + $cgr_opt(GetAttributes) = 1; + $cgr_opt(GetSuppliers) = 1; + $cgr_opt(AuthorizeResources) = 1; + $cgr_opt(AllocateResources) = 1; + $cgr_opt(ReleaseResources) = 1; + $cgr_opt(ProcessThresholds) = 1; + $cgr_opt(ProcessStatQueues) = 1; + $cgr(RequestType) = "*prepaid"; + $cgr(OriginHost) = "127.0.0.1"; + $cgr(Source) = "OpenSIPS"; + + if (!async(cgrates_auth("$fU", "$rU"), resume_cgr_auth)) { + sl_send_reply(503, "Service Unavailable"); + exit; + } +} + +route [resume_cgr_auth] { + if ($rc != 1) { + xlog("Call not authorized: code=$cgrret!\n"); + send_reply(403, "Forbidden"); + exit; + } + $var(idx) = 0; + while ($(cgr_ret(AttributesDigest){s.select,$var(idx),,}) != NULL) { + $avp($(cgr_ret(AttributesDigest){s.select,$var(idx),,}{s.select,0,:})) + = $(cgr_ret(AttributesDigest){s.select,$var(idx),,}{s.select,1,:}); + $var(idx) = $var(idx) + 1; + } + cgrates_acc("cdr|missed", "$fU", "$rU"); + xlog("### Have authorized the call and it should go through"); + route(relay); +} + + +route[relay] { + # for INVITEs enable some additional helper routes + if (is_method("INVITE")) { + t_on_branch("per_branch_ops"); + t_on_reply("handle_nat"); + t_on_failure("missed_call"); + } + + if (!t_relay()) { + send_reply(500,"Internal Error"); + } + exit; +} + + + + +branch_route[per_branch_ops] { + xlog("new branch at $ru\n"); +} + + +onreply_route[handle_nat] { + xlog("incoming reply\n"); +} + + +failure_route[missed_call] { + if (t_was_cancelled()) { + exit; + } +} diff --git a/general_tests/tutorial_calls_test.go b/general_tests/tutorial_calls_test.go index 00480f764..edcc9b757 100755 --- a/general_tests/tutorial_calls_test.go +++ b/general_tests/tutorial_calls_test.go @@ -42,10 +42,10 @@ var tutorialCallsRpc *rpc.Client var tutorialCallsPjSuaListener *os.File var waitRater = flag.Int("wait_rater", 1000, "Number of miliseconds to wait for rater to start and cache") var dataDir = flag.String("data_dir", "/usr/share/cgrates", "CGR data dir path here") -var fsConfig = flag.String("fsConfig", "/usr/share/cgrates/tutorials/fs_evsock", "FreeSwitch tutorial folder") -var kamConfig = flag.String("kamConfig", "/usr/share/cgrates/tutorials/kamevapi", "Kamailio tutorial folder") -var oSipsConfig = flag.String("osConfig", "/usr/share/cgrates/tutorials/osips_native", "OpenSips tutorial folder") -var ariConf = flag.String("ariConf", "/usr/share/cgrates/tutorials/asterisk_ari", "Asterisk tutorial folder") +var fsConfig = flag.String("fsConfig", "/usr/share/cgrates/tutorials_test/fs_evsock", "FreeSwitch tutorial folder") +var kamConfig = flag.String("kamConfig", "/usr/share/cgrates/tutorials_test/kamevapi", "Kamailio tutorial folder") +var oSipsConfig = flag.String("osConfig", "/usr/share/cgrates/tutorials_test/osips", "OpenSips tutorial folder") +var ariConf = flag.String("ariConf", "/usr/share/cgrates/tutorials_test/asterisk_ari", "Asterisk tutorial folder") var optConf string var sTestsCalls = []func(t *testing.T){