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: http://svn.digium.com/svn/asterisk/trunk@53817 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
0fbac396a5
commit
be94f38009
1842
apps/app_meetme.c
1842
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 sendonly = 0;
|
||||
int numberofports;
|
||||
struct ast_channel *bridgepeer = NULL;
|
||||
struct ast_rtp *newaudiortp, *newvideortp; /* Buffers for codec handling */
|
||||
int newjointcapability; /* Negotiated capability */
|
||||
int newpeercapability;
|
||||
|
@ -5309,22 +5308,21 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
|
|||
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) {
|
||||
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
|
||||
/* Activate a re-invite */
|
||||
ast_queue_frame(p->owner, &ast_null_frame);
|
||||
} else if (!sin.sin_addr.s_addr || sendonly) {
|
||||
ast_queue_control_data(p->owner, AST_CONTROL_HOLD,
|
||||
S_OR(p->mohsuggest, NULL),
|
||||
!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
|
||||
if (sendonly)
|
||||
ast_rtp_stop(p->rtp);
|
||||
/* RTCP needs to go ahead, even if we're on hold!!! */
|
||||
/* Activate a re-invite */
|
||||
ast_queue_frame(p->owner, &ast_null_frame);
|
||||
}
|
||||
if (sin.sin_addr.s_addr && !sendonly) {
|
||||
ast_log(LOG_DEBUG, "Queueing UNHOLD!\n");
|
||||
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
|
||||
/* Activate a re-invite */
|
||||
ast_queue_frame(p->owner, &ast_null_frame);
|
||||
} 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,
|
||||
S_OR(p->mohsuggest, NULL),
|
||||
!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
|
||||
if (sendonly)
|
||||
ast_rtp_stop(p->rtp);
|
||||
/* RTCP needs to go ahead, even if we're on hold!!! */
|
||||
/* Activate a re-invite */
|
||||
ast_queue_frame(p->owner, &ast_null_frame);
|
||||
}
|
||||
|
||||
/* Manager Hold and Unhold events must be generated, if necessary */
|
||||
|
|
|
@ -1,26 +1,82 @@
|
|||
; Configuration file for SLAs (Shared Line Appearances).
|
||||
|
||||
; Defining a SLA uses the following syntax:
|
||||
;
|
||||
; type => Technology/TechData
|
||||
;
|
||||
; 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.
|
||||
; Configuration for Shared Line Appearances (SLA).
|
||||
;
|
||||
|
||||
; define a SLA called junky
|
||||
[junky]
|
||||
trunk => SIP/10
|
||||
station => SIP/15
|
||||
station => SIP/16
|
||||
; ---- General Options ----------------
|
||||
[general]
|
||||
; There are none!
|
||||
|
||||
;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"
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
#define BEGIN_OPTIONS {
|
||||
#define END_OPTIONS }
|
||||
|
||||
/*!
|
||||
\brief Declares an array of options for an application.
|
||||
\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 */
|
||||
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_TRYING, /*!< Currently trying to dial */
|
||||
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);
|
||||
|
||||
#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
#include "asterisk/strings.h"
|
||||
|
||||
#endif /* _ASTERISK_UTILS_H */
|
||||
|
|
51
main/dial.c
51
main/dial.c
|
@ -228,33 +228,37 @@ static int begin_dial(struct ast_dial *dial, struct ast_channel *chan)
|
|||
ast_copy_string(numsubst, channel->device, sizeof(numsubst));
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
channel->owner->appl = "AppDial2";
|
||||
channel->owner->data = "(Outgoing Line)";
|
||||
channel->owner->whentohangup = 0;
|
||||
|
||||
/* Inherit everything from he who spawned this Dial */
|
||||
ast_channel_inherit_variables(chan, channel->owner);
|
||||
if (chan) {
|
||||
ast_channel_inherit_variables(chan, channel->owner);
|
||||
|
||||
/* Copy over callerid information */
|
||||
S_REPLACE(channel->owner->cid.cid_num, ast_strdup(chan->cid.cid_num));
|
||||
S_REPLACE(channel->owner->cid.cid_name, ast_strdup(chan->cid.cid_name));
|
||||
S_REPLACE(channel->owner->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
|
||||
S_REPLACE(channel->owner->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
|
||||
|
||||
ast_string_field_set(channel->owner, language, chan->language);
|
||||
ast_string_field_set(channel->owner, accountcode, chan->accountcode);
|
||||
channel->owner->cdrflags = chan->cdrflags;
|
||||
if (ast_strlen_zero(channel->owner->musicclass))
|
||||
ast_string_field_set(channel->owner, musicclass, chan->musicclass);
|
||||
|
||||
channel->owner->cid.cid_pres = chan->cid.cid_pres;
|
||||
channel->owner->cid.cid_ton = chan->cid.cid_ton;
|
||||
channel->owner->cid.cid_tns = chan->cid.cid_tns;
|
||||
channel->owner->adsicpe = chan->adsicpe;
|
||||
channel->owner->transfercapability = chan->transfercapability;
|
||||
/* Copy over callerid information */
|
||||
S_REPLACE(channel->owner->cid.cid_num, ast_strdup(chan->cid.cid_num));
|
||||
S_REPLACE(channel->owner->cid.cid_name, ast_strdup(chan->cid.cid_name));
|
||||
S_REPLACE(channel->owner->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
|
||||
S_REPLACE(channel->owner->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
|
||||
|
||||
ast_string_field_set(channel->owner, language, chan->language);
|
||||
ast_string_field_set(channel->owner, accountcode, chan->accountcode);
|
||||
channel->owner->cdrflags = chan->cdrflags;
|
||||
if (ast_strlen_zero(channel->owner->musicclass))
|
||||
ast_string_field_set(channel->owner, musicclass, chan->musicclass);
|
||||
|
||||
channel->owner->cid.cid_pres = chan->cid.cid_pres;
|
||||
channel->owner->cid.cid_ton = chan->cid.cid_ton;
|
||||
channel->owner->cid.cid_tns = chan->cid.cid_tns;
|
||||
channel->owner->adsicpe = chan->adsicpe;
|
||||
channel->owner->transfercapability = chan->transfercapability;
|
||||
}
|
||||
|
||||
/* Actually call the device */
|
||||
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;
|
||||
|
||||
/* Ensure required arguments are passed */
|
||||
if (!dial || !chan)
|
||||
if (!dial || (!chan && !async)) {
|
||||
ast_log(LOG_DEBUG, "invalid #1\n");
|
||||
return AST_DIAL_RESULT_INVALID;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Dial each requested channel */
|
||||
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 (async) {
|
||||
dial->status = AST_DIAL_RESULT_TRYING;
|
||||
/* Try to create a thread */
|
||||
if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) {
|
||||
/* Failed to create the thread - hangup all dialed channels and return failed */
|
||||
|
|
Reference in New Issue