/** * Computes, set and return the outbound interface * based on remote_uri, next_hop_ip, outbound_proxy, route. */ int AmBasicSipDialog::getOutboundIf() { if (outbound_interface >= 0) return outbound_interface; if(AmConfig::SIP_Ifs.size() == 1){ return (outbound_interface = 0); } // Destination priority: // 1. next_hop // 2. outbound_proxy (if 1st req or force_outbound_proxy) // 3. first route // 4. remote URI string dest_uri; string dest_ip; string local_ip; multimap<string,unsigned short>::iterator if_it; list<sip_destination> ip_list; if(!next_hop.empty() && !parse_next_hop(stl2cstr(next_hop),ip_list) && !ip_list.empty()) { dest_ip = c2stlstr(ip_list.front().host); } else if(!outbound_proxy.empty() && (remote_tag.empty() || force_outbound_proxy)) { dest_uri = outbound_proxy; } else if(!route.empty()){ // parse first route sip_header fr; fr.value = stl2cstr(route); sip_uri* route_uri = get_first_route_uri(&fr); if(!route_uri){ ERROR("Could not parse route (local_tag='%s';route='%s')", local_tag.c_str(),route.c_str()); goto error; } dest_ip = c2stlstr(route_uri->host); } else { dest_uri = remote_uri; } if(dest_uri.empty() && dest_ip.empty()) { ERROR("No destination found (local_tag='%s')",local_tag.c_str()); goto error; } if(!dest_uri.empty()){ sip_uri d_uri; if(parse_uri(&d_uri,dest_uri.c_str(),dest_uri.length()) < 0){ ERROR("Could not parse destination URI (local_tag='%s';dest_uri='%s')", local_tag.c_str(),dest_uri.c_str()); goto error; } dest_ip = c2stlstr(d_uri.host); } if(get_local_addr_for_dest(dest_ip,local_ip) < 0){ ERROR("No local address for dest '%s' (local_tag='%s')",dest_ip.c_str(),local_tag.c_str()); goto error; } if_it = AmConfig::LocalSIPIP2If.find(local_ip); if(if_it == AmConfig::LocalSIPIP2If.end()){ ERROR("Could not find a local interface for resolved local IP (local_tag='%s';local_ip='%s')", local_tag.c_str(), local_ip.c_str()); goto error; } setOutboundInterface(if_it->second); return if_it->second; error: WARN("Error while computing outbound interface: default interface will be used instead."); setOutboundInterface(0); return 0; }
int trans_layer::send_request(sip_msg* msg, char* tid, unsigned int& tid_len) { // Request-URI // To // From // Call-ID // CSeq // Max-Forwards // Via // Contact // Supported / Require // Content-Length / Content-Type assert(transport); tid_len = 0; if(set_next_hop(msg->route,msg->u.request->ruri_str, &msg->remote_ip) < 0){ // TODO: error handling DBG("set_next_hop failed\n"); //delete msg; return -1; } // assume that msg->route headers are not in msg->hdrs msg->hdrs.insert(msg->hdrs.begin(),msg->route.begin(),msg->route.end()); int request_len = request_line_len(msg->u.request->method_str, msg->u.request->ruri_str); char branch_buf[BRANCH_BUF_LEN]; compute_branch(branch_buf,msg->callid->value,msg->cseq->value); cstring branch(branch_buf,BRANCH_BUF_LEN); string via(transport->get_local_ip()); if(transport->get_local_port() != 5060) via += ":" + int2str(transport->get_local_port()); request_len += via_len(stl2cstr(via),branch); request_len += copy_hdrs_len(msg->hdrs); string content_len = int2str(msg->body.len); request_len += content_length_len(stl2cstr(content_len)); request_len += 2/* CRLF end-of-headers*/; if(msg->body.len){ request_len += msg->body.len; } // Allocate new message sip_msg* p_msg = new sip_msg(); p_msg->buf = new char[request_len]; p_msg->len = request_len; // generate it char* c = p_msg->buf; request_line_wr(&c,msg->u.request->method_str, msg->u.request->ruri_str); via_wr(&c,stl2cstr(via),branch); copy_hdrs_wr(&c,msg->hdrs); content_length_wr(&c,stl2cstr(content_len)); *c++ = CR; *c++ = LF; if(msg->body.len){ memcpy(c,msg->body.s,msg->body.len); // Not needed by now as the message is finished //c += body.len; } // and parse it if(parse_sip_msg(p_msg)){ ERROR("Parser failed on generated request\n"); ERROR("Message was: <%.*s>\n",p_msg->len,p_msg->buf); delete p_msg; return MALFORMED_SIP_MSG; } memcpy(&p_msg->remote_ip,&msg->remote_ip,sizeof(sockaddr_storage)); DBG("Sending to %s:%i <%.*s>\n", get_addr_str(((sockaddr_in*)&p_msg->remote_ip)->sin_addr).c_str(), ntohs(((sockaddr_in*)&p_msg->remote_ip)->sin_port), p_msg->len,p_msg->buf); trans_bucket* bucket = get_trans_bucket(p_msg->callid->value, get_cseq(p_msg)->num_str); bucket->lock(); int send_err = transport->send(&p_msg->remote_ip,p_msg->buf,p_msg->len); if(send_err < 0){ ERROR("Error from transport layer\n"); delete p_msg; } else { sip_trans* t = bucket->add_trans(p_msg,TT_UAC); if(p_msg->u.request->method == sip_request::INVITE){ // if transport == UDP t->reset_timer(STIMER_A,A_TIMER,bucket->get_id()); // for any transport type t->reset_timer(STIMER_B,B_TIMER,bucket->get_id()); } else { // if transport == UDP t->reset_timer(STIMER_E,E_TIMER,bucket->get_id()); // for any transport type t->reset_timer(STIMER_F,F_TIMER,bucket->get_id()); } string t_id = int2hex(bucket->get_id()).substr(5,string::npos) + ":" + long2hex((unsigned long)t); memcpy(tid,t_id.c_str(),t_id.length()); tid_len = t_id.length(); } bucket->unlock(); return send_err; }