SIP cleanups for database linkage

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2781 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer 2004-04-26 14:54:33 +00:00
parent 0d048dee56
commit f4b55b802c
1 changed files with 187 additions and 135 deletions

View File

@ -59,7 +59,7 @@
#include <mysql/mysql.h>
#endif
#define VIDEO_CODEC_MASK 0x1fc0000 // Video codecs from H.261 thru AST_FORMAT_MAX_VIDEO
#define VIDEO_CODEC_MASK 0x1fc0000 /* Video codecs from H.261 thru AST_FORMAT_MAX_VIDEO */
#ifndef IPTOS_MINCOST
#define IPTOS_MINCOST 0x02
#endif
@ -445,10 +445,10 @@ static int transmit_message_with_text(struct sip_pvt *p, char *text);
static int transmit_refer(struct sip_pvt *p, char *dest);
static struct sip_peer *temp_peer(char *name);
static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader, char *msg, int init);
// static char *getsipuri(char *header);
/* static char *getsipuri(char *header); */
static void free_old_route(struct sip_route *route);
static int build_reply_digest(struct sip_pvt *p, char *orig_header, char *digest, int digest_len);
static int find_user(struct sip_pvt *fup, int event);
static int update_user_counter(struct sip_pvt *fup, int event);
static void prune_peers(void);
static int sip_do_reload(void);
@ -805,6 +805,65 @@ static struct sip_peer *mysql_peer(char *peer, struct sockaddr_in *sin)
}
#endif /* MYSQL_FRIENDS */
static void update_peer(struct sip_peer *p, int expiry)
{
#ifdef MYSQL_FRIENDS
if (p->temponly)
mysql_update_peer(p->name, &p->addr, p->username, expiry);
#endif
return;
}
static struct sip_peer *find_peer(char *peer, struct sockaddr_in *sin)
{
struct sip_peer *p = NULL;
p = peerl.peers;
if (peer) {
/* Find by peer name */
while(p) {
if (!strcasecmp(p->name, peer)) {
break;
}
p = p->next;
}
}
else {
/* Find by sin */
while(p) {
if (!inaddrcmp(&p->addr, sin) ||
(p->insecure &&
(p->addr.sin_addr.s_addr == sin->sin_addr.s_addr))) {
break;
}
p = p->next;
}
}
#ifdef MYSQL_FRIENDS
if (!p) {
p = mysql_peer(peer, sin);
}
#endif
return(p);
}
static struct sip_user *find_user(char *name)
{
struct sip_user *u = NULL;
u = userl.users;
while(u) {
if (!strcasecmp(u->name, name)) {
break;
}
u = u->next;
}
return(u);
}
static int create_addr(struct sip_pvt *r, char *peer)
{
struct hostent *hp;
@ -817,16 +876,7 @@ static int create_addr(struct sip_pvt *r, char *peer)
r->sa.sin_family = AF_INET;
ast_mutex_lock(&peerl.lock);
p = peerl.peers;
while(p) {
if (!strcasecmp(p->name, peer))
break;
p = p->next;
}
#ifdef MYSQL_FRIENDS
if (!p)
p = mysql_peer(peer, NULL);
#endif
p = find_peer(peer, NULL);
if (p) {
found++;
@ -879,8 +929,12 @@ static int create_addr(struct sip_pvt *r, char *peer)
}
memcpy(&r->recv, &r->sa, sizeof(r->recv));
} else {
if (p->temponly)
if (p->temponly) {
if (p->ha) {
ast_free_ha(p->ha);
}
free(p);
}
p = NULL;
}
}
@ -920,8 +974,12 @@ static int create_addr(struct sip_pvt *r, char *peer)
} else if (!p)
return -1;
else {
if (p->temponly)
if (p->temponly) {
if (p->ha) {
ast_free_ha(p->ha);
}
free(p);
}
return 0;
}
}
@ -1039,7 +1097,7 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
res = 0;
p->outgoing = 1;
ast_log(LOG_DEBUG, "Outgoing Call for %s\n", p->username);
res = find_user(p,INC_OUT_USE);
res = update_user_counter(p,INC_OUT_USE);
if ( res != -1 ) {
p->restrictcid = ast->restrictcid;
p->jointcapability = p->capability;
@ -1123,19 +1181,13 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
}
}
static int find_user(struct sip_pvt *fup, int event)
static int update_user_counter(struct sip_pvt *fup, int event)
{
char name[256] = "";
struct sip_user *u;
strncpy(name, fup->username, sizeof(name) - 1);
ast_mutex_lock(&userl.lock);
u = userl.users;
while(u) {
if (!strcasecmp(u->name, name)) {
break;
}
u = u->next;
}
u = find_user(name);
if (!u) {
ast_log(LOG_DEBUG, "%s is not a local user\n", name);
ast_mutex_unlock(&userl.lock);
@ -1156,11 +1208,11 @@ static int find_user(struct sip_pvt *fup, int event)
if (u->incominglimit > 0 ) {
if (u->inUse >= u->incominglimit) {
ast_log(LOG_ERROR, "Call from user '%s' rejected due to usage limit of %d\n", u->name, u->incominglimit);
ast_mutex_unlock(&userl.lock);
/* inc inUse as well */
if ( event == INC_OUT_USE ) {
u->inUse++;
}
ast_mutex_unlock(&userl.lock);
return -1;
}
}
@ -1187,7 +1239,7 @@ static int find_user(struct sip_pvt *fup, int event)
break;
*/
default:
ast_log(LOG_ERROR, "find_user(%s,%d) called with no event!\n",u->name,event);
ast_log(LOG_ERROR, "update_user_counter(%s,%d) called with no event!\n",u->name,event);
}
ast_mutex_unlock(&userl.lock);
return 0;
@ -1241,11 +1293,11 @@ static int sip_hangup(struct ast_channel *ast)
}
ast_mutex_lock(&p->lock);
if ( p->outgoing ) {
ast_log(LOG_DEBUG, "find_user(%s) - decrement outUse counter\n", p->username);
find_user(p, DEC_OUT_USE);
ast_log(LOG_DEBUG, "update_user_counter(%s) - decrement outUse counter\n", p->username);
update_user_counter(p, DEC_OUT_USE);
} else {
ast_log(LOG_DEBUG, "find_user(%s) - decrement inUse counter\n", p->username);
find_user(p, DEC_IN_USE);
ast_log(LOG_DEBUG, "update_user_counter(%s) - decrement inUse counter\n", p->username);
update_user_counter(p, DEC_IN_USE);
}
/* Determine how to disconnect */
if (p->owner != ast) {
@ -1282,10 +1334,10 @@ static int sip_hangup(struct ast_channel *ast)
/* channel still up - reverse dec of inUse counter
only if the channel is not auto-congested */
if ( p->outgoing ) {
find_user(p, INC_OUT_USE);
update_user_counter(p, INC_OUT_USE);
}
else {
find_user(p, INC_IN_USE);
update_user_counter(p, INC_IN_USE);
}
}
} else {
@ -2057,7 +2109,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
while ((m = get_sdp_iterate(&iterator, req, "m"))[0] != '\0') {
if ((sscanf(m, "audio %d RTP/AVP %n", &x, &len) == 1)) {
portno = x;
// Scan through the RTP payload types specified in a "m=" line:
/* Scan through the RTP payload types specified in a "m=" line: */
ast_rtp_pt_clear(p->rtp);
codecs = m + len;
while(strlen(codecs)) {
@ -2074,11 +2126,11 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
}
}
if (p->vrtp)
ast_rtp_pt_clear(p->vrtp); // Must be cleared in case no m=video line exists
ast_rtp_pt_clear(p->vrtp); /* Must be cleared in case no m=video line exists */
if (p->vrtp && (sscanf(m, "video %d RTP/AVP %n", &x, &len) == 1)) {
vportno = x;
// Scan through the RTP payload types specified in a "m=" line:
/* Scan through the RTP payload types specified in a "m=" line: */
codecs = m + len;
while(strlen(codecs)) {
if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
@ -2107,11 +2159,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
#if 0
printf("Peer RTP is at port %s:%d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
#endif
// Next, scan through each "a=rtpmap:" line, noting each
// specified RTP payload type (with corresponding MIME subtype):
/* Next, scan through each "a=rtpmap:" line, noting each
* specified RTP payload type (with corresponding MIME subtype):
*/
sdpLineNum_iterator_init(&iterator);
while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
char* mimeSubtype = ast_strdupa(a); // ensures we have enough space
char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */
if (!strcasecmp(a, "sendonly")) {
sendonly=1;
continue;
@ -2122,13 +2175,13 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue;
if (sipdebug)
ast_verbose("Found description format %s\n", mimeSubtype);
// Note: should really look at the 'freq' and '#chans' params too
/* Note: should really look at the 'freq' and '#chans' params too */
ast_rtp_set_rtpmap_type(p->rtp, codec, "audio", mimeSubtype);
if (p->vrtp)
ast_rtp_set_rtpmap_type(p->vrtp, codec, "video", mimeSubtype);
}
// Now gather all of the codecs that were asked for:
/* Now gather all of the codecs that were asked for: */
ast_rtp_get_current_formats(p->rtp,
&peercapability, &peernoncodeccapability);
if (p->vrtp)
@ -2799,7 +2852,7 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *
if ((sizeof(m) <= strlen(m) - 2) || (sizeof(m2) <= strlen(m2) - 2) || (sizeof(a) == strlen(a)) || (sizeof(a2) == strlen(a2)))
ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
if ((p->vrtp) && (p->jointcapability & VIDEO_CODEC_MASK)) // only if video response is appropriate
if ((p->vrtp) && (p->jointcapability & VIDEO_CODEC_MASK)) /* only if video response is appropriate */
len += strlen(m2) + strlen(a2);
snprintf(costr, sizeof(costr), "%d", len);
add_header(resp, "Content-Type", "application/sdp");
@ -2811,7 +2864,7 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *
add_line(resp, t);
add_line(resp, m);
add_line(resp, a);
if ((p->vrtp) && (p->jointcapability & VIDEO_CODEC_MASK)) { // only if video response is appropriate
if ((p->vrtp) && (p->jointcapability & VIDEO_CODEC_MASK)) { /* only if video response is appropriate */
add_line(resp, m2);
add_line(resp, a2);
}
@ -3854,17 +3907,18 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si
strncpy(p->exten, name, sizeof(p->exten) - 1);
build_contact(p);
ast_mutex_lock(&peerl.lock);
peer = peerl.peers;
while(peer) {
if (!strcasecmp(peer->name, name) && ast_apply_ha(peer->ha,sin))
break;
peer = peer->next;
peer = find_peer(name, NULL);
if (!(peer && ast_apply_ha(peer->ha, sin))) {
if (peer && peer->temponly) {
if (peer->ha) {
ast_free_ha(peer->ha);
}
free(peer);
}
peer = NULL;
}
ast_mutex_unlock(&peerl.lock);
#ifdef MYSQL_FRIENDS
if (!peer)
peer = mysql_peer(name, NULL);
#endif
if (peer) {
if (!peer->dynamic) {
ast_log(LOG_NOTICE, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name);
@ -3876,10 +3930,7 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si
if (parse_contact(p, peer, req)) {
ast_log(LOG_WARNING, "Failed to parse contact info\n");
} else {
#ifdef MYSQL_FRIENDS
if (peer->temponly)
mysql_update_peer(peer->name, &peer->addr, peer->username, p->expiry);
#endif
update_peer(peer, p->expiry);
/* Say OK and ask subsystem to retransmit msg counter */
transmit_response_with_date(p, "200 OK", req);
peer->lastmsgssent = -1;
@ -3911,8 +3962,12 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si
}
if (res < 0)
transmit_response(p, "401 Unauthorized", &p->initreq);
if (peer && peer->temponly)
if (peer && peer->temponly) {
if (peer->ha) {
ast_free_ha(peer->ha);
}
free(peer);
}
return res;
}
@ -4293,65 +4348,54 @@ static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, cha
if (!strlen(of))
return 0;
ast_mutex_lock(&userl.lock);
user = userl.users;
while(user) {
if (!strcasecmp(user->name, of) && ast_apply_ha(user->ha,sin)) {
p->nat = user->nat;
if (p->rtp) {
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat);
ast_rtp_setnat(p->rtp, p->nat);
}
if (p->vrtp) {
ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", p->nat);
ast_rtp_setnat(p->vrtp, p->nat);
}
if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, user->md5secret, cmd, uri, reliable, ignore))) {
sip_cancel_destroy(p);
if (strlen(user->context))
strncpy(p->context, user->context, sizeof(p->context) - 1);
if (strlen(user->callerid) && strlen(p->callerid))
strncpy(p->callerid, user->callerid, sizeof(p->callerid) - 1);
strncpy(p->username, user->name, sizeof(p->username) - 1);
strncpy(p->peersecret, user->secret, sizeof(p->peersecret) - 1);
strncpy(p->peermd5secret, user->md5secret, sizeof(p->peermd5secret) - 1);
strncpy(p->accountcode, user->accountcode, sizeof(p->accountcode) -1);
strncpy(p->language, user->language, sizeof(p->language) -1);
p->canreinvite = user->canreinvite;
p->amaflags = user->amaflags;
p->callgroup = user->callgroup;
p->pickupgroup = user->pickupgroup;
p->restrictcid = user->restrictcid;
p->capability = user->capability;
p->jointcapability = user->capability;
if (user->dtmfmode) {
p->dtmfmode = user->dtmfmode;
if (p->dtmfmode & SIP_DTMF_RFC2833)
p->noncodeccapability |= AST_RTP_DTMF;
else
p->noncodeccapability &= ~AST_RTP_DTMF;
}
}
break;
user = find_user(of);
if (user && ast_apply_ha(user->ha, sin)) {
p->nat = user->nat;
if (p->rtp) {
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat);
ast_rtp_setnat(p->rtp, p->nat);
}
if (p->vrtp) {
ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", p->nat);
ast_rtp_setnat(p->vrtp, p->nat);
}
if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, user->md5secret, cmd, uri, reliable, ignore))) {
sip_cancel_destroy(p);
if (strlen(user->context))
strncpy(p->context, user->context, sizeof(p->context) - 1);
if (strlen(user->callerid) && strlen(p->callerid))
strncpy(p->callerid, user->callerid, sizeof(p->callerid) - 1);
strncpy(p->username, user->name, sizeof(p->username) - 1);
strncpy(p->peersecret, user->secret, sizeof(p->peersecret) - 1);
strncpy(p->peermd5secret, user->md5secret, sizeof(p->peermd5secret) - 1);
strncpy(p->accountcode, user->accountcode, sizeof(p->accountcode) -1);
strncpy(p->language, user->language, sizeof(p->language) -1);
p->canreinvite = user->canreinvite;
p->amaflags = user->amaflags;
p->callgroup = user->callgroup;
p->pickupgroup = user->pickupgroup;
p->restrictcid = user->restrictcid;
p->capability = user->capability;
p->jointcapability = user->capability;
if (user->dtmfmode) {
p->dtmfmode = user->dtmfmode;
if (p->dtmfmode & SIP_DTMF_RFC2833)
p->noncodeccapability |= AST_RTP_DTMF;
else
p->noncodeccapability &= ~AST_RTP_DTMF;
}
}
user = user->next;
}
ast_mutex_unlock(&userl.lock);
if (!user) {
/* If we didn't find a user match, check for peers */
ast_mutex_lock(&peerl.lock);
peer = peerl.peers;
while(peer) {
if (!inaddrcmp(&peer->addr, &p->recv) ||
(peer->insecure && (peer->addr.sin_addr.s_addr == p->recv.sin_addr.s_addr))) {
break;
}
peer = peer->next;
}
/* which should be used? non-mysql code uses "p->recv", but
* mysql code used "sin"
*/
peer = find_peer(NULL, &p->recv);
/* peer = find_peer(NULL, sin); */
ast_mutex_unlock(&peerl.lock);
#ifdef MYSQL_FRIENDS
if (!peer)
peer = mysql_peer(NULL, sin);
#endif
if (peer) {
/* Take the peer */
p->nat = peer->nat;
@ -4382,8 +4426,12 @@ static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, cha
else
p->noncodeccapability &= ~AST_RTP_DTMF;
}
if (peer->temponly)
if (peer->temponly) {
if (peer->ha) {
ast_free_ha(peer->ha);
}
free(peer);
}
}
}
return res;
@ -5205,10 +5253,10 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
case 487:
/* channel now destroyed - dec the inUse counter */
if ( p->outgoing ) {
find_user(p, DEC_OUT_USE);
update_user_counter(p, DEC_OUT_USE);
}
else {
find_user(p, DEC_IN_USE);
update_user_counter(p, DEC_IN_USE);
}
break;
case 486: /* Busy here */
@ -5442,7 +5490,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
strncpy(p->context, context, sizeof(p->context) - 1);
/* Check number of concurrent calls -vs- incoming limit HERE */
ast_log(LOG_DEBUG, "Check for res for %s\n", p->username);
res = find_user(p,INC_IN_USE);
res = update_user_counter(p,INC_IN_USE);
if (res) {
if (res < 0) {
ast_log(LOG_DEBUG, "Failed to place call for user %s, too many calls\n", p->username);
@ -5459,10 +5507,10 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
if (gotdest) {
if (gotdest < 0) {
transmit_response(p, "404 Not Found", req);
find_user(p,DEC_IN_USE);
update_user_counter(p,DEC_IN_USE);
} else {
transmit_response(p, "484 Address Incomplete", req);
find_user(p,DEC_IN_USE);
update_user_counter(p,DEC_IN_USE);
}
p->needdestroy = 1;
} else {
@ -5699,7 +5747,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
p->needdestroy = 1;
return 0;
}
// The next line can be removed if the SNOM200 Expires bug is fixed
/* The next line can be removed if the SNOM200 Expires bug is fixed */
if (p->subscribed == 1) {
if (p->expiry>max_expiry)
p->expiry = max_expiry;
@ -5916,6 +5964,7 @@ restartsearch:
ast_mutex_lock(&monlock);
if (res >= 0)
ast_sched_runq(sched);
/* needs work to send mwi to mysql peers */
ast_mutex_lock(&peerl.lock);
peer = peerl.peers;
time(&t);
@ -6068,19 +6117,15 @@ static int sip_devicestate(void *data)
}
ast_mutex_lock(&peerl.lock);
p = peerl.peers;
while (p) {
if (!strcasecmp(p->name, host)) {
found++;
res = AST_DEVICE_UNAVAILABLE;
if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
(!p->maxms || ((p->lastms > -1) && (p->lastms <= p->maxms)))) {
/* peer found and valid */
res = AST_DEVICE_UNKNOWN;
break;
}
p = find_peer(host, NULL);
if (p) {
found++;
res = AST_DEVICE_UNAVAILABLE;
if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
(!p->maxms || ((p->lastms > -1) && (p->lastms <= p->maxms)))) {
/* peer found and valid */
res = AST_DEVICE_UNKNOWN;
}
p = p->next;
}
ast_mutex_unlock(&peerl.lock);
if (!p && !found) {
@ -6251,8 +6296,10 @@ static struct sip_user *build_user(char *name, struct ast_variable *v)
user->insecure = ast_true(v->value);
} else if (!strcasecmp(v->name, "restrictcid")) {
user->restrictcid = ast_true(v->value);
} //else if (strcasecmp(v->name,"type"))
// ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
}
/*else if (strcasecmp(v->name,"type"))
* ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
*/
v = v->next;
}
}
@ -6444,8 +6491,10 @@ static struct sip_peer *build_peer(char *name, struct ast_variable *v)
ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of sip.conf\n", peer->name, v->lineno);
peer->maxms = 0;
}
} //else if (strcasecmp(v->name,"type"))
// ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
}
/* else if (strcasecmp(v->name,"type"))
* ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
*/
v=v->next;
}
if (!strlen(peer->methods))
@ -6619,8 +6668,10 @@ static int reload_config(void)
} else if (!strcasecmp(v->name, "dbname")) {
strncpy(mydbname, v->value, sizeof(mydbname) - 1);
#endif
} //else if (strcasecmp(v->name,"type"))
// ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
}
/* else if (strcasecmp(v->name,"type"))
* ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
*/
v = v->next;
}
@ -6678,7 +6729,7 @@ static int reload_config(void)
if (sipsock < 0) {
ast_log(LOG_WARNING, "Unable to create SIP socket: %s\n", strerror(errno));
} else {
// Allow SIP clients on the same host to access us:
/* Allow SIP clients on the same host to access us: */
const int reuseFlag = 1;
setsockopt(sipsock, SOL_SOCKET, SO_REUSEADDR,
(const char*)&reuseFlag,
@ -7070,7 +7121,8 @@ char *description()
}
#if 0
// XXX What is this?
/* XXX What is this?
*/
static char *getsipuri(char *header)
{
char *c, *d, *retval;