[svn-commits] oej: branch oej/codename-pineapple r45740 - in
/team/oej/codename-pineapple/c...
svn-commits at lists.digium.com
svn-commits at lists.digium.com
Fri Oct 20 00:32:59 MST 2006
Author: oej
Date: Fri Oct 20 02:32:58 2006
New Revision: 45740
URL: http://svn.digium.com/view/asterisk?rev=45740&view=rev
Log:
Updates
Modified:
team/oej/codename-pineapple/channels/chan_sip3.c
team/oej/codename-pineapple/channels/sip3/sip3.h
team/oej/codename-pineapple/channels/sip3/sip3_callerid.c
team/oej/codename-pineapple/channels/sip3/sip3_parse.c
Modified: team/oej/codename-pineapple/channels/chan_sip3.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/chan_sip3.c?rev=45740&r1=45739&r2=45740&view=diff
==============================================================================
--- team/oej/codename-pineapple/channels/chan_sip3.c (original)
+++ team/oej/codename-pineapple/channels/chan_sip3.c Fri Oct 20 02:32:58 2006
@@ -200,6 +200,8 @@
#include "asterisk/localtime.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/compiler.h"
+#include "asterisk/threadstorage.h"
+
#include "sip3/sip3.h"
#include "sip3/sip3funcs.h"
@@ -260,6 +262,9 @@
/*! \brief The register list: Other SIP proxys we register with and place calls to */
struct sip_register_list regl;
+
+/*! \brief A per-thread temporary pvt structure */
+AST_THREADSTORAGE_CUSTOM(ts_temp_pvt, temp_pvt_init, temp_pvt_cleanup);
/*! \todo Move the sip_auth list to AST_LIST */
struct sip_auth *authl = NULL; /*!< Authentication list for realm authentication */
@@ -288,6 +293,7 @@
/*--- Transmitting responses and requests */
static int __transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
static int transmit_sip_request(struct sip_pvt *p, struct sip_request *req);
+static int transmit_response_using_temp(ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg);
static int transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req);
static int transmit_response_reliable(struct sip_pvt *p, const char *msg, const struct sip_request *req);
static int transmit_response_with_date(struct sip_pvt *p, const char *msg, const struct sip_request *req);
@@ -2759,7 +2765,7 @@
Called by handle_request, sipsock_read */
GNURK struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method)
{
- struct sip_pvt *p;
+ struct sip_pvt *p = NULL;
char *tag = ""; /* note, tag is never NULL */
char totag[128];
char fromtag[128];
@@ -2820,9 +2826,25 @@
}
}
ast_mutex_unlock(&iflock);
- /* Allocate new call */
- if ((p = sip_alloc(callid, sin, 1, intended_method)))
- ast_mutex_lock(&p->lock);
+ if (sip_methods[intended_method].creates_dialog == CAN_CREATE_DIALOG) {
+ /* This method creates dialog */
+ if ((p = sip_alloc(callid, sin, 1, intended_method)))
+ /* Ok, we've created a dialog, let's go and process it */
+ ast_mutex_lock(&p->lock);
+ return(p);
+ } else if (intented_method = SIP_REFER) {
+
+ /* We do not support out-of-dialog REFERs yet */
+ transmit_response_using_temp(callid, sin, 1, intended_method, req, "603 Declined (no dialog)");
+ } else if (intented_method = SIP_NOTIFY) {
+ /* We do not support out-of-dialog NOTIFY either,
+ like voicemail notification, so cancel that early */
+ transmit_response_using_temp(callid, sin, 1, intended_method, req, "489 Bad event");
+ } else {
+ if (intended_method != SIP_RESPONSE)
+ transmit_response_using_temp(callid, sin, 1, intended_method, req, "481 Call leg/transaction does not exist");
+ }
+
return p;
}
@@ -3450,6 +3472,73 @@
add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
}
return send_response(p, &resp, reliable, seqno);
+}
+
+/*! \brief Initialize temporary PVT */
+static int temp_pvt_init(void *data)
+{
+ struct sip_pvt *p = data;
+
+ ast_set_flag(&p->flags[0], SIP_NO_HISTORY);
+ return ast_string_field_init(p, 512);
+}
+
+/*! \brief Cleanup temporary PVT */
+static void temp_pvt_cleanup(void *data)
+{
+ struct sip_pvt *p = data;
+
+ ast_string_field_free_pools(p);
+
+ free(data);
+}
+
+/*! \brief Transmit response, no retransmits, using a temporary pvt structure */
+static int transmit_response_using_temp(ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg)
+{
+ struct sip_pvt *p = NULL;
+
+ if (!(p = ast_threadstorage_get(&ts_temp_pvt, sizeof(*p)))) {
+ ast_log(LOG_NOTICE, "Failed to get temporary pvt\n");
+ return -1;
+ }
+
+ memset(p, 0, sizeof(*p));
+
+ /* Initialize the bare minimum */
+ if (ast_string_field_init(p, 512))
+ return -1;
+
+ p->method = intended_method;
+
+ if (sin) {
+ p->sa = *sin;
+ if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
+ p->ourip = __ourip;
+ } else
+ p->ourip = __ourip;
+
+ p->branch = ast_random();
+ make_our_tag(p->tag, sizeof(p->tag));
+ p->ocseq = INITIAL_CSEQ;
+
+ if (useglobal_nat && sin) {
+ ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT);
+ p->recv = *sin;
+ do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE);
+ }
+
+ ast_string_field_set(p, fromdomain, global.default_fromdomain);
+ build_via(p);
+ ast_string_field_set(p, callid, callid);
+
+ /* Use this temporary pvt structure to send the message */
+ __transmit_response(p, msg, req, XMIT_UNRELIABLE);
+
+ /* Now do a simple destruction */
+ ast_string_field_free_all(p);
+
+ return 0;
}
/*! \brief Transmit response, no retransmits */
@@ -6052,81 +6141,6 @@
}
}
}
-
-/*! \brief Get caller id name from SIP headers */
-static char *get_calleridname(const char *input, char *output, size_t outputsize)
-{
- const char *end = strchr(input,'<'); /* first_bracket */
- const char *tmp = strchr(input,'"'); /* first quote */
- int bytes = 0;
- int maxbytes = outputsize - 1;
-
- if (!end || end == input) /* we require a part in brackets */
- return NULL;
-
- /* move away from "<" */
- end--;
-
- /* we found "name" */
- if (tmp && tmp < end) {
- end = strchr(tmp+1, '"');
- if (!end)
- return NULL;
- bytes = (int) (end - tmp);
- /* protect the output buffer */
- if (bytes > maxbytes)
- bytes = maxbytes;
- ast_copy_string(output, tmp + 1, bytes);
- } else {
- /* we didn't find "name" */
- /* clear the empty characters in the begining*/
- input = ast_skip_blanks(input);
- /* clear the empty characters in the end */
- while(*end && *end < 33 && end > input)
- end--;
- if (end >= input) {
- bytes = (int) (end - input) + 2;
- /* protect the output buffer */
- if (bytes > maxbytes)
- bytes = maxbytes;
- ast_copy_string(output, input, bytes);
- } else
- return NULL;
- }
- return output;
-}
-
-/*! \brief Get caller id number from Remote-Party-ID header field
- * Returns true if number should be restricted (privacy setting found)
- * output is set to NULL if no number found
- */
-static int get_rpid_num(const char *input, char *output, int maxlen)
-{
- char *start;
- char *end;
-
- start = strchr(input,':');
- if (!start) {
- output[0] = '\0';
- return 0;
- }
- start++;
-
- /* we found "number" */
- ast_copy_string(output,start,maxlen);
- output[maxlen-1] = '\0';
-
- end = strchr(output,'@');
- if (end)
- *end = '\0';
- else
- output[0] = '\0';
- if (strstr(input,"privacy=full") || strstr(input,"privacy=uri"))
- return AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
-
- return 0;
-}
-
/*! \brief Check if matching user or peer is defined
Match user on From: user name and peer on IP/port
@@ -9506,7 +9520,10 @@
return NULL;
}
-/*! \brief Handle incoming notifications */
+/*! \brief Handle incoming notifications
+ * \note Out of dialog NOTIFY messages are killed in find_call()
+ If implementing VMI support, that needs to change
+ */
static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e)
{
/* This is mostly a skeleton for future improvements */
@@ -10478,6 +10495,7 @@
We can't destroy dialogs, since we want the call to continue.
*/
+/* XXX note that out-of-dialog refers are killed in find_call() */
static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, int *nounlock)
{
struct sip_dual current; /* Chan1: Call between asterisk and transferer */
@@ -11445,6 +11463,59 @@
}
+/*! \brief helper function for the monitoring thread */
+static void check_rtp_timeout(struct sip_pvt *sip, time_t t)
+{
+ if (sip->rtp && sip->owner &&
+ (sip->owner->_state == AST_STATE_UP) &&
+ !sip->redirip.sin_addr.s_addr) {
+ if (sip->lastrtptx &&
+ sip->rtpkeepalive &&
+ (t > sip->lastrtptx + sip->rtpkeepalive)) {
+ /* Need to send an empty RTP packet */
+ sip->lastrtptx = time(NULL);
+ ast_rtp_sendcng(sip->rtp, 0);
+ }
+ if (sip->lastrtprx &&
+ (sip->rtptimeout || sip->rtpholdtimeout) &&
+ (t > sip->lastrtprx + sip->rtptimeout)) {
+ /* Might be a timeout now -- see if we're on hold */
+ struct sockaddr_in sin;
+ ast_rtp_get_peer(sip->rtp, &sin);
+ if (sin.sin_addr.s_addr ||
+ (sip->rtpholdtimeout &&
+ (t > sip->lastrtprx + sip->rtpholdtimeout))) {
+ /* Needs a hangup */
+ if (sip->rtptimeout) {
+ while (sip->owner && ast_channel_trylock(sip->owner)) {
+ ast_mutex_unlock(&sip->lock);
+ usleep(1);
+ ast_mutex_lock(&sip->lock);
+ }
+ if (sip->owner) {
+ if (!(ast_rtp_get_bridged(sip->rtp))) {
+ ast_log(LOG_NOTICE,
+ "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n",
+ sip->owner->name,
+ (long) (t - sip->lastrtprx));
+ /* Issue a softhangup */
+ ast_softhangup_nolock(sip->owner, AST_SOFTHANGUP_DEV);
+ } else
+ ast_log(LOG_NOTICE, "'%s' will not be disconnected in %ld seconds because it is directly bridged to another RTP stream\n", sip->owner->name, (long) (t - sip->lastrtprx));
+ ast_channel_unlock(sip->owner);
+ /* forget the timeouts for this call, since a hangup
+ has already been requested and we don't want to
+ repeatedly request hangups
+ */
+ sip->rtptimeout = 0;
+ sip->rtpholdtimeout = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
/*! \brief The SIP monitoring thread
\note This thread monitors all the SIP sessions and peers that needs notification of mwi
(and thus do not have a separate thread) indefinitely
@@ -11491,54 +11562,7 @@
for (sip = dialoglist; !fastrestart && sip; sip = sip->next) {
ast_mutex_lock(&sip->lock);
/* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */
- if (sip->rtp && sip->owner &&
- (sip->owner->_state == AST_STATE_UP) &&
- !sip->redirip.sin_addr.s_addr) {
- if (sip->lastrtptx &&
- sip->rtpkeepalive &&
- (t > sip->lastrtptx + sip->rtpkeepalive)) {
- /* Need to send an empty RTP packet */
- sip->lastrtptx = time(NULL);
- ast_rtp_sendcng(sip->rtp, 0);
- }
- if (sip->lastrtprx &&
- (sip->rtptimeout || sip->rtpholdtimeout) &&
- (t > sip->lastrtprx + sip->rtptimeout)) {
- /* Might be a timeout now -- see if we're on hold */
- struct sockaddr_in sin;
- ast_rtp_get_peer(sip->rtp, &sin);
- if (sin.sin_addr.s_addr ||
- (sip->rtpholdtimeout &&
- (t > sip->lastrtprx + sip->rtpholdtimeout))) {
- /* Needs a hangup */
- if (sip->rtptimeout) {
- while (sip->owner && ast_channel_trylock(sip->owner)) {
- ast_mutex_unlock(&sip->lock);
- usleep(1);
- ast_mutex_lock(&sip->lock);
- }
- if (sip->owner) {
- if (!(ast_rtp_get_bridged(sip->rtp))) {
- ast_log(LOG_NOTICE,
- "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n",
- sip->owner->name,
- (long) (t - sip->lastrtprx));
- /* Issue a softhangup */
- ast_softhangup_nolock(sip->owner, AST_SOFTHANGUP_DEV);
- } else
- ast_log(LOG_NOTICE, "'%s' will not be disconnected in %ld seconds because it is directly bridged to another RTP stream\n", sip->owner->name, (long) (t - sip->lastrtprx));
- ast_channel_unlock(sip->owner);
- /* forget the timeouts for this call, since a hangup
- has already been requested and we don't want to
- repeatedly request hangups
- */
- sip->rtptimeout = 0;
- sip->rtpholdtimeout = 0;
- }
- }
- }
- }
- }
+ check_rtp_timeout(sip, t);
/* If we have sessions that needs to be destroyed, do it now */
if (ast_test_flag(&sip->flags[0], SIP_NEEDDESTROY) && !sip->packets &&
!sip->owner) {
Modified: team/oej/codename-pineapple/channels/sip3/sip3.h
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3.h?rev=45740&r1=45739&r2=45740&view=diff
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3.h (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3.h Fri Oct 20 02:32:58 2006
@@ -332,6 +332,7 @@
enum sipmethod id;
int need_rtp; /*!< when this is the 'primary' use for a pvt structure, does it need RTP? */
char * const text;
+ int creates_dialog; /*! Whether or not this method can create dialog */
};
/*! \brief Structure for expiration times for inbound/outbound REGISTER */
@@ -553,6 +554,9 @@
#define SIP_PKT_IGNORE (1 << 2) /*!< This is a re-transmit, ignore it */
#define SIP_PKT_IGNORE_RESP (1 << 3) /*!< Resp ignore - ??? */
#define SIP_PKT_IGNORE_REQ (1 << 4) /*!< Req ignore - ??? */
+
+#define CAN_CREATE_DIALOG 0
+#define CAN_NOT_CREATE_DIALOG 1
/* T.38 set of flags */
#define T38FAX_FILL_BIT_REMOVAL (1 << 0) /*!< Default: 0 (unset)*/
Modified: team/oej/codename-pineapple/channels/sip3/sip3_callerid.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3_callerid.c?rev=45740&r1=45739&r2=45740&view=diff
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3_callerid.c (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3_callerid.c Fri Oct 20 02:32:58 2006
@@ -80,3 +80,76 @@
#include "sip3.h"
+/*! \brief Get caller id number from Remote-Party-ID header field
+ * Returns true if number should be restricted (privacy setting found)
+ * output is set to NULL if no number found
+ */
+static int get_rpid_num(const char *input, char *output, int maxlen)
+{
+ char *start;
+ char *end;
+
+ start = strchr(input,':');
+ if (!start) {
+ output[0] = '\0';
+ return 0;
+ }
+ start++;
+
+ /* we found "number" */
+ ast_copy_string(output,start,maxlen);
+ output[maxlen-1] = '\0';
+
+ end = strchr(output,'@');
+ if (end)
+ *end = '\0';
+ else
+ output[0] = '\0';
+ if (strstr(input,"privacy=full") || strstr(input,"privacy=uri"))
+ return AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+
+ return 0;
+}
+
+/*! \brief Get caller id name from SIP headers */
+static char *get_calleridname(const char *input, char *output, size_t outputsize)
+{
+ const char *end = strchr(input,'<'); /* first_bracket */
+ const char *tmp = strchr(input,'"'); /* first quote */
+ int bytes = 0;
+ int maxbytes = outputsize - 1;
+
+ if (!end || end == input) /* we require a part in brackets */
+ return NULL;
+
+ /* move away from "<" */
+ end--;
+
+ /* we found "name" */
+ if (tmp && tmp < end) {
+ end = strchr(tmp+1, '"');
+ if (!end)
+ return NULL;
+ bytes = (int) (end - tmp);
+ /* protect the output buffer */
+ if (bytes > maxbytes)
+ bytes = maxbytes;
+ ast_copy_string(output, tmp + 1, bytes);
+ } else {
+ /* we didn't find "name" */
+ /* clear the empty characters in the begining*/
+ input = ast_skip_blanks(input);
+ /* clear the empty characters in the end */
+ while(*end && *end < 33 && end > input)
+ end--;
+ if (end >= input) {
+ bytes = (int) (end - input) + 2;
+ /* protect the output buffer */
+ if (bytes > maxbytes)
+ bytes = maxbytes;
+ ast_copy_string(output, input, bytes);
+ } else
+ return NULL;
+ }
+ return output;
+}
Modified: team/oej/codename-pineapple/channels/sip3/sip3_parse.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3_parse.c?rev=45740&r1=45739&r2=45740&view=diff
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3_parse.c (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3_parse.c Fri Oct 20 02:32:58 2006
@@ -91,22 +91,22 @@
/*! XXX Note that sip_methods[i].id == i must hold or the code breaks */
static const struct cfsip_methods sip_methods[] = {
- { SIP_UNKNOWN, RTP, "-UNKNOWN-" },
- { SIP_RESPONSE, NO_RTP, "SIP/2.0" },
- { SIP_REGISTER, NO_RTP, "REGISTER" },
- { SIP_OPTIONS, NO_RTP, "OPTIONS" },
- { SIP_NOTIFY, NO_RTP, "NOTIFY" },
- { SIP_INVITE, RTP, "INVITE" },
- { SIP_ACK, NO_RTP, "ACK" },
- { SIP_PRACK, NO_RTP, "PRACK" },
- { SIP_BYE, NO_RTP, "BYE" },
- { SIP_REFER, NO_RTP, "REFER" },
- { SIP_SUBSCRIBE, NO_RTP, "SUBSCRIBE" },
- { SIP_MESSAGE, NO_RTP, "MESSAGE" },
- { SIP_UPDATE, NO_RTP, "UPDATE" },
- { SIP_INFO, NO_RTP, "INFO" },
- { SIP_CANCEL, NO_RTP, "CANCEL" },
- { SIP_PUBLISH, NO_RTP, "PUBLISH" }
+ { SIP_UNKNOWN, RTP, "-UNKNOWN-", CAN_NOT_CREATE_DIALOG},
+ { SIP_RESPONSE, NO_RTP, "SIP/2.0" , CAN_NOT_CREATE_DIALOG},
+ { SIP_REGISTER, NO_RTP, "REGISTER" , CAN_CREATE_DIALOG},
+ { SIP_OPTIONS, NO_RTP, "OPTIONS" , CAN_CREATE_DIALOG},
+ { SIP_NOTIFY, NO_RTP, "NOTIFY" , CAN_CREATE_DIALOG},
+ { SIP_INVITE, RTP, "INVITE" , CAN_CREATE_DIALOG},
+ { SIP_ACK, NO_RTP, "ACK" , CAN_NOT_CREATE_DIALOG},
+ { SIP_PRACK, NO_RTP, "PRACK" , CAN_NOT_CREATE_DIALOG},
+ { SIP_BYE, NO_RTP, "BYE" , CAN_NOT_CREATE_DIALOG},
+ { SIP_REFER, NO_RTP, "REFER" , CAN_CREATE_DIALOG},
+ { SIP_SUBSCRIBE, NO_RTP, "SUBSCRIBE" , CAN_CREATE_DIALOG},
+ { SIP_MESSAGE, NO_RTP, "MESSAGE" , CAN_CREATE_DIALOG},
+ { SIP_UPDATE, NO_RTP, "UPDATE" , CAN_NOT_CREATE_DIALOG},
+ { SIP_INFO, NO_RTP, "INFO" , CAN_NOT_CREATE_DIALOG},
+ { SIP_CANCEL, NO_RTP, "CANCEL" , CAN_NOT_CREATE_DIALOG},
+ { SIP_PUBLISH, NO_RTP, "PUBLISH", CAN_CREATE_DIALOG}
};
/*! \brief List of well-known SIP options. If we get this in a require,
More information about the svn-commits
mailing list