* Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* Description: Network util.
*/
#include "datasystem/common/util/net_util.h"
#include <sstream>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <securec.h>
#include "datasystem/common/util/status_helper.h"
#include "datasystem/common/util/validator.h"
namespace datasystem {
Status ParseToHostPortString(const std::string &str, std::string &host, std::string &port, bool &isIPv6)
{
std::string addrStr;
std::string portNumStr;
CHECK_FAIL_RETURN_STATUS(Validator::ValidateHostPortString("HostPort", str), K_INVALID,
"Invalid IP address and port parsed");
auto pos = str.find_last_of(':');
portNumStr = str.substr(pos + 1);
if (str[0] != '[') {
addrStr = str.substr(0, pos);
} else {
const int lastCharPosTruncate = 2;
isIPv6 = true;
addrStr = str.substr(1, pos - lastCharPosTruncate);
}
host = addrStr;
port = portNumStr;
return Status::OK();
}
Status IsPortAvailable(const std::string &host, int port)
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
inet_pton(AF_INET, host.c_str(), &addr.sin_addr);
if (bind(sockfd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0 && errno == EADDRINUSE) {
close(sockfd);
return Status(StatusCode::K_RUNTIME_ERROR,
FormatString("Port %d on %s is already in use", port, host));
}
close(sockfd);
return Status::OK();
}
std::vector<std::string> Split(const std::string &input, const std::string &pattern)
{
std::string str = input;
std::string::size_type pos;
std::vector<std::string> result;
str += pattern;
size_t len = str.size();
for (size_t i = 0; i < len; i++) {
pos = str.find(pattern, i);
if (pos < len) {
std::string ss = str.substr(i, pos - i);
result.push_back(ss);
i = pos + pattern.size() - 1;
}
}
return result;
}
HostPort::HostPort(std::string host, int port)
: host_(std::move(host)), port_(port)
{
if (!host_.empty() && host_.find(':') != std::string::npos) {
isIPv6_ = true;
}
}
Status HostPort::ParseString(const std::string &str)
{
std::string port;
RETURN_IF_NOT_OK(ParseToHostPortString(str, host_, port, isIPv6_));
StringToInt(port, port_);
return Status::OK();
}
}