summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
authorMatt O'Gorman <mogorman@digium.com>2006-09-18 23:32:57 +0000
committerMatt O'Gorman <mogorman@digium.com>2006-09-18 23:32:57 +0000
commit465adf2bf165ad6b27cd2659ad731ff1d24dfed5 (patch)
treed7fed805868cbb9500e7ddc7978cfa89bb93d52a /channels
parent9177d1143b295559497b46d08869e60f8ac9b887 (diff)
allow for packetization on rtp channel drivers, need to add
option for setting our own packetization as apposed to just doing what is asked. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@43243 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_sip.c103
-rw-r--r--channels/chan_skinny.c44
2 files changed, 116 insertions, 31 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 74c59822e..940653825 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -543,6 +543,8 @@ static int regobjs = 0; /*!< Registry objects */
static struct ast_flags global_flags[2] = {{0}}; /*!< global SIP_ flags */
+static int global_autoframing = 0;
+
/*! \brief Protect the SIP dialog list (of sip_pvt's) */
AST_MUTEX_DEFINE_STATIC(iflock);
@@ -966,6 +968,7 @@ static struct sip_pvt {
struct ast_variable *chanvars; /*!< Channel variables to set for inbound call */
struct sip_pvt *next; /*!< Next dialog in chain */
struct sip_invite_param *options; /*!< Options for INVITE */
+ int autoframing;
} *iflist = NULL;
#define FLAG_RESPONSE (1 << 0)
@@ -1015,6 +1018,7 @@ struct sip_user {
struct ast_ha *ha; /*!< ACL setting */
struct ast_variable *chanvars; /*!< Variables to set for channel created by user */
int maxcallbitrate; /*!< Maximum Bitrate for a video call */
+ int autoframing;
};
/*! \brief Structure for SIP peer data, we place calls to peers if registered or fixed IP address (host) */
@@ -1077,6 +1081,7 @@ struct sip_peer {
struct ast_variable *chanvars; /*!< Variables to set for channel created by user */
struct sip_pvt *mwipvt; /*!< Subscription for MWI */
int lastmsg;
+ int autoframing;
};
@@ -2541,6 +2546,11 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %s\n", natflags ? "On" : "Off");
ast_udptl_setnat(dialog->udptl, natflags);
}
+ /* Set Frame packetization */
+ if (dialog->rtp) {
+ ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs);
+ dialog->autoframing = peer->autoframing;
+ }
ast_string_field_set(dialog, peername, peer->username);
ast_string_field_set(dialog, authname, peer->username);
ast_string_field_set(dialog, username, peer->username);
@@ -4702,6 +4712,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
*/
/* XXX This needs to be done per media stream, since it's media stream specific */
iterator = req->sdp_start;
+ int found_rtpmap_codecs[32];
+ int last_rtpmap_codec=0;
while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */
if (option_debug > 1) {
@@ -4752,17 +4764,49 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
} else if (!strcasecmp(a, "sendrecv")) {
sendonly = 0;
continue;
- } else if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2)
+ } else if (strlen(a) > 5 && !strncasecmp(a, "ptime", 5)) {
+ char *tmp = strrchr(a, ':');
+ long int framing = 0;
+ if (tmp) {
+ tmp++;
+ framing = strtol(tmp, NULL, 10);
+ if (framing == LONG_MIN || framing == LONG_MAX) {
+ framing = 0;
+ ast_log(LOG_DEBUG, "Can't read framing from SDP: %s\n", a);
+ }
+ }
+ if (framing && last_rtpmap_codec) {
+ if (p->autoframing || global_autoframing) {
+ struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp);
+ int codec_n;
+ int format = 0;
+ for (codec_n = 0; codec_n < last_rtpmap_codec; codec_n++) {
+ format = ast_rtp_codec_getformat(found_rtpmap_codecs[codec_n]);
+ if (!format) /* non-codec or not found */
+ continue;
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Setting framing for %d to %ld\n", format, framing);
+ ast_codec_pref_setsize(pref, format, framing);
+ }
+ ast_rtp_codec_setpref(p->rtp, pref);
+ }
+ }
+ memset(&found_rtpmap_codecs, 0, sizeof(found_rtpmap_codecs));
+ last_rtpmap_codec = 0;
continue;
- /* We have a rtpmap to handle */
- if (debug)
- ast_verbose("Found description format %s for ID %d\n", mimeSubtype, codec);
+ } else if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) == 2) {
+ /* We have a rtpmap to handle */
+ if (debug)
+ ast_verbose("Found description format %s for ID %d\n", mimeSubtype, codec);
+ found_rtpmap_codecs[last_rtpmap_codec] = codec;
+ last_rtpmap_codec++;
- /* Note: should really look at the 'freq' and '#chans' params too */
- ast_rtp_set_rtpmap_type(newaudiortp, codec, "audio", mimeSubtype,
+ /* Note: should really look at the 'freq' and '#chans' params too */
+ ast_rtp_set_rtpmap_type(newaudiortp, codec, "audio", mimeSubtype,
ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0);
- if (p->vrtp)
- ast_rtp_set_rtpmap_type(newvideortp, codec, "video", mimeSubtype, 0);
+ if (p->vrtp)
+ ast_rtp_set_rtpmap_type(newvideortp, codec, "video", mimeSubtype, 0);
+ }
}
if (udptlportno != -1) {
@@ -5593,12 +5637,19 @@ static void add_codec_to_sdp(const struct sip_pvt *p, int codec, int sample_rate
int debug)
{
int rtp_code;
+ struct ast_format_list fmt;
+
if (debug)
ast_verbose("Adding codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
if ((rtp_code = ast_rtp_lookup_code(p->rtp, 1, codec)) == -1)
return;
+ if (p->rtp) {
+ struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp);
+ fmt = ast_codec_pref_getsize(pref, codec);
+ } else /* I dont see how you couldn't have p->rtp, but good to check for and error out if not there like earlier code */
+ return;
ast_build_string(m_buf, m_size, " %d", rtp_code);
ast_build_string(a_buf, a_size, "a=rtpmap:%d %s/%d\r\n", rtp_code,
ast_rtp_lookup_mime_subtype(1, codec,
@@ -5608,9 +5659,12 @@ static void add_codec_to_sdp(const struct sip_pvt *p, int codec, int sample_rate
/* Indicate that we don't support VAD (G.729 annex B) */
ast_build_string(a_buf, a_size, "a=fmtp:%d annexb=no\r\n", rtp_code);
} else if (codec == AST_FORMAT_ILBC) {
- /* Add information about us using only 20 ms packetization */
- ast_build_string(a_buf, a_size, "a=fmtp:%d mode=20\r\n", rtp_code);
-
+ /* Add information about us using only 20/30 ms packetization */
+ ast_build_string(a_buf, a_size, "a=fmtp:%d mode=%d\r\n", rtp_code, fmt.cur_ms);
+ }
+
+ if (codec != AST_FORMAT_ILBC) {
+ ast_build_string(a_buf, a_size, "a=ptime:%d\r\n", fmt.cur_ms);
}
}
@@ -6084,6 +6138,11 @@ static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const
}
respprep(&resp, p, msg, req);
if (p->rtp) {
+ if (!p->autoframing && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Setting framing from config on incoming call\n");
+ ast_rtp_codec_setpref(p->rtp, &p->prefs);
+ }
try_suggested_sip_codec(p);
add_sdp(&resp, p);
} else
@@ -7930,6 +7989,11 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
ASTOBJ_UNREF(peer, sip_destroy_peer);
}
if (peer) {
+ /* Set Frame packetization */
+ if (p->rtp) {
+ ast_rtp_codec_setpref(p->rtp, &peer->prefs);
+ p->autoframing = peer->autoframing;
+ }
if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC)) {
ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name);
} else {
@@ -8663,6 +8727,11 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
}
}
p->prefs = user->prefs;
+ /* Set Frame packetization */
+ if (p->rtp) {
+ ast_rtp_codec_setpref(p->rtp, &p->prefs);
+ p->autoframing = user->autoframing;
+ }
/* replace callerid if rpid found, and not restricted */
if (!ast_strlen_zero(rpid_num) && ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) {
char *tmp;
@@ -8771,6 +8840,11 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
peer = find_peer(NULL, &p->recv, 1);
if (peer) {
+ /* Set Frame packetization */
+ if (p->rtp) {
+ ast_rtp_codec_setpref(p->rtp, &peer->prefs);
+ p->autoframing = peer->autoframing;
+ }
if (debug)
ast_verbose("Found peer '%s'\n", peer->name);
@@ -9528,6 +9602,7 @@ static void print_codec_to_cli(int fd, struct ast_codec_pref *pref)
if (!codec)
break;
ast_cli(fd, "%s", ast_getformatname(codec));
+ ast_cli(fd, ":%d", pref->framing[x]);
if (x < 31 && ast_codec_pref_index(pref, x + 1))
ast_cli(fd, ",");
}
@@ -15167,6 +15242,8 @@ static struct sip_user *build_user(const char *name, struct ast_variable *v, int
ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1);
} else if (!strcasecmp(v->name, "disallow")) {
ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 0);
+ } else if (!strcasecmp(v->name, "autoframing")) {
+ user->autoframing = ast_true(v->value);
} else if (!strcasecmp(v->name, "callingpres")) {
user->callingpres = ast_parse_caller_presentation(v->value);
if (user->callingpres == -1)
@@ -15446,6 +15523,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1);
} else if (!strcasecmp(v->name, "disallow")) {
ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0);
+ } else if (!strcasecmp(v->name, "autoframing")) {
+ peer->autoframing = ast_true(v->value);
} else if (!strcasecmp(v->name, "rtptimeout")) {
if ((sscanf(v->value, "%d", &peer->rtptimeout) != 1) || (peer->rtptimeout < 0)) {
ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno);
@@ -15807,6 +15886,8 @@ static int reload_config(enum channelreloadreason reason)
ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, 1);
} else if (!strcasecmp(v->name, "disallow")) {
ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, 0);
+ } else if (!strcasecmp(v->name, "autoframing")) {
+ global_autoframing = ast_true(v->value);
} else if (!strcasecmp(v->name, "allowexternaldomains")) {
allow_external_domains = ast_true(v->value);
} else if (!strcasecmp(v->name, "autodomain")) {
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 3d16ab92f..e42a29a2e 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -81,7 +81,8 @@ static const char tdesc[] = "Skinny Client Control Protocol (Skinny)";
static const char config[] = "skinny.conf";
/* Just about everybody seems to support ulaw, so make it a nice default */
-static int capability = AST_FORMAT_ULAW;
+static int default_capability = AST_FORMAT_ULAW;
+static struct ast_codec_pref default_prefs;
#define DEFAULT_SKINNY_PORT 2000
#define DEFAULT_SKINNY_BACKLOG 2
@@ -948,6 +949,7 @@ struct skinny_line {
int hookstate;
int nat;
+ struct ast_codec_pref prefs;
struct skinny_subchannel *sub;
struct skinny_line *next;
struct skinny_device *parent;
@@ -980,11 +982,13 @@ static struct skinny_device {
int registered;
int lastlineinstance;
int lastcallreference;
+ int capability;
struct sockaddr_in addr;
struct in_addr ourip;
struct skinny_line *lines;
struct skinny_speeddial *speeddials;
struct skinny_addon *addons;
+ struct ast_codec_pref prefs;
struct ast_ha *ha;
struct skinnysession *session;
struct skinny_device *next;
@@ -1022,7 +1026,7 @@ static int skinny_senddigit_end(struct ast_channel *ast, char digit);
static const struct ast_channel_tech skinny_tech = {
.type = "Skinny",
.description = tdesc,
- .capabilities = AST_FORMAT_ULAW,
+ .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
.properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
.requester = skinny_request,
.call = skinny_call,
@@ -1407,7 +1411,7 @@ static void transmit_connect(struct skinnysession *s, struct skinny_subchannel *
req->data.openreceivechannel.conferenceId = htolel(0);
req->data.openreceivechannel.partyId = htolel(sub->callid);
- req->data.openreceivechannel.packets = htolel(20);
+ req->data.openreceivechannel.packets = htolel(l->prefs.framing[0]);
req->data.openreceivechannel.capability = htolel(convert_cap(l->capability));
req->data.openreceivechannel.echo = htolel(0);
req->data.openreceivechannel.bitrate = htolel(0);
@@ -1927,6 +1931,8 @@ static struct skinny_device *build_device(const char *cat, struct ast_variable *
} else {
ast_copy_string(d->name, cat, sizeof(d->name));
d->lastlineinstance = 1;
+ d->capability = default_capability;
+ d->prefs = default_prefs;
while(v) {
if (!strcasecmp(v->name, "host")) {
if (ast_get_ip(&d->addr, v->value)) {
@@ -1941,6 +1947,10 @@ static struct skinny_device *build_device(const char *cat, struct ast_variable *
d->ha = ast_append_ha(v->name, v->value, d->ha);
} else if (!strcasecmp(v->name, "context")) {
ast_copy_string(context, v->value, sizeof(context));
+ } else if (!strcasecmp(v->name, "allow")) {
+ ast_parse_allow_disallow(&d->prefs, &d->capability, v->value, 1);
+ } else if (!strcasecmp(v->name, "disallow")) {
+ ast_parse_allow_disallow(&d->prefs, &d->capability, v->value, 0);
} else if (!strcasecmp(v->name, "version")) {
ast_copy_string(d->version_id, v->value, sizeof(d->version_id));
} else if (!strcasecmp(v->name, "nat")) {
@@ -2040,7 +2050,8 @@ static struct skinny_device *build_device(const char *cat, struct ast_variable *
ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, d->name, l->name);
}
l->msgstate = -1;
- l->capability = capability;
+ l->capability = d->capability;
+ l->prefs = d->prefs;
l->parent = d;
if (!strcasecmp(v->name, "trunk")) {
l->type = TYPE_TRUNK;
@@ -2167,6 +2178,10 @@ static void start_rtp(struct skinny_subchannel *sub)
if (sub->vrtp) {
ast_rtp_setnat(sub->vrtp, l->nat);
}
+ /* Set Frame packetization */
+ if (sub->rtp)
+ ast_rtp_codec_setpref(sub->rtp, &l->prefs);
+
/* Create the RTP connection */
transmit_connect(d->session, sub);
ast_mutex_unlock(&sub->lock);
@@ -2680,7 +2695,7 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state)
tmp->tech_pvt = sub;
tmp->nativeformats = l->capability;
if (!tmp->nativeformats)
- tmp->nativeformats = capability;
+ tmp->nativeformats = default_capability;
fmt = ast_best_codec(tmp->nativeformats);
if (skinnydebug)
ast_verbose("skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
@@ -3566,7 +3581,7 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc
req->data.startmedia.passThruPartyId = htolel(sub->callid);
req->data.startmedia.remoteIp = htolel(d->ourip.s_addr);
req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
- req->data.startmedia.packetSize = htolel(20);
+ req->data.startmedia.packetSize = htolel(l->prefs.framing[0]);
req->data.startmedia.payloadType = htolel(convert_cap(l->capability));
req->data.startmedia.qualifier.precedence = htolel(127);
req->data.startmedia.qualifier.vad = htolel(0);
@@ -4277,7 +4292,7 @@ static struct ast_channel *skinny_request(const char *type, int format, void *da
char *dest = data;
oldformat = format;
- format &= capability;
+ format &= default_capability;
if (!format) {
ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
return NULL;
@@ -4308,7 +4323,6 @@ static int reload_config(void)
int on = 1;
struct ast_config *cfg;
struct ast_variable *v;
- int format;
char *cat;
struct skinny_device *d;
int oldport = ntohs(bindaddr.sin_port);
@@ -4350,19 +4364,9 @@ static int reload_config(void)
} else if (!strcasecmp(v->name, "dateformat")) {
ast_copy_string(date_format, v->value, sizeof(date_format));
} else if (!strcasecmp(v->name, "allow")) {
- format = ast_getformatbyname(v->value);
- if (format < 1) {
- ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
- } else {
- capability |= format;
- }
+ ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 1);
} else if (!strcasecmp(v->name, "disallow")) {
- format = ast_getformatbyname(v->value);
- if (format < 1) {
- ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
- } else {
- capability &= ~format;
- }
+ ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 0);
} else if (!strcasecmp(v->name, "bindport") || !strcasecmp(v->name, "port")) {
if (sscanf(v->value, "%d", &ourport) == 1) {
bindaddr.sin_port = htons(ourport);