in tensorpipe/transport/ibv/sockaddr.cc [25:108]
Sockaddr Sockaddr::createInetSockAddr(const std::string& str) {
int port = 0;
std::string addrStr;
std::string portStr;
// If the input string is an IPv6 address with port, the address
// itself must be wrapped with brackets.
if (addrStr.empty()) {
auto start = str.find("[");
auto stop = str.find("]");
if (start < stop && start != std::string::npos &&
stop != std::string::npos) {
addrStr = str.substr(start + 1, stop - (start + 1));
if (stop + 1 < str.size() && str[stop + 1] == ':') {
portStr = str.substr(stop + 2);
}
}
}
// If the input string is an IPv4 address with port, we expect
// at least a single period and a single colon in the string.
if (addrStr.empty()) {
auto period = str.find(".");
auto colon = str.find(":");
if (period != std::string::npos && colon != std::string::npos) {
addrStr = str.substr(0, colon);
portStr = str.substr(colon + 1);
}
}
// Fallback to using entire input string as address without port.
if (addrStr.empty()) {
addrStr = str;
}
// Parse port number if specified.
if (!portStr.empty()) {
port = std::stoi(portStr);
if (port < 0 || port > std::numeric_limits<uint16_t>::max()) {
TP_THROW_EINVAL() << str;
}
}
// Try to convert an IPv4 address.
{
struct sockaddr_in addr;
std::memset(&addr, 0, sizeof(addr));
auto rv = inet_pton(AF_INET, addrStr.c_str(), &addr.sin_addr);
TP_THROW_SYSTEM_IF(rv < 0, errno);
if (rv == 1) {
addr.sin_family = AF_INET;
addr.sin_port = ntohs(port);
return Sockaddr(reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr));
}
}
// Try to convert an IPv6 address.
{
struct sockaddr_in6 addr;
std::memset(&addr, 0, sizeof(addr));
auto interfacePos = addrStr.find('%');
if (interfacePos != std::string::npos) {
addr.sin6_scope_id =
if_nametoindex(addrStr.substr(interfacePos + 1).c_str());
addrStr = addrStr.substr(0, interfacePos);
}
auto rv = inet_pton(AF_INET6, addrStr.c_str(), &addr.sin6_addr);
TP_THROW_SYSTEM_IF(rv < 0, errno);
if (rv == 1) {
addr.sin6_family = AF_INET6;
addr.sin6_port = ntohs(port);
return Sockaddr(reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr));
}
}
// Invalid address.
TP_THROW_EINVAL() << str;
// Return bogus to silence "return from non-void function" warning.
// Note: we don't reach this point per the throw above.
return Sockaddr(nullptr, 0);
}