summaryrefslogtreecommitdiff
path: root/res/res_sip.c
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2013-06-22 14:03:22 +0000
committerJoshua Colp <jcolp@digium.com>2013-06-22 14:03:22 +0000
commit77002bc377f19ea11e60732c486b6ef371688773 (patch)
treec19fd245c519c6d7905403849a7af9c7e4a4be3e /res/res_sip.c
parentea03516cb5426915d183526335d3a7d662ea29dc (diff)
Merge in current pimp_my_sip work, including:
1. Security events 2. Websocket support 3. Diversion header + redirecting support 4. An anonymous endpoint identifier 5. Inbound extension state subscription support 6. PIDF notify generation 7. One touch recording support (special thanks Sean Bright!) 8. Blind and attended transfer support 9. Automatic inbound registration expiration 10. SRTP support 11. Media offer control dialplan function 12. Connected line support 13. SendText() support 14. Qualify support 15. Inband DTMF detection 16. Call and pickup groups 17. Messaging support Thanks everyone! Side note: I'm reminded of the song "How Far We've Come" by Matchbox Twenty. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@392565 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/res_sip.c')
-rw-r--r--res/res_sip.c204
1 files changed, 184 insertions, 20 deletions
diff --git a/res/res_sip.c b/res/res_sip.c
index 1af3fb78e..ebbf596de 100644
--- a/res/res_sip.c
+++ b/res/res_sip.c
@@ -53,7 +53,7 @@
It contains the core SIP related options only, endpoints are <emphasis>NOT</emphasis>
dialable entries of their own. Communication with another SIP device is
accomplished via Addresses of Record (AoRs) which have one or more
- contacts assicated with them. Endpoints <emphasis>NOT</emphasis> configured to
+ contacts assicated with them. Endpoints <emphasis>NOT</emphasis> configured to
use a <literal>transport</literal> will default to first transport found
in <filename>res_sip.conf</filename> that matches its type.
</para>
@@ -62,6 +62,12 @@
first transport that matches the type. A SIP URI of <literal>sip:5000@[11::33]</literal>
will use the first IPv6 transport and try to send the request.
</para>
+ <para>If the anonymous endpoint identifier is in use an endpoint with the name
+ "anonymous@domain" will be searched for as a last resort. If this is not found
+ it will fall back to searching for "anonymous". If neither endpoints are found
+ the anonymous endpoint identifier will not return an endpoint and anonymous
+ calling will not be possible.
+ </para>
</description>
<configOption name="100rel" default="yes">
<synopsis>Allow support for RFC3262 provisional ACK tags</synopsis>
@@ -161,6 +167,19 @@
</enumlist>
</description>
</configOption>
+ <configOption name="connected_line_method" default="invite">
+ <synopsis>Connected line method type</synopsis>
+ <description>
+ <para>Method used when updating connected line information.</para>
+ <enumlist>
+ <enum name="invite" />
+ <enum name="reinvite">
+ <para>Alias for the <literal>invite</literal> value.</para>
+ </enum>
+ <enum name="update" />
+ </enumlist>
+ </description>
+ </configOption>
<configOption name="direct_media" default="yes">
<synopsis>Determines whether media may flow directly between endpoints.</synopsis>
</configOption>
@@ -223,13 +242,6 @@
<configOption name="outbound_proxy">
<synopsis>Proxy through which to send requests</synopsis>
</configOption>
- <configOption name="qualify_frequency" default="0">
- <synopsis>Interval at which to qualify an endpoint</synopsis>
- <description><para>
- Interval between attempts to qualify the endpoint for reachability.
- If <literal>0</literal> never qualify. Time in seconds.
- </para></description>
- </configOption>
<configOption name="rewrite_contact">
<synopsis>Allow Contact header to be rewritten with the source IP address-port</synopsis>
</configOption>
@@ -298,6 +310,75 @@
<configOption name="use_ptime" default="no">
<synopsis>Use Endpoint's requested packetisation interval</synopsis>
</configOption>
+ <configOption name="use_avpf" default="no">
+ <synopsis>Determines whether res_sip will use and enforce usage of AVPF for this
+ endpoint.</synopsis>
+ <description><para>
+ If set to <literal>yes</literal>, res_sip will use use the AVPF or SAVPF RTP
+ profile for all media offers on outbound calls and media updates and will
+ decline media offers not using the AVPF or SAVPF profile.
+ </para><para>
+ If set to <literal>no</literal>, res_sip will use use the AVP or SAVP RTP
+ profile for all media offers on outbound calls and media updates and will
+ decline media offers not using the AVP or SAVP profile.
+ </para></description>
+ </configOption>
+ <configOption name="media_encryption" default="no">
+ <synopsis>Determines whether res_sip will use and enforce usage of media encryption
+ for this endpoint.</synopsis>
+ <description>
+ <enumlist>
+ <enum name="no"><para>
+ res_sip will offer no encryption and allow no encryption to be setup.
+ </para></enum>
+ <enum name="sdes"><para>
+ res_sip will offer standard SRTP setup via in-SDP keys. Encrypted SIP
+ transport should be used in conjunction with this option to prevent
+ exposure of media encryption keys.
+ </para></enum>
+ </enumlist>
+ </description>
+ </configOption>
+ <configOption name="inband_progress" default="no">
+ <synopsis>Determines whether chan_gulp will indicate ringing using inband
+ progress.</synopsis>
+ <description><para>
+ If set to <literal>yes</literal>, chan_gulp will send a 183 Session Progress
+ when told to indicate ringing and will immediately start sending ringing
+ as audio.
+ </para><para>
+ If set to <literal>no</literal>, chan_gulp will send a 180 Ringing when told
+ to indicate ringing and will NOT send it as audio.
+ </para></description>
+ </configOption>
+ <configOption name="callgroup">
+ <synopsis>The numeric pickup groups for a channel.</synopsis>
+ <description><para>
+ Can be set to a comma separated list of numbers or ranges between the values
+ of 0-63 (maximum of 64 groups).
+ </para></description>
+ </configOption>
+ <configOption name="pickupgroup">
+ <synopsis>The numeric pickup groups that a channel can pickup.</synopsis>
+ <description><para>
+ Can be set to a comma separated list of numbers or ranges between the values
+ of 0-63 (maximum of 64 groups).
+ </para></description>
+ </configOption>
+ <configOption name="namedcallgroup">
+ <synopsis>The named pickup groups for a channel.</synopsis>
+ <description><para>
+ Can be set to a comma separated list of case sensitive strings limited by
+ supported line length.
+ </para></description>
+ </configOption>
+ <configOption name="namedpickupgroup">
+ <synopsis>The named pickup groups that a channel can pickup.</synopsis>
+ <description><para>
+ Can be set to a comma separated list of case sensitive strings limited by
+ supported line length.
+ </para></description>
+ </configOption>
<configOption name="devicestate_busy_at" default="0">
<synopsis>The number of in-use channels which will cause busy to be returned as device state</synopsis>
<description><para>
@@ -479,6 +560,35 @@
Time to keep alive a contact. String style specification.
</para></description>
</configOption>
+ <configOption name="qualify_frequency" default="0">
+ <synopsis>Interval at which to qualify a contact</synopsis>
+ <description><para>
+ Interval between attempts to qualify the contact for reachability.
+ If <literal>0</literal> never qualify. Time in seconds.
+ </para></description>
+ </configOption>
+ </configObject>
+ <configObject name="contact_status">
+ <synopsis>Status for a contact</synopsis>
+ <description><para>
+ The contact status keeps track of whether or not a contact is reachable
+ and how long it took to qualify the contact (round trip time).
+ </para></description>
+ <configOption name="status">
+ <synopsis>A contact's status</synopsis>
+ <description>
+ <enumlist>
+ <enum name="AVAILABLE" />
+ <enum name="UNAVAILABLE" />
+ </enumlist>
+ </description>
+ </configOption>
+ <configOption name="rtt">
+ <synopsis>Round trip time</synopsis>
+ <description><para>
+ The time, in microseconds, it took to qualify the contact.
+ </para></description>
+ </configOption>
</configObject>
<configObject name="aor">
<synopsis>The configuration for a location of an endpoint</synopsis>
@@ -549,6 +659,20 @@
<configOption name="type">
<synopsis>Must be of type 'aor'.</synopsis>
</configOption>
+ <configOption name="qualify_frequency" default="0">
+ <synopsis>Interval at which to qualify an AoR</synopsis>
+ <description><para>
+ Interval between attempts to qualify the AoR for reachability.
+ If <literal>0</literal> never qualify. Time in seconds.
+ </para></description>
+ </configOption>
+ <configOption name="authenticate_qualify" default="no">
+ <synopsis>Authenticates a qualify request if needed</synopsis>
+ <description><para>
+ If true and a qualify request receives a challenge or authenticate response
+ authentication is attempted before declaring the contact available.
+ </para></description>
+ </configOption>
</configObject>
</configFile>
</configInfo>
@@ -782,7 +906,7 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u
}
/* If the host is IPv6 turn the transport into an IPv6 version */
- if (pj_strchr(&sip_uri->host, ':')) {
+ if (pj_strchr(&sip_uri->host, ':') && type < PJSIP_TRANSPORT_START_OTHER) {
type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
}
@@ -792,8 +916,8 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u
return -1;
}
- /* If IPv6 was not specified in the host but is in the transport, set the proper type */
- if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
+ /* If IPv6 was specified in the transport, set the proper type */
+ if (pj_strchr(&local_addr, ':') && type < PJSIP_TRANSPORT_START_OTHER) {
type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
}
@@ -828,10 +952,10 @@ static int sip_get_tpselector_from_endpoint(const struct ast_sip_endpoint *endpo
return -1;
}
- if (transport->type == AST_TRANSPORT_UDP) {
+ if (transport->state->transport) {
selector->type = PJSIP_TPSELECTOR_TRANSPORT;
selector->u.transport = transport->state->transport;
- } else if (transport->type == AST_TRANSPORT_TCP || transport->type == AST_TRANSPORT_TLS) {
+ } else if (transport->state->factory) {
selector->type = PJSIP_TPSELECTOR_LISTENER;
selector->u.listener = transport->state->factory;
} else {
@@ -841,6 +965,22 @@ static int sip_get_tpselector_from_endpoint(const struct ast_sip_endpoint *endpo
return 0;
}
+static int sip_get_tpselector_from_uri(const char *uri, pjsip_tpselector *selector)
+{
+ RAII_VAR(struct ast_sip_contact_transport *, contact_transport, NULL, ao2_cleanup);
+
+ contact_transport = ast_sip_location_retrieve_contact_transport_by_uri(uri);
+
+ if (!contact_transport) {
+ return -1;
+ }
+
+ selector->type = PJSIP_TPSELECTOR_TRANSPORT;
+ selector->u.transport = contact_transport->transport;
+
+ return 0;
+}
+
pjsip_dialog *ast_sip_create_dialog(const struct ast_sip_endpoint *endpoint, const char *uri, const char *request_user)
{
pj_str_t local_uri = { "sip:temp@temp", 13 }, remote_uri;
@@ -855,7 +995,7 @@ pjsip_dialog *ast_sip_create_dialog(const struct ast_sip_endpoint *endpoint, con
return NULL;
}
- if (sip_get_tpselector_from_endpoint(endpoint, &selector)) {
+ if (sip_get_tpselector_from_uri(uri, &selector) && sip_get_tpselector_from_endpoint(endpoint, &selector)) {
pjsip_dlg_terminate(dlg);
return NULL;
}
@@ -905,6 +1045,7 @@ pjsip_dialog *ast_sip_create_dialog(const struct ast_sip_endpoint *endpoint, con
/* PJSIP doesn't know about the INFO method, so we have to define it ourselves */
const pjsip_method pjsip_info_method = {PJSIP_OTHER_METHOD, {"INFO", 4} };
+const pjsip_method pjsip_message_method = {PJSIP_OTHER_METHOD, {"MESSAGE", 7} };
static struct {
const char *method;
@@ -920,6 +1061,7 @@ static struct {
{ "NOTIFY", &pjsip_notify_method },
{ "PUBLISH", &pjsip_publish_method },
{ "INFO", &pjsip_info_method },
+ { "MESSAGE", &pjsip_message_method },
};
static const pjsip_method *get_pjsip_method(const char *method)
@@ -953,6 +1095,11 @@ static int create_out_of_dialog_request(const pjsip_method *method, struct ast_s
pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
if (ast_strlen_zero(uri)) {
+ if (!endpoint) {
+ ast_log(LOG_ERROR, "An endpoint and/or uri must be specified\n");
+ return -1;
+ }
+
contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->aors);
if (!contact || ast_strlen_zero(contact->uri)) {
ast_log(LOG_ERROR, "Unable to retrieve contact for endpoint %s\n",
@@ -965,10 +1112,12 @@ static int create_out_of_dialog_request(const pjsip_method *method, struct ast_s
pj_cstr(&remote_uri, uri);
}
- if (sip_get_tpselector_from_endpoint(endpoint, &selector)) {
- ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport selector for endpoint %s\n",
+ if (endpoint) {
+ if (sip_get_tpselector_from_endpoint(endpoint, &selector)) {
+ ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport selector for endpoint %s\n",
ast_sorcery_object_get_id(endpoint));
- return -1;
+ return -1;
+ }
}
pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Outbound request", 256, 256);
@@ -1073,7 +1222,7 @@ int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value
pj_str_t hdr_name;
pj_str_t hdr_value;
pjsip_generic_string_hdr *hdr;
-
+
pj_cstr(&hdr_name, name);
pj_cstr(&hdr_value, value);
@@ -1092,7 +1241,7 @@ static pjsip_msg_body *ast_body_to_pjsip_body(pj_pool_t *pool, const struct ast_
pj_cstr(&type, body->type);
pj_cstr(&subtype, body->subtype);
pj_cstr(&body_text, body->body_text);
-
+
return pjsip_msg_body_create(pool, &type, &subtype, &body_text);
}
@@ -1213,13 +1362,26 @@ int ast_sip_push_task_synchronous(struct ast_taskprocessor *serializer, int (*si
return std.fail;
}
-void ast_copy_pj_str(char *dest, pj_str_t *src, size_t size)
+void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
{
size_t chars_to_copy = MIN(size - 1, pj_strlen(src));
memcpy(dest, pj_strbuf(src), chars_to_copy);
dest[chars_to_copy] = '\0';
}
+int ast_sip_is_content_type(pjsip_media_type *content_type, char *type, char *subtype)
+{
+ pjsip_media_type compare;
+
+ if (!content_type) {
+ return 0;
+ }
+
+ pjsip_media_type_init2(&compare, type, subtype);
+
+ return pjsip_media_type_cmp(content_type, &compare, 0) ? -1 : 0;
+}
+
pj_caching_pool caching_pool;
pj_pool_t *memory_pool;
pj_thread_t *monitor_thread;
@@ -1352,6 +1514,8 @@ static int load_module(void)
ast_res_sip_init_options_handling(0);
+ ast_res_sip_init_contact_transports();
+
return AST_MODULE_LOAD_SUCCESS;
error: