1304 lines
54 KiB
C++
1304 lines
54 KiB
C++
|
|
#include "iobox_api.h"
|
||
|
|
#include "cJSON.h"
|
||
|
|
|
||
|
|
namespace ANSCENTER {
|
||
|
|
iobox_api::iobox_api(std::string ip_mcast, int port_mcast)
|
||
|
|
{
|
||
|
|
this->ip_mcast = ip_mcast;
|
||
|
|
this->port_mcast = port_mcast;
|
||
|
|
WSADATA wsaData;
|
||
|
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||
|
|
std::cerr << "WSAStartup failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
iobox_api::~iobox_api()
|
||
|
|
{
|
||
|
|
WSACleanup();
|
||
|
|
}
|
||
|
|
|
||
|
|
bool isStringExistInVectorString(const std::vector<std::string>& vec, const std::string& str) {
|
||
|
|
try {
|
||
|
|
for (const auto& item : vec) {
|
||
|
|
if (item.find(str) != std::string::npos) {
|
||
|
|
std::cout << "Found partial match: " << str << " in " << item << std::endl;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// for (const auto& item : vec) {
|
||
|
|
// if (item == str) {
|
||
|
|
// std::cout << "Found duplicate: " << str << std::endl;
|
||
|
|
// return true;
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
return false;
|
||
|
|
// return std::find(vec.begin(), vec.end(), str) != vec.end();
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void printBufferAsHex(const char* buffer, size_t length) {
|
||
|
|
try {
|
||
|
|
for (size_t i = 0; i < length; ++i) {
|
||
|
|
printf("%02X ", static_cast<unsigned char>(buffer[i]));
|
||
|
|
if ((i + 1) % 16 == 0) {
|
||
|
|
printf("\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
printf("\n");
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void printStringAsHex(const std::string& str) {
|
||
|
|
try {
|
||
|
|
for (size_t i = 0; i < str.size(); ++i) {
|
||
|
|
printf("%02X ", static_cast<unsigned char>(str[i]));
|
||
|
|
if ((i + 1) % 16 == 0) {
|
||
|
|
printf("\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
printf("\n");
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
bool isValidIp(const std::string& ip) {
|
||
|
|
struct sockaddr_in sa;
|
||
|
|
return inet_pton(AF_INET, ip.c_str(), &(sa.sin_addr)) != 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string hostNameToIp(std::string hostName) {
|
||
|
|
struct hostent* host;
|
||
|
|
struct in_addr addr;
|
||
|
|
if ((host = gethostbyname(hostName.c_str())) == NULL) {
|
||
|
|
std::cerr << "Failed to get host by name: " << hostName << std::endl;
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
addr.s_addr = *(u_long*)host->h_addr_list[0];
|
||
|
|
return inet_ntoa(addr);
|
||
|
|
}
|
||
|
|
std::string checkIpFromRemote(const std::string& remote) {
|
||
|
|
std::string ip;
|
||
|
|
if (!isValidIp(remote)) {
|
||
|
|
std::cout << "Host name address: " << remote << std::endl;
|
||
|
|
ip = hostNameToIp(remote);
|
||
|
|
if (ip == "") {
|
||
|
|
std::cerr << "Failed to get ip from host name: " << remote << std::endl;
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
return ip;
|
||
|
|
}
|
||
|
|
else return remote;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
iobox_info_t parseIoboxResponseObj(cJSON* responseObj) {
|
||
|
|
try {
|
||
|
|
iobox_info_t info;
|
||
|
|
cJSON* model = cJSON_GetObjectItem(responseObj, "Model");
|
||
|
|
if (model != nullptr) {
|
||
|
|
info.model = model->valuestring;
|
||
|
|
}
|
||
|
|
cJSON* serial = cJSON_GetObjectItem(responseObj, "Serial");
|
||
|
|
if (serial != nullptr) {
|
||
|
|
//info.serial_number = serial->valuestring;
|
||
|
|
}
|
||
|
|
cJSON* hwVer = cJSON_GetObjectItem(responseObj, "HwVer");
|
||
|
|
if (hwVer != nullptr) {
|
||
|
|
info.hardware_version = hwVer->valuestring;
|
||
|
|
}
|
||
|
|
cJSON* fwVer = cJSON_GetObjectItem(responseObj, "FwVer");
|
||
|
|
if (fwVer != nullptr) {
|
||
|
|
info.firmware_version = fwVer->valuestring;
|
||
|
|
}
|
||
|
|
cJSON* macAddr = cJSON_GetObjectItem(responseObj, "macAddr");
|
||
|
|
if (macAddr != nullptr) {
|
||
|
|
info.mac_address = macAddr->valuestring;
|
||
|
|
info.serial_number = macAddr->valuestring;
|
||
|
|
}
|
||
|
|
cJSON* localIp = cJSON_GetObjectItem(responseObj, "localIp");
|
||
|
|
if (localIp != nullptr) {
|
||
|
|
info.ip_address = localIp->valuestring;
|
||
|
|
}
|
||
|
|
return info;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return iobox_info_t();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
iobox_info_t parseIoboxResponse(const std::string& response) {
|
||
|
|
try{
|
||
|
|
//exp: {"response": { "Model":"ANS IOBOX","Serial":"IO123","HwVer":"11", "FwVer":"22","macAddr":"a2c3d4e5f6","localIp":"192.168.110.121"}}
|
||
|
|
iobox_info_t info;
|
||
|
|
cJSON* root = cJSON_Parse(response.c_str());
|
||
|
|
if (root == nullptr) {
|
||
|
|
std::cerr << "Failed to parse JSON" << std::endl;
|
||
|
|
return info;
|
||
|
|
}
|
||
|
|
cJSON* responseObj = cJSON_GetObjectItem(root, "response");
|
||
|
|
if (responseObj == nullptr) {
|
||
|
|
std::cerr << "Failed to get response object" << std::endl;
|
||
|
|
cJSON_Delete(root);
|
||
|
|
return info;
|
||
|
|
}
|
||
|
|
info = parseIoboxResponseObj(responseObj);
|
||
|
|
cJSON_Delete(root);
|
||
|
|
|
||
|
|
std::cout << "Parsed IOBox Info:" << std::endl;
|
||
|
|
std::cout << " Model: " << info.model << std::endl;
|
||
|
|
std::cout << " Serial Number: " << info.serial_number << std::endl;
|
||
|
|
std::cout << " Hardware Version: " << info.hardware_version << std::endl;
|
||
|
|
std::cout << " Firmware Version: " << info.firmware_version << std::endl;
|
||
|
|
std::cout << " MAC Address: " << info.mac_address << std::endl;
|
||
|
|
std::cout << " IP Address: " << info.ip_address << std::endl;
|
||
|
|
std::cout << " Public IP Address: " << info.ip_public_address << std::endl;
|
||
|
|
return info;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return iobox_info_t();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void show_info_iobox(iobox_info_t iobox_info) {
|
||
|
|
std::cout << " IP Address: " << iobox_info.ip_address << std::endl;
|
||
|
|
}
|
||
|
|
void iobox_api::show_profile_iobox(std::string remote) {
|
||
|
|
try {
|
||
|
|
std::string ip = checkIpFromRemote(remote);
|
||
|
|
if (ip == "") {
|
||
|
|
std::cerr << "Failed to get ip from remote: " << remote << std::endl;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
iobox_profile_t* profile = findProfileByIp(ip);
|
||
|
|
if (profile == nullptr) {
|
||
|
|
std::cerr << "IP address not found: " << ip << std::endl;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
show_profile_iobox(*profile);
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void iobox_api::show_profile_iobox(iobox_profile_t profile) {
|
||
|
|
try {
|
||
|
|
// std::cout << "Profile ioboxs: " << this->iobox_profiles.size() << std::endl;
|
||
|
|
// for (const iobox_profile_t& profile : this->iobox_profiles) {
|
||
|
|
// std::cout << "* Index: " << &profile - &this->iobox_profiles[0] << std::endl;
|
||
|
|
show_info_iobox(profile.iobox_info);
|
||
|
|
std::cout << " Is connected: " << profile.is_connected << std::endl;
|
||
|
|
std::cout << " Is anthenticated: " << profile.is_anthenticated << std::endl;
|
||
|
|
std::cout << " TCP Socket: " << profile.sock_tcp << std::endl;
|
||
|
|
std::cout << " Counting get: " << profile.counting_get << std::endl;
|
||
|
|
std::cout << " Model: " << profile.iobox_info.model << std::endl;
|
||
|
|
std::cout << " Serial Number: " << profile.iobox_info.serial_number << std::endl;
|
||
|
|
std::cout << " Hardware Version: " << profile.iobox_info.hardware_version << std::endl;
|
||
|
|
std::cout << " Firmware Version: " << profile.iobox_info.firmware_version << std::endl;
|
||
|
|
std::cout << " MAC Address: " << profile.iobox_info.mac_address << std::endl;
|
||
|
|
std::cout << " IP Address: " << profile.iobox_info.ip_address << std::endl;
|
||
|
|
std::cout << " Public IP Address: " << profile.iobox_info.ip_public_address << std::endl;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void iobox_api::show_profile_ioboxs() {
|
||
|
|
try {
|
||
|
|
if (this->iobox_profiles.size() == 0) {
|
||
|
|
std::cout << "No iobox profiles" << std::endl;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
for (const auto& profile : this->iobox_profiles) {
|
||
|
|
std::cout << "* Index: " << &profile - &this->iobox_profiles[0] << std::endl;
|
||
|
|
show_profile_iobox(profile);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void iobox_api::save_info_iobox(iobox_info_t iobox_info) {
|
||
|
|
try {
|
||
|
|
iobox_profile_t profile;
|
||
|
|
profile.counting_get = 0;
|
||
|
|
profile.is_connected = false;
|
||
|
|
profile.is_anthenticated = false;
|
||
|
|
profile.sock_tcp = INVALID_SOCKET;
|
||
|
|
profile.iobox_info = iobox_info;
|
||
|
|
this->iobox_profiles.push_back(profile);
|
||
|
|
std::cout << "Save iobox, num device current: " << this->iobox_profiles.size() << std::endl;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void iobox_api::remove_last_info_iobox() {
|
||
|
|
try {
|
||
|
|
if (this->iobox_profiles.size() == 0) {
|
||
|
|
std::cout << "No iobox profiles" << std::endl;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this->iobox_profiles.pop_back();
|
||
|
|
std::cout << "Remove last iobox, num device current: " << this->iobox_profiles.size() << std::endl;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
bool iobox_api::sendTcpMessage(const std::string& ip, const char* buffer, size_t length, bool needCheckAuthen) {
|
||
|
|
try {
|
||
|
|
for (auto& profile : this->iobox_profiles) {
|
||
|
|
if ((profile.iobox_info.ip_address == ip || profile.iobox_info.ip_public_address == ip) && profile.is_connected && profile.sock_tcp != INVALID_SOCKET) {
|
||
|
|
if (needCheckAuthen && !profile.is_anthenticated) {
|
||
|
|
std::cerr << "Please anthenticate before send message" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
int result = send(profile.sock_tcp, buffer, length, 0);
|
||
|
|
if (result == SOCKET_ERROR) {
|
||
|
|
std::cerr << "send failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
std::cout << "Sent " << length << " bytes message to " << ip << std::endl;
|
||
|
|
std::cout << "Message: " << buffer << std::endl;
|
||
|
|
// printBufferAsHex(buffer, length);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
std::cerr << "IP address not found or not connected: " << ip << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool iobox_api::receiveTcpMessage(const std::string& ip, char* buffer, size_t& length) {
|
||
|
|
try {
|
||
|
|
for (auto& profile : this->iobox_profiles) {
|
||
|
|
if ((profile.iobox_info.ip_address == ip || profile.iobox_info.ip_public_address == ip) && profile.is_connected && profile.sock_tcp != INVALID_SOCKET) {
|
||
|
|
setSocketTimeout(profile.sock_tcp, 3000);
|
||
|
|
int recvLen = recv(profile.sock_tcp, buffer, length, 0);
|
||
|
|
if (recvLen > 0) {
|
||
|
|
length = recvLen;
|
||
|
|
buffer[length] = '\0';
|
||
|
|
std::cout << "Received message: " << length << " bytes" << std::endl;
|
||
|
|
std::cout << "Message: " << buffer << std::endl;
|
||
|
|
// printBufferAsHex(buffer, recvLen);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "recv failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
std::cerr << "IP address not found or not connected: " << ip << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void iobox_api::sendMulticastMessage(const std::string& message) {
|
||
|
|
try {
|
||
|
|
SOCKET sock = INVALID_SOCKET;
|
||
|
|
struct sockaddr_in multicastAddr;
|
||
|
|
|
||
|
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
|
|
if (sock == INVALID_SOCKET) {
|
||
|
|
std::cerr << "socket failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
WSACleanup();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(&multicastAddr, 0, sizeof(multicastAddr));
|
||
|
|
multicastAddr.sin_family = AF_INET;
|
||
|
|
multicastAddr.sin_addr.s_addr = inet_addr(this->ip_mcast.c_str());
|
||
|
|
multicastAddr.sin_port = htons(this->port_mcast);
|
||
|
|
|
||
|
|
if (sendto(sock, message.c_str(), message.length(), 0, (struct sockaddr*)&multicastAddr, sizeof(multicastAddr)) == SOCKET_ERROR) {
|
||
|
|
std::cerr << "sendto failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cout << "Sent message: " << message << std::endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
closesocket(sock);
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void iobox_api::setSocketTimeout(SOCKET sock, int timeout) {
|
||
|
|
try
|
||
|
|
{
|
||
|
|
struct timeval tv;
|
||
|
|
tv.tv_sec = timeout;
|
||
|
|
tv.tv_usec = 0;
|
||
|
|
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)) < 0) {
|
||
|
|
std::cerr << "setsockopt failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
std::string createAliasName(const std::string& serial, const std::string& hwVer, const std::string& fwVer, uint16_t index) {
|
||
|
|
return "SN" + serial + "H" + hwVer + "F" + fwVer + "I" + std::to_string(index);
|
||
|
|
}
|
||
|
|
std::string createMulticastAlias(const std::string& aliasName, const std::string& model, const std::string& serial, const std::string& ip)
|
||
|
|
{
|
||
|
|
//exp: Alias-Model-SN-IP
|
||
|
|
return aliasName + "-" + model + "-" + serial + "-" + ip;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint16_t iobox_api::getIndexIoboxFromIp(const std::string& ip) {
|
||
|
|
try {
|
||
|
|
for (const auto& profile : this->iobox_profiles) {
|
||
|
|
if (profile.iobox_info.ip_address == ip || profile.iobox_info.ip_public_address == ip) {
|
||
|
|
return &profile - &this->iobox_profiles[0] + 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
std::vector<std::string> iobox_api::scanNetworkDevicesMulticast(int timeout) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
try {
|
||
|
|
std::vector<std::string> devices;
|
||
|
|
for (const auto& item : this->iobox_profiles) {
|
||
|
|
if (item.is_connected || item.sock_tcp != INVALID_SOCKET) {
|
||
|
|
std::cout << "Please close connection to " << item.iobox_info.ip_address << "(public: " << item.iobox_info.ip_public_address << ") " << "befor new scan" << std::endl;
|
||
|
|
if (!item.iobox_info.ip_public_address.empty())
|
||
|
|
{
|
||
|
|
disconnectToIobox(item.iobox_info.ip_public_address);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
disconnectToIobox(item.iobox_info.ip_address);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//remove all elements from iobox_profiles before and we start with new scan
|
||
|
|
this->iobox_profiles.clear();
|
||
|
|
|
||
|
|
// WSADATA wsaData;
|
||
|
|
SOCKET sock = INVALID_SOCKET;
|
||
|
|
struct sockaddr_in multicastAddr;
|
||
|
|
struct ip_mreq multicastRequest;
|
||
|
|
char recvBuf[1024];
|
||
|
|
struct sockaddr_in recvAddr;
|
||
|
|
int recvAddrLen = sizeof(recvAddr);
|
||
|
|
std::string message = "{\"request\":\"Discovery\"}";
|
||
|
|
|
||
|
|
// if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||
|
|
// std::cerr << "WSAStartup failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
// return devices;
|
||
|
|
// }
|
||
|
|
|
||
|
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
|
|
if (sock == INVALID_SOCKET) {
|
||
|
|
std::cerr << "socket failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
// WSACleanup();
|
||
|
|
return devices;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(&multicastAddr, 0, sizeof(multicastAddr));
|
||
|
|
multicastAddr.sin_family = AF_INET;
|
||
|
|
multicastAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||
|
|
multicastAddr.sin_port = htons(this->port_mcast);
|
||
|
|
if (bind(sock, (struct sockaddr*)&multicastAddr, sizeof(multicastAddr)) == SOCKET_ERROR) {
|
||
|
|
std::cerr << "bind failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
closesocket(sock);
|
||
|
|
// WSACleanup();
|
||
|
|
return devices;
|
||
|
|
}
|
||
|
|
multicastRequest.imr_multiaddr.s_addr = inet_addr(this->ip_mcast.c_str());
|
||
|
|
multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
|
||
|
|
|
||
|
|
#ifndef TEST_FIX_IP
|
||
|
|
// if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&multicastRequest, sizeof(multicastRequest)) < 0) {
|
||
|
|
// std::cerr << "setsockopt failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
// closesocket(sock);
|
||
|
|
// // WSACleanup();
|
||
|
|
// return devices;
|
||
|
|
// }
|
||
|
|
#endif
|
||
|
|
setSocketTimeout(sock, 3000);
|
||
|
|
|
||
|
|
auto start = std::chrono::steady_clock::now();
|
||
|
|
sendMulticastMessage(message);
|
||
|
|
while (std::chrono::steady_clock::now() - start < std::chrono::seconds(timeout)) {
|
||
|
|
int recvLen = recvfrom(sock, recvBuf, sizeof(recvBuf) - 1, 0, (struct sockaddr*)&recvAddr, &recvAddrLen);
|
||
|
|
if (recvLen > 0) {
|
||
|
|
recvBuf[recvLen] = '\0';
|
||
|
|
std::string message_rsp(recvBuf);
|
||
|
|
std::string senderIp = inet_ntoa(recvAddr.sin_addr);
|
||
|
|
std::cout << "Received message: \"" << message_rsp << "\" from " << senderIp << std::endl;
|
||
|
|
|
||
|
|
iobox_info_t info = parseIoboxResponse(message_rsp);
|
||
|
|
|
||
|
|
if (info.ip_address == senderIp && info.ip_address != "" && !isStringExistInVectorString(devices, senderIp)) {
|
||
|
|
std::string aliasName = createAliasName(info.serial_number, info.hardware_version, info.firmware_version, devices.size() + 1);
|
||
|
|
std::string multicastAlias = createMulticastAlias(aliasName, info.model, info.serial_number, info.ip_address);
|
||
|
|
std::cout << "multicast alias: " << multicastAlias << std::endl;
|
||
|
|
devices.push_back(multicastAlias);
|
||
|
|
save_info_iobox(info);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
// std::cerr << "recvfrom failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
// sendMulticastMessage(message);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#ifndef TEST_FIX_IP
|
||
|
|
// setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&multicastRequest, sizeof(multicastRequest));
|
||
|
|
#endif
|
||
|
|
closesocket(sock);
|
||
|
|
// WSACleanup();
|
||
|
|
return devices;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return std::vector<std::string>();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool parseResponeCommon(const std::string& response, const std::string& action, std::string& getResult, std::string& getReason, iobox_info_t& iobox_info) {
|
||
|
|
try {
|
||
|
|
cJSON* root = cJSON_Parse(response.c_str());
|
||
|
|
if (root == nullptr) {
|
||
|
|
std::cerr << "Failed to parse JSON" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
cJSON* responseObj = cJSON_GetObjectItem(root, "response");
|
||
|
|
if (responseObj == nullptr) {
|
||
|
|
std::cerr << "Failed to get response object" << std::endl;
|
||
|
|
cJSON_Delete(root);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
cJSON* actionResponse = cJSON_GetObjectItem(responseObj, "action");
|
||
|
|
if (actionResponse == nullptr || strcmp(actionResponse->valuestring, action.c_str()) != 0) {
|
||
|
|
std::cerr << "Action mismatch or not found" << std::endl;
|
||
|
|
cJSON_Delete(root);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
cJSON* resultResponse = cJSON_GetObjectItem(responseObj, "result");
|
||
|
|
if (resultResponse == nullptr) {
|
||
|
|
std::cerr << "Failed to get result" << std::endl;
|
||
|
|
cJSON_Delete(root);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (resultResponse->type == cJSON_Array) {
|
||
|
|
char* result = cJSON_PrintUnformatted(resultResponse);
|
||
|
|
std::cout << "Result: " << result << std::endl;
|
||
|
|
std::string resultStr(result);
|
||
|
|
cJSON_free(result);
|
||
|
|
getResult = resultStr;
|
||
|
|
}
|
||
|
|
else if (resultResponse->type == cJSON_String) {
|
||
|
|
getResult = resultResponse->valuestring;
|
||
|
|
}
|
||
|
|
if (cJSON_HasObjectItem(responseObj, "info"))
|
||
|
|
{
|
||
|
|
cJSON* infoResponse = cJSON_GetObjectItem(responseObj, "info");
|
||
|
|
if (infoResponse == nullptr) {
|
||
|
|
std::cerr << "Failed to get info" << std::endl;
|
||
|
|
cJSON_Delete(root);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
iobox_info = parseIoboxResponseObj(infoResponse);
|
||
|
|
}
|
||
|
|
cJSON* reasonResponse = cJSON_GetObjectItem(responseObj, "reason");
|
||
|
|
if (reasonResponse == nullptr) {
|
||
|
|
// std::cerr << "Failed to get reason" << std::endl;
|
||
|
|
cJSON_Delete(root);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
getReason = reasonResponse->valuestring;
|
||
|
|
|
||
|
|
cJSON_Delete(root);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string iobox_api::connectToIobox(const std::string& remote, int port, const std::string& username, const std::string& password) {
|
||
|
|
// check ip is already in iobox_profiles
|
||
|
|
bool is_exist = false;
|
||
|
|
iobox_profile_t* item = nullptr;
|
||
|
|
std::string aliasConnect = "";
|
||
|
|
bool is_onlyAuthen = false;
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(this->_mutex);
|
||
|
|
std::string ip = checkIpFromRemote(remote);
|
||
|
|
if (ip == "") {
|
||
|
|
std::cerr << "Failed to get ip from remote: " << remote << std::endl;
|
||
|
|
return aliasConnect;
|
||
|
|
}
|
||
|
|
std::cout << "IP address: " << ip << std::endl;
|
||
|
|
try {
|
||
|
|
for (auto& profile : this->iobox_profiles) {
|
||
|
|
if (profile.iobox_info.ip_address == ip || profile.iobox_info.ip_public_address == ip) {
|
||
|
|
is_exist = true;
|
||
|
|
item = &profile;
|
||
|
|
if (item->is_connected && item->is_anthenticated) {
|
||
|
|
std::cout << "Ip is already connected and anthenticated: " << ip << std::endl;
|
||
|
|
uint16_t idx = getIndexIoboxFromIp(ip);
|
||
|
|
std::string aliasName = createAliasName(item->iobox_info.serial_number, item->iobox_info.hardware_version, item->iobox_info.firmware_version, idx);
|
||
|
|
aliasConnect = createMulticastAlias(aliasName, item->iobox_info.model, item->iobox_info.serial_number, item->iobox_info.ip_public_address == "" ? item->iobox_info.ip_address : item->iobox_info.ip_public_address);
|
||
|
|
return aliasConnect;
|
||
|
|
}
|
||
|
|
else if (item->is_connected && !item->is_anthenticated) {
|
||
|
|
std::cout << "Ip is already connected but not anthenticated: " << ip << std::endl;
|
||
|
|
// std::cout << "Please disconnect before reconnect" << std::endl;
|
||
|
|
// return aliasConnect;
|
||
|
|
is_onlyAuthen = true;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (is_exist == false) {
|
||
|
|
std::cout << "Ip is not exist in list scan, now retry connect to this ip and append it to profile: " << ip << std::endl;
|
||
|
|
// return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// WSADATA wsaData;
|
||
|
|
SOCKET sock = INVALID_SOCKET;
|
||
|
|
struct sockaddr_in serverAddr;
|
||
|
|
char recvBuf[1024];
|
||
|
|
int recvLen = 0;
|
||
|
|
struct timeval tv;
|
||
|
|
tv.tv_sec = 3000;
|
||
|
|
tv.tv_usec = 0;
|
||
|
|
// Initialize Winsock
|
||
|
|
// int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||
|
|
// if (result != 0) {
|
||
|
|
// std::cerr << "WSAStartup failed: " << result << std::endl;
|
||
|
|
// return false;
|
||
|
|
// }
|
||
|
|
if (is_onlyAuthen == false)
|
||
|
|
{
|
||
|
|
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||
|
|
if (sock == INVALID_SOCKET) {
|
||
|
|
std::cerr << "socket failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
// WSACleanup();
|
||
|
|
return aliasConnect;
|
||
|
|
}
|
||
|
|
|
||
|
|
serverAddr.sin_family = AF_INET;
|
||
|
|
serverAddr.sin_addr.s_addr = inet_addr(ip.c_str());
|
||
|
|
serverAddr.sin_port = htons(port);
|
||
|
|
|
||
|
|
if (connect(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
|
||
|
|
std::cerr << "connect failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
closesocket(sock);
|
||
|
|
// WSACleanup();
|
||
|
|
return aliasConnect;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
sock = item->sock_tcp;
|
||
|
|
}
|
||
|
|
|
||
|
|
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
|
||
|
|
|
||
|
|
std::string action = "auth";
|
||
|
|
//{"request":{"action":"auth","username":"<name>","password":"<pass>"}}
|
||
|
|
std::string authMessage = "{\"request\":{\"action\":\"" + action + "\",\"username\":\"" + username + "\",\"password\":\"" + password + "\"}}";
|
||
|
|
|
||
|
|
int sendLen = send(sock, authMessage.c_str(), authMessage.length(), 0);
|
||
|
|
if (sendLen == SOCKET_ERROR) {
|
||
|
|
std::cerr << "send failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
closesocket(sock);
|
||
|
|
// WSACleanup();
|
||
|
|
return aliasConnect;
|
||
|
|
}
|
||
|
|
//{"response":{"action":"auth","result":"<success/fail>","reason":"<if any error>"}}
|
||
|
|
iobox_info_t info;
|
||
|
|
|
||
|
|
recvLen = recv(sock, recvBuf, sizeof(recvBuf) - 1, 0);
|
||
|
|
if (recvLen > 0) {
|
||
|
|
recvBuf[recvLen] = '\0';
|
||
|
|
std::cout << "Received message: " << recvBuf << std::endl;
|
||
|
|
|
||
|
|
std::string response(recvBuf);
|
||
|
|
std::string result;
|
||
|
|
std::string reason;
|
||
|
|
if (parseResponeCommon(response, action, result, reason, info)) {
|
||
|
|
std::cout << "Parse response success" << std::endl;
|
||
|
|
if (result == "success") {
|
||
|
|
std::cout << "Authentication success" << std::endl;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Authentication failed" << std::endl;
|
||
|
|
std::cerr << "Reason: " << reason << std::endl;
|
||
|
|
closesocket(sock);
|
||
|
|
// WSACleanup();
|
||
|
|
return aliasConnect;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Parse response failed" << std::endl;
|
||
|
|
closesocket(sock);
|
||
|
|
// WSACleanup();
|
||
|
|
return aliasConnect;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "recv failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
closesocket(sock);
|
||
|
|
// WSACleanup();
|
||
|
|
return aliasConnect;
|
||
|
|
}
|
||
|
|
|
||
|
|
// closesocket(sock);
|
||
|
|
// WSACleanup();
|
||
|
|
if (item == nullptr) {
|
||
|
|
if (info.ip_address == "") {
|
||
|
|
std::cerr << "Failed to get info from response" << std::endl;
|
||
|
|
closesocket(sock);
|
||
|
|
return aliasConnect;
|
||
|
|
}
|
||
|
|
if (info.ip_address != ip) {
|
||
|
|
info.ip_public_address = ip;
|
||
|
|
}
|
||
|
|
save_info_iobox(info);
|
||
|
|
for (auto& profile : this->iobox_profiles) {
|
||
|
|
if (profile.iobox_info.ip_address == ip || profile.iobox_info.ip_public_address == ip) {
|
||
|
|
item = &profile;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (item == nullptr) return aliasConnect;
|
||
|
|
uint16_t idx = getIndexIoboxFromIp(ip);
|
||
|
|
std::string aliasName = createAliasName(item->iobox_info.serial_number, item->iobox_info.hardware_version, item->iobox_info.firmware_version, idx);
|
||
|
|
aliasConnect = createMulticastAlias(aliasName, item->iobox_info.model, item->iobox_info.serial_number, item->iobox_info.ip_public_address == "" ? item->iobox_info.ip_address : item->iobox_info.ip_public_address);
|
||
|
|
std::cout << "alias: " << aliasConnect << std::endl;
|
||
|
|
item->sock_tcp = sock;
|
||
|
|
item->is_connected = true;
|
||
|
|
item->is_anthenticated = true;
|
||
|
|
return aliasConnect;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return aliasConnect;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool iobox_api::connectToIoboxWithoutAuthen(const std::string& remote, int port) {
|
||
|
|
// check ip is already in iobox_profiles
|
||
|
|
bool is_exist = false;
|
||
|
|
iobox_profile_t* item = nullptr;
|
||
|
|
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(this->_mutex);
|
||
|
|
std::string ip = checkIpFromRemote(remote);
|
||
|
|
if (ip == "") {
|
||
|
|
std::cerr << "Failed to get ip from remote: " << remote << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
for (auto& profile : this->iobox_profiles) {
|
||
|
|
if (profile.iobox_info.ip_address == ip || profile.iobox_info.ip_public_address == ip) {
|
||
|
|
is_exist = true;
|
||
|
|
item = &profile;
|
||
|
|
if (item->is_connected) {
|
||
|
|
std::cout << "Ip is already connected: " << ip << std::endl;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (is_exist == false) {
|
||
|
|
std::cout << "Ip is not exist in list scan" << ip << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// WSADATA wsaData;
|
||
|
|
SOCKET sock = INVALID_SOCKET;
|
||
|
|
struct sockaddr_in serverAddr;
|
||
|
|
char recvBuf[1024];
|
||
|
|
int recvLen = 0;
|
||
|
|
struct timeval tv;
|
||
|
|
tv.tv_sec = 3000;
|
||
|
|
tv.tv_usec = 0;
|
||
|
|
// Initialize Winsock
|
||
|
|
// int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||
|
|
// if (result != 0) {
|
||
|
|
// std::cerr << "WSAStartup failed: " << result << std::endl;
|
||
|
|
// return false;
|
||
|
|
// }
|
||
|
|
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||
|
|
if (sock == INVALID_SOCKET) {
|
||
|
|
std::cerr << "socket failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
// WSACleanup();
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
serverAddr.sin_family = AF_INET;
|
||
|
|
serverAddr.sin_addr.s_addr = inet_addr(ip.c_str());
|
||
|
|
serverAddr.sin_port = htons(port);
|
||
|
|
|
||
|
|
if (connect(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
|
||
|
|
std::cerr << "connect failed with error: " << WSAGetLastError() << std::endl;
|
||
|
|
closesocket(sock);
|
||
|
|
// WSACleanup();
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// closesocket(sock);
|
||
|
|
// WSACleanup();
|
||
|
|
item->sock_tcp = sock;
|
||
|
|
item->is_connected = true;
|
||
|
|
item->is_anthenticated = false;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool iobox_api::disconnectToIobox(const std::string& remote) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(this->_mutex);
|
||
|
|
std::string ip = checkIpFromRemote(remote);
|
||
|
|
if (ip == "") {
|
||
|
|
std::cerr << "Failed to get ip from remote: " << remote << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
// check ip is already in iobox_profiles
|
||
|
|
bool is_exist = false;
|
||
|
|
iobox_profile_t* item = nullptr;
|
||
|
|
|
||
|
|
for (auto& profile : this->iobox_profiles) {
|
||
|
|
if (profile.iobox_info.ip_address == ip || profile.iobox_info.ip_public_address == ip) {
|
||
|
|
item = &profile;
|
||
|
|
is_exist = true;
|
||
|
|
if (item->is_connected) {
|
||
|
|
std::cout << "Ip is already connected: " << ip << std::endl;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (is_exist == false) {
|
||
|
|
std::cout << "Ip is not exist in list scan" << ip << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
item->counting_get = 0;
|
||
|
|
item->is_connected = false;
|
||
|
|
item->is_anthenticated = false;
|
||
|
|
closesocket(item->sock_tcp);
|
||
|
|
item->sock_tcp = INVALID_SOCKET;
|
||
|
|
// WSACleanup();
|
||
|
|
std::cout << "Disconnected" << std::endl;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool iobox_api::setAuthenticationIobox(const std::string& remote, const std::string& username, const std::string& password) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(this->_mutex);
|
||
|
|
std::string ip = checkIpFromRemote(remote);
|
||
|
|
if (ip == "") {
|
||
|
|
std::cerr << "Failed to get ip from remote: " << remote << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
iobox_profile_t* profile = findProfileByIp(ip);
|
||
|
|
if (profile == nullptr) {
|
||
|
|
std::cerr << "IP address not found: " << ip << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string action = "change_auth";
|
||
|
|
//{"request": {"action":"change_auth","username":"<name>","password":"<pass>"}}
|
||
|
|
std::string authMessage = "{\"request\":{\"action\":\"" + action + "\",\"username\":\"" + username + "\",\"password\":\"" + password + "\"}}";
|
||
|
|
if (!sendTcpMessage(ip, authMessage.c_str(), authMessage.length(), true)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
//{"response":{"action":"change_auth","result":"<success/fail>","reason":"<if any error>"}}
|
||
|
|
char revBuf[256];
|
||
|
|
size_t responseLength = sizeof(revBuf);
|
||
|
|
if (!receiveTcpMessage(ip, revBuf, responseLength)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
revBuf[responseLength] = '\0';
|
||
|
|
std::string response(revBuf);
|
||
|
|
std::string result;
|
||
|
|
std::string reason;
|
||
|
|
iobox_info_t info;
|
||
|
|
if (parseResponeCommon(response, action, result, reason, info)) {
|
||
|
|
std::cout << "Parse response success" << std::endl;
|
||
|
|
if (result == "success") {
|
||
|
|
std::cout << "Change auth success" << std::endl;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Change auth failed" << std::endl;
|
||
|
|
std::cerr << "Reason: " << reason << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Parse response failed" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
std::string iobox_api::generateToken(const std::string& remote)
|
||
|
|
{
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
try {
|
||
|
|
std::string ip = checkIpFromRemote(remote);
|
||
|
|
if (ip == "") {
|
||
|
|
std::cerr << "Failed to get ip from remote: " << remote << std::endl;
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
iobox_profile_t* profile = findProfileByIp(ip);
|
||
|
|
if (profile == nullptr) {
|
||
|
|
std::cerr << "IP address not found: " << ip << std::endl;
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
//may be change this later
|
||
|
|
return profile->iobox_info.serial_number + profile->iobox_info.model;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
bool iobox_api::resetAuthenticationIobox(const std::string& remote, const std::string& token)
|
||
|
|
{
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(this->_mutex);
|
||
|
|
std::string ip = checkIpFromRemote(remote);
|
||
|
|
if (ip == "") {
|
||
|
|
std::cerr << "Failed to get ip from remote: " << remote << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
bool needRemove = false;
|
||
|
|
iobox_profile_t* profile = findProfileByIp(ip);
|
||
|
|
if (profile == nullptr) {
|
||
|
|
std::cerr << "IP address not found: " << ip << std::endl;
|
||
|
|
// return false;
|
||
|
|
// need temporary save iobox_info
|
||
|
|
iobox_info_t info;
|
||
|
|
info.ip_address = ip;
|
||
|
|
save_info_iobox(info);
|
||
|
|
profile = findProfileByIp(ip);
|
||
|
|
needRemove = true;
|
||
|
|
}
|
||
|
|
if (connectToIoboxWithoutAuthen(ip, DEVICE_TCP_PORT) == false) {
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
//{"request": {"action":"factory_reset","token":"<token>"}}
|
||
|
|
std::string action = "factory_reset";
|
||
|
|
std::string resetMessage = "{\"request\":{\"action\":\"" + action + "\",\"token\":\"" + token + "\"}}";
|
||
|
|
if (!sendTcpMessage(ip, resetMessage.c_str(), resetMessage.length(), false)) {
|
||
|
|
if (profile->is_anthenticated == false)
|
||
|
|
{
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
char revBuf[256];
|
||
|
|
size_t responseLength = sizeof(revBuf);
|
||
|
|
if (!receiveTcpMessage(ip, revBuf, responseLength)) {
|
||
|
|
if (profile->is_anthenticated == false)
|
||
|
|
{
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
revBuf[responseLength] = '\0';
|
||
|
|
std::string response(revBuf);
|
||
|
|
std::string result;
|
||
|
|
std::string reason;
|
||
|
|
iobox_info_t info;
|
||
|
|
if (parseResponeCommon(response, action, result, reason, info)) {
|
||
|
|
std::cout << "Parse response success" << std::endl;
|
||
|
|
if (result == "success") {
|
||
|
|
std::cout << "Factory reset success" << std::endl;
|
||
|
|
if (profile->is_anthenticated == false)
|
||
|
|
{
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Factory reset failed" << std::endl;
|
||
|
|
std::cerr << "Reason: " << reason << std::endl;
|
||
|
|
if (profile->is_anthenticated == false)
|
||
|
|
{
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Parse response failed" << std::endl;
|
||
|
|
if (profile->is_anthenticated == false)
|
||
|
|
{
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool iobox_api::resetIobox(const std::string& remote, const std::string& token)
|
||
|
|
{
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(this->_mutex);
|
||
|
|
std::string ip = checkIpFromRemote(remote);
|
||
|
|
if (ip == "") {
|
||
|
|
std::cerr << "Failed to get ip from remote: " << remote << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
bool needRemove = false;
|
||
|
|
iobox_profile_t* profile = findProfileByIp(ip);
|
||
|
|
if (profile == nullptr) {
|
||
|
|
std::cerr << "IP address not found: " << ip << std::endl;
|
||
|
|
// return false;
|
||
|
|
// need temporary save iobox_info
|
||
|
|
iobox_info_t info;
|
||
|
|
info.ip_address = ip;
|
||
|
|
save_info_iobox(info);
|
||
|
|
profile = findProfileByIp(ip);
|
||
|
|
needRemove = true;
|
||
|
|
}
|
||
|
|
if (connectToIoboxWithoutAuthen(ip, DEVICE_TCP_PORT) == false) {
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
//{"request": {"action":"restart","token":"<token>"}}
|
||
|
|
std::string action = "restart";
|
||
|
|
std::string resetMessage = "{\"request\":{\"action\":\"" + action + "\",\"token\":\"" + token + "\"}}";
|
||
|
|
if (!sendTcpMessage(ip, resetMessage.c_str(), resetMessage.length(), false)) {
|
||
|
|
if (profile->is_anthenticated == false)
|
||
|
|
{
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
char revBuf[256];
|
||
|
|
size_t responseLength = sizeof(revBuf);
|
||
|
|
if (!receiveTcpMessage(ip, revBuf, responseLength)) {
|
||
|
|
if (profile->is_anthenticated == false)
|
||
|
|
{
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
revBuf[responseLength] = '\0';
|
||
|
|
std::string response(revBuf);
|
||
|
|
std::string result;
|
||
|
|
std::string reason;
|
||
|
|
iobox_info_t info;
|
||
|
|
if (parseResponeCommon(response, action, result, reason, info)) {
|
||
|
|
std::cout << "Parse response success" << std::endl;
|
||
|
|
if (result == "success") {
|
||
|
|
std::cout << "Restart success" << std::endl;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Restart failed" << std::endl;
|
||
|
|
std::cerr << "Reason: " << reason << std::endl;
|
||
|
|
if (profile->is_anthenticated == false)
|
||
|
|
{
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Parse response failed" << std::endl;
|
||
|
|
if (profile->is_anthenticated == false)
|
||
|
|
{
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
iobox_profile_t* iobox_api::findProfileByIp(const std::string& ip) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
try {
|
||
|
|
iobox_profile_t* profile = nullptr;
|
||
|
|
for (auto& item : this->iobox_profiles) {
|
||
|
|
if (item.iobox_info.ip_address == ip || item.iobox_info.ip_public_address == ip) {
|
||
|
|
profile = &item;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return profile;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string iobox_api::getValueDataStringIoboxFromChannelName(const std::string& remote, const std::string& channelName) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(this->_mutex);
|
||
|
|
std::string ip = checkIpFromRemote(remote);
|
||
|
|
if (ip == "") {
|
||
|
|
std::cerr << "Failed to get ip from remote: " << remote << std::endl;
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
iobox_profile_t* profile = findProfileByIp(ip);
|
||
|
|
if (profile == nullptr) {
|
||
|
|
std::cerr << "IP address not found: " << ip << std::endl;
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
//{"request": {"action":"getValue","channel":"<channel>"}}
|
||
|
|
std::string action = "getValue";
|
||
|
|
std::string getValueMessage = "{\"request\":{\"action\":\"" + action + "\",\"channel\":\"" + channelName + "\"}}";
|
||
|
|
if (!sendTcpMessage(ip, getValueMessage.c_str(), getValueMessage.length(), true)) {
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
char revBuf[256];
|
||
|
|
size_t responseLength = sizeof(revBuf);
|
||
|
|
if (!receiveTcpMessage(ip, revBuf, responseLength)) {
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
revBuf[responseLength] = '\0';
|
||
|
|
std::string response(revBuf);
|
||
|
|
std::string result;
|
||
|
|
std::string reason;
|
||
|
|
iobox_info_t info;
|
||
|
|
if (parseResponeCommon(response, action, result, reason, info)) {
|
||
|
|
std::cout << "Parse response success" << std::endl;
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Parse response failed" << std::endl;
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
bool iobox_api::setValueDataStringIoboxFromChannelName(const std::string& remote, const std::string& channelName, const std::string& value) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(this->_mutex);
|
||
|
|
std::string ip = checkIpFromRemote(remote);
|
||
|
|
if (ip == "") {
|
||
|
|
std::cerr << "Failed to get ip from remote: " << remote << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
iobox_profile_t* profile = findProfileByIp(ip);
|
||
|
|
if (profile == nullptr) {
|
||
|
|
std::cerr << "IP address not found: " << ip << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
//not check valid channel name here
|
||
|
|
|
||
|
|
//{"request": {"action":"setValue", "channel":"<channel>","value":"<value>"}}
|
||
|
|
std::string action = "setValue";
|
||
|
|
std::string setValueMessage = "{\"request\":{\"action\":\"" + action + "\",\"channel\":\"" + channelName + "\",\"value\":\"" + value + "\"}}";
|
||
|
|
if (!sendTcpMessage(ip, setValueMessage.c_str(), setValueMessage.length(), true)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
char revBuf[256];
|
||
|
|
size_t responseLength = sizeof(revBuf);
|
||
|
|
if (!receiveTcpMessage(ip, revBuf, responseLength)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
revBuf[responseLength] = '\0';
|
||
|
|
std::string response(revBuf);
|
||
|
|
std::string result;
|
||
|
|
std::string reason;
|
||
|
|
iobox_info_t info;
|
||
|
|
if (parseResponeCommon(response, action, result, reason, info)) {
|
||
|
|
std::cout << "Parse response success" << std::endl;
|
||
|
|
if (result == "success") {
|
||
|
|
std::cout << "Set value success" << std::endl;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Set value failed" << std::endl;
|
||
|
|
std::cerr << "Reason: " << reason << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Parse response failed" << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
std::vector<std::string> iobox_api::getDeviceChannelNames(const std::string& remote)
|
||
|
|
{
|
||
|
|
bool needRemove = false;
|
||
|
|
std::vector<std::string> channelNames;
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(this->_mutex);
|
||
|
|
std::string ip = checkIpFromRemote(remote);
|
||
|
|
if (ip == "") {
|
||
|
|
std::cerr << "Failed to get ip from remote: " << remote << std::endl;
|
||
|
|
return channelNames;
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
iobox_profile_t* profile = findProfileByIp(ip);
|
||
|
|
if (profile == nullptr) {
|
||
|
|
std::cerr << "IP address not found: " << ip << std::endl;
|
||
|
|
// return channelNames;
|
||
|
|
// need temporary save iobox_info
|
||
|
|
iobox_info_t info;
|
||
|
|
info.ip_address = ip;
|
||
|
|
save_info_iobox(info);
|
||
|
|
profile = findProfileByIp(ip);
|
||
|
|
needRemove = true;
|
||
|
|
}
|
||
|
|
if (connectToIoboxWithoutAuthen(ip, DEVICE_TCP_PORT) == false) {
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
return channelNames;
|
||
|
|
}
|
||
|
|
//{"request": {"action":"channelList"}}
|
||
|
|
std::string action = "channelList";
|
||
|
|
std::string channelListMessage = "{\"request\":{\"action\":\"" + action + "\"}}";
|
||
|
|
if (!sendTcpMessage(ip, channelListMessage.c_str(), channelListMessage.length(), false)) {
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
return channelNames;
|
||
|
|
}
|
||
|
|
char revBuf[1024];
|
||
|
|
size_t responseLength = sizeof(revBuf);
|
||
|
|
if (!receiveTcpMessage(ip, revBuf, responseLength)) {
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
return channelNames;
|
||
|
|
}
|
||
|
|
revBuf[responseLength] = '\0';
|
||
|
|
std::string response(revBuf);
|
||
|
|
std::string result;
|
||
|
|
std::string reason;
|
||
|
|
iobox_info_t info;
|
||
|
|
if (parseResponeCommon(response, action, result, reason, info)) {
|
||
|
|
std::cout << "Parse response success" << std::endl;
|
||
|
|
|
||
|
|
cJSON* root = cJSON_Parse(result.c_str());
|
||
|
|
if (root == nullptr) {
|
||
|
|
std::cerr << "Failed to parse JSON" << std::endl;
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
return channelNames;
|
||
|
|
}
|
||
|
|
if (root->type != cJSON_Array) {
|
||
|
|
std::cerr << "Failed to get array" << std::endl;
|
||
|
|
cJSON_Delete(root);
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
return channelNames;
|
||
|
|
}
|
||
|
|
cJSON* channelList = root;
|
||
|
|
if (info.ip_address != ip)
|
||
|
|
{
|
||
|
|
info.ip_public_address = ip;
|
||
|
|
}
|
||
|
|
profile->iobox_info = info;
|
||
|
|
int arraySize = cJSON_GetArraySize(channelList);
|
||
|
|
for (int i = 0; i < arraySize; ++i) {
|
||
|
|
cJSON* channel = cJSON_GetArrayItem(channelList, i);
|
||
|
|
if (channel != nullptr && channel->type == cJSON_String) {
|
||
|
|
uint16_t idx = getIndexIoboxFromIp(ip);
|
||
|
|
std::string aliasName = createAliasName(info.serial_number, info.hardware_version, info.firmware_version, idx);
|
||
|
|
std::string multicastAlias = createMulticastAlias(aliasName, info.model, info.serial_number, info.ip_public_address == "" ? info.ip_address : info.ip_public_address);
|
||
|
|
std::string channelName = multicastAlias + "-" + channel->valuestring;
|
||
|
|
|
||
|
|
channelNames.push_back(channelName);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
cJSON_Delete(root);
|
||
|
|
|
||
|
|
// disconnectToIobox(ip);
|
||
|
|
//not need remove
|
||
|
|
return channelNames;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Parse response failed" << std::endl;
|
||
|
|
disconnectToIobox(ip);
|
||
|
|
if (needRemove) remove_last_info_iobox();
|
||
|
|
return channelNames;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << e.what() << std::endl;
|
||
|
|
return channelNames;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
bool iobox_api::openRS232(const std::string& ip, const std::string& port, int baudrate, int databits, int stopbits, int parity) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
bool iobox_api::closeRS232(const std::string& ip) { return false; }
|
||
|
|
bool iobox_api::writeRS232(const std::string& ip, std::string dataToSend, int timeout) { return false; }
|
||
|
|
bool iobox_api::readRS232(const std::string& ip, std::string& receivedData, const std::string& terminateString, int timeout) { return false; }
|
||
|
|
bool iobox_api::readRS232Bytes(const std::string& ip, std::string& receivedData, int numBytes, int timeout) { return false; }
|
||
|
|
|
||
|
|
|
||
|
|
}
|