[asterisk-commits] oej: branch oej/sipregister r44756 - in
/team/oej/sipregister: ./ channels/
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Mon Oct 9 04:39:51 MST 2006
Author: oej
Date: Mon Oct 9 06:39:50 2006
New Revision: 44756
URL: http://svn.digium.com/view/asterisk?rev=44756&view=rev
Log:
Update 2
Modified:
team/oej/sipregister/ (props changed)
team/oej/sipregister/channels/chan_sip.c
Propchange: team/oej/sipregister/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Oct 9 06:39:50 2006
@@ -1,1 +1,1 @@
-/trunk:1-44726
+/trunk:1-44755
Modified: team/oej/sipregister/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/sipregister/channels/chan_sip.c?rev=44756&r1=44755&r2=44756&view=diff
==============================================================================
--- team/oej/sipregister/channels/chan_sip.c (original)
+++ team/oej/sipregister/channels/chan_sip.c Mon Oct 9 06:39:50 2006
@@ -1581,7 +1581,7 @@
{
int res;
const struct sockaddr_in *dst = sip_real_dst(p);
- res=sendto(sipsock, data, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
+ res = sendto(sipsock, data, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in));
if (res != len)
ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s:%d returned %d: %s\n", data, len, ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), res, strerror(errno));
@@ -2804,7 +2804,7 @@
static int update_call_counter(struct sip_pvt *fup, int event)
{
char name[256];
- int *inuse, *call_limit;
+ int *inuse, *call_limit, *inringing;
int outgoing = ast_test_flag(&fup->flags[0], SIP_OUTGOING);
struct sip_user *u = NULL;
struct sip_peer *p = NULL;
@@ -2818,65 +2818,91 @@
ast_copy_string(name, fup->username, sizeof(name));
- /* Check the list of users */
- if (!outgoing) /* Only check users for incoming calls */
- u = find_user(name, 1);
-
- if (u) {
+ /* Check the list of users only for incoming calls */
+ if (!outgoing && (u = find_user(name, 1)) ) {
inuse = &u->inUse;
call_limit = &u->call_limit;
- p = NULL;
+ inringing = NULL;
+ } else if ( (p = find_peer(fup->peername, NULL, 1) ) ) { /* Try to find peer */
+ inuse = &p->inUse;
+ call_limit = &p->call_limit;
+ inringing = &p->inRinging;
+ ast_copy_string(name, fup->peername, sizeof(name));
} else {
- /* Try to find peer */
- if (!p)
- p = find_peer(fup->peername, NULL, 1);
- if (p) {
- inuse = &p->inUse;
- call_limit = &p->call_limit;
- ast_copy_string(name, fup->peername, sizeof(name));
+ if (option_debug > 1)
+ ast_log(LOG_DEBUG, "%s is not a local device, no call limit\n", name);
+ return 0;
+ }
+
+ switch(event) {
+ /* incoming and outgoing affects the inUse counter */
+ case DEC_CALL_LIMIT:
+ if ( *inuse > 0 ) {
+ if (ast_test_flag(&fup->flags[0], SIP_INC_COUNT))
+ (*inuse)--;
} else {
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "%s is not a local user, no call limit\n", name);
- return 0;
- }
- }
- switch(event) {
- /* incoming and outgoing affects the inUse counter */
- case DEC_CALL_LIMIT:
- if ( *inuse > 0 ) {
- if (ast_test_flag(&fup->flags[0], SIP_INC_COUNT))
- (*inuse)--;
- } else {
- *inuse = 0;
+ *inuse = 0;
+ }
+ if (inringing) {
+ if (ast_test_flag(&fup->flags[1], SIP_PAGE2_INC_RINGING)) {
+ if (*inringing > 0)
+ (*inringing)--;
+ else
+ ast_log(LOG_WARNING, "Inringing for peer '%s' < 0?\n", fup->peername);
+ ast_clear_flag(&fup->flags[1], SIP_PAGE2_INC_RINGING);
}
- if (option_debug > 1 || sipdebug) {
- ast_log(LOG_DEBUG, "Call %s %s '%s' removed from call limit %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *call_limit);
+ }
+ if (option_debug > 1 || sipdebug) {
+ ast_log(LOG_DEBUG, "Call %s %s '%s' removed from call limit %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *call_limit);
+ }
+ break;
+
+ case INC_CALL_RINGING:
+ case INC_CALL_LIMIT:
+ if (*call_limit > 0 ) {
+ if (*inuse >= *call_limit) {
+ ast_log(LOG_ERROR, "Call %s %s '%s' rejected due to usage limit of %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *call_limit);
+ if (u)
+ ASTOBJ_UNREF(u, sip_destroy_user);
+ else
+ ASTOBJ_UNREF(p, sip_destroy_peer);
+ return -1;
}
- break;
- case INC_CALL_LIMIT:
- if (*call_limit > 0 ) {
- if (*inuse >= *call_limit) {
- ast_log(LOG_ERROR, "Call %s %s '%s' rejected due to usage limit of %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *call_limit);
- if (u)
- ASTOBJ_UNREF(u, sip_destroy_user);
- else
- ASTOBJ_UNREF(p, sip_destroy_peer);
- return -1;
- }
+ }
+ if (inringing && (event == INC_CALL_RINGING)) {
+ if (!ast_test_flag(&fup->flags[1], SIP_PAGE2_INC_RINGING)) {
+ (*inringing)++;
+ ast_set_flag(&fup->flags[1], SIP_PAGE2_INC_RINGING);
}
- (*inuse)++;
- ast_set_flag(&fup->flags[0], SIP_INC_COUNT);
- if (option_debug > 1 || sipdebug) {
- ast_log(LOG_DEBUG, "Call %s %s '%s' is %d out of %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *inuse, *call_limit);
+ }
+ /* Continue */
+ (*inuse)++;
+ ast_set_flag(&fup->flags[0], SIP_INC_COUNT);
+ if (option_debug > 1 || sipdebug) {
+ ast_log(LOG_DEBUG, "Call %s %s '%s' is %d out of %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *inuse, *call_limit);
+ }
+ break;
+
+ case DEC_CALL_RINGING:
+ if (inringing) {
+ if (ast_test_flag(&fup->flags[1], SIP_PAGE2_INC_RINGING)) {
+ if (*inringing > 0)
+ (*inringing)--;
+ else
+ ast_log(LOG_WARNING, "Inringing for peer '%s' < 0?\n", p->name);
+ ast_clear_flag(&fup->flags[1], SIP_PAGE2_INC_RINGING);
}
- break;
- default:
- ast_log(LOG_ERROR, "update_call_counter(%s, %d) called with no event!\n", name, event);
- }
- if (u)
+ }
+ break;
+
+ default:
+ ast_log(LOG_ERROR, "update_call_counter(%s, %d) called with no event!\n", name, event);
+ }
+ if (p) {
+ ast_device_state_changed("SIP/%s", p->name);
+ ASTOBJ_UNREF(p, sip_destroy_peer);
+ } else /* u must be set */
ASTOBJ_UNREF(u, sip_destroy_user);
- else
- ASTOBJ_UNREF(p, sip_destroy_peer);
return 0;
}
@@ -4184,70 +4210,43 @@
*/
static void parse_request(struct sip_request *req)
{
- /* Divide fields by NULL's */
- char *c;
- int f = 0;
-
- c = req->data;
-
- /* First header starts immediately */
- req->header[f] = c;
- while(*c) {
- if (*c == '\n') {
- /* We've got a new header */
- *c = 0;
-
+ char *c = req->data, **dst = req->header;
+ int i = 0, lim = SIP_MAX_HEADERS - 1;
+
+ req->header[0] = c;
+ req->headers = -1; /* mark that we are working on the header */
+ for (; *c; c++) {
+ if (*c == '\r') /* remove \r */
+ *c = '\0';
+ else if (*c == '\n') { /* end of this line */
+ *c = '\0';
if (sipdebug && option_debug > 3)
- ast_log(LOG_DEBUG, "Header %d: %s (%d)\n", f, req->header[f], (int) strlen(req->header[f]));
- if (ast_strlen_zero(req->header[f])) {
- /* Line by itself means we're now in content */
- c++;
- break;
+ ast_log(LOG_DEBUG, "%7s %2d [%3d]: %s\n",
+ req->headers < 0 ? "Header" : "Body",
+ i, strlen(dst[i]), dst[i]);
+ if (ast_strlen_zero(dst[i]) && req->headers < 0) {
+ req->headers = i; /* record number of header lines */
+ dst = req->line; /* start working on the body */
+ i = 0;
+ lim = SIP_MAX_LINES - 1;
+ } else { /* move to next line, check for overflows */
+ if (i++ >= lim)
+ break;
}
- if (f >= SIP_MAX_HEADERS - 1) {
- ast_log(LOG_WARNING, "Too many SIP headers. Ignoring.\n");
- } else
- f++;
- req->header[f] = c + 1;
- } else if (*c == '\r') {
- /* Ignore but eliminate \r's */
- *c = 0;
- }
- c++;
- }
- /* Check for last header */
- if (!ast_strlen_zero(req->header[f])) {
- if (sipdebug && option_debug > 3)
- ast_log(LOG_DEBUG, "Header %d: %s (%d)\n", f, req->header[f], (int) strlen(req->header[f]));
- f++;
- }
- req->headers = f;
- /* Now we process any mime content */
- f = 0;
- req->line[f] = c;
- while(*c) {
- if (*c == '\n') {
- /* We've got a new line */
- *c = 0;
- if (sipdebug && option_debug > 3)
- ast_log(LOG_DEBUG, "Line: %s (%d)\n", req->line[f], (int) strlen(req->line[f]));
- if (f >= SIP_MAX_LINES - 1) {
- ast_log(LOG_WARNING, "Too many SDP lines. Ignoring.\n");
- } else
- f++;
- req->line[f] = c + 1;
- } else if (*c == '\r') {
- /* Ignore and eliminate \r's */
- *c = 0;
- }
- c++;
- }
- /* Check for last line */
- if (!ast_strlen_zero(req->line[f]))
- f++;
- req->lines = f;
- if (*c)
- ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
+ dst[i] = c + 1; /* record start of next line */
+ }
+ }
+ /* update count of header or body lines */
+ if (req->headers >= 0) /* we are in the body */
+ req->lines = i;
+ else { /* no body */
+ req->headers = i;
+ req->lines = 0;
+ req->line[0] = "";
+ }
+
+ if (*c)
+ ast_log(LOG_WARNING, "Too many lines, skipping <%s>\n", c);
/* Split up the first line parts */
determine_firstline_parts(req);
}
@@ -6108,31 +6107,25 @@
char tmp[BUFSIZ/2];
char tmp2[BUFSIZ/2];
const char *l = NULL, *n = NULL;
- int x;
- char urioptions[256]="";
+ const char *urioptions = "";
if (ast_test_flag(&p->flags[0], SIP_USEREQPHONE)) {
- char onlydigits = TRUE;
- x=0;
+ const char *s = p->username; /* being a string field, cannot be NULL */
/* Test p->username against allowed characters in AST_DIGIT_ANY
If it matches the allowed characters list, then sipuser = ";user=phone"
If not, then sipuser = ""
*/
/* + is allowed in first position in a tel: uri */
- if (p->username && p->username[0] == '+')
- x=1;
-
- for (; x < strlen(p->username); x++) {
- if (!strchr(AST_DIGIT_ANYNUM, p->username[x])) {
- onlydigits = FALSE;
+ if (*s == '+')
+ s++;
+ for (; *s; s++) {
+ if (!strchr(AST_DIGIT_ANYNUM, *s) )
break;
- }
- }
-
+ }
/* If we have only digits, add ;user=phone to the uri */
- if (onlydigits)
- strcpy(urioptions, ";user=phone");
+ if (*s)
+ urioptions = ";user=phone";
}
@@ -6276,25 +6269,21 @@
add_header(&req, "Allow", ALLOWED_METHODS);
add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
- if (p->options && p->options->addsipheaders ) {
- struct ast_channel *ast;
- struct varshead *headp = NULL;
- const struct ast_var_t *current;
-
- ast = p->owner; /* The owner channel */
- if (ast) {
- char *headdup;
- headp = &ast->varshead;
+ if (p->options && p->options->addsipheaders && p->owner) {
+ struct ast_channel *ast = p->owner; /* The owner channel */
+ struct varshead *headp = &ast->varshead;
+
if (!headp)
ast_log(LOG_WARNING,"No Headp for the channel...ooops!\n");
else {
+ const struct ast_var_t *current;
AST_LIST_TRAVERSE(headp, current, entries) {
/* SIPADDHEADER: Add SIP header to outgoing call */
if (!strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) {
char *content, *end;
const char *header = ast_var_value(current);
-
- headdup = ast_strdupa(header);
+ char *headdup = ast_strdupa(header);
+
/* Strip of the starting " (if it's there) */
if (*headdup == '"')
headdup++;
@@ -6313,7 +6302,6 @@
}
}
}
- }
}
if (sdp) {
if (p->udptl && p->t38.state == T38_LOCAL_DIRECT) {
@@ -11416,7 +11404,7 @@
}
/*! \brief Immediately stop RTP, VRTP and UDPTL as applicable */
-static void stop_data_flows(struct sip_pvt *p)
+static void stop_media_flows(struct sip_pvt *p)
{
/* Immediately stop RTP, VRTP and UDPTL as applicable */
if (p->rtp)
@@ -11615,7 +11603,7 @@
ast_verbose(VERBOSE_PREFIX_3 "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(p->sa.sin_addr));
ast_set_flag(&p->flags[0], SIP_ALREADYGONE);
- stop_data_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */
+ stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */
/* XXX Locking issues?? XXX */
switch(resp) {
@@ -13256,7 +13244,7 @@
ast_log(LOG_DEBUG, "Got CANCEL on an answered call. Ignoring... \n");
return 0;
}
- stop_data_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */
+ stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */
if (p->owner)
ast_queue_hangup(p->owner);
@@ -13305,7 +13293,7 @@
}
}
- stop_data_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */
+ stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */
if (!ast_strlen_zero(get_header(req, "Also"))) {
ast_log(LOG_NOTICE, "Client '%s' using deprecated BYE/Also transfer method. Ask vendor to support REFER instead\n",
@@ -13853,11 +13841,11 @@
struct sockaddr_in sin = { 0, };
struct sip_pvt *p;
int res;
- socklen_t len;
+ socklen_t len = sizeof(sin);
int nounlock;
int recount = 0;
-
- len = sizeof(sin);
+ int lockretry;
+
memset(&req, 0, sizeof(req));
res = recvfrom(sipsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
if (res < 0) {
@@ -13885,51 +13873,59 @@
parse_request(&req);
req.method = find_sip_method(req.rlPart1);
- if (ast_test_flag(&req, SIP_PKT_DEBUG)) {
+
+ if (ast_test_flag(&req, SIP_PKT_DEBUG))
ast_verbose("--- (%d headers %d lines)%s ---\n", req.headers, req.lines, (req.headers + req.lines == 0) ? " Nat keepalive" : "");
- }
-
- if (req.headers < 2) {
- /* Must have at least two headers */
+
+ if (req.headers < 2) /* Must have at least two headers */
return 1;
- }
-
-
- /* Process request, with netlock held */
-retrylock:
- ast_mutex_lock(&netlock);
-
- /* Find the active SIP dialog or create a new one */
- p = find_call(&req, &sin, req.method); /* returns p locked */
- if (p) {
+
+ /* Process request, with netlock held, and with usual deadlock avoidance */
+ for (lockretry = 100; lockretry > 0; lockretry--) {
+ ast_mutex_lock(&netlock);
+
+ /* Find the active SIP dialog or create a new one */
+ p = find_call(&req, &sin, req.method); /* returns p locked */
+ if (p == NULL) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Invalid SIP message - rejected , no callid, len %d\n", req.len);
+ ast_mutex_unlock(&netlock);
+ return 1;
+ }
/* Go ahead and lock the owner if it has one -- we may need it */
/* becaues this is deadlock-prone, we need to try and unlock if failed */
- if (p->owner && ast_channel_trylock(p->owner)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Failed to grab lock, trying again...\n");
- ast_mutex_unlock(&p->lock);
- ast_mutex_unlock(&netlock);
- /* Sleep infintismly short amount of time */
- usleep(1);
- goto retrylock;
- }
- p->recv = sin;
- if (recordhistory) /* This is a request or response, note what it was for */
- append_history(p, "Rx", "%s / %s / %s", req.data, get_header(&req, "CSeq"), req.rlPart2);
- nounlock = 0;
- if (handle_request(p, &req, &sin, &recount, &nounlock) == -1) {
- /* Request failed */
- if (option_debug)
- ast_log(LOG_DEBUG, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>");
- }
+ if (!p->owner || !ast_channel_trylock(p->owner))
+ break; /* locking succeeded */
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Failed to grab owner channel lock, trying again. (SIP call %s)\n", p->callid);
+ ast_mutex_unlock(&p->lock);
+ ast_mutex_unlock(&netlock);
+ /* Sleep for a very short amount of time */
+ usleep(1);
+ }
+ p->recv = sin;
+
+ if (recordhistory) /* This is a request or response, note what it was for */
+ append_history(p, "Rx", "%s / %s / %s", req.data, get_header(&req, "CSeq"), req.rlPart2);
+
+ if (!lockretry) {
+ ast_log(LOG_ERROR, "We could NOT get the channel lock for %s! \n", S_OR(p->owner->name, "- no channel name ??? - "));
+ ast_log(LOG_ERROR, "SIP transaction failed: %s \n", p->callid);
+ transmit_response(p, "503 Server error", &req); /* We must respond according to RFC 3261 sec 12.2 */
+ /* XXX We could add retry-after to make sure they come back */
+ append_history(p, "LockFail", "Owner lock failed, transaction failed.");
+ return 1;
+ }
+ nounlock = 0;
+ if (handle_request(p, &req, &sin, &recount, &nounlock) == -1) {
+ /* Request failed */
+ if (option_debug)
+ ast_log(LOG_DEBUG, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>");
+ }
- if (p->owner && !nounlock)
- ast_channel_unlock(p->owner);
- ast_mutex_unlock(&p->lock);
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Invalid SIP message - rejected , bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>");
- }
+ if (p->owner && !nounlock)
+ ast_channel_unlock(p->owner);
+ ast_mutex_unlock(&p->lock);
ast_mutex_unlock(&netlock);
if (recount)
ast_update_use_count();
@@ -15631,13 +15627,13 @@
close(sipsock);
sipsock = -1;
} else {
- if (option_verbose > 1) {
+ if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "SIP Listening on %s:%d\n",
- ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
- ast_verbose(VERBOSE_PREFIX_2 "Using SIP TOS: %s\n", ast_tos2str(global_tos_sip));
- }
+ ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
if (setsockopt(sipsock, IPPROTO_IP, IP_TOS, &global_tos_sip, sizeof(global_tos_sip)))
ast_log(LOG_WARNING, "Unable to set SIP TOS to %s\n", ast_tos2str(global_tos_sip));
+ else if (option_verbose > 1)
+ ast_verbose(VERBOSE_PREFIX_2 "Using SIP TOS: %s\n", ast_tos2str(global_tos_sip));
}
}
}
More information about the asterisk-commits
mailing list