blob: bd1537736dae394c45ccc2ca1a244e1fdd61857e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
#include "UtilAll.h"
#include "LoggerImpl.h"
#include "zlib.h"
#include <cstring>
#if defined(__APPLE__)
#include <net/if_dl.h>
#define AF_FAMILY AF_LINK
#elif defined(__linux__)
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netpacket/packet.h>
#define AF_FAMILY AF_PACKET
#elif defined(_WIN32)
#include <Windows.h>
#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")
#endif
#ifndef _WIN32
#include <ifaddrs.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#endif
#include "asio.hpp"
ROCKETMQ_NAMESPACE_BEGIN
std::string UtilAll::hostname() {
return asio::ip::host_name();
}
bool UtilAll::macAddress(std::vector<unsigned char>& mac) {
static std::vector<unsigned char> cache;
static bool mac_cached = false;
if (mac_cached) {
mac = cache;
return true;
}
#ifndef _WIN32
struct ifaddrs *head = nullptr, *node;
if (getifaddrs(&head)) {
return false;
}
for (node = head; node; node = node->ifa_next) {
if (node->ifa_addr->sa_family == AF_FAMILY) {
#if defined(__APPLE__)
auto* ptr = reinterpret_cast<unsigned char*>(LLADDR(reinterpret_cast<struct sockaddr_dl*>(node->ifa_addr)));
#elif defined(__linux__)
auto* ptr = reinterpret_cast<unsigned char*>(reinterpret_cast<struct sockaddr_ll*>(node->ifa_addr)->sll_addr);
#endif
bool all_zero = true;
for (int i = 0; i < 6; i++) {
if (*(ptr + i) != 0) {
all_zero = false;
break;
}
}
if (all_zero) {
SPDLOG_TRACE("Skip MAC address of network interface {}", node->ifa_name);
continue;
}
SPDLOG_DEBUG("Use MAC address of network interface {}", node->ifa_name);
// MAC address has 48 bits
cache.resize(6);
memcpy(cache.data(), ptr, 6);
mac_cached = true;
mac = cache;
break;
}
}
freeifaddrs(head);
return true;
#else
PIP_ADAPTER_INFO adaptor_info;
DWORD buf_len = sizeof(IP_ADAPTER_INFO);
char mac_address[18];
adaptor_info = (IP_ADAPTER_INFO*)malloc(buf_len);
if (!adaptor_info) {
// TODO: running out of memroy
}
if (GetAdaptersInfo(adaptor_info, &buf_len) == NO_ERROR) {
PIP_ADAPTER_INFO item = adaptor_info;
do {
bool all_zero = true;
for (auto& b : item->Address) {
if (b != 0) {
all_zero = false;
break;
}
}
if (!all_zero) {
cache.resize(6);
memcpy(cache.data(), item->Address, 6);
mac_cached = true;
mac = cache;
break;
}
item = item->Next;
} while (item);
} else {
free(adaptor_info);
}
#endif
}
bool UtilAll::compress(const std::string& src, std::string& dst) {
z_stream stream;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.next_in = reinterpret_cast<unsigned char*>(const_cast<char*>(src.c_str()));
stream.avail_in = src.length();
deflateInit(&stream, Z_DEFAULT_COMPRESSION);
uint32_t bound = deflateBound(&stream, src.length());
std::vector<unsigned char> buffer(bound);
stream.next_out = buffer.data();
stream.avail_out = bound;
int status = deflate(&stream, Z_FINISH);
// zlib is unexpected wrong.
if (Z_STREAM_END != status) {
deflateEnd(&stream);
return false;
}
dst.reserve(stream.total_out);
assert(stream.total_out == bound - stream.avail_out);
std::copy(buffer.data(), buffer.data() + stream.total_out, std::back_inserter(dst));
deflateEnd(&stream);
return true;
}
bool UtilAll::uncompress(const std::string& src, std::string& dst) {
int status;
uint32_t buffer_length = 4096;
std::vector<unsigned char> buffer(buffer_length);
z_stream stream;
// Use default malloc / free allocator.
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.next_in = reinterpret_cast<unsigned char*>(const_cast<char*>(src.c_str()));
stream.avail_in = src.length();
inflateInit(&stream);
stream.next_out = buffer.data();
stream.avail_out = buffer_length;
while (true) {
status = inflate(&stream, Z_SYNC_FLUSH);
if (Z_STREAM_ERROR == status) {
return false;
}
std::copy(buffer.data(), buffer.data() + buffer_length - stream.avail_out, std::back_inserter(dst));
stream.avail_out = buffer_length;
stream.next_out = buffer.data();
// inflation completed OK
if (Z_STREAM_END == status) {
inflateEnd(&stream);
return true;
}
// inflation made some progress
if (Z_OK == status) {
continue;
}
// Something is wrong
inflateEnd(&stream);
return false;
}
}
ROCKETMQ_NAMESPACE_END