summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
authorMark Spencer <markster@digium.com>2004-12-02 22:18:09 +0000
committerMark Spencer <markster@digium.com>2004-12-02 22:18:09 +0000
commitf375ebee86b2bb32bbba1018cfccb6ae90feddf9 (patch)
treecc0d57a18f2ab0df82d5a25de7745f4ed98d39fb /channels
parent36928f0644486ed0082ec55ca4a4ea29d1e1ba35 (diff)
Merge SIP portion of new codec work from bug #2945
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4371 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rwxr-xr-xchannels/chan_sip.c244
1 files changed, 78 insertions, 166 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index b5f427f34..0540c49a9 100755
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -163,6 +163,7 @@ static int global_mwitime = DEFAULT_MWITIME; /* Time between MWI checks for peer
static int usecnt =0;
AST_MUTEX_DEFINE_STATIC(usecnt_lock);
+
/* Protect the interface list (of sip_pvt's) */
AST_MUTEX_DEFINE_STATIC(iflock);
@@ -220,10 +221,8 @@ static struct io_context *io;
#define DEC_OUT_USE 2
#define INC_OUT_USE 3
-static struct sip_codec_pref {
- int codec;
- struct sip_codec_pref *next;
-} *prefs;
+static struct ast_codec_pref prefs;
+
/* sip_request: The data grabbed from the UDP socket */
struct sip_request {
@@ -254,6 +253,7 @@ static struct sip_pvt {
ast_mutex_t lock; /* Channel private lock */
char callid[80]; /* Global CallID */
char randdata[80]; /* Random data */
+ struct ast_codec_pref prefs; /* codec prefs */
unsigned int ocseq; /* Current outgoing seqno */
unsigned int icseq; /* Current incoming seqno */
unsigned int callgroup; /* Call group */
@@ -391,6 +391,7 @@ struct sip_user {
char language[MAX_LANGUAGE]; /* Default language for this user */
char musicclass[MAX_LANGUAGE]; /* Music on Hold class */
char useragent[256]; /* User agent in SIP request */
+ struct ast_codec_pref prefs; /* codec prefs */
unsigned int callgroup; /* Call group */
unsigned int pickupgroup; /* Pickup Group */
int nat; /* NAT setting */
@@ -435,6 +436,7 @@ struct sip_peer {
char language[MAX_LANGUAGE]; /* Default language for prompts */
char musicclass[MAX_LANGUAGE]; /* Music on Hold class */
char useragent[256]; /* User agent in SIP request (saved from registration) */
+ struct ast_codec_pref prefs; /* codec prefs */
int lastmsgssent;
time_t lastmsgcheck; /* Last time we checked for MWI */
int dynamic; /* Dynamic? Yes or no. Dynamic hosts register with us */
@@ -1364,71 +1366,8 @@ static int auto_congest(void *nothing)
return 0;
}
-/*--- sip_prefs_free: Free codec list in preference structure ---*/
-static void sip_prefs_free(void)
-{
- struct sip_codec_pref *cur, *next;
- cur = prefs;
- while(cur) {
- next = cur->next;
- free(cur);
- cur = next;
- }
- prefs = NULL;
-}
-/*--- sip_pref_remove: Remove codec from pref list ---*/
-static void sip_pref_remove(int format)
-{
- struct sip_codec_pref *cur, *prev=NULL;
- cur = prefs;
- while(cur) {
- if (cur->codec == format) {
- if (prev)
- prev->next = cur->next;
- else
- prefs = cur->next;
- free(cur);
- return;
- }
- prev = cur;
- cur = cur->next;
- }
-}
-/*--- sip_pref_append: Append codec to list ---*/
-static int sip_pref_append(int format)
-{
- struct sip_codec_pref *cur, *tmp;
- sip_pref_remove(format);
- tmp = (struct sip_codec_pref *)malloc(sizeof(struct sip_codec_pref));
- if (!tmp)
- return -1;
- memset(tmp, 0, sizeof(struct sip_codec_pref));
- tmp->codec = format;
- if (prefs) {
- cur = prefs;
- while(cur->next)
- cur = cur->next;
- cur->next = tmp;
- } else
- prefs = tmp;
- return 0;
-}
-
-/*--- sip_codec_choose: Pick a codec ---*/
-static int sip_codec_choose(int formats)
-{
- struct sip_codec_pref *cur;
- formats &= ((AST_FORMAT_MAX_AUDIO << 1) - 1);
- cur = prefs;
- while(cur) {
- if (formats & cur->codec)
- return cur->codec;
- cur = cur->next;
- }
- return ast_best_codec(formats);
-}
/*--- sip_call: Initiate SIP call from PBX ---*/
/* used from the dial() application */
@@ -1985,12 +1924,14 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title)
if (tmp) {
/* Select our native format based on codec preference until we receive
something from another device to the contrary. */
+ ast_mutex_lock(&i->lock);
if (i->jointcapability)
- tmp->nativeformats = sip_codec_choose(i->jointcapability);
+ tmp->nativeformats = ast_codec_choose(&i->prefs, i->jointcapability, 1);
else if (i->capability)
- tmp->nativeformats = sip_codec_choose(i->capability);
+ tmp->nativeformats = ast_codec_choose(&i->prefs, i->capability, 1);
else
- tmp->nativeformats = sip_codec_choose(global_capability);
+ tmp->nativeformats = ast_codec_choose(&i->prefs, global_capability, 1);
+ ast_mutex_unlock(&i->lock);
fmt = ast_best_codec(tmp->nativeformats);
if (title)
snprintf(tmp->name, sizeof(tmp->name), "SIP/%s-%04x", title, rand() & 0xffff);
@@ -2083,6 +2024,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title)
}
for (v = i->vars ; v ; v = v->next)
pbx_builtin_setvar_helper(tmp,v->name,v->value);
+
} else
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
return tmp;
@@ -2291,9 +2233,11 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg
/* Keep track of stuff */
memset(p, 0, sizeof(struct sip_pvt));
ast_mutex_init(&p->lock);
+
p->initid = -1;
p->autokillid = -1;
p->stateid = -1;
+ p->prefs = prefs;
#ifdef OSP_SUPPORT
p->osphandle = -1;
#endif
@@ -2770,7 +2714,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
p->noncodeccapability = noncodeccapability & peernoncodeccapability;
if (debug) {
- const unsigned slen=80;
+ /* shame on whoever coded this.... */
+ const unsigned slen=512;
char s1[slen], s2[slen], s3[slen], s4[slen];
ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s, combined - %s\n",
@@ -2790,12 +2735,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
}
if (p->owner) {
if (!(p->owner->nativeformats & p->jointcapability)) {
- const unsigned slen=80;
+ const unsigned slen=512;
char s1[slen], s2[slen];
ast_log(LOG_DEBUG, "Oooh, we need to change our formats since our peer supports only %s and not %s\n",
ast_getformatname_multiple(s1, slen, p->jointcapability),
ast_getformatname_multiple(s2, slen, p->owner->nativeformats));
- p->owner->nativeformats = sip_codec_choose(p->jointcapability);
+ p->owner->nativeformats = ast_codec_choose(&p->prefs, p->jointcapability, 1);
ast_set_read_format(p->owner, p->owner->readformat);
ast_set_write_format(p->owner, p->owner->writeformat);
}
@@ -3336,13 +3281,13 @@ static int add_digit(struct sip_request *req, char digit)
/*--- add_sdp: Add Session Description Protocol message ---*/
static int add_sdp(struct sip_request *resp, struct sip_pvt *p)
{
- int len;
- int codec;
+ int len = 0;
+ int codec = 0;
+ int pref_codec = 0;
int alreadysent = 0;
char costr[80];
struct sockaddr_in sin;
struct sockaddr_in vsin;
- struct sip_codec_pref *cur;
char v[256] = "";
char s[256] = "";
char o[256] = "";
@@ -3353,11 +3298,13 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p)
char a[1024] = "";
char a2[1024] = "";
char iabuf[INET_ADDRSTRLEN];
- int x;
- int capability;
+ int x = 0;
+ int capability = 0 ;
struct sockaddr_in dest;
struct sockaddr_in vdest = { 0, };
- int debug=sip_debug_test_pvt(p);
+ int debug=0;
+
+ debug = sip_debug_test_pvt(p);
/* XXX We break with the "recommendation" and send our IP, in order that our
peer doesn't have to ast_gethostbyname() us XXX */
@@ -3409,6 +3356,7 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p)
snprintf(t, sizeof(t), "t=0 0\r\n");
snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
snprintf(m2, sizeof(m2), "m=video %d RTP/AVP", ntohs(vdest.sin_port));
+ /* Prefer the codec we were requested to use, first, no matter what */
if (capability & p->prefcodec) {
if (debug)
ast_verbose("Answering/Requesting with root capability %d\n", p->prefcodec);
@@ -3428,33 +3376,34 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p)
alreadysent |= p->prefcodec;
}
/* Start by sending our preferred codecs */
- cur = prefs;
- while(cur) {
- if ((capability & cur->codec) && !(alreadysent & cur->codec)) {
+ for (x = 0 ; x < 32 ; x++) {
+ if(!(pref_codec = ast_codec_pref_index(&p->prefs,x)))
+ break;
+ if ((capability & pref_codec) && !(alreadysent & pref_codec)) {
if (debug)
- ast_verbose("Answering with preferred capability 0x%x(%s)\n", cur->codec, ast_getformatname(cur->codec));
- codec = ast_rtp_lookup_code(p->rtp, 1, cur->codec);
+ ast_verbose("Answering with preferred capability 0x%x (%s)\n", pref_codec, ast_getformatname(pref_codec));
+ codec = ast_rtp_lookup_code(p->rtp, 1, pref_codec);
if (codec > -1) {
snprintf(costr, sizeof(costr), " %d", codec);
- if (cur->codec <= AST_FORMAT_MAX_AUDIO) {
+ if (pref_codec <= AST_FORMAT_MAX_AUDIO) {
strncat(m, costr, sizeof(m) - strlen(m) - 1);
- snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, cur->codec));
+ snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, pref_codec));
strncat(a, costr, sizeof(a) - strlen(a) - 1);
} else {
strncat(m2, costr, sizeof(m2) - strlen(m2) - 1);
- snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/90000\r\n", codec, ast_rtp_lookup_mime_subtype(1, cur->codec));
+ snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/90000\r\n", codec, ast_rtp_lookup_mime_subtype(1, pref_codec));
strncat(a2, costr, sizeof(a2) - strlen(a) - 1);
}
}
}
- alreadysent |= cur->codec;
- cur = cur->next;
+ alreadysent |= pref_codec;
}
+
/* Now send any other common codecs, and non-codec formats: */
for (x = 1; x <= ((videosupport && p->vrtp) ? AST_FORMAT_MAX_VIDEO : AST_FORMAT_MAX_AUDIO); x <<= 1) {
if ((capability & x) && !(alreadysent & x)) {
if (debug)
- ast_verbose("Answering with capability 0x%x(%s)\n", x, ast_getformatname(x));
+ ast_verbose("Answering with capability 0x%x (%s)\n", x, ast_getformatname(x));
codec = ast_rtp_lookup_code(p->rtp, 1, x);
if (codec > -1) {
snprintf(costr, sizeof(costr), " %d", codec);
@@ -3473,7 +3422,7 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p)
for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
if (p->noncodeccapability & x) {
if (debug)
- ast_verbose("Answering with non-codec capability 0x%x(%s)\n", x, ast_getformatname(x));
+ ast_verbose("Answering with non-codec capability 0x%x (%s)\n", x, ast_rtp_lookup_mime_subtype(0, x));
codec = ast_rtp_lookup_code(p->rtp, 0, x);
if (codec > -1) {
snprintf(costr, sizeof(costr), " %d", codec);
@@ -5349,6 +5298,7 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd
p->vars = tmpvar;
}
}
+ p->prefs = user->prefs;
p->nat = user->nat;
#ifdef OSP_SUPPORT
p->ospauth = user->ospauth;
@@ -5700,7 +5650,7 @@ static int sip_show_peers(int fd, int argc, char *argv[])
snprintf(srch, sizeof(srch), FORMAT, name,
peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
peer->dynamic ? " D " : " ", /* Dynamic or not? */
- (peer->nat & SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */
+ (peer->nat & SIP_NAT_ROUTE) ? " Y " : " ", /* NAT=yes? */
peer->ha ? " A " : " ", /* permit/deny */
nm, ntohs(peer->addr.sin_port), status);
@@ -5760,6 +5710,9 @@ static int sip_show_peer(int fd, int argc, char *argv[])
char cbuf[256];
char iabuf[INET_ADDRSTRLEN];
struct sip_peer *peer;
+ char codec_buf[512];
+ struct ast_codec_pref *pref;
+ int x = 0, codec = 0;
if (argc != 4)
return RESULT_SHOWUSAGE;
@@ -5805,38 +5758,23 @@ static int sip_show_peer(int fd, int argc, char *argv[])
ast_cli(fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
ast_cli(fd, " Username : %s\n", peer->username);
ast_cli(fd, " Codecs : ");
- /* This should really be a function in frame.c */
- if (peer->capability & AST_FORMAT_G723_1)
- ast_cli(fd, "G723 ");
- if (peer->capability & AST_FORMAT_GSM)
- ast_cli(fd, "GSM ");
- if (peer->capability & AST_FORMAT_ULAW)
- ast_cli(fd, "ULAW ");
- if (peer->capability & AST_FORMAT_ALAW)
- ast_cli(fd, "ALAW ");
- if (peer->capability & AST_FORMAT_G726)
- ast_cli(fd, "G.726 ");
- if (peer->capability & AST_FORMAT_SLINEAR)
- ast_cli(fd, "SLINR ");
- if (peer->capability & AST_FORMAT_LPC10)
- ast_cli(fd, "LPC10 ");
- if (peer->capability & AST_FORMAT_ADPCM)
- ast_cli(fd, "ADPCM ");
- if (peer->capability & AST_FORMAT_G729A)
- ast_cli(fd, "G.729A ");
- if (peer->capability & AST_FORMAT_SPEEX)
- ast_cli(fd, "SPEEX ");
- if (peer->capability & AST_FORMAT_ILBC)
- ast_cli(fd, "ILBC ");
- if (peer->capability & AST_FORMAT_JPEG)
- ast_cli(fd, "JPEG ");
- if (peer->capability & AST_FORMAT_PNG)
- ast_cli(fd, "PNG ");
- if (peer->capability & AST_FORMAT_H261)
- ast_cli(fd, "H.261 ");
- if (peer->capability & AST_FORMAT_H263)
- ast_cli(fd, "H.263 ");
- ast_cli(fd, "\n");
+ ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
+ ast_cli(fd, "%s\n", codec_buf);
+ ast_cli(fd, " Codec Order : (");
+ pref = &peer->prefs;
+ for(x = 0; x < 32 ; x++) {
+ codec = ast_codec_pref_index(pref,x);
+ if(!codec)
+ break;
+ ast_cli(fd, "%s", ast_getformatname(codec));
+ if(x < 31 && ast_codec_pref_index(pref,x+1))
+ ast_cli(fd, "|");
+ }
+
+ if (!x)
+ ast_cli(fd, "none");
+ ast_cli(fd, ")\n");
+
ast_cli(fd, " Status : ");
if (peer->lastms < 0)
strncpy(status, "UNREACHABLE", sizeof(status) - 1);
@@ -8188,6 +8126,7 @@ static struct sip_user *build_user(const char *name, struct ast_variable *v)
user->trustrpid = global_trustrpid;
user->dtmfmode = global_dtmfmode;
user->progressinband = global_progressinband;
+ user->prefs = prefs;
#ifdef OSP_SUPPORT
user->ospauth = global_ospauth;
#endif
@@ -8271,17 +8210,9 @@ static struct sip_user *build_user(const char *name, struct ast_variable *v)
user->amaflags = 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
- user->capability |= format;
+ ast_parse_allow_deny(&user->prefs, &user->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
- user->capability &= ~format;
+ ast_parse_allow_deny(&user->prefs, &user->capability, v->value, 0);
} else if (!strcasecmp(v->name, "insecure")) {
user->insecure = ast_true(v->value);
} else if (!strcasecmp(v->name, "callingpres")) {
@@ -8324,6 +8255,7 @@ static struct sip_peer *temp_peer(char *name)
peer = malloc(sizeof(struct sip_peer));
if (!peer)
return NULL;
+
memset(peer, 0, sizeof(struct sip_peer));
peer->expire = -1;
peer->pokeexpire = -1;
@@ -8346,6 +8278,7 @@ static struct sip_peer *temp_peer(char *name)
peer->dynamic = 1;
peer->trustrpid = global_trustrpid;
peer->progressinband = global_progressinband;
+ peer->prefs = prefs;
#ifdef OSP_SUPPORT
peer->ospauth = global_ospauth;
#endif
@@ -8360,7 +8293,6 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
struct sip_peer *prev;
struct ast_ha *oldha = NULL;
int maskfound=0;
- int format;
int found=0;
prev = NULL;
@@ -8407,6 +8339,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
peer->defaddr.sin_family = AF_INET;
peer->expiry = expiry;
}
+ peer->prefs = prefs;
oldha = peer->ha;
peer->ha = NULL;
peer->addr.sin_family = AF_INET;
@@ -8521,17 +8454,9 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
} else if (!strcasecmp(v->name, "pickupgroup")) {
peer->pickupgroup = ast_get_group(v->value);
} 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
- peer->capability |= format;
+ ast_parse_allow_deny(&peer->prefs, &peer->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
- peer->capability &= ~format;
+ ast_parse_allow_deny(&peer->prefs, &peer->capability, v->value, 0);
} else if (!strcasecmp(v->name, "insecure")) {
if (!strcasecmp(v->value, "very")) {
peer->insecure = 2;
@@ -8626,12 +8551,11 @@ static int reload_config(void)
}
- sip_prefs_free();
-
/* Reset IP addresses */
memset(&bindaddr, 0, sizeof(bindaddr));
memset(&localaddr, 0, sizeof(localaddr));
memset(&externip, 0, sizeof(externip));
+ memset(&prefs, 0 , sizeof(struct ast_codec_pref));
/* Initialize some reasonable defaults at SIP reload */
global_nat = SIP_NAT_RFC3581;
@@ -8794,21 +8718,9 @@ static int reload_config(void)
else
memcpy(&externip.sin_addr, hp->h_addr, sizeof(externip.sin_addr));
} 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 {
- global_capability |= format;
- sip_pref_append(format);
- }
+ ast_parse_allow_deny(&prefs, &global_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 {
- global_capability &= ~format;
- sip_pref_remove(format);
- }
+ ast_parse_allow_deny(&prefs, &global_capability, v->value, 0);
} else if (!strcasecmp(v->name, "register")) {
sip_register(v->value, v->lineno);
} else if (!strcasecmp(v->name, "recordhistory")) {
@@ -9127,7 +9039,6 @@ static int sip_do_reload(void)
struct sip_peer *peer;
delete_users();
reload_config();
-
prune_peers();
/* And start the monitor for the first time */
ast_mutex_lock(&regl.lock);
@@ -9171,9 +9082,9 @@ int load_module()
struct sip_peer *peer;
struct sip_registry *reg;
- ast_mutex_init(&userl.lock);
- ast_mutex_init(&peerl.lock);
- ast_mutex_init(&regl.lock);
+ ast_mutex_init(&userl.lock);
+ ast_mutex_init(&peerl.lock);
+ ast_mutex_init(&regl.lock);
sched = sched_context_create();
if (!sched) {
ast_log(LOG_WARNING, "Unable to create schedule context\n");
@@ -9182,7 +9093,8 @@ int load_module()
if (!io) {
ast_log(LOG_WARNING, "Unable to create I/O context\n");
}
-
+
+
res = reload_config();
if (!res) {
/* Make sure we can register our sip channel type */