/* Copyright(C) 2007-2016 VoIP objects (voipobjects.com) * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ICECandidate.h" #include "ICEError.h" #include "ICELog.h" #include #include #define LOG_SUBSYSTEM "ICE" using namespace ice; void Candidate::setLocalAndExternalAddresses(std::string& ip, unsigned short portNumber) { mLocalAddr.setIp(ip); mLocalAddr.setPort(portNumber); mExternalAddr.setIp(ip); mExternalAddr.setPort(portNumber); } void Candidate::setLocalAndExternalAddresses(NetworkAddress& addr) { mLocalAddr = addr; mExternalAddr = addr; } void Candidate::setLocalAndExternalAddresses(NetworkAddress &addr, unsigned short altPort) { mLocalAddr = addr; mExternalAddr = addr; mLocalAddr.setPort(altPort); mExternalAddr.setPort(altPort); } void Candidate::computePriority(int* typepreflist) { mPriority = (typepreflist[mType] << 24) + (mInterfacePriority << 8) + (256 - mComponentId); } void Candidate::computeFoundation() { sprintf(mFoundation, "%u", unsigned((mType << 24) + inet_addr(mLocalAddr.ip().c_str()))); } const char* Candidate::type() { switch (mType) { case Candidate::Host: return "host"; case Candidate::ServerReflexive: return "srflx"; case Candidate::ServerRelayed: return "relay"; case Candidate::PeerReflexive: return "prflx"; default: ICELogCritical(<< "Bad candidate type, reverted to Host."); return "host"; } } std::string Candidate::createSdp() { char buffer[512]; unsigned port = (unsigned)mExternalAddr.port(); #define SDP_CANDIDATE_FORMAT "%s %u %s %u %s %u typ %s" sprintf(buffer, SDP_CANDIDATE_FORMAT, strlen(mFoundation) ? mFoundation : "16777000" , mComponentId, "UDP", mPriority, mExternalAddr.ip().c_str(), port, type()); if (mType != Candidate::Host) { char relattr[64]; sprintf(relattr, " raddr %s rport %u", mLocalAddr.ip().c_str(), (unsigned int)mLocalAddr.port()); strcat(buffer, relattr); } return buffer; } Candidate Candidate::parseSdp(const char* sdp) { Candidate result(Candidate::Host); char protocol[32], externalIP[128], candtype[32], raddr[64]; unsigned int remoteport = 0; unsigned int externalPort = 0; // Look for "typ" string const char* formatstring; if (strstr(sdp, "typ")) formatstring = "%s %u %s %u %s %u typ %s raddr %s rport %u"; else formatstring = "%s %u %s %u %s %u %s raddr %s rport %u"; int wasread = sscanf(sdp, formatstring, &result.mFoundation, &result.mComponentId, protocol, &result.mPriority, externalIP, &externalPort, candtype, raddr, &remoteport); if (wasread >= 7) { // Save external address result.mExternalAddr.setIp( externalIP ); result.mExternalAddr.setPort( externalPort ); result.mLocalAddr = result.mExternalAddr; // Check the protocol (UDP4/6 is supported only) #ifdef _WIN32 _strupr(protocol); _strupr(candtype); #else strupr(protocol); strupr(candtype); #endif if (strcmp(protocol, "UDP") != 0) throw Exception(UDP_SUPPORTED_ONLY); // Save candidate type result.mType = typeFromString(candtype); } return result; } Candidate::Type Candidate::typeFromString(const char* candtype) { if (!strcmp(candtype, "HOST")) return Candidate::Host; else if (!strcmp(candtype, "SRFLX")) return Candidate::ServerReflexive; else if (!strcmp(candtype, "PRFLX")) return Candidate::PeerReflexive; else if (!strcmp(candtype, "RELAY")) return Candidate::ServerRelayed; else { ICELogCritical(<< "Bad candidate type in parser. Reverted to Host"); return Candidate::Host; } } bool Candidate::equal(Candidate& cand1, Candidate& cand2) { if (cand1.mType != cand2.mType) return false; switch (cand1.mType) { case Candidate::Host: return (cand1.mLocalAddr == cand2.mLocalAddr); case Candidate::ServerReflexive: case Candidate::PeerReflexive: case Candidate::ServerRelayed: return (cand1.mExternalAddr == cand2.mExternalAddr); } ICELogCritical(<< "Bad candidate type, comparing as Host"); return cand1.mLocalAddr == cand2.mLocalAddr; } bool Candidate::operator == (const Candidate& rhs) const { bool relayed1 = mType == ServerRelayed, relayed2 = rhs.mType == ServerRelayed; return relayed1 == relayed2 && mLocalAddr == rhs.mLocalAddr && mExternalAddr == rhs.mExternalAddr; } void Candidate::dump(std::ostream& output) { output << Logger::TabPrefix<< Logger::TabPrefix << createSdp().c_str() << std::endl; } int Candidate::component() { return mComponentId; }