mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-11 07:13:20 +00:00
Merged revisions 53810 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r53810 | russell | 2007-02-09 18:35:09 -0600 (Fri, 09 Feb 2007) | 24 lines Merge team/russell/sla_rewrite This is a completely new implementation of the SLA functionality introduced in Asterisk 1.4. It is now functional and ready for testing. However, I will be adding some additional features over the next week, as well. For information on how to set this up, see configs/sla.conf.sample and doc/sla.txt. In addition to the changes in app_meetme.c for the SLA implementation itself, this merge brings in various other changes: chan_sip: - Add the ability to indicate HOLD state in NOTIFY messages. - Queue HOLD and UNHOLD control frames even if the channel is not bridged to another channel. linkedlists.h: - Add support for rwlock based linked lists. dial.c: - Add the ability to run ast_dial_start() without a reference channel to inherit information from. ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@53817 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
1736
apps/app_meetme.c
1736
apps/app_meetme.c
File diff suppressed because it is too large
Load Diff
@@ -4818,7 +4818,6 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
|
|||||||
int iterator;
|
int iterator;
|
||||||
int sendonly = 0;
|
int sendonly = 0;
|
||||||
int numberofports;
|
int numberofports;
|
||||||
struct ast_channel *bridgepeer = NULL;
|
|
||||||
struct ast_rtp *newaudiortp, *newvideortp; /* Buffers for codec handling */
|
struct ast_rtp *newaudiortp, *newvideortp; /* Buffers for codec handling */
|
||||||
int newjointcapability; /* Negotiated capability */
|
int newjointcapability; /* Negotiated capability */
|
||||||
int newpeercapability;
|
int newpeercapability;
|
||||||
@@ -5309,13 +5308,13 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
|
|||||||
ast_set_write_format(p->owner, p->owner->writeformat);
|
ast_set_write_format(p->owner, p->owner->writeformat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Turn on/off music on hold if we are holding/unholding */
|
|
||||||
if ((bridgepeer = ast_bridged_channel(p->owner))) {
|
|
||||||
if (sin.sin_addr.s_addr && !sendonly) {
|
if (sin.sin_addr.s_addr && !sendonly) {
|
||||||
|
ast_log(LOG_DEBUG, "Queueing UNHOLD!\n");
|
||||||
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
|
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
|
||||||
/* Activate a re-invite */
|
/* Activate a re-invite */
|
||||||
ast_queue_frame(p->owner, &ast_null_frame);
|
ast_queue_frame(p->owner, &ast_null_frame);
|
||||||
} else if (!sin.sin_addr.s_addr || sendonly) {
|
} else if (!sin.sin_addr.s_addr || sendonly) {
|
||||||
|
ast_log(LOG_DEBUG, "Going on HOLD!\n");
|
||||||
ast_queue_control_data(p->owner, AST_CONTROL_HOLD,
|
ast_queue_control_data(p->owner, AST_CONTROL_HOLD,
|
||||||
S_OR(p->mohsuggest, NULL),
|
S_OR(p->mohsuggest, NULL),
|
||||||
!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
|
!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
|
||||||
@@ -5325,7 +5324,6 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
|
|||||||
/* Activate a re-invite */
|
/* Activate a re-invite */
|
||||||
ast_queue_frame(p->owner, &ast_null_frame);
|
ast_queue_frame(p->owner, &ast_null_frame);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Manager Hold and Unhold events must be generated, if necessary */
|
/* Manager Hold and Unhold events must be generated, if necessary */
|
||||||
if (sin.sin_addr.s_addr && !sendonly) {
|
if (sin.sin_addr.s_addr && !sendonly) {
|
||||||
|
@@ -1,26 +1,82 @@
|
|||||||
; Configuration file for SLAs (Shared Line Appearances).
|
|
||||||
|
|
||||||
; Defining a SLA uses the following syntax:
|
|
||||||
;
|
;
|
||||||
; type => Technology/TechData
|
; Configuration for Shared Line Appearances (SLA).
|
||||||
;
|
|
||||||
; type => trunk or station
|
|
||||||
; Technology => the channel driver (see show channeltypes)
|
|
||||||
; TechData => the data specific to the channel driver
|
|
||||||
;
|
|
||||||
; The Technology/TechData information is the same as that provided to the
|
|
||||||
; Dial application.
|
|
||||||
;
|
;
|
||||||
|
|
||||||
; define a SLA called junky
|
; ---- General Options ----------------
|
||||||
[junky]
|
[general]
|
||||||
trunk => SIP/10
|
; There are none!
|
||||||
station => SIP/15
|
|
||||||
station => SIP/16
|
|
||||||
|
|
||||||
;define a SLA called markster
|
; -------------------------------------
|
||||||
[markster]
|
|
||||||
trunk => Zap/1
|
|
||||||
station => SIP/20
|
; ---- Trunk Declarations -------------
|
||||||
|
|
||||||
|
; Provide a name for this trunk.
|
||||||
|
[line1]
|
||||||
|
; This line is what marks this entry as a trunk.
|
||||||
|
type=trunk
|
||||||
|
; Map this trunk declaration to a specific device.
|
||||||
|
; NOTE: At this point, this *must* be a zap channel!
|
||||||
|
device=Zap/3
|
||||||
|
; This supports automatic generation of the dialplan entries if the autocontext
|
||||||
|
; option is used. Each trunk should have a unique context name. Then, in
|
||||||
|
; zapata.conf, this device should be configured to have incoming calls go to
|
||||||
|
; this context.
|
||||||
|
autocontext=line1
|
||||||
|
|
||||||
|
[line2]
|
||||||
|
type=trunk
|
||||||
|
device=Zap/4
|
||||||
|
autocontext=line2
|
||||||
|
|
||||||
|
[line3]
|
||||||
|
type=trunk
|
||||||
|
device=Zap/3
|
||||||
|
autocontext=line3
|
||||||
|
|
||||||
|
[line4]
|
||||||
|
type=trunk
|
||||||
|
device=Zap/4
|
||||||
|
autocontext=line4
|
||||||
|
; --------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
; ---- Station Declarations ------------
|
||||||
|
|
||||||
|
; In this example, all stations have the same trunks, so this configuration
|
||||||
|
; template is used to simplify the declaration of each station.
|
||||||
|
[station](!)
|
||||||
|
; This line indicates that this entry is a station.
|
||||||
|
type=station
|
||||||
|
; This supports automatic generation of the dialplan entries if the autocontext
|
||||||
|
; option is used. All stations can use the same context without conflict. The
|
||||||
|
; device for this station should have its context configured to the same one
|
||||||
|
; listed here.
|
||||||
|
autocontext=sla_stations
|
||||||
|
; Individually list all of the trunks that will appear on this station. This
|
||||||
|
; order is significant. It should be the same order as they appear on the
|
||||||
|
; phone. The order here defines the order of preference that the trunks will
|
||||||
|
; be used.
|
||||||
|
trunk=line1
|
||||||
|
trunk=line2
|
||||||
|
trunk=line3
|
||||||
|
trunk=line4
|
||||||
|
|
||||||
|
; Define a station that uses the configuration from the template "station".
|
||||||
|
[station1](station)
|
||||||
|
; Each station must be mapped to a device.
|
||||||
|
device=SIP/station1
|
||||||
|
|
||||||
|
[station2](station)
|
||||||
|
device=SIP/station2
|
||||||
|
|
||||||
|
[station3](station)
|
||||||
|
device=SIP/station3
|
||||||
|
|
||||||
|
[station4](station)
|
||||||
|
device=SIP/station4
|
||||||
|
|
||||||
|
[station5](station)
|
||||||
|
device=SIP/station5
|
||||||
|
; --------------------------------------
|
||||||
|
|
||||||
; Also you can see SLA infos via the CLI, by typing "sla show"
|
|
||||||
|
93
doc/sla.txt
Normal file
93
doc/sla.txt
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
-------------------------------------------------------------
|
||||||
|
--- Shared Line Appearances ---------------------------------
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
-------------------------------------------------------------
|
||||||
|
INTRODUCTION
|
||||||
|
|
||||||
|
The "SLA" functionality in Asterisk is intended to allow a setup that emulates
|
||||||
|
a simple key system. It uses the various abstraction layers already built into
|
||||||
|
Asterisk to emulate key system functionality across various devices, including
|
||||||
|
IP channels.
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
-------------------------------------------------------------
|
||||||
|
DIALPLAN CONFIGURATION
|
||||||
|
|
||||||
|
The SLA implementation can automatically generate the dialplan necessary for
|
||||||
|
basic operation if the "autocontext" option is set for trunks and stations in
|
||||||
|
sla.conf. However, for reference, here is an automatically generated dialplan
|
||||||
|
to help with custom building of the dialplan to include other features, such as
|
||||||
|
voicemail:
|
||||||
|
|
||||||
|
[line1]
|
||||||
|
exten => s,1,SLATrunk(line1)
|
||||||
|
|
||||||
|
[line2]
|
||||||
|
exten => s,2,SLATRUNK(line2)
|
||||||
|
|
||||||
|
[sla_stations]
|
||||||
|
exten => station1,1,SLAStation(station1)
|
||||||
|
exten => station1_line1,hint,SLA:station1_line1
|
||||||
|
exten => station1_line1,1,SLAStation(station1_line1)
|
||||||
|
exten => station1_line2,hint,SLA:station1_line2
|
||||||
|
exten => station1_line2,1,SLAStation(station1_line2)
|
||||||
|
|
||||||
|
exten => station2,1,SLAStation(station2)
|
||||||
|
exten => station2_line1,hint,SLA:station2_line1
|
||||||
|
exten => station2_line1,1,SLAStation(station2_line1)
|
||||||
|
exten => station2_line2,hint,SLA:station2_line2
|
||||||
|
exten => station2_line2,1,SLAStation(station2_line2)
|
||||||
|
|
||||||
|
exten => station3,1,SLAStation(station3)
|
||||||
|
exten => station3_line1,hint,SLA:station3_line1
|
||||||
|
exten => station3_line1,1,SLAStation(station3_line1)
|
||||||
|
exten => station3_line2,hint,SLA:station3_line2
|
||||||
|
exten => station3_line2,1,SLAStation(station3_line2)
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
-------------------------------------------------------------
|
||||||
|
TRUNKS
|
||||||
|
|
||||||
|
For the trunk side of SLA, the only channels that are currently supported are
|
||||||
|
Zap channels. Support for IP trunks is planned, but not yet implemented.
|
||||||
|
|
||||||
|
Be sure to configure the trunk's context to be the same one that is set for the
|
||||||
|
"autocontext" option in sla.conf if automatic dialplan configuration is used.
|
||||||
|
|
||||||
|
If the dialplan is being built manually, ensure that calls coming in on a trunk
|
||||||
|
execute the SLATrunk() application with an argument of the trunk name.
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------
|
||||||
|
STATIONS
|
||||||
|
|
||||||
|
Currently, the only channel driver that has all of the features necessary to
|
||||||
|
support an SLA environment is chan_sip. Here are some hints on configuring
|
||||||
|
a SIP phone for use with SLA:
|
||||||
|
|
||||||
|
1) Add the SIP channel as a [station] in sla.conf.
|
||||||
|
|
||||||
|
2) Configure the phone in sip.conf. If automatic dialplan configuration was
|
||||||
|
used by enabling the "autocontext" option in sla.conf, then this entry in
|
||||||
|
sip.conf should have the same context setting.
|
||||||
|
|
||||||
|
3) On the phone itself, there are various things that must be configured to
|
||||||
|
make everything work correctly:
|
||||||
|
|
||||||
|
Let's say this phone is called "station1" in sla.conf, and it uses trunks
|
||||||
|
named "line1" and line2".
|
||||||
|
|
||||||
|
a) Two line buttons must be configured to subscribe to the state of the
|
||||||
|
following extensions:
|
||||||
|
- station1_line1
|
||||||
|
- station1_line2
|
||||||
|
|
||||||
|
b) The line appearance buttons should be configured to dial the extensions
|
||||||
|
that they are subscribed to when they are pressed.
|
||||||
|
|
||||||
|
c) If you would like the phone to automatically connect to a trunk when it
|
||||||
|
is taken off hook, then the phone should be automatically configured to
|
||||||
|
dial "station1" when it is taken off hook.
|
||||||
|
-------------------------------------------------------------
|
@@ -308,6 +308,9 @@ struct ast_app_option {
|
|||||||
unsigned int arg_index;
|
unsigned int arg_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BEGIN_OPTIONS {
|
||||||
|
#define END_OPTIONS }
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Declares an array of options for an application.
|
\brief Declares an array of options for an application.
|
||||||
\param holder The name of the array to be created
|
\param holder The name of the array to be created
|
||||||
|
@@ -42,7 +42,7 @@ enum ast_dial_option {
|
|||||||
|
|
||||||
/*! \brief List of return codes for dial run API calls */
|
/*! \brief List of return codes for dial run API calls */
|
||||||
enum ast_dial_result {
|
enum ast_dial_result {
|
||||||
AST_DIAL_RESULT_INVALID = 0, /*!< Invalid options were passed to run function */
|
AST_DIAL_RESULT_INVALID, /*!< Invalid options were passed to run function */
|
||||||
AST_DIAL_RESULT_FAILED, /*!< Attempts to dial failed before reaching critical state */
|
AST_DIAL_RESULT_FAILED, /*!< Attempts to dial failed before reaching critical state */
|
||||||
AST_DIAL_RESULT_TRYING, /*!< Currently trying to dial */
|
AST_DIAL_RESULT_TRYING, /*!< Currently trying to dial */
|
||||||
AST_DIAL_RESULT_RINGING, /*!< Dial is presently ringing */
|
AST_DIAL_RESULT_RINGING, /*!< Dial is presently ringing */
|
||||||
|
@@ -553,5 +553,8 @@ int _ast_vasprintf(char **ret, const char *file, int lineno, const char *func, c
|
|||||||
*/
|
*/
|
||||||
void ast_enable_packet_fragmentation(int sock);
|
void ast_enable_packet_fragmentation(int sock);
|
||||||
|
|
||||||
|
#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
|
||||||
|
|
||||||
#include "asterisk/strings.h"
|
#include "asterisk/strings.h"
|
||||||
|
|
||||||
#endif /* _ASTERISK_UTILS_H */
|
#endif /* _ASTERISK_UTILS_H */
|
||||||
|
15
main/dial.c
15
main/dial.c
@@ -228,14 +228,17 @@ static int begin_dial(struct ast_dial *dial, struct ast_channel *chan)
|
|||||||
ast_copy_string(numsubst, channel->device, sizeof(numsubst));
|
ast_copy_string(numsubst, channel->device, sizeof(numsubst));
|
||||||
|
|
||||||
/* Request that the channel be created */
|
/* Request that the channel be created */
|
||||||
if (!(channel->owner = ast_request(channel->tech, chan->nativeformats, numsubst, &channel->cause)))
|
if (!(channel->owner = ast_request(channel->tech,
|
||||||
|
chan ? chan->nativeformats : AST_FORMAT_AUDIO_MASK, numsubst, &channel->cause))) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
channel->owner->appl = "AppDial2";
|
channel->owner->appl = "AppDial2";
|
||||||
channel->owner->data = "(Outgoing Line)";
|
channel->owner->data = "(Outgoing Line)";
|
||||||
channel->owner->whentohangup = 0;
|
channel->owner->whentohangup = 0;
|
||||||
|
|
||||||
/* Inherit everything from he who spawned this Dial */
|
/* Inherit everything from he who spawned this Dial */
|
||||||
|
if (chan) {
|
||||||
ast_channel_inherit_variables(chan, channel->owner);
|
ast_channel_inherit_variables(chan, channel->owner);
|
||||||
|
|
||||||
/* Copy over callerid information */
|
/* Copy over callerid information */
|
||||||
@@ -255,6 +258,7 @@ static int begin_dial(struct ast_dial *dial, struct ast_channel *chan)
|
|||||||
channel->owner->cid.cid_tns = chan->cid.cid_tns;
|
channel->owner->cid.cid_tns = chan->cid.cid_tns;
|
||||||
channel->owner->adsicpe = chan->adsicpe;
|
channel->owner->adsicpe = chan->adsicpe;
|
||||||
channel->owner->transfercapability = chan->transfercapability;
|
channel->owner->transfercapability = chan->transfercapability;
|
||||||
|
}
|
||||||
|
|
||||||
/* Actually call the device */
|
/* Actually call the device */
|
||||||
if ((res = ast_call(channel->owner, numsubst, 0))) {
|
if ((res = ast_call(channel->owner, numsubst, 0))) {
|
||||||
@@ -530,12 +534,16 @@ enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *cha
|
|||||||
enum ast_dial_result res = AST_DIAL_RESULT_TRYING;
|
enum ast_dial_result res = AST_DIAL_RESULT_TRYING;
|
||||||
|
|
||||||
/* Ensure required arguments are passed */
|
/* Ensure required arguments are passed */
|
||||||
if (!dial || !chan)
|
if (!dial || (!chan && !async)) {
|
||||||
|
ast_log(LOG_DEBUG, "invalid #1\n");
|
||||||
return AST_DIAL_RESULT_INVALID;
|
return AST_DIAL_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
/* If there are no channels to dial we can't very well try to dial them */
|
/* If there are no channels to dial we can't very well try to dial them */
|
||||||
if (AST_LIST_EMPTY(&dial->channels))
|
if (AST_LIST_EMPTY(&dial->channels)) {
|
||||||
|
ast_log(LOG_DEBUG, "invalid #2\n");
|
||||||
return AST_DIAL_RESULT_INVALID;
|
return AST_DIAL_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
/* Dial each requested channel */
|
/* Dial each requested channel */
|
||||||
if (!begin_dial(dial, chan))
|
if (!begin_dial(dial, chan))
|
||||||
@@ -543,6 +551,7 @@ enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *cha
|
|||||||
|
|
||||||
/* If we are running async spawn a thread and send it away... otherwise block here */
|
/* If we are running async spawn a thread and send it away... otherwise block here */
|
||||||
if (async) {
|
if (async) {
|
||||||
|
dial->status = AST_DIAL_RESULT_TRYING;
|
||||||
/* Try to create a thread */
|
/* Try to create a thread */
|
||||||
if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) {
|
if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) {
|
||||||
/* Failed to create the thread - hangup all dialed channels and return failed */
|
/* Failed to create the thread - hangup all dialed channels and return failed */
|
||||||
|
Reference in New Issue
Block a user