mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 10:06:24 +05:00
Added SIP redirect example
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,6 +12,7 @@ dean*
|
|||||||
data/vagrant/.vagrant
|
data/vagrant/.vagrant
|
||||||
data/vagrant/vagrant_ansible_inventory_default
|
data/vagrant/vagrant_ansible_inventory_default
|
||||||
data/tutorials/fs_evsock/freeswitch/etc/freeswitch/
|
data/tutorials/fs_evsock/freeswitch/etc/freeswitch/
|
||||||
|
data/tutorials/sip_redirect/freeswitch/etc/freeswitch/
|
||||||
data/tutorial_tests/fs_evsock/freeswitch/etc/freeswitch/
|
data/tutorial_tests/fs_evsock/freeswitch/etc/freeswitch/
|
||||||
vendor
|
vendor
|
||||||
*.test
|
*.test
|
||||||
|
|||||||
@@ -119,6 +119,9 @@ func (sa *SIPAgent) serveUDP(stop chan struct{}) (err error) {
|
|||||||
wg.Done()
|
wg.Done()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if "ACK" == sipMessage.MethodFrom("Request") {
|
||||||
|
return
|
||||||
|
}
|
||||||
var sipAnswer sipingo.Message
|
var sipAnswer sipingo.Message
|
||||||
var err error
|
var err error
|
||||||
if sipAnswer, err = sa.handleMessage(sipMessage, saddr.String()); err != nil {
|
if sipAnswer, err = sa.handleMessage(sipMessage, saddr.String()); err != nil {
|
||||||
@@ -204,6 +207,9 @@ func (sa *SIPAgent) serveTCP(stop chan struct{}) (err error) {
|
|||||||
wg.Done()
|
wg.Done()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if "ACK" == sipMessage.MethodFrom("Request") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
var sipAnswer sipingo.Message
|
var sipAnswer sipingo.Message
|
||||||
if sipAnswer, err = sa.handleMessage(sipMessage, conn.LocalAddr().String()); err != nil {
|
if sipAnswer, err = sa.handleMessage(sipMessage, conn.LocalAddr().String()); err != nil {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
#Tenant,Account,ActionPlanId,ActionTriggersId,AllowNegative,Disabled
|
#Tenant,Account,ActionPlanId,ActionTriggersId,AllowNegative,Disabled
|
||||||
cgrates.org,1001,AP_PACKAGE_10,,,
|
cgrates.org,1001,AP_PACKAGE_10,,,
|
||||||
|
cgrates.org,1002,AP_PACKAGE_10,,,
|
||||||
|
5
data/tariffplans/sipagent/Chargers.csv
Normal file
5
data/tariffplans/sipagent/Chargers.csv
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#Tenant,ID,FilterIDs,ActivationInterval,RunID,AttributeIDs,Weight
|
||||||
|
cgrates.org,DEFAULT,,,*default,*none,0
|
||||||
|
cgrates.org,route1,,,*raw,*constant:*req.RequestType:*none;*constant:*req.Destination:1003,0
|
||||||
|
cgrates.org,route2,,,*raw,*constant:*req.RequestType:*none;*constant:*req.Destination:1004,0
|
||||||
|
cgrates.org,route3,,,*raw,*constant:*req.RequestType:*none;*constant:*req.Destination:1005,0
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
#Tenant,ID,FilterIDs,ActivationInterval,Sorting,SortingParameters,RouteID,RouteFilterIDs,RouteAccountIDs,RouteRatingPlanIDs,RouteResourceIDs,RouteStatIDs,RouteWeight,RouteBlocker,RouteParameters,Weight
|
#Tenant,ID,FilterIDs,ActivationInterval,Sorting,SortingParameters,RouteID,RouteFilterIDs,RouteAccountIDs,RouteRatingPlanIDs,RouteResourceIDs,RouteStatIDs,RouteWeight,RouteBlocker,RouteParameters,Weight
|
||||||
cgrates.org,SPL_ACNT_1001,*string:~*req.Account:1001,2017-11-27T00:00:00Z,*weight,,supplier1,,1001,RP_10CNT,,,20,,cgrates.org,20
|
cgrates.org,SPL_ACNT_1001,*string:~*req.Account:1001,2017-11-27T00:00:00Z,*weight,,route1,,1001,RP_10CNT,,,20,,cgrates.org,20
|
||||||
cgrates.org,SPL_ACNT_1001,,,,,supplier2,,1001,RP_20CNT,,,10,,cgrates.net,10
|
cgrates.org,SPL_ACNT_1001,,,,,route2,,1001,RP_20CNT,,,10,,cgrates.net,10
|
||||||
cgrates.org,SPL_ACNT_1001,,,,,supplier3,,1001,RP_1CNT,,,5,,cgrates.com,5
|
cgrates.org,SPL_ACNT_1001,,,,,route3,,1001,RP_1CNT,,,5,,cgrates.com,5
|
||||||
|
cgrates.org,SPL_ACNT_1002,*string:~*req.Account:1002,2017-11-27T00:00:00Z,*weight,,route1,,1002,RP_10CNT,,,20,,1003@192.168.56.203,20
|
||||||
|
cgrates.org,SPL_ACNT_1002,,,,,route2,,1002,RP_20CNT,,,10,,1004@192.168.57.203,10
|
||||||
|
cgrates.org,SPL_ACNT_1002,,,,,route3,,1002,RP_1CNT,,,5,,1005@192.168.58.203,5
|
||||||
|
|||||||
|
18
data/tutorials/sip_redirect/README.md
Normal file
18
data/tutorials/sip_redirect/README.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
Tutorial SIP Redirect
|
||||||
|
================
|
||||||
|
|
||||||
|
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 a redirect for the destinatin 1001 to the CGRateS SIPAgent that will populate the Contact header and add X-Identity header
|
||||||
|
|
||||||
|
- **CGRateS** with following components:
|
||||||
|
|
||||||
|
- RALs to calculate the maxusage
|
||||||
|
- RouteS to get the rounting information
|
||||||
|
- ChargerS to change the destination for each route
|
||||||
|
- SIPAgent to comunicate with FreeSWITCH
|
||||||
|
- SessionS to comunicate with the agent
|
||||||
105
data/tutorials/sip_redirect/cgrates/etc/cgrates/cgrates.json
Normal file
105
data/tutorials/sip_redirect/cgrates/etc/cgrates/cgrates.json
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
// Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||||
|
// Copyright (C) ITsysCOM GmbH
|
||||||
|
|
||||||
|
"general": {
|
||||||
|
"log_level": 7,
|
||||||
|
"node_id":"CGRSIP",
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"listen": {
|
||||||
|
"rpc_json": ":2012",
|
||||||
|
"rpc_gob": ":2013",
|
||||||
|
"http": ":2080",
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"stor_db": {
|
||||||
|
"db_password": "CGRateS.org",
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"schedulers": {
|
||||||
|
"enabled": true,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"rals": {
|
||||||
|
"enabled": true,
|
||||||
|
"thresholds_conns": ["*localhost"],
|
||||||
|
"stats_conns": ["*localhost"],
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"cdrs": {
|
||||||
|
"enabled": true,
|
||||||
|
"stats_conns": ["*localhost"],
|
||||||
|
"chargers_conns": ["*internal"],
|
||||||
|
"rals_conns": ["*localhost"],
|
||||||
|
"sessions_cost_retries": 5,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"chargers": {
|
||||||
|
"enabled": true,
|
||||||
|
"attributes_conns": ["*internal"],
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"sessions": {
|
||||||
|
"enabled": true,
|
||||||
|
"rals_conns": ["*localhost"],
|
||||||
|
"cdrs_conns": ["*localhost"],
|
||||||
|
"resources_conns": ["*localhost"],
|
||||||
|
"routes_conns": ["*localhost"],
|
||||||
|
"attributes_conns": ["*localhost"],
|
||||||
|
"stats_conns": ["*localhost"],
|
||||||
|
"thresholds_conns": ["*localhost"],
|
||||||
|
"chargers_conns": ["*internal"],
|
||||||
|
"debit_interval": "5s",
|
||||||
|
"channel_sync_interval":"7s",
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"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"],
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"routes": {
|
||||||
|
"enabled": true,
|
||||||
|
"resources_conns": ["*internal"],
|
||||||
|
"stats_conns": ["*internal"],
|
||||||
|
"rals_conns": ["*internal"],
|
||||||
|
"string_indexed_fields": ["Account"],
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"apiers": {
|
||||||
|
"enabled": true,
|
||||||
|
"scheduler_conns": ["*internal"],
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
141
data/tutorials/sip_redirect/cgrates/etc/cgrates/redirect.json
Normal file
141
data/tutorials/sip_redirect/cgrates/etc/cgrates/redirect.json
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
"sip_agent": {
|
||||||
|
"enabled": true, // enables the SIP agent: <true|false>
|
||||||
|
"listen": "192.168.56.203:6060", // address where to listen for SIP requests <x.y.z.y:1234>
|
||||||
|
"listen_net": "udp", // network to listen on <udp|tcp|tcp-tls>
|
||||||
|
"request_processors": [
|
||||||
|
{
|
||||||
|
"id": "Register",
|
||||||
|
"filters": ["*notstring:~*vars.Method:INVITE"],
|
||||||
|
"flags": ["*none"],
|
||||||
|
"request_fields":[],
|
||||||
|
"reply_fields":[
|
||||||
|
{"tag": "Request", "path": "*rep.Request", "type": "*constant",
|
||||||
|
"value": "SIP/2.0 405 Method Not Allowed"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "RoutesQuery",
|
||||||
|
"filters": ["*string:~*vars.Method:INVITE"],
|
||||||
|
"flags": ["*event", "*routes","*stir_initiate","*continue"],
|
||||||
|
"request_fields":[
|
||||||
|
{"tag": "Account", "path": "*cgreq.Account", "type": "*variable",
|
||||||
|
"value": "~*req.From{*sipuri_user}", "mandatory": true},
|
||||||
|
{"tag": "Destination", "path": "*cgreq.Destination", "type": "*variable",
|
||||||
|
"value": "~*req.To{*sipuri_user}", "mandatory": true},
|
||||||
|
{"tag": "SetupTime", "path": "*cgreq.SetupTime", "type": "*variable",
|
||||||
|
"value": "*now", "mandatory": true},
|
||||||
|
{"tag": "Category", "path": "*cgreq.Category", "type": "*variable",
|
||||||
|
"value": "call", "mandatory": true},
|
||||||
|
{"tag": "STIRPublicKeyPath", "path": "*opts.STIRPublicKeyPath", "type": "*constant",
|
||||||
|
"value": "/usr/share/cgrates/stir/stir_pubkey.pem", "mandatory": true},
|
||||||
|
{"tag": "STIRPrivateKeyPath", "path": "*opts.STIRPrivateKeyPath", "type": "*constant",
|
||||||
|
"value": "/usr/share/cgrates/stir/stir_privatekey.pem", "mandatory": true},
|
||||||
|
],
|
||||||
|
"reply_fields":[
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "RoutesQueryOneRoute",
|
||||||
|
"filters": ["*string:~*vars.Method:INVITE",
|
||||||
|
"*gte:~*cgrep.Routes.Count:1",
|
||||||
|
],
|
||||||
|
"flags": ["*none","*continue"], // do not send request to CGRateS
|
||||||
|
"reply_fields":[
|
||||||
|
{"tag": "Request", "path": "*rep.Request", "type": "*constant",
|
||||||
|
"value": "SIP/2.0 302 Moved Temporarily"},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"\"1003\" <sip:"},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value": "~*cgrep.Routes.SortedRoutes[0].RouteParameters"},
|
||||||
|
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"*constant:;q=0.7; expires=3600;cgr_cost="},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"~*cgrep.Routes.SortedRoutes[0].SortingData.Cost"},
|
||||||
|
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"*constant:;cgr_maxusage="},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"~*cgrep.Routes.SortedRoutes[0].SortingData.MaxUsage"},
|
||||||
|
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"*constant:;cgr_route="},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"~*cgrep.Routes.SortedRoutes[0].RouteID"},
|
||||||
|
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"*constant:>"},
|
||||||
|
|
||||||
|
{"tag": "X-Identity", "path": "*rep.X-Identity", "type": "*variable",
|
||||||
|
"value":"~*cgrep.STIRIdentity[~*cgrep.Routes.SortedRoutes[0].RouteID]"},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": "RoutesQueryTwoRoute",
|
||||||
|
"filters": ["*string:~*vars.Method:INVITE",
|
||||||
|
"*gte:~*cgrep.Routes.Count:2",
|
||||||
|
],
|
||||||
|
"flags": ["*none","*continue"], // do not send request to CGRateS
|
||||||
|
"reply_fields":[
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":",\"1004\" <sip:"},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value": "~*cgrep.Routes.SortedRoutes[1].RouteParameters"},
|
||||||
|
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"*constant:;q=0.7; expires=3600;cgr_cost="},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"~*cgrep.Routes.SortedRoutes[1].SortingData.Cost"},
|
||||||
|
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"*constant:;cgr_maxusage="},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"~*cgrep.Routes.SortedRoutes[1].SortingData.MaxUsage"},
|
||||||
|
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"*constant:;cgr_route="},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"~*cgrep.Routes.SortedRoutes[1].RouteID"},
|
||||||
|
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"*constant:>"},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "RoutesQueryThreeRoute",
|
||||||
|
"filters": ["*string:~*vars.Method:INVITE",
|
||||||
|
"*gte:~*cgrep.Routes.Count:2",
|
||||||
|
],
|
||||||
|
"flags": ["*none","*continue"], // do not send request to CGRateS
|
||||||
|
"reply_fields":[
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":",\"1005\" <sip:"},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value": "~*cgrep.Routes.SortedRoutes[2].RouteParameters"},
|
||||||
|
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"*constant:;q=0.7; expires=3600;cgr_cost="},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"~*cgrep.Routes.SortedRoutes[2].SortingData.Cost"},
|
||||||
|
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"*constant:;cgr_maxusage="},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"~*cgrep.Routes.SortedRoutes[2].SortingData.MaxUsage"},
|
||||||
|
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"*constant:;cgr_route="},
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"~*cgrep.Routes.SortedRoutes[2].RouteID"},
|
||||||
|
|
||||||
|
{"tag": "Contact", "path": "*rep.Contact", "type": "*composed",
|
||||||
|
"value":"*constant:>"},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
184
data/tutorials/sip_redirect/cgrates/etc/init.d/cgrates
Executable file
184
data/tutorials/sip_redirect/cgrates/etc/init.d/cgrates
Executable file
@@ -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 <danb@cgrates.org>
|
||||||
|
#
|
||||||
|
# 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/sip_redirect/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
|
||||||
|
ERSINDIR=$TMP_DIR/ers/in
|
||||||
|
ERSOUTDIR=$TMP_DIR/ers/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 ers folder
|
||||||
|
if [ ! -d $ERSINDIR ]; then
|
||||||
|
mkdir -p $ERSINDIR
|
||||||
|
chown $USER:$GROUP $ERSINDIR
|
||||||
|
mkdir -p $ERSOUTDIR
|
||||||
|
chown $USER:$GROUP $ERSOUTDIR
|
||||||
|
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
|
||||||
|
|
||||||
|
:
|
||||||
Binary file not shown.
145
data/tutorials/sip_redirect/freeswitch/etc/init.d/freeswitch
Executable file
145
data/tutorials/sip_redirect/freeswitch/etc/init.d/freeswitch
Executable file
@@ -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 <tc@traviscross.com>
|
||||||
|
|
||||||
|
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||||
|
DESC=freeswitch
|
||||||
|
NAME=freeswitch
|
||||||
|
DAEMON=/usr/bin/freeswitch
|
||||||
|
USER=freeswitch
|
||||||
|
GROUP=freeswitch
|
||||||
|
TUTDIR=/usr/share/cgrates/tutorials/sip_redirect/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
|
||||||
Reference in New Issue
Block a user