summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2009-05-29 15:48:04 +0000
committerMark Michelson <mmichelson@digium.com>2009-05-29 15:48:04 +0000
commit14d05f57d72959ae0a26c32e041e483d31cafbcb (patch)
treedb10470cb7b8ed31d1dca66ddcb947873d51e7e3 /channels
parentce004fbf1f91dcfc6766bbc5116e08c447922506 (diff)
A few fixes to SIP with regards to connected line updates during transfers.
* Set the invitestate to INV_CALLING when we send a connected line reinvite. This prevents us from potentially rapid-firing reinvites to a single peer. * Use the astdb to store a peer's allowed methods. This prevents us from sending an UPDATE during the interval between startup and the peer's first registration if the peer does not support the UPDATE method. * Handle Polycom's method of indicating allowed methods in REGISTER. Instead of using an Allow header, they place the allowed methods in a methods= parameter in the Contact header. ABE-1873 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@197959 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_sip.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index d803429c8..3e074c7d2 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -7404,18 +7404,28 @@ static unsigned int parse_allowed_methods(struct sip_request *req)
unsigned int allowed_methods = SIP_UNKNOWN;
if (ast_strlen_zero(allow)) {
- /* RFC 3261 states:
- *
- * "The absence of an Allow header field MUST NOT be
- * interpreted to mean that the UA sending the message supports no
- * methods. Rather, it implies that the UA is not providing any
- * information on what methods it supports."
- *
- * For simplicity, we'll assume that the peer allows all known
- * SIP methods if they have no Allow header. We can then clear out the necessary
- * bits if the peer lets us know that we have sent an unsupported method.
+ /* I have witnessed that REGISTER requests from Polycom phones do not
+ * place the phone's allowed methods in an Allow header. Instead, they place the
+ * allowed methods in a methods= parameter in the Contact header.
*/
- return UINT_MAX;
+ char *contact = ast_strdupa(get_header(req, "Contact"));
+ char *methods = strstr(contact, ";methods=");
+
+ if (ast_strlen_zero(methods)) {
+ /* RFC 3261 states:
+ *
+ * "The absence of an Allow header field MUST NOT be
+ * interpreted to mean that the UA sending the message supports no
+ * methods. Rather, it implies that the UA is not providing any
+ * information on what methods it supports."
+ *
+ * For simplicity, we'll assume that the peer allows all known
+ * SIP methods if they have no Allow header. We can then clear out the necessary
+ * bits if the peer lets us know that we have sent an unsupported method.
+ */
+ return UINT_MAX;
+ }
+ allow = ast_strip_quoted(methods + 9, "\"", "\"");
}
for (method = strsep(&allow, ","); !ast_strlen_zero(method); method = strsep(&allow, ",")) {
int id = find_sip_method(ast_skip_blanks(method));
@@ -11020,6 +11030,7 @@ static void update_connectedline(struct sip_pvt *p, const void *data, size_t dat
initialize_initreq(p, &req);
p->lastinvite = p->ocseq;
ast_set_flag(&p->flags[0], SIP_OUTGOING);
+ p->invitestate = INV_CALLING;
send_request(p, &req, XMIT_CRITICAL, p->ocseq);
} else if (is_method_allowed(&p->allowed_methods, SIP_UPDATE)) {
reqprep(&req, p, SIP_UPDATE, 0, 1);
@@ -11614,6 +11625,7 @@ static void destroy_association(struct sip_peer *peer)
ast_update_realtime(tablename, "name", peer->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", peer->deprecated_username ? "username" : "defaultuser", "", "regserver", "", "useragent", "", "lastms", "", SENTINEL);
} else {
ast_db_del("SIP/Registry", peer->name);
+ ast_db_del("SIP/PeerMethods", peer->name);
}
}
}
@@ -11691,11 +11703,13 @@ static void reg_source_db(struct sip_peer *peer)
int expire;
int port;
char *scan, *addr, *port_str, *expiry_str, *username, *contact;
+ char allowed_methods_str[256] = "";
if (peer->rt_fromcontact)
return;
if (ast_db_get("SIP/Registry", peer->name, data, sizeof(data)))
return;
+ ast_db_get("SIP/PeerMethods", peer->name, allowed_methods_str, sizeof(allowed_methods_str));
scan = data;
addr = strsep(&scan, ":");
@@ -11722,6 +11736,10 @@ static void reg_source_db(struct sip_peer *peer)
if (contact)
ast_string_field_set(peer, fullcontact, contact);
+ if (!ast_strlen_zero(allowed_methods_str)) {
+ peer->allowed_methods = atoi(allowed_methods_str);
+ }
+
ast_debug(2, "SIP Seeding peer from astdb: '%s' at %s@%s:%d for %d\n",
peer->name, peer->username, ast_inet_ntoa(in), port, expire);
@@ -12756,6 +12774,11 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
if (peer->allowed_methods == SIP_UNKNOWN) {
peer->allowed_methods = set_pvt_allowed_methods(p, req);
}
+ if (!peer->rt_fromcontact) {
+ char allowed_methods_str[256];
+ snprintf(allowed_methods_str, sizeof(allowed_methods_str), "%u", peer->allowed_methods);
+ ast_db_put("SIP/PeerMethods", peer->name, allowed_methods_str);
+ }
ao2_unlock(peer);
unref_peer(peer, "register_verify: unref_peer: tossing stack peer pointer at end of func");
}