bool LUAIPAddress::Read(Exception& ex, lua_State *pState, int index, IPAddress& address,bool withDNS) { if (lua_type(pState, index)==LUA_TSTRING) // lua_type because can be encapsulated in a lua_next return withDNS ? address.setWithDNS(ex, lua_tostring(pState,index)) : address.set(ex, lua_tostring(pState,index)); if(lua_istable(pState,index)) { bool isConst; IPAddress* pOther = Script::ToObject<IPAddress>(pState, isConst, index); if (pOther) { address.set(*pOther); return true; } SocketAddress* pAddress = Script::ToObject<SocketAddress>(pState, isConst, index); if (pAddress) { address.set(pAddress->host()); return true; } ServerConnection* pServer = Script::ToObject<ServerConnection>(pState, isConst, index); if (pServer) { address.set(pServer->address.host()); return true; } } ex.set(Exception::NETADDRESS, "No valid IPAddress available to read"); return false; }
bool DNS::Resolve(Exception& ex, const char* address, HostEntry& host) { IPAddress ip; Exception ignore; if (ip.set(ignore, address)) return HostByAddress(ex,ip,host); return HostByName(ex, address, host); }
bool SocketAddress::setIntern(Exception& ex,const string& host, UInt16 port,bool resolveHost) { IPAddress ip; Exception ignore; if (ip.set(ignore, host)) { set(ip, port); return true; } HostEntry entry; if (!resolveHost) { if (ignore) ex.set(ignore); return false; } if (!DNS::HostByName(ex, host, entry)) return false; auto& addresses = entry.addresses(); if (addresses.size() > 0) { // if we get both IPv4 and IPv6 addresses, prefer IPv4 for (const IPAddress& address : addresses) { if (address.family() == IPAddress::IPv4) { set(address, port); return true; } } set(addresses.front(), port); return true; } ex.set(Exception::NETADDRESS, "No address found for the host ", host); return false; }
ADD_TEST(DNSTest, HostByAddress) { Exception ex; HostEntry hostEntry; IPAddress ip; ip.set(ex, "80.122.195.86"); CHECK(!ex) DNS::HostByAddress(ex, ip, hostEntry); CHECK(!ex) CHECK(hostEntry.name() == "mailhost.appinf.com"); CHECK(hostEntry.aliases().empty()); CHECK(hostEntry.addresses().size() >= 1); CHECK(hostEntry.addresses().front().toString() == "80.122.195.86"); ip.set(ex, "10.0.244.253"); CHECK(!ex) DNS::HostByAddress(ex, ip, hostEntry); CHECK(ex) }
bool SDP::build(Exception& ex, const char* text) { SDPMedia* pMedia = NULL; String::ForEach forEach([this,&pMedia,&ex](UInt32 index,const char* line){ if(strlen(line)==0 || line[1] != '=') { ex.set(Exception::FORMATTING, "SDP line ",line," malformed, second byte isn't an equal sign"); return false; } UInt8 type = line[0]; line = String::TrimLeft(line); // RFC 4566 switch(type) { case 'v': // v= (protocol version) version = String::ToNumber<UInt32>(ex, line); break; case 'o': { // o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address> String::ForEach forEach([&ex,this](UInt32 index, const char* value) { switch (index) { case 0: user.assign(value); break; case 1: sessionId = String::ToNumber<UInt32>(ex, value); break; case 2: sessionVersion = String::ToNumber<UInt32>(ex, value); break; case 4: unicastAddress.set(IPAddress::Wildcard(String::ICompare(value,"IP6")==0 ? IPAddress::IPv6 : IPAddress::IPv4)); break; case 5: unicastAddress.set(ex,value,unicastAddress.family()); break; } return !ex; }); if(String::Split(line, " ", forEach, String::SPLIT_IGNORE_EMPTY | String::SPLIT_TRIM)<6) ex.set(Exception::PROTOCOL, "SDP o line required 6 values (<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>)"); break; } case 's': // s= (session name) sessionName = line; break; /// Optional lines case 'i': // i=* (session information) sessionInfos = line; break; case 'u': // u=* (URI of description) uri = line; break; case 'e': // e=* (email address) email = line; break; case 'p': // p=* (phone number) phone = line; break; case 'c': { // c=* (connection information -- not required if included in all media) IPAddress defaultAddress; // TODO defaultAddress is useless for what? String::ForEach forEach([&ex,&defaultAddress, this](UInt32 index, const char* value) { switch (index) { case 1: defaultAddress.set(IPAddress::Wildcard(String::ICompare(value,"IP6")==0 ? IPAddress::IPv6 : IPAddress::IPv4)); break; case 2: defaultAddress.set(ex,value,defaultAddress.family()); break; } return !ex; }); if(String::Split(line, " ", forEach, String::SPLIT_IGNORE_EMPTY | String::SPLIT_TRIM)<3) ex.set(Exception::PROTOCOL, "SDP c line required 3 values"); break; } case 'b': // b=* (zero or more bandwidth information lines) // TODO useless? break; // One or more time descriptions ("t=" and "r=" lines; see below) // t= (time the session is active) // r=* (zero or more repeat times) case 't': // TODO useless? break; case 'r': // TODO useless? break; case 'z': // z=* (time zone adjustments) // TODO useless? break; case 'k': // k=* (encryption key) encryptKey = line; break; case 'm': { // m=<name> <port> <proto> <fmt> string name; UInt16 port; String::ForEach forEach([&ex, &pMedia, &name, &port, this](UInt32 index, const char* value) { switch (index) { case 0: name = value; break; case 1: port = String::ToNumber<UInt16>(ex, value); break; case 2: pMedia = addMedia(name, port, value); break; } return !ex; }); if(String::Split(line, " ", forEach, String::SPLIT_IGNORE_EMPTY | String::SPLIT_TRIM)<4) ex.set(Exception::PROTOCOL, "SDP m line required 4 values (<name> <port> <proto> <fmt>)"); break; } case 'a': { // a=* (zero or more session attribute lines) vector<string>* pFields = NULL; bool isMsId = false; string fingerHash; // TODO SDPSource* pSource = NULL; // TODO list<UInt32>* pSourceGroupe = NULL; String::ForEach forEach([&ex, &pMedia, &pFields, &isMsId, &fingerHash, this](UInt32 index, const char* value) { // RFC 5576 if(pMedia) { /* TODO if(pSourceGroupe) pSourceGroupe->push_back(NumberParser::parseUnsigned(field)); else if(pSource) { if(isMsId) pSource->msData = field; else if(key=="cname") // cname:<value> pSource->cname = value; else if(key=="msid") {// draft-alvestrand-mmusic-msid-00 isMsId = true; pSource->msId = value; } else if(key=="mslabel") // draft-alvestrand-rtcweb-mid-01 pSource->msLabel = value; else if(key=="label") // draft-alvestrand-rtcweb-mid-01 pSource->label = value; else WARN("Media source attribute ",key," unknown"); } else if(key=="ssrc") // a=ssrc:<ssrc-id> pSource = &sources[NumberParser::parseUnsigned(key)];// a=ssrc:<ssrc-id> <attribute> else if(key=="rtcp-mux") pMedia->rtcpMux = true; else if(key=="mid") // RFC 3388, a=mid:<token> pMedia->mid = value; else if(key=="ssrc-group") // a=ssrc-group:<semantics> pSourceGroupe = &sourceGroupes[value]; else if(key="crypto") { // a=crypto:<tag> <crypto-suite> <key-params> [<session-params>] StringTokenizer values(value," ",StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); poco_assert(values.size()>2) pMedia->cryptoTag = } else WARN("Media attribute ",key," unknown");*/ ERROR("TODO") } else if(pFields) pFields->emplace_back(value); else if(!fingerHash.empty()) int i=0; // TODO finger = talk_base::SSLFingerprint::CreateFromRfc4572(fingerHash, field); else { const char* key(value); const char* value(String::Empty.c_str()); const char* colon(strchr(value,':')); if (colon) { *(char*)colon = 0; value = colon + 1; } if (String::ICompare(key,"group")==0) // RFC 5888 and draft-holmberg-mmusic-sdp-bundle-negotiation-00 pFields = &groups[value]; else if (String::ICompare(key,"ice-ufrag")==0) iceUFrag = value; else if (String::ICompare(key,"ice-pwd")==0) icePwd = value; else if (String::ICompare(key,"ice-options")==0) { pFields = &iceOptions; iceOptions.emplace_back(value); } else if (String::ICompare(key,"fingerprint")==0) // fingerprint:<hash> <algo> fingerHash = value; // fingerprint:<hash> else if (String::ICompare(key,"msid-semantic")==0) supportMsId = String::ICompare(value ,"VMS")==0; else if (String::ICompare(key,"extmap")==0) // RFC 5285 a=extmap:<value>["/"<direction>] <URI> <extensionattributes> pFields = &extensions[value]; else WARN("SDP attribute ", key, " unknown"); } return true; }); String::Split(line, " ", forEach, String::SPLIT_IGNORE_EMPTY | String::SPLIT_TRIM); break; } // case 'a': } // switch(type)
bool SDP::build(Exception& ex, const string& text) { SDPMedia* pMedia = NULL; vector<string> lines; String::Split(text, "\r\n", lines, String::SPLIT_IGNORE_EMPTY | String::SPLIT_TRIM); for(string& line : lines) { if(line.empty() || line[1] != '=') { ex.set(Exception::FORMATTING, "SDP line ",line," malformed, second byte isn't an equal sign"); return false; } UInt8 type = line[0]; line.erase(0,2); String::Trim(line, String::TRIM_LEFT); // RFC 4566 switch(type) { case 'v': // v= (protocol version) version = String::ToNumber<UInt32>(ex, line); break; case 'o': { // o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address> vector<string> fields; String::Split(line, " ", fields, String::SPLIT_IGNORE_EMPTY | String::SPLIT_TRIM); if (fields.size()!=6) { ex.set(Exception::PROTOCOL, "fields.size()!=6"); break; } user = fields[0]; sessionId = String::ToNumber<UInt32>(ex, fields[1]); if (ex) break; sessionVersion = String::ToNumber<UInt32>(ex, fields[2]); if (ex) break; unicastAddress.set(ex,fields[5],fields[4]=="IP6" ? IPAddress::IPv6 : IPAddress::IPv4); break; } case 's': // s= (session name) sessionName = line; break; /// Optional lines case 'i': // i=* (session information) sessionInfos = line; break; case 'u': // u=* (URI of description) uri = line; break; case 'e': // e=* (email address) email = line; break; case 'p': // p=* (phone number) phone = line; break; case 'c': { // c=* (connection information -- not required if included in all media) vector<string> fields; String::Split(line, " ", fields, String::SPLIT_IGNORE_EMPTY | String::SPLIT_TRIM); if(fields.size()!=3) { ex.set(Exception::PROTOCOL, "fields.size()!=3"); break; } IPAddress defaultAddress; // TODO defaultAddress is useless for what? defaultAddress.set(ex,fields[2], fields[1] == "IP6" ? IPAddress::IPv6 : IPAddress::IPv4); break; } case 'b': // b=* (zero or more bandwidth information lines) // TODO useless? break; // One or more time descriptions ("t=" and "r=" lines; see below) // t= (time the session is active) // r=* (zero or more repeat times) case 't': // TODO useless? break; case 'r': // TODO useless? break; case 'z': // z=* (time zone adjustments) // TODO useless? break; case 'k': // k=* (encryption key) encryptKey = line; break; case 'm': { // m=<name> <port> <proto> <fmt> vector<string> values; String::Split(line, " ", values, String::SPLIT_IGNORE_EMPTY | String::SPLIT_TRIM); if (values.size()<4) { ex.set(Exception::PROTOCOL , "values.size()<4"); break; } UInt16 val = String::ToNumber<UInt16>(ex, values[1]); if (ex) break; pMedia = addMedia(values[0], val, values[2]); for(const string& st : values) { pMedia->formats.emplace_back(String::ToNumber<UInt8>(ex, st)); if (ex) break; } break; } case 'a': { // a=* (zero or more session attribute lines) vector<string>* pFields = NULL; bool isMsId = false; string fingerHash; // TODO SDPSource* pSource = NULL; // TODO list<UInt32>* pSourceGroupe = NULL; vector<string> fields; String::Split(line, " ", fields, String::SPLIT_IGNORE_EMPTY | String::SPLIT_TRIM); for(const string& st : fields) { size_t pos = st.find(':'); string key,value; if(pos!=string::npos) { key = st.substr(0,pos); value = st.substr(pos+1); } else key = st; // RFC 5576 if(pMedia) { /* TODO if(pSourceGroupe) pSourceGroupe->push_back(NumberParser::parseUnsigned(field)); else if(pSource) { if(isMsId) pSource->msData = field; else if(key=="cname") // cname:<value> pSource->cname = value; else if(key=="msid") {// draft-alvestrand-mmusic-msid-00 isMsId = true; pSource->msId = value; } else if(key=="mslabel") // draft-alvestrand-rtcweb-mid-01 pSource->msLabel = value; else if(key=="label") // draft-alvestrand-rtcweb-mid-01 pSource->label = value; else WARN("Media source attribute ",key," unknown"); } else if(key=="ssrc") // a=ssrc:<ssrc-id> pSource = &sources[NumberParser::parseUnsigned(key)];// a=ssrc:<ssrc-id> <attribute> else if(key=="rtcp-mux") pMedia->rtcpMux = true; else if(key=="mid") // RFC 3388, a=mid:<token> pMedia->mid = value; else if(key=="ssrc-group") // a=ssrc-group:<semantics> pSourceGroupe = &sourceGroupes[value]; else if(key="crypto") { // a=crypto:<tag> <crypto-suite> <key-params> [<session-params>] StringTokenizer values(value," ",StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); poco_assert(values.size()>2) pMedia->cryptoTag = } else */ WARN("Media attribute ",key," unknown"); } else if(pFields) pFields->emplace_back(st); else if(!fingerHash.empty()) int i=0; // TODO finger = talk_base::SSLFingerprint::CreateFromRfc4572(fingerHash, field); else if(key=="group") // RFC 5888 and draft-holmberg-mmusic-sdp-bundle-negotiation-00 pFields = &groups[value]; else if(key=="ice-ufrag") iceUFrag = value; else if(key=="ice-pwd") icePwd = value; else if(key=="ice-options") { pFields = &iceOptions; iceOptions.emplace_back(value); } else if(key=="fingerprint") // fingerprint:<hash> <algo> fingerHash = value; // fingerprint:<hash> else if(key=="msid-semantic") supportMsId = value=="VMS"; else if(key=="extmap") // RFC 5285 a=extmap:<value>["/"<direction>] <URI> <extensionattributes> pFields = &extensions[value]; else WARN("SDP attribute ",key," unknown"); } } // case 'a': break; } // switch(type) if (ex) { ex.set(Exception::PROTOCOL, "SDP '",type,"' value ",line," malformed, ",ex.error()); return false; } } // for(string& line : lines) return true; }