123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619 |
- #include <stdio.h>
- #include <limits.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include "fileutil.h"
- #include "strutil.h"
- #include "mqttcfg.h"
- #include "debug.h"
- #define _DEFAULT_CFG_FILE_NAME "mqttcl.cfg.json"
- #define _CFG_KEY_NAME_BROKER_ADDR "brokerAddr"
- #define _CFG_KEY_NAME_BROKER_PORT "brokerPort"
- #define _CFG_KEY_NAME_DEFAULT_QOS "defaultQos"
- #define _CFG_KEY_NAME_DEFAULT_RETAIN "defaultRetain"
- #define _CFG_KEY_NAME_DEVICE_PREFIX "devicePrefix"
- #define _CFG_KEY_NAME_DEVICE_ID "deviceID"
- #define _CFG_KEY_NAME_TLS_MODE "tlsMode"
- #define _CFG_KEY_NAME_TLS_CA_CRT_FILE "tlsCaCrtFile"
- #define _CFG_KEY_NAME_TLS_CL_CRT_FILE "tlsClCrtFile"
- #define _CFG_KEY_NAME_TLS_CL_KEY_FILE "tlsClKeyFile"
- #define _CFG_KEY_NAME_TLS_PSK "tlsPsk"
- #define _CFG_KEY_NAME_LAST_WILL_MSG_STR "lastWillMsgStr"
- #define _CFG_KEY_NAME_LAST_WILL_MSG_INT "lastWillMsgInt"
- #define _CFG_KEY_NAME_LAST_WILL_TOPIC "lastWillTopic"
- #define _CFG_KEY_NAME_LAST_WILL_QOS "lastWillQos"
- #define _CFG_KEY_NAME_LAST_WILL_RETAIN "lastWillRetain"
- #define _CFG_KEY_NAME_LAST_WILL_ON_EXIT "lastWillOnExit"
- #define _CFG_KEY_NAME_LAST_WILL_ON_EXIT_MSG_STR "lastWillOnExitMsgStr"
- #define _CFG_KEY_NAME_LAST_WILL_ON_EXIT_MSG_INT "lastWillOnExitMsgInt"
- #define _CFG_KEY_NAME_CONNECT_MSG_STR "connectMsgStr"
- #define _CFG_KEY_NAME_CONNECT_MSG_INT "connectMsgInt"
- #define _CFG_KEY_NAME_CONNECT_TOPIC "connectTopic"
- #define _CFG_KEY_NAME_CONNECT_QOS "connectQos"
- #define _CFG_KEY_NAME_CONNECT_RETAIN "connectRetain"
- #define _CFG_KEY_NAME_MAX_KEEP_ALIVE "maxKeepAlive"
- #define _CFG_KEY_NAME_TOPIC_PREFIX_STRING "topicPrefix"
- #define _CFG_KEY_NAME_DISABLE_TOPIC_PREFIX "disableTopicPrefix"
- /////////////////////////////////////////////////////////////////////////////
- CMqttClConfig::CMqttClConfig(const char *pszShmUuid) : m_strShmID(formatString("SHM-%s", strucase(pszShmUuid).c_str())),
- m_nBrokerPort(0),
- m_nDefaultQOS(0),
- m_bDefaultRetain(MQTTCL_DEFAULT_RETAIN),
- m_nLastWillMessage(0),
- m_nLastWillQos(m_nDefaultQOS),
- m_bLastWillRetain(MQTTCL_DEFAULT_RETAIN),
- m_bHasLastWill(false),
- m_bLastWillOnExit(false),
- m_nLastWillOnExitMsg(0),
- m_nConnectMessage(0),
- m_nConnectQos(m_nDefaultQOS),
- m_bConnectRetain(MQTTCL_DEFAULT_RETAIN),
- m_bHasConnect(false),
- m_bDisableTopicPrefix(false),
- m_bHasPrefix(false),
- m_nTlsMode(0),
- m_nMaxKeepAlive(MQTTCL_DEFAULT_MAX_KEEP_ALIVE_TIME)
- {
- }
- CMqttClConfig::~CMqttClConfig(void)
- {
- }
- /////////////////////////////////////////////////////////////////////////////
- // LoadCfg
- bool CMqttClConfig::LoadCfg(const char *pszCfgFilePath, CLogfile &rlf)
- {
- char szCfgFilePath[PATH_MAX];
- std::string strErr;
- if(!pszCfgFilePath)
- { // use default config file path
- pszCfgFilePath = ::BuildCanonicalFilePath(NULL, _DEFAULT_CFG_FILE_NAME, szCfgFilePath, sizeof(szCfgFilePath));
- }
- /////////////////////////////////////////////////////////////////////////
- // load and parse config file
- json_t *pjtCfg;
- json_error_t err;
- if(!(pjtCfg = ::json_load_file(pszCfgFilePath, JSON_REJECT_DUPLICATES, &err)))
- {
- rlf.Error("LoadCfg: Error loading file %s: %s!\n", pszCfgFilePath, err.text);
- return false;
- }
- CJson_t jtCfg(pjtCfg, true);
- /////////////////////////////////////////////////////////////////////////
- // tlsMode
- if(!GetIntValue(jtCfg, _CFG_KEY_NAME_TLS_MODE, m_nTlsMode, strErr))
- {
- m_nTlsMode = MQTTCL_TLS_MODE_OFF;
- rlf.Warning("LoadCfg: TLS will not be used!\n");
- }
- else if((m_nTlsMode < MQTTCL_TLS_MODE_OFF) || (m_nTlsMode > MQTTCL_TLS_MODE_PSK))
- {
- rlf.Error("LoadCfg: Invalid TLS mode: %d! No way to continue!\n", m_nTlsMode);
- return false;
- }
- /////////////////////////////////////////////////////////////////////////
- // brokerAddr
- if(!GetStringValue(jtCfg, _CFG_KEY_NAME_BROKER_ADDR, m_strBrokerAddr, strErr))
- {
- rlf.Error("LoadCfg: %s!\n", strErr.c_str());
- return false;
- }
- /////////////////////////////////////////////////////////////////////////
- // brokerPort
- if(!GetIntValue(jtCfg, _CFG_KEY_NAME_BROKER_PORT, m_nBrokerPort, strErr))
- {
- m_nBrokerPort = (m_nTlsMode > MQTTCL_TLS_MODE_OFF) ? 8883 : 1883;
- rlf.Info("LoadCfg: Using default broker port %d!\n", m_nBrokerPort);
- }
- else if(m_nBrokerPort < 0 || m_nBrokerPort > 0xffff)
- {
- rlf.Error("LoadCfg: Invalid broker port number: %d! No way to continue!\n", m_nBrokerPort);
- return false;
- }
- /////////////////////////////////////////////////////////////////////////
- // defaultQos
- if(!GetIntValue(jtCfg, _CFG_KEY_NAME_DEFAULT_QOS, m_nDefaultQOS, strErr))
- {
- m_nDefaultQOS = MQTTCL_DEFAULT_QOS;
- rlf.Info("LoadCfg: Using default QOS: %d!\n", m_nDefaultQOS);
- }
- else if(m_nDefaultQOS < MQTTCL_MIN_QOS)
- {
- rlf.Warning("LoadCfg: Invalid QOS: %d - adjusted to %d!\n", m_nDefaultQOS, MQTTCL_MIN_QOS);
- m_nDefaultQOS = MQTTCL_MIN_QOS;
- }
- else if(m_nDefaultQOS > MQTTCL_MAX_QOS)
- {
- rlf.Warning("LoadCfg: Invalid QOS: %d - adjusted to %d!\n", m_nDefaultQOS, MQTTCL_MAX_QOS);
- m_nDefaultQOS = MQTTCL_MAX_QOS;
- }
- else
- {
- rlf.Info("LoadCfg: Default QOS: %d!\n", m_nDefaultQOS);
- }
- /////////////////////////////////////////////////////////////////////////
- // defaultRetain
- if(!GetBoolValue(jtCfg, _CFG_KEY_NAME_DEFAULT_RETAIN, m_bDefaultRetain, strErr))
- {
- m_bDefaultRetain = MQTTCL_DEFAULT_RETAIN;
- rlf.Info("LoadCfg: Using default retain \"%s\"!\n", m_bDefaultRetain ? "true" : "false");
- }
- /////////////////////////////////////////////////////////////////////////
- // lastWillMsgStr
- if(GetStringValue(jtCfg, _CFG_KEY_NAME_LAST_WILL_MSG_STR, m_strLastWillMessage, strErr))
- {
- m_bHasLastWill = true;
- rlf.Info("LoadCfg: Last Will - String message: \"%s\".\n", m_strLastWillMessage.c_str());
- }
- /////////////////////////////////////////////////////////////////////////
- // lastWillMsgInt
- if(!m_bHasLastWill)
- {
- if(GetInt64Value(jtCfg, _CFG_KEY_NAME_LAST_WILL_MSG_INT, m_nLastWillMessage, strErr))
- {
- m_bHasLastWill = true;
- rlf.Info("LoadCfg: Last Will - Numeric message: %lld.\n", m_nLastWillMessage);
- }
- else
- {
- rlf.Warning("LoadCfg: %s! No Last Will Message provided.\n", strErr.c_str());
- }
- }
- if(m_bHasLastWill)
- {
- /////////////////////////////////////////////////////////////////////
- // lastWillTopic
- if(!GetStringValue(jtCfg, _CFG_KEY_NAME_LAST_WILL_TOPIC, m_strLastWillTopic, strErr))
- {
- m_strLastWillTopic = MQTTCL_DEFAULT_LAST_WILL_CONNECT_TOPIC;
- rlf.Info("LoadCfg: %s! Setting Last Will Topic to default: \"%s\".\n", strErr.c_str(), m_strLastWillTopic.c_str());
- }
- /////////////////////////////////////////////////////////////////////
- // lastWillQos
- if(!GetIntValue(jtCfg, _CFG_KEY_NAME_LAST_WILL_QOS, m_nLastWillQos, strErr))
- {
- m_nLastWillQos = m_nDefaultQOS;
- rlf.Info("LoadCfg: %s! Using default Last Will QOS: %d!\n", strErr.c_str(), m_nLastWillQos);
- }
- /////////////////////////////////////////////////////////////////////
- // lastWillRetain
- if(!GetBoolValue(jtCfg, _CFG_KEY_NAME_LAST_WILL_RETAIN, m_bLastWillRetain, strErr))
- {
- m_bLastWillRetain = m_bDefaultRetain;
- rlf.Info("LoadCfg: %s! Using default Last Will retain: \"%s\"!\n", strErr.c_str(), m_bLastWillRetain ? "true" : "false");
- }
- /////////////////////////////////////////////////////////////////////
- // lastWillOnExit
- if(!GetBoolValue(jtCfg, _CFG_KEY_NAME_LAST_WILL_ON_EXIT, m_bLastWillOnExit, strErr))
- {
- m_bLastWillOnExit = false;
- rlf.Warning("LoadCfg: %s! No Last Will on Exit.\n", strErr.c_str());
- }
- if(m_bLastWillOnExit)
- {
- /////////////////////////////////////////////////////////////////
- // lastWillOnExitMsgStr, lastWillOnExitMsgInt
- if(GetStringValue(jtCfg, _CFG_KEY_NAME_LAST_WILL_ON_EXIT_MSG_STR, m_strLastWillOnExitMsg, strErr))
- {
- rlf.Info("LoadCfg: Last Will on Exit - String message: \"%s\".\n", m_strLastWillOnExitMsg.c_str());
- }
- else
- {
- if(GetInt64Value(jtCfg, _CFG_KEY_NAME_LAST_WILL_ON_EXIT_MSG_INT, m_nLastWillOnExitMsg, strErr))
- {
- rlf.Info("LoadCfg: Last Will on Exit - Numeric message: %lld.\n", m_nLastWillOnExitMsg);
- }
- else
- {
- if(!m_strLastWillMessage.empty())
- {
- m_strLastWillOnExitMsg = m_strLastWillMessage;
- rlf.Info("LoadCfg: Setting Last Will Exit Message to Last Will string: \"%s\".\n", m_strLastWillOnExitMsg.c_str());
- }
- else
- {
- m_nLastWillOnExitMsg = m_nLastWillMessage;
- rlf.Info("LoadCfg: Setting Last Will Exit Message to Last Will numeric: %lld.\n", m_nLastWillOnExitMsg);
- }
- }
- }
- }
- }
- /////////////////////////////////////////////////////////////////////////
- // connectMsgStr
- if(GetStringValue(jtCfg, _CFG_KEY_NAME_CONNECT_MSG_STR, m_strConnectMessage, strErr))
- {
- m_bHasConnect = true;
- rlf.Info("LoadCfg: Connect - String message: \"%s\".\n", m_strConnectMessage.c_str());
- }
- /////////////////////////////////////////////////////////////////////////
- // connectMsgInt
- if(!m_bHasConnect)
- {
- if(GetInt64Value(jtCfg, _CFG_KEY_NAME_CONNECT_MSG_INT, m_nConnectMessage, strErr))
- {
- m_bHasConnect = true;
- rlf.Info("LoadCfg: Connect - Numeric message: %lld.\n", m_nConnectMessage);
- }
- else
- {
- rlf.Warning("LoadCfg: %s! No Connect message provided.\n", strErr.c_str());
- }
- }
- if(m_bHasConnect)
- {
- /////////////////////////////////////////////////////////////////////
- // connectTopic
- if(!GetStringValue(jtCfg, _CFG_KEY_NAME_CONNECT_TOPIC, m_strConnectTopic, strErr))
- {
- if(m_bHasLastWill)
- {
- m_strConnectTopic = m_strLastWillTopic;
- rlf.Info("LoadCfg: %s! Setting Connect Topic to Last Will Topic: \"%s\".\n", strErr.c_str(), m_strConnectTopic.c_str());
- }
- else
- {
- m_strConnectTopic = MQTTCL_DEFAULT_LAST_WILL_CONNECT_TOPIC;
- rlf.Info("LoadCfg: %s! Setting Connect Topic to default: \"%s\".\n", strErr.c_str(), m_strConnectTopic.c_str());
- }
- }
- /////////////////////////////////////////////////////////////////////
- // connectQos
- if(!GetIntValue(jtCfg, _CFG_KEY_NAME_CONNECT_QOS, m_nConnectQos, strErr))
- {
- m_nConnectQos = m_nDefaultQOS;
- rlf.Info("LoadCfg: %s! Using default Connect Qos: %d!\n", strErr.c_str(), m_nConnectQos);
- }
- /////////////////////////////////////////////////////////////////////
- // connectRetain
- if(!GetBoolValue(jtCfg, _CFG_KEY_NAME_CONNECT_RETAIN, m_bConnectRetain, strErr))
- {
- m_bConnectRetain = m_bDefaultRetain;
- rlf.Info("LoadCfg: %s! Using default Last Will retain: %s!\n", strErr.c_str(), m_bConnectRetain ? "true" : "false");
- }
- }
- /////////////////////////////////////////////////////////////////////////
- // maxKeepAlive
- if(!GetIntValue(jtCfg, _CFG_KEY_NAME_MAX_KEEP_ALIVE, m_nMaxKeepAlive, strErr))
- {
- m_nMaxKeepAlive = MQTTCL_DEFAULT_MAX_KEEP_ALIVE_TIME;
- rlf.Info("LoadCfg: %s! Using default Keep-alive time: %d!\n", strErr.c_str(), m_nMaxKeepAlive);
- }
- else if(m_nMaxKeepAlive < MQTTCL_MIN_MAX_KEEP_ALIVE_TIME)
- {
- rlf.Warning("LoadCfg: Adjusting max keep-alive time from %d to %d!\n", m_nMaxKeepAlive, MQTTCL_MIN_MAX_KEEP_ALIVE_TIME);
- m_nMaxKeepAlive = MQTTCL_MIN_MAX_KEEP_ALIVE_TIME;
- }
- /////////////////////////////////////////////////////////////////////////
- // devicePrefix
- if(!GetStringValue(jtCfg, _CFG_KEY_NAME_DEVICE_PREFIX, m_strDevicePrefix, strErr))
- {
- rlf.Warning("LoadCfg: %s! Using empty device prefix!\n", strErr.c_str());
- }
- /////////////////////////////////////////////////////////////////////////
- // deviceID
- if(GetStringValue(jtCfg, _CFG_KEY_NAME_DEVICE_ID, m_strDeviceID, strErr))
- {
- rlf.Info("LoadCfg: Using configured device ID: \"%s\"!\n", m_strDeviceID.c_str());
- }
- else
- {
- m_strDeviceID = CreateDeviceID(m_strDevicePrefix.c_str());
- rlf.Info("LoadCfg: Using automatic device ID: \"%s\"!\n", m_strDeviceID.c_str());
- }
- /////////////////////////////////////////////////////////////////////
- // disableTopicPrefix
- if(!GetBoolValue(jtCfg, _CFG_KEY_NAME_DISABLE_TOPIC_PREFIX, m_bDisableTopicPrefix, strErr))
- {
- m_bDisableTopicPrefix = false;
- }
- /////////////////////////////////////////////////////////////////////////
- // topicPrefix
- if(!m_bDisableTopicPrefix)
- {
- if(GetStringValue(jtCfg, _CFG_KEY_NAME_TOPIC_PREFIX_STRING, m_strTopicPrefix, strErr))
- {
- rlf.Info("LoadCfg: Using configured topic prefix: \"%s\"!\n", m_strTopicPrefix.c_str());
- }
- else
- {
- m_strTopicPrefix = formatString("%s/%s", GetDeviceID(), GetShmID());
- rlf.Info("LoadCfg: Using automatic topic prefix: \"%s\"!\n", m_strTopicPrefix.c_str());
- }
- }
- else
- {
- m_strTopicPrefix.clear();
- rlf.Warning("LoadCfg: Topic prefix disabled!\n");
- }
- /////////////////////////////////////////////////////////////////////////
- // if m_nTlsMode != MQTTCL_TLS_MODE_OFF
- if(m_nTlsMode == MQTTCL_TLS_MODE_CRT)
- {
- /////////////////////////////////////////////////////////////////////
- // tlsCaCrtFile
- if(!GetStringValue(jtCfg, _CFG_KEY_NAME_TLS_CA_CRT_FILE, m_strTlsCaCrtFile, strErr))
- {
- rlf.Error("LoadCfg: %s! TLS-Mode = %d and no Certificate Authority file provided! No way to continue!\n", strErr.c_str(), m_nTlsMode);
- return false;
- }
- /////////////////////////////////////////////////////////////////////
- // tlsClCrtFile
- if(!GetStringValue(jtCfg, _CFG_KEY_NAME_TLS_CL_CRT_FILE, m_strTlsClCrtFile, strErr))
- {
- rlf.Error("LoadCfg: %s! TLS-Mode = %d and no public Key Certificate file provided! No way to continue!\n", strErr.c_str(), m_nTlsMode);
- return false;
- }
- /////////////////////////////////////////////////////////////////////
- // tlsClKeyFile
- if(!GetStringValue(jtCfg, _CFG_KEY_NAME_TLS_CL_KEY_FILE, m_strTlsClKeyFile, strErr))
- {
- rlf.Error("LoadCfg: %s! TLS-Mode = %d and no private Key file provided! No way to continue!\n", strErr.c_str(), m_nTlsMode);
- return false;
- }
- }
- else if(m_nTlsMode == MQTTCL_TLS_MODE_PSK)
- {
- /////////////////////////////////////////////////////////////////////
- // tlsPsk
- if(!GetStringValue(jtCfg, _CFG_KEY_NAME_TLS_PSK, m_strTlsPSK, strErr))
- {
- rlf.Error("LoadCfg: %s! TLS-Mode = %d and no Preshared Key provided! No way to continue!\n", strErr.c_str(), m_nTlsMode);
- return false;
- }
- }
- return true;
- }
- /////////////////////////////////////////////////////////////////////////////
- bool CMqttClConfig::GetValue(CJson_t &rjtParent, const char *pszKey, CJson_t &rjtVal, std::string &strErr)
- {
- if(!rjtParent.GetValue(pszKey, rjtVal))
- {
- strErr = formatString("Key \"%s\" not found", pszKey);
- return false;
- }
- return true;
- }
- /////////////////////////////////////////////////////////////////////////////
- bool CMqttClConfig::GetBoolValue(CJson_t &rjtParent, const char *pszKey, bool &rbVal, std::string &strErr)
- {
- CJson_t jtVal;
- if(GetValue(rjtParent, pszKey, jtVal, strErr))
- {
- int nType;
- switch((nType = jtVal.Type()))
- {
- case JSON_TRUE:
- case JSON_FALSE:
- rbVal = (nType == JSON_TRUE);
- return true;
- default:
- strErr = formatString("\"%s\" (type=%d) is not a boolean value", pszKey, nType);
- return false;
- }
- }
- return false;
- }
- /////////////////////////////////////////////////////////////////////////////
- bool CMqttClConfig::GetIntValue(CJson_t &rjtParent, const char *pszKey, int &rnVal, std::string &strErr)
- {
- CJson_t jtVal;
- if(GetValue(rjtParent, pszKey, jtVal, strErr))
- {
- if(json_is_integer(jtVal.operator const json_t*()))
- {
- rnVal = (int)::json_integer_value(jtVal);
- return true;
- }
- strErr = formatString("\"%s\" (type=%d) is not an integer value", pszKey, jtVal.Type());
- }
- return false;
- }
- /////////////////////////////////////////////////////////////////////////////
- bool CMqttClConfig::GetInt64Value(CJson_t &rjtParent, const char *pszKey, long long &rnVal, std::string &strErr)
- {
- CJson_t jtVal;
- if(GetValue(rjtParent, pszKey, jtVal, strErr))
- {
- if(json_is_integer(jtVal.operator const json_t*()))
- {
- rnVal = (long long)::json_integer_value(jtVal);
- return true;
- }
- strErr = formatString("\"%s\" (type=%d) is not an integer value", pszKey, jtVal.Type());
- }
- return false;
- }
- /////////////////////////////////////////////////////////////////////////////
- bool CMqttClConfig::GetStringValue(CJson_t &rjtParent, const char *pszKey, std::string &rstrVal, std::string &strErr)
- {
- CJson_t jtVal;
- if(GetValue(rjtParent, pszKey, jtVal, strErr))
- {
- if(json_is_string(jtVal.operator const json_t*()))
- {
- rstrVal = ::json_string_value(jtVal);
- return !rstrVal.empty();
- }
- strErr = formatString("\"%s\" (type=%d) is not a string value", pszKey, jtVal.Type());
- }
- rstrVal.clear();
- return false;
- }
- /////////////////////////////////////////////////////////////////////////////
- sa_family_t CMqttClConfig::GetDevIdInterfaceName(char *pszItfName, size_t nCChItfName, const char *pszRequested)
- {
- sa_family_t nFamily = 0;
- struct ifaddrs *ifaddr, *ifa;
- memset(pszItfName, 0, nCChItfName);
- if(getifaddrs(&ifaddr) == 0)
- {
- for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
- {
- if(!ifa->ifa_addr || (ifa->ifa_flags & IFF_LOOPBACK))
- continue;
- if( ifa->ifa_addr->sa_family == AF_INET ||
- ifa->ifa_addr->sa_family == AF_INET6)
- {
- if(!strcmp(ifa->ifa_name, pszRequested))
- {
- strncpy(pszItfName, ifa->ifa_name, nCChItfName - 1);
- nFamily = ifa->ifa_addr->sa_family;
- break;
- }
- else if(!nFamily)
- {
- strncpy(pszItfName, ifa->ifa_name, nCChItfName - 1);
- nFamily = ifa->ifa_addr->sa_family;
- }
- }
- }
- freeifaddrs(ifaddr);
- }
- return nFamily;
- }
- bool CMqttClConfig::GetPreferredMacAddress(const char *pszRequested, std::string &s)
- {
- std::string sVal, sPath = ::formatString("/sys/class/net/%s/address", pszRequested);
- if(::readFile(sPath.c_str(), sVal))
- {
- sVal = ::trim(sVal);
- if(!sVal.empty())
- {
- s = ::strucase(sVal.c_str());
- return true;
- }
- }
- return false;
- }
- const char* CMqttClConfig::GetMacAddress(std::string &s)
- {
- int fd;
- struct ifreq ifr;
- s.clear();
-
- if(GetPreferredMacAddress("eth0", s))
- {
- return s.c_str();
- }
- if((ifr.ifr_addr.sa_family = CMqttClConfig::GetDevIdInterfaceName(ifr.ifr_name, sizeof(ifr.ifr_name), "eth0")))
- {
- if((fd = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) >= 0)
- {
- if( (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) &&
- (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER))
- {
- const char *m = (const char*)ifr.ifr_hwaddr.sa_data;
- s = formatString("%0.2hhX:%0.2hhX:%0.2hhX:%0.2hhX:%0.2hhX:%0.2hhX" , m[0], m[1], m[2], m[3], m[4], m[5]);
- }
- close(fd);
- }
- }
- return s.c_str();
- }
- std::string CMqttClConfig::CreateDeviceID(const char *pszDevicePrefix)
- {
- std::string m, s;
- if(pszDevicePrefix && *pszDevicePrefix)
- s = formatString("%s-%s", pszDevicePrefix, CMqttClConfig::GetMacAddress(m));
- else
- CMqttClConfig::GetMacAddress(s);
- return s;
- }
|