int cf_msg_logger::log(const char* buf, int len, sockaddr_storage* src_ip, sockaddr_storage* dst_ip, cstring method, int reply_code) { string src = addr2str(src_ip); string dst = addr2str(dst_ip); AmLock _l(fd_mut); write_src_dst(src); write_src_dst(dst); string what = c2stlstr(method); if(reply_code > 0) { what = int2str(reply_code) + " / " + what; } WRITE_CSTSTR("<call src='"); WRITE_STLSTR(src); WRITE_CSTSTR("' dst='"); WRITE_STLSTR(dst); WRITE_CSTSTR("' desc='"); WRITE_STLSTR(what); WRITE_CSTSTR("'>\n"); if(write(buf,len) != len) return -1; WRITE_CSTSTR("</call>\n"); return 0; }
/** * 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; }
// // Ref. RFC 3261 "12.2.1.1 Generating the Request" // int trans_layer::set_next_hop(list<sip_header*>& route_hdrs, cstring& r_uri, sockaddr_storage* remote_ip) { string next_hop; unsigned short next_port=0; //assert(msg->type == SIP_REQUEST); int err=0; if(!route_hdrs.empty()){ sip_header* fr = route_hdrs.front(); sip_nameaddr na; const char* c = fr->value.s; if(parse_nameaddr(&na, &c, fr->value.len)<0) { DBG("Parsing name-addr failed\n"); return -1; } if(parse_uri(&na.uri,na.addr.s,na.addr.len) < 0) { DBG("Parsing route uri failed\n"); return -1; } bool is_lr = false; if(!na.uri.params.empty()){ list<sip_avp*>::iterator it = na.uri.params.begin(); for(;it != na.uri.params.end(); it++){ if( ((*it)->name.len == 2) && (!memcmp((*it)->name.s,"lr",2)) ) { is_lr = true; break; } } } if (SipCtrlInterfaceFactory::outbound_host.empty()) { next_hop = c2stlstr(na.uri.host); next_port = na.uri.port; } else { next_hop = SipCtrlInterfaceFactory::outbound_host; next_port = SipCtrlInterfaceFactory::outbound_port; } if(!is_lr){ // detect beginning of next route enum { RR_PARAMS=0, RR_QUOTED, RR_SEP_SWS, // space(s) after ',' RR_NXT_ROUTE }; int st = RR_PARAMS; const char* end = fr->value.s + fr->value.len; for(;c<end;c++){ switch(st){ case RR_PARAMS: switch(*c){ case SP: case HTAB: case CR: case LF: break; case COMMA: st = RR_SEP_SWS; break; case DQUOTE: st = RR_QUOTED; break; } break; case RR_QUOTED: switch(*c){ case BACKSLASH: c++; break; case DQUOTE: st = RR_PARAMS; break; } break; case RR_SEP_SWS: switch(*c){ case SP: case HTAB: case CR: case LF: break; default: st = RR_NXT_ROUTE; goto nxt_route; } break; } } nxt_route: switch(st){ case RR_QUOTED: case RR_SEP_SWS: DBG("Malformed first route header\n"); case RR_PARAMS: // remove current route header from message DBG("delete (fr=0x%p)\n",fr); delete fr; // route_hdrs.front(); route_hdrs.pop_front(); DBG("route_hdrs.length() = %i\n",(int)route_hdrs.size()); break; case RR_NXT_ROUTE: // remove current route from this header fr->value.s = c; fr->value.len = end-c; break; } // copy r_uri at the end of // the route set. route_hdrs.push_back(new sip_header(0,"Route",r_uri)); r_uri = na.addr; } } else { if (SipCtrlInterfaceFactory::outbound_host.empty()) { sip_uri parsed_r_uri; err = parse_uri(&parsed_r_uri,r_uri.s,r_uri.len); if(err < 0){ ERROR("Invalid Request URI\n"); return -1; } next_hop = c2stlstr(parsed_r_uri.host); next_port = parsed_r_uri.port; } else { next_hop = SipCtrlInterfaceFactory::outbound_host; next_port = SipCtrlInterfaceFactory::outbound_port; } } DBG("next_hop:next_port is <%s:%u>\n", next_hop.c_str(), next_port); err = resolver::instance()->resolve_name(next_hop.c_str(), remote_ip,IPv4,UDP); if(err < 0){ ERROR("Unresolvable Request URI\n"); return -1; } ((sockaddr_in*)remote_ip)->sin_port = htons(next_port); return 0; }