Implement SIP retransmissions

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@710 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Mark Spencer 22 years ago
parent 33fbc73fc5
commit 235fb19b74

@ -65,6 +65,9 @@ static int default_expirey = DEFAULT_DEFAULT_EXPIREY;
#define DEFAULT_FREQ_OK 60 * 1000 /* How often to check for the host to be up */ #define DEFAULT_FREQ_OK 60 * 1000 /* How often to check for the host to be up */
#define DEFAULT_FREQ_NOTOK 10 * 1000 /* How often to check, if the host is down... */ #define DEFAULT_FREQ_NOTOK 10 * 1000 /* How often to check, if the host is down... */
#define DEFAULT_RETRANS 1000 /* How frequently to retransmit */
#define MAX_RETRANS 5 /* Try only 5 times for retransmissions */
static char *desc = "Session Initiation Protocol (SIP)"; static char *desc = "Session Initiation Protocol (SIP)";
static char *type = "sip"; static char *type = "sip";
static char *tdesc = "Session Initiation Protocol (SIP)"; static char *tdesc = "Session Initiation Protocol (SIP)";
@ -185,6 +188,7 @@ static struct sip_pvt {
int maxtime; /* Max time for first response */ int maxtime; /* Max time for first response */
int initid; /* Auto-congest ID if appropriate */ int initid; /* Auto-congest ID if appropriate */
int autokillid; /* Auto-kill ID */
int dtmfmode; int dtmfmode;
struct ast_dsp *vad; struct ast_dsp *vad;
@ -200,6 +204,7 @@ struct sip_pkt {
struct sip_pkt *next; /* Next packet */ struct sip_pkt *next; /* Next packet */
int retrans; /* Retransmission number */ int retrans; /* Retransmission number */
int seqno; /* Sequence number */ int seqno; /* Sequence number */
int resp; /* non-zero if this is a response packet (e.g. 200 OK) */
struct sip_pvt *owner; /* Owner call */ struct sip_pvt *owner; /* Owner call */
int retransid; /* Retransmission ID */ int retransid; /* Retransmission ID */
int packetlen; /* Length of packet */ int packetlen; /* Length of packet */
@ -306,8 +311,8 @@ static struct sockaddr_in bindaddr;
static struct ast_frame *sip_read(struct ast_channel *ast); static struct ast_frame *sip_read(struct ast_channel *ast);
static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req); static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req);
static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req); static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req);
static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, char *rand); static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, char *rand, int reliable);
static int transmit_request(struct sip_pvt *p, char *msg, int inc); static int transmit_request(struct sip_pvt *p, char *msg, int inc, int reliable);
static int transmit_invite(struct sip_pvt *p, char *msg, int sendsdp, char *auth, char *vxml_url); static int transmit_invite(struct sip_pvt *p, char *msg, int sendsdp, char *auth, char *vxml_url);
static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp); static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp);
static int transmit_info_with_digit(struct sip_pvt *p, char digit); static int transmit_info_with_digit(struct sip_pvt *p, char digit);
@ -328,31 +333,136 @@ static int __sip_xmit(struct sip_pvt *p, char *data, int len)
return res; return res;
} }
static int send_response(struct sip_pvt *p, struct sip_request *req) static void sip_destroy(struct sip_pvt *p);
static int retrans_pkt(void *data)
{
struct sip_pkt *pkt=data;
int res = 0;
ast_pthread_mutex_lock(&pkt->owner->lock);
if (pkt->retrans < MAX_RETRANS) {
pkt->retrans++;
if (sipdebug) {
if (pkt->owner->nat)
ast_verbose("Retransmitting #%d (NAT):\n%s\n to %s:%d\n", pkt->retrans, pkt->data, inet_ntoa(pkt->owner->recv.sin_addr), ntohs(pkt->owner->recv.sin_port));
else
ast_verbose("Retransmitting #%d (no NAT):\n%s\n to %s:%d\n", pkt->retrans, pkt->data, inet_ntoa(pkt->owner->sa.sin_addr), ntohs(pkt->owner->sa.sin_port));
}
__sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
res = 1;
} else {
ast_log(LOG_WARNING, "Maximum retries exceeded on call %s for seqno %d (%s)\n", pkt->owner->callid, pkt->seqno, pkt->resp ? "Response" : "Request");
pkt->retransid = -1;
if (pkt->owner->owner) {
/* XXX Potential deadlocK?? XXX */
ast_queue_hangup(pkt->owner->owner, 1);
} else {
/* If no owner, destroy now */
sip_destroy(pkt->owner);
}
}
ast_pthread_mutex_unlock(&pkt->owner->lock);
return res;
}
static int __sip_reliable_xmit(struct sip_pvt *p, int seqno, int resp, char *data, int len)
{
struct sip_pkt *pkt;
pkt = malloc(sizeof(struct sip_pkt) + len);
if (!pkt)
return -1;
memset(pkt, 0, sizeof(struct sip_pkt));
memcpy(pkt->data, data, len);
pkt->packetlen = len;
pkt->next = p->packets;
pkt->owner = p;
pkt->seqno = seqno;
pkt->resp = resp;
/* Schedule retransmission */
pkt->retransid = ast_sched_add(sched, 1000, retrans_pkt, pkt);
pkt->next = p->packets;
p->packets = pkt;
__sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
return 0;
}
static int __sip_autodestruct(void *data)
{
struct sip_pvt *p = data;
p->autokillid = -1;
ast_log(LOG_DEBUG, "Auto destroying call '%s'\n", p->callid);
if (p->owner) {
ast_log(LOG_WARNING, "Autodestruct on call '%s' with owner in place\n", p->callid);
ast_queue_hangup(p->owner, 0);
} else {
sip_destroy(p);
}
return 0;
}
static int sip_scheddestroy(struct sip_pvt *p, int ms)
{
if (p->autokillid > -1)
ast_sched_del(sched, p->autokillid);
p->autokillid = ast_sched_add(sched, ms, __sip_autodestruct, p);
return 0;
}
static int __sip_ack(struct sip_pvt *p, int seqno, int resp)
{
struct sip_pkt *cur, *prev = NULL;
int res = -1;
cur = p->packets;
while(cur) {
if ((cur->seqno == seqno) && (cur->resp == resp)) {
/* this is our baby */
if (prev)
prev->next = cur->next;
else
p->packets = cur->next;
if (cur->retransid > -1)
ast_sched_del(sched, cur->retransid);
free(cur);
res = 0;
break;
}
prev = cur;
cur = cur->next;
}
return res;
}
static int send_response(struct sip_pvt *p, struct sip_request *req, int reliable, int seqno)
{ {
int res; int res;
if (sipdebug) { if (sipdebug) {
if (p->nat) if (p->nat)
ast_verbose("Transmitting (NAT):\n%s\n to %s:%d\n", req->data, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); ast_verbose("%sTransmitting (NAT):\n%s\n to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
else else
ast_verbose("Transmitting (no NAT):\n%s\n to %s:%d\n", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); ast_verbose("%sTransmitting (no NAT):\n%s\n to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port));
} }
res = __sip_xmit(p, req->data, req->len); if (reliable)
res = __sip_reliable_xmit(p, seqno, 1, req->data, req->len);
else
res = __sip_xmit(p, req->data, req->len);
if (res > 0) if (res > 0)
res = 0; res = 0;
return res; return res;
} }
static int send_request(struct sip_pvt *p, struct sip_request *req) static int send_request(struct sip_pvt *p, struct sip_request *req, int reliable, int seqno)
{ {
int res; int res;
if (sipdebug) { if (sipdebug) {
if (p->nat) if (p->nat)
ast_verbose("XXX Need to handle Retransmitting XXX:\n%s (NAT) to %s:%d\n", req->data, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); ast_verbose("%sTransmitting:\n%s (NAT) to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
else else
ast_verbose("XXX Need to handle Retransmitting XXX:\n%s (no NAT) to %s:%d\n", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); ast_verbose("%sTransmitting:\n%s (no NAT) to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port));
} }
res = __sip_xmit(p, req->data, req->len); if (reliable)
res = __sip_reliable_xmit(p, seqno, 0, req->data, req->len);
else
res = __sip_xmit(p, req->data, req->len);
return res; return res;
} }
@ -568,6 +678,10 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
{ {
struct sip_pvt *cur, *prev = NULL; struct sip_pvt *cur, *prev = NULL;
struct sip_pkt *cp; struct sip_pkt *cp;
if (p->initid > -1)
ast_sched_del(sched, p->initid);
if (p->autokillid > -1)
ast_sched_del(sched, p->autokillid);
if (p->rtp) { if (p->rtp) {
ast_rtp_destroy(p->rtp); ast_rtp_destroy(p->rtp);
} }
@ -741,10 +855,10 @@ static int sip_hangup(struct ast_channel *ast)
/* Start the process if it's not already started */ /* Start the process if it's not already started */
if (!p->alreadygone && strlen(p->initreq.data)) { if (!p->alreadygone && strlen(p->initreq.data)) {
if (needcancel) { if (needcancel) {
transmit_request(p, "CANCEL", 0); transmit_request(p, "CANCEL", 0, 1);
} else { } else {
/* Send a hangup */ /* Send a hangup */
transmit_request(p, "BYE", 1); transmit_request(p, "BYE", 1, 1);
} }
} }
ast_pthread_mutex_unlock(&p->lock); ast_pthread_mutex_unlock(&p->lock);
@ -1157,6 +1271,7 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg
/* Keep track of stuff */ /* Keep track of stuff */
memset(p, 0, sizeof(struct sip_pvt)); memset(p, 0, sizeof(struct sip_pvt));
p->initid = -1; p->initid = -1;
p->autokillid = -1;
p->rtp = ast_rtp_new(NULL, NULL); p->rtp = ast_rtp_new(NULL, NULL);
p->branch = rand(); p->branch = rand();
p->tag = rand(); p->tag = rand();
@ -1770,7 +1885,7 @@ static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *r
respprep(&resp, p, msg, req); respprep(&resp, p, msg, req);
add_header(&resp, "Content-Length", "0"); add_header(&resp, "Content-Length", "0");
add_blank_header(&resp); add_blank_header(&resp);
return send_response(p, &resp); return send_response(p, &resp, 0, 0);
} }
static int transmit_response_with_allow(struct sip_pvt *p, char *msg, struct sip_request *req) static int transmit_response_with_allow(struct sip_pvt *p, char *msg, struct sip_request *req)
@ -1781,19 +1896,24 @@ static int transmit_response_with_allow(struct sip_pvt *p, char *msg, struct sip
add_header(&resp, "Accept", "application/sdp"); add_header(&resp, "Accept", "application/sdp");
add_header(&resp, "Content-Length", "0"); add_header(&resp, "Content-Length", "0");
add_blank_header(&resp); add_blank_header(&resp);
return send_response(p, &resp); return send_response(p, &resp, 0, 0);
} }
static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, char *randdata) static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, char *randdata, int reliable)
{ {
struct sip_request resp; struct sip_request resp;
char tmp[256]; char tmp[256];
int seqno = 0;
if (reliable && (sscanf(get_header(req, "CSeq"), "%i ", &seqno) != 1)) {
ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq"));
return -1;
}
snprintf(tmp, sizeof(tmp), "Digest realm=\"asterisk\", nonce=\"%s\"", randdata); snprintf(tmp, sizeof(tmp), "Digest realm=\"asterisk\", nonce=\"%s\"", randdata);
respprep(&resp, p, msg, req); respprep(&resp, p, msg, req);
add_header(&resp, "Proxy-Authenticate", tmp); add_header(&resp, "Proxy-Authenticate", tmp);
add_header(&resp, "Content-Length", "0"); add_header(&resp, "Content-Length", "0");
add_blank_header(&resp); add_blank_header(&resp);
return send_response(p, &resp); return send_response(p, &resp, reliable, seqno);
} }
static int add_text(struct sip_request *req, char *text) static int add_text(struct sip_request *req, char *text)
@ -1943,9 +2063,14 @@ static void copy_request(struct sip_request *dst,struct sip_request *src)
static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req) static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req)
{ {
struct sip_request resp; struct sip_request resp;
int seqno;
if (sscanf(get_header(req, "CSeq"), "%i ", &seqno) != 1) {
ast_log(LOG_WARNING, "Unable to get seqno from '%s'\n", get_header(req, "CSeq"));
return -1;
}
respprep(&resp, p, msg, req); respprep(&resp, p, msg, req);
add_sdp(&resp, p, NULL); add_sdp(&resp, p, NULL);
return send_response(p, &resp); return send_response(p, &resp, 1, seqno);
} }
static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp) static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp)
@ -1953,7 +2078,7 @@ static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp)
struct sip_request resp; struct sip_request resp;
reqprep(&resp, p, "INVITE", 1); reqprep(&resp, p, "INVITE", 1);
add_sdp(&resp, p, rtp); add_sdp(&resp, p, rtp);
return send_response(p, &resp); return send_response(p, &resp, 1, p->ocseq);
} }
static void initreqprep(struct sip_request *req, struct sip_pvt *p, char *cmd, char *vxml_url) static void initreqprep(struct sip_request *req, struct sip_pvt *p, char *cmd, char *vxml_url)
@ -2034,7 +2159,7 @@ static int transmit_invite(struct sip_pvt *p, char *cmd, int sdp, char *auth, ch
parse(&p->initreq); parse(&p->initreq);
} }
p->lastinvite = p->ocseq; p->lastinvite = p->ocseq;
return send_request(p, &req); return send_request(p, &req, 1, p->ocseq);
} }
static int transmit_notify(struct sip_pvt *p, int newmsgs, int oldmsgs) static int transmit_notify(struct sip_pvt *p, int newmsgs, int oldmsgs)
@ -2061,7 +2186,7 @@ static int transmit_notify(struct sip_pvt *p, int newmsgs, int oldmsgs)
} }
p->lastinvite = p->ocseq; p->lastinvite = p->ocseq;
return send_request(p, &req); return send_request(p, &req, 1, p->ocseq);
} }
static int transmit_register(struct sip_registry *r, char *cmd, char *auth); static int transmit_register(struct sip_registry *r, char *cmd, char *auth);
@ -2165,7 +2290,7 @@ static int transmit_register(struct sip_registry *r, char *cmd, char *auth)
add_header(&req, "Event", "registration"); add_header(&req, "Event", "registration");
copy_request(&p->initreq, &req); copy_request(&p->initreq, &req);
r->regstate=auth?REG_STATE_AUTHSENT:REG_STATE_REGSENT; r->regstate=auth?REG_STATE_AUTHSENT:REG_STATE_REGSENT;
return send_request(p, &req); return send_request(p, &req, 1, p->ocseq);
} }
static int transmit_message_with_text(struct sip_pvt *p, char *text) static int transmit_message_with_text(struct sip_pvt *p, char *text)
@ -2173,7 +2298,7 @@ static int transmit_message_with_text(struct sip_pvt *p, char *text)
struct sip_request req; struct sip_request req;
reqprep(&req, p, "MESSAGE", 1); reqprep(&req, p, "MESSAGE", 1);
add_text(&req, text); add_text(&req, text);
return send_request(p, &req); return send_request(p, &req, 1, p->ocseq);
} }
static int transmit_info_with_digit(struct sip_pvt *p, char digit) static int transmit_info_with_digit(struct sip_pvt *p, char digit)
@ -2181,16 +2306,16 @@ static int transmit_info_with_digit(struct sip_pvt *p, char digit)
struct sip_request req; struct sip_request req;
reqprep(&req, p, "INFO", 1); reqprep(&req, p, "INFO", 1);
add_digit(&req, digit); add_digit(&req, digit);
return send_request(p, &req); return send_request(p, &req, 1, p->ocseq);
} }
static int transmit_request(struct sip_pvt *p, char *msg, int inc) static int transmit_request(struct sip_pvt *p, char *msg, int inc, int reliable)
{ {
struct sip_request resp; struct sip_request resp;
reqprep(&resp, p, msg, inc); reqprep(&resp, p, msg, inc);
add_header(&resp, "Content-Length", "0"); add_header(&resp, "Content-Length", "0");
add_blank_header(&resp); add_blank_header(&resp);
return send_request(p, &resp); return send_request(p, &resp, reliable, p->ocseq);
} }
static int expire_register(void *data) static int expire_register(void *data)
@ -2312,7 +2437,7 @@ static void md5_hash(char *output, char *input)
ptr += sprintf(ptr, "%2.2x", digest[x]); ptr += sprintf(ptr, "%2.2x", digest[x]);
} }
static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata, int randlen, char *username, char *secret, char *method, char *uri) static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata, int randlen, char *username, char *secret, char *method, char *uri, int reliable)
{ {
int res = -1; int res = -1;
/* Always OK if no secret */ /* Always OK if no secret */
@ -2320,7 +2445,9 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
return 0; return 0;
if (!strlen(randdata) || !strlen(get_header(req, "Proxy-Authorization"))) { if (!strlen(randdata) || !strlen(get_header(req, "Proxy-Authorization"))) {
snprintf(randdata, randlen, "%08x", rand()); snprintf(randdata, randlen, "%08x", rand());
transmit_response_with_auth(p, "407 Proxy Authentication Required", req, randdata); transmit_response_with_auth(p, "407 Proxy Authentication Required", req, randdata, reliable);
/* Schedule auto destroy in 15 seconds */
sip_scheddestroy(p, 15000);
res = 1; res = 1;
} else { } else {
/* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting /* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting
@ -2427,7 +2554,7 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si
if (!strcasecmp(peer->name, name) && peer->dynamic) { if (!strcasecmp(peer->name, name) && peer->dynamic) {
p->nat = peer->nat; p->nat = peer->nat;
transmit_response(p, "100 Trying", req); transmit_response(p, "100 Trying", req);
if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, peer->secret, "REGISTER", uri))) { if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, peer->secret, "REGISTER", uri, 0))) {
if (parse_contact(p, peer, req)) { if (parse_contact(p, peer, req)) {
ast_log(LOG_WARNING, "Failed to parse contact info\n"); ast_log(LOG_WARNING, "Failed to parse contact info\n");
} else { } else {
@ -2672,7 +2799,7 @@ static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, cha
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat); ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat);
ast_rtp_setnat(p->rtp, p->nat); ast_rtp_setnat(p->rtp, p->nat);
} }
if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, cmd, uri))) { if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, cmd, uri, 1))) {
strncpy(p->context, user->context, sizeof(p->context) - 1); strncpy(p->context, user->context, sizeof(p->context) - 1);
if (strlen(user->callerid) && strlen(p->callerid)) if (strlen(user->callerid) && strlen(p->callerid))
strncpy(p->callerid, user->callerid, sizeof(p->callerid) - 1); strncpy(p->callerid, user->callerid, sizeof(p->callerid) - 1);
@ -3134,7 +3261,11 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
struct sip_peer *peer; struct sip_peer *peer;
int pingtime; int pingtime;
struct timeval tv; struct timeval tv;
int seqno=0;
c = get_header(req, "Cseq"); c = get_header(req, "Cseq");
if (sscanf(c, "%d ", &seqno) != 1) {
ast_log(LOG_WARNING, "Unable to determine sequence number\n");
}
msg = strchr(c, ' '); msg = strchr(c, ' ');
if (!msg) msg = ""; else msg++; if (!msg) msg = ""; else msg++;
retrylock: retrylock:
@ -3171,7 +3302,7 @@ retrylock:
if (peer->pokeexpire > -1) if (peer->pokeexpire > -1)
ast_sched_del(sched, peer->pokeexpire); ast_sched_del(sched, peer->pokeexpire);
if (!strcasecmp(msg, "INVITE")) if (!strcasecmp(msg, "INVITE"))
transmit_request(p, "ACK", 0); transmit_request(p, "ACK", 0, 0);
sip_destroy(p); sip_destroy(p);
p = NULL; p = NULL;
/* Try again eventually */ /* Try again eventually */
@ -3181,6 +3312,8 @@ retrylock:
peer->pokeexpire = ast_sched_add(sched, DEFAULT_FREQ_OK, sip_poke_peer_s, peer); peer->pokeexpire = ast_sched_add(sched, DEFAULT_FREQ_OK, sip_poke_peer_s, peer);
} }
} else if (p->outgoing) { } else if (p->outgoing) {
/* Acknowledge sequence number */
__sip_ack(p, seqno, 0);
if (p->initid > -1) { if (p->initid > -1) {
/* Don't auto congest anymore since we've gotten something useful back */ /* Don't auto congest anymore since we've gotten something useful back */
ast_sched_del(sched, p->initid); ast_sched_del(sched, p->initid);
@ -3215,18 +3348,26 @@ retrylock:
} }
break; break;
case 200: case 200:
if (strlen(get_header(req, "Content-Type"))) if (!strcasecmp(msg, "NOTIFY")) {
process_sdp(p, req); /* They got the notify, this is the end */
if (p->owner) { if (p->owner) {
if (p->owner->_state != AST_STATE_UP) { ast_log(LOG_WARNING, "Notify answer on an owned channel?\n");
ast_setstate(p->owner, AST_STATE_UP); ast_queue_hangup(p->owner, 0);
ast_queue_control(p->owner, AST_CONTROL_ANSWER, 0); } else {
sip_destroy(p);
p = NULL;
} }
} } else if (!strcasecmp(msg, "INVITE")) {
if (!strcasecmp(msg, "INVITE")) if (strlen(get_header(req, "Content-Type")))
transmit_request(p, "ACK", 0); process_sdp(p, req);
else if (!strcasecmp(msg, "REGISTER")) if (p->owner) {
{ if (p->owner->_state != AST_STATE_UP) {
ast_setstate(p->owner, AST_STATE_UP);
ast_queue_control(p->owner, AST_CONTROL_ANSWER, 0);
}
}
transmit_request(p, "ACK", 0, 0);
} else if (!strcasecmp(msg, "REGISTER")) {
/* char *exp; */ /* char *exp; */
int expires; int expires;
struct sip_registry *r; struct sip_registry *r;
@ -3255,7 +3396,7 @@ retrylock:
break; break;
case 407: case 407:
/* First we ACK */ /* First we ACK */
transmit_request(p, "ACK", 0); transmit_request(p, "ACK", 0, 0);
/* Then we AUTH */ /* Then we AUTH */
do_proxy_auth(p, req); do_proxy_auth(p, req);
/* This is just a hack to kill the channel while testing */ /* This is just a hack to kill the channel while testing */
@ -3303,7 +3444,7 @@ retrylock:
ast_queue_hangup(p->owner, 0); ast_queue_hangup(p->owner, 0);
break; break;
} }
transmit_request(p, "ACK", 0); transmit_request(p, "ACK", 0, 0);
p->alreadygone = 1; p->alreadygone = 1;
} else } else
ast_log(LOG_NOTICE, "Dunno anything about a %d %s response from %s\n", resp, rest, p->owner ? p->owner->name : inet_ntoa(p->sa.sin_addr)); ast_log(LOG_NOTICE, "Dunno anything about a %d %s response from %s\n", resp, rest, p->owner ? p->owner->name : inet_ntoa(p->sa.sin_addr));
@ -3314,7 +3455,7 @@ retrylock:
switch(resp) { switch(resp) {
case 200: case 200:
if (!strcasecmp(msg, "INVITE") || !strcasecmp(msg, "REGISTER") ) if (!strcasecmp(msg, "INVITE") || !strcasecmp(msg, "REGISTER") )
transmit_request(p, "ACK", 0); transmit_request(p, "ACK", 0, 0);
break; break;
} }
} }
@ -3610,7 +3751,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
} }
} }
/* Always increment on a BYE */ /* Always increment on a BYE */
transmit_request(p, "BYE", 1); transmit_request(p, "BYE", 1, 1);
p->alreadygone = 1; p->alreadygone = 1;
} }
} else if (!strcasecmp(cmd, "CANCEL") || !strcasecmp(cmd, "BYE")) { } else if (!strcasecmp(cmd, "CANCEL") || !strcasecmp(cmd, "BYE")) {
@ -3648,6 +3789,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
/* Uhm, I haven't figured out the point of the ACK yet. Are we /* Uhm, I haven't figured out the point of the ACK yet. Are we
supposed to retransmit responses until we get an ack? supposed to retransmit responses until we get an ack?
Make sure this is on a valid call */ Make sure this is on a valid call */
__sip_ack(p, seqno, 1);
if (strlen(get_header(req, "Content-Type"))) { if (strlen(get_header(req, "Content-Type"))) {
if (process_sdp(p, req)) if (process_sdp(p, req))
return -1; return -1;
@ -3740,9 +3882,9 @@ static int sip_send_mwi_to_peer(struct sip_peer *peer)
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=%08x", inet_ntoa(p->ourip), ourport, p->branch); snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=%08x", inet_ntoa(p->ourip), ourport, p->branch);
build_callid(p->callid, sizeof(p->callid), p->ourip); build_callid(p->callid, sizeof(p->callid), p->ourip);
/* Send MWI */ /* Send MWI */
p->outgoing = 1;
transmit_notify(p, newmsgs, oldmsgs); transmit_notify(p, newmsgs, oldmsgs);
/* Destroy channel */ sip_scheddestroy(p, 15000);
sip_destroy(p);
return 0; return 0;
} }

Loading…
Cancel
Save