diff --git a/core/plug-in/sipctrl/SipCtrlInterface.cpp b/core/plug-in/sipctrl/SipCtrlInterface.cpp index 6779ecc7..da7488ac 100644 --- a/core/plug-in/sipctrl/SipCtrlInterface.cpp +++ b/core/plug-in/sipctrl/SipCtrlInterface.cpp @@ -557,17 +557,11 @@ void SipCtrlInterface::handle_sip_reply(sip_msg* msg) reply.dstip = get_addr_str(((sockaddr_in*)(&msg->local_ip))->sin_addr); //FIXME: IPv6 reply.port = int2str(ntohs(((sockaddr_in*)(&msg->local_ip))->sin_port)); - if( (get_cseq(msg)->method == sip_request::INVITE) - && (msg->u.reply->code >= 200) - && (msg->u.reply->code < 300) ){ - - tl->send_200_ack(msg); - } - - // - // Will be computed in send_request() - // - // reply.next_hop; + //if( (get_cseq(msg)->method == sip_request::INVITE) + // && (msg->u.reply->code >= 200) + // && (msg->u.reply->code < 300) ){ + // tl->send_200_ack(msg); + //} prepare_routes_uac(msg->record_route, reply.route); diff --git a/core/plug-in/sipctrl/sip_trans.cpp b/core/plug-in/sipctrl/sip_trans.cpp index d78dab43..71da6c0b 100644 --- a/core/plug-in/sipctrl/sip_trans.cpp +++ b/core/plug-in/sipctrl/sip_trans.cpp @@ -38,6 +38,9 @@ sip_trans::~sip_trans() reset_all_timers(); delete msg; delete [] retr_buf; + if((type == TT_UAC) && to_tag.s){ + delete [] to_tag.s; + } } /** diff --git a/core/plug-in/sipctrl/trans_layer.cpp b/core/plug-in/sipctrl/trans_layer.cpp index 4198cd21..ccd2642e 100644 --- a/core/plug-in/sipctrl/trans_layer.cpp +++ b/core/plug-in/sipctrl/trans_layer.cpp @@ -876,7 +876,7 @@ int trans_layer::update_uac_trans(trans_bucket* bucket, sip_trans* t, sip_msg* m case TS_PROCEEDING: t->state = TS_COMPLETED; - send_non_200_ack(t,msg); + send_non_200_ack(msg,t); // TODO: set D timer if UDP t->reset_timer(STIMER_D, D_TIMER, bucket->get_id()); @@ -909,10 +909,35 @@ int trans_layer::update_uac_trans(trans_bucket* bucket, sip_trans* t, sip_msg* m // - (send BYE (check for existing UAC trans)). // - else: // - re-transmit ACK. - t->state = TS_TERMINATED; - bucket->remove_trans(t); + + t->state = TS_TERMINATED_200; + + t->to_tag.s = new char[to_tag.len]; + t->to_tag.len = to_tag.len; + memcpy((void*)t->to_tag.s,to_tag.s,to_tag.len); + + send_200_ack(msg,t); + goto pass_reply; + case TS_TERMINATED_200: + + if( (to_tag.len != t->to_tag.len) || + (memcmp(to_tag.s,t->to_tag.s,to_tag.len) != 0) ){ + + // TODO: + // (this should be implemented in the UA) + // we should send 200 ACK also here, + // but this would mean that we should + // also be sending a BYE also to quit + // this dialog. + // + goto end; + } + + retransmit(t); + goto end; + default: goto end; } @@ -1045,7 +1070,7 @@ int trans_layer::update_uas_request(trans_bucket* bucket, sip_trans* t, sip_msg* return -1; } -void trans_layer::send_non_200_ack(sip_trans* t, sip_msg* reply) +void trans_layer::send_non_200_ack(sip_msg* reply, sip_trans* t) { sip_msg* inv = t->msg; @@ -1099,7 +1124,7 @@ void trans_layer::send_non_200_ack(sip_trans* t, sip_msg* reply) t->retr_len = ack_len; } -void trans_layer::send_200_ack(sip_msg* reply) +void trans_layer::send_200_ack(sip_msg* reply, sip_trans* t) { // Set request URI // TODO: use correct R-URI instead of just 'Contact' @@ -1118,10 +1143,19 @@ void trans_layer::send_200_ack(sip_msg* reply) cstring r_uri = na.addr; list route_hdrs; - for(list::reverse_iterator it = reply->record_route.rbegin(); - it != reply->record_route.rend(); ++it) { - - route_hdrs.push_back(new sip_header(0,"Route",(*it)->value)); + if(t && !t->msg->route.empty()){ + for(list::iterator it = t->msg->route.begin(); + it != t->msg->route.end(); ++it) { + + route_hdrs.push_back(new sip_header(0,"Route",(*it)->value)); + } + } + else { + for(list::reverse_iterator it = reply->record_route.rbegin(); + it != reply->record_route.rend(); ++it) { + + route_hdrs.push_back(new sip_header(0,"Route",(*it)->value)); + } } sockaddr_storage remote_ip; @@ -1163,6 +1197,7 @@ void trans_layer::send_200_ack(sip_msg* reply) copy_hdr_wr(&msg,reply->to); copy_hdr_wr(&msg,reply->callid); copy_hdr_wr(&msg,max_forward); + delete max_forward; cseq_wr(&msg,get_cseq(reply)->num_str,cstring("ACK",3)); *msg++ = CR; @@ -1175,10 +1210,14 @@ void trans_layer::send_200_ack(sip_msg* reply) int send_err = transport->send(&remote_ip,ack_buf,request_len); if(send_err < 0){ ERROR("Error from transport layer\n"); + delete [] ack_buf; + } + else if(t){ + delete [] t->retr_buf; + t->retr_buf = ack_buf; + t->retr_len = request_len; + memcpy(&t->retr_addr,&remote_ip,sizeof(sockaddr_storage)); } - - delete [] ack_buf; - delete max_forward; } void trans_layer::retransmit(sip_trans* t) @@ -1239,6 +1278,9 @@ void trans_layer::timer_expired(timer* t, trans_bucket* bucket, sip_trans* tr) DBG("Transaction timeout!\n"); timeout(bucket,tr); break; + case TS_TERMINATED_200: + bucket->remove_trans(tr); + break; } break; diff --git a/core/plug-in/sipctrl/trans_layer.h b/core/plug-in/sipctrl/trans_layer.h index ed1b6841..bb4d5394 100644 --- a/core/plug-in/sipctrl/trans_layer.h +++ b/core/plug-in/sipctrl/trans_layer.h @@ -65,7 +65,7 @@ class trans_layer /** * Send ACK coresponding to error replies */ - void send_non_200_ack(sip_trans* t, sip_msg* reply); + void send_non_200_ack(sip_msg* reply, sip_trans* t); /** * Fills the address structure passed and modifies @@ -137,7 +137,7 @@ class trans_layer * Sends an end-to-end ACK for the reply * passed as a parameter. */ - void send_200_ack(sip_msg* reply); + void send_200_ack(sip_msg* reply, sip_trans* t=NULL); /**