refactor: simplifying project until runs on embedded system
This commit is contained in:
+267
-183
@@ -4,198 +4,282 @@
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPITSOcket is the base class for WindowsSocket and UnixSocket.
|
||||
* File: SPITSocket.cpp
|
||||
/*
|
||||
* Unix implementation of a SPITSocket.
|
||||
*
|
||||
* File: UnixSocket.cpp
|
||||
* Author: Hagi
|
||||
*
|
||||
* Created on 12. April 2019, 15:40
|
||||
*
|
||||
* Created on 12. April 2019, 15:58
|
||||
*/
|
||||
|
||||
#include "SPITSocket.h"
|
||||
#include "Task.hpp"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp/uuid.h"
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
//----- initialize static members -----
|
||||
fos::Mutex SPITSocket::s_MutexIPAddresses;
|
||||
unordered_map<string, SPITSocket::IPAddress*> SPITSocket::s_IPAddresses;
|
||||
int SPITSocket::FAMILY_IP4 = 2;
|
||||
int SPITSocket::FAMILY_IP6 = 23;
|
||||
/**
|
||||
* Creates socket. If there exist some, they will be closed.
|
||||
* @return
|
||||
*/
|
||||
bool SPITSocket::createSocket_UDP() {
|
||||
bool boolSuccess = true;
|
||||
int intResult = -1;
|
||||
int intOptionValue4 = 1;
|
||||
|
||||
// ip4
|
||||
if (m_UDPSocketIP4 != INVALID_SOCKET) {
|
||||
close(m_UDPSocketIP4);
|
||||
m_UDPSocketIP4 = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
m_UDPSocketIP4 = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (m_UDPSocketIP4 == INVALID_SOCKET) {
|
||||
boolSuccess = false;
|
||||
} else {
|
||||
intResult = setsockopt(m_UDPSocketIP4, SOL_SOCKET, SO_REUSEADDR, (void *)&intOptionValue4, sizeof(intOptionValue4));
|
||||
}
|
||||
|
||||
// // set the m_UDPSocketIP4 in NON BLOCKING mode because
|
||||
// // if the UDPSockets are in blocking mode the receiveMessage does not return in every constellation
|
||||
// int intFlags;
|
||||
// intFlags = fcntl(m_UDPSocketIP4, F_GETFL);
|
||||
// fcntl(m_UDPSocketIP4, F_SETFL, intFlags | O_NONBLOCK);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 1; // seconds
|
||||
tv.tv_usec = 0; // microseconds (0.0 sec)
|
||||
|
||||
// This sets the receive timeout
|
||||
setsockopt(m_UDPSocketIP4, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
||||
|
||||
|
||||
SPITSocket::SPITSocket() {
|
||||
m_ServerIP = "";
|
||||
m_ServerPort = "";
|
||||
m_ClientIP = "";
|
||||
m_ClientPort = "";
|
||||
m_BoundClientPort = "";
|
||||
m_BoundClientFamily = 0;
|
||||
m_IsBound = false;
|
||||
if (intResult < 0) {
|
||||
boolSuccess = false;
|
||||
}
|
||||
return boolSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the socket to the client's ip address and port. The socket option SO_REUSEADDR is set to true.
|
||||
* @param p_ClientIP ip address of the client
|
||||
* @param p_ClientPort port of the client.
|
||||
* if p_Port == "0" any free port will be used
|
||||
* @return -1 id bind fails, o if bind is ok
|
||||
*
|
||||
*/
|
||||
int SPITSocket::bindSocket(string p_ClientIP, string p_ClientPort) {
|
||||
addrinfo *clientAI;
|
||||
struct sockaddr_in *ptrIP4SocketAddress;
|
||||
struct sockaddr_in o_IP4SocketAddress;
|
||||
int intSocklen;
|
||||
string stringClientPort;
|
||||
if (p_ClientPort.length() <= 0)
|
||||
stringClientPort = "0";
|
||||
else
|
||||
stringClientPort = p_ClientPort;
|
||||
// int intResult = SOCKET_ERROR;
|
||||
int intResult = 0;
|
||||
if (getaddrinfo(p_ClientIP.data(), p_ClientPort.data(), NULL, &clientAI) != 0) {
|
||||
return -1;
|
||||
}
|
||||
switch (clientAI->ai_family) {
|
||||
case AF_INET:
|
||||
if (m_UDPSocketIP4 == INVALID_SOCKET) {
|
||||
break;
|
||||
}
|
||||
ptrIP4SocketAddress = reinterpret_cast<sockaddr_in *>(clientAI->ai_addr);
|
||||
intSocklen = sizeof(*ptrIP4SocketAddress);
|
||||
// copy the ptrIP4SocketAddress, may be not filled correct by getaddrinfo
|
||||
memset(&o_IP4SocketAddress, 0, intSocklen);
|
||||
o_IP4SocketAddress.sin_addr = ptrIP4SocketAddress->sin_addr;
|
||||
o_IP4SocketAddress.sin_family = ptrIP4SocketAddress->sin_family;
|
||||
// o_IP4SocketAddress.sin_zero = ptrIP4SocketAddress->sin_zero;
|
||||
o_IP4SocketAddress.sin_port = ptrIP4SocketAddress->sin_port;
|
||||
intResult = bind(m_UDPSocketIP4, (const sockaddr *)(ptrIP4SocketAddress), (socklen_t)intSocklen);
|
||||
if (intResult < 0) {
|
||||
break;
|
||||
}
|
||||
setBoundClientFamily(AF_INET);
|
||||
if (intResult == 0) {
|
||||
if (getsockname(m_UDPSocketIP4, (sockaddr *)ptrIP4SocketAddress, (socklen_t *)&intSocklen) != -1) {
|
||||
setBoundClientPort(to_string((int)ptrIP4SocketAddress->sin_port));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
setBoundClientFamily(0);
|
||||
intResult = -1;
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(clientAI);
|
||||
|
||||
if (intResult == -1) {
|
||||
setIsBound(false);
|
||||
} else {
|
||||
setIsBound(true);
|
||||
}
|
||||
return intResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the sockat are brodcast sockets or not. Set the sockopt SO_BROADCAST to 0 or 1
|
||||
* @param p_Broadcast true SO_BROADCAST is set
|
||||
* false = SO_BROADCAST is not set
|
||||
* @return 0 = ok, -1 = error
|
||||
*/
|
||||
int SPITSocket::setBroadcast(bool p_Broadcast) {
|
||||
int intResult;
|
||||
int intOptionValue = 1;
|
||||
u_char charOptionValue = 0x01;
|
||||
// IP4
|
||||
if (p_Broadcast) {
|
||||
intOptionValue = 1;
|
||||
} else {
|
||||
intOptionValue = 0;
|
||||
}
|
||||
intResult = setsockopt(m_UDPSocketIP4, SOL_SOCKET, SO_BROADCAST, &intOptionValue, sizeof(int));
|
||||
// intResult = setsockopt(m_UDPSocketIP4, IPPROTO_IP, IP_MULTICAST_LOOP, (void*)&charOptionValue, sizeof(charOptionValue));
|
||||
|
||||
return intResult;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param p_InetFamily AF_INET or AF_INET6
|
||||
* @param p_ServerIP the ip address of the server
|
||||
* @param p_ServerPort the port of the server
|
||||
* @param p_MessageBytes buffer containing the message
|
||||
* @param p_MessageLength the length of the message
|
||||
* @return -1 send fails
|
||||
* 0 send is done
|
||||
*/
|
||||
int SPITSocket::sendMessageTo(int p_InetFamily, string p_ServerIP, string p_ServerPort, const char *p_MessageBytes, int p_MessageLength) {
|
||||
if (m_UDPSocketIP4 == INVALID_SOCKET)
|
||||
return -1;
|
||||
struct addrinfo *ptrAddressInfo;
|
||||
struct sockaddr_in *ptrIP4SocketAddress;
|
||||
struct sockaddr_in o_IP4SocketAddress;
|
||||
int intSocklen;
|
||||
int intResult = -1;
|
||||
|
||||
// prepare AddressInfo
|
||||
if (getaddrinfo(p_ServerIP.data(), p_ServerPort.data(), NULL, &ptrAddressInfo) != 0) {
|
||||
return -1;
|
||||
}
|
||||
switch (ptrAddressInfo->ai_family) {
|
||||
case AF_INET:
|
||||
ptrIP4SocketAddress = reinterpret_cast<sockaddr_in *>(ptrAddressInfo->ai_addr);
|
||||
intSocklen = sizeof(*ptrIP4SocketAddress);
|
||||
if (m_UDPSocketIP4 != INVALID_SOCKET) {
|
||||
// copy the ptrIP4SocketAddress, may be not filled correct by getaddrinfo
|
||||
memset(&o_IP4SocketAddress, 0, intSocklen);
|
||||
o_IP4SocketAddress.sin_addr = ptrIP4SocketAddress->sin_addr;
|
||||
o_IP4SocketAddress.sin_family = ptrIP4SocketAddress->sin_family;
|
||||
o_IP4SocketAddress.sin_port = ptrIP4SocketAddress->sin_port;
|
||||
intResult = sendto(m_UDPSocketIP4, p_MessageBytes, p_MessageLength, 0, (const sockaddr *)&o_IP4SocketAddress, (socklen_t)intSocklen);
|
||||
if (intResult < 0) {
|
||||
printf("UnixSocket::sendMessageTo IP4 sendto %s FAILED %s\n", p_ServerIP.data(), strerror(errno));
|
||||
printf("UnixSocket::sendMessageTo ret=%d %s / %s / %d\n", intResult,
|
||||
p_ServerPort.data(), p_MessageBytes, p_MessageLength);
|
||||
}
|
||||
freeaddrinfo(ptrAddressInfo);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
intResult = -1;
|
||||
}
|
||||
|
||||
if (intResult == -1) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Call this for receiving a message
|
||||
* This will block until a message is received or the underlying socket is closed
|
||||
* @param p_InetFamily either AF_INET or AF_INET6<br>
|
||||
* The SPITSocket creates two udp sockets, one for IP4 and one for IP6
|
||||
* This parameter decides from which socket should a message recieved
|
||||
* @param p_Buffer the buffer containing the received message later.
|
||||
* @param p_BufferLength the size of the buffer
|
||||
* @param p_ServerIP a pointer to a string, when a messages is received the string will contain the ip address of the sender/server
|
||||
* if p_ServerIP is NULL - no detection of the server will be done.
|
||||
* @return
|
||||
*/
|
||||
int SPITSocket::receiveMessage(int p_InetFamily, char *p_Buffer, int p_BufferLength, string *p_ServerIP) {
|
||||
int intResult = -1;
|
||||
// ADDRINFO *AI;
|
||||
struct sockaddr_in o_IP4SocketAddress;
|
||||
int intSocklen;
|
||||
|
||||
switch (p_InetFamily) {
|
||||
case AF_INET:
|
||||
if (m_UDPSocketIP4 == INVALID_SOCKET) {
|
||||
break;
|
||||
}
|
||||
intSocklen = sizeof(o_IP4SocketAddress);
|
||||
memset(&o_IP4SocketAddress, 0, intSocklen);
|
||||
intResult = recvfrom(m_UDPSocketIP4, (void *)p_Buffer, p_BufferLength, 0 , (sockaddr *)&o_IP4SocketAddress, (socklen_t *)&intSocklen);
|
||||
if (intResult >= 0) {
|
||||
if (p_ServerIP != NULL) {
|
||||
char bufferIP4[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &(o_IP4SocketAddress.sin_addr), bufferIP4, intSocklen);
|
||||
*p_ServerIP = bufferIP4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return intResult;
|
||||
}
|
||||
|
||||
|
||||
SPITSocket::~SPITSocket() {
|
||||
{
|
||||
fos::MutexGuard o_LockSocket(m_MutexSocket);
|
||||
m_IsBound = false;
|
||||
SPITSocket::IPAddress SPITSocket::getAdaptersInfo() {
|
||||
// iterate over active interfaces, and print out IPs
|
||||
esp_netif_t *netif = NULL;
|
||||
while ((netif = esp_netif_next_unsafe(netif)) != NULL) {
|
||||
ESP_LOGI("SPIT", "Connected to %s", esp_netif_get_desc(netif));
|
||||
esp_netif_ip_info_t ip;
|
||||
ESP_ERROR_CHECK(esp_netif_get_ip_info(netif, &ip));
|
||||
ESP_LOGI("SPIT", "- IPv4 address: " IPSTR ",", IP2STR(&ip.ip));
|
||||
ESP_LOGI("SPIT", "- IPv4 netmask: " IPSTR ",", IP2STR(&ip.netmask));
|
||||
char buffer[64];
|
||||
|
||||
sprintf(buffer, IPSTR, IP2STR(&ip.ip));
|
||||
string stringIP4 = buffer;
|
||||
sprintf(buffer, IPSTR, IP2STR(&ip.netmask));
|
||||
string stringSubnet = buffer;
|
||||
return {stringIP4, stringSubnet};
|
||||
}
|
||||
return {"0.0.0.0", "0.0.0.0"};
|
||||
}
|
||||
|
||||
string createGUID() {
|
||||
// uuid_t id;
|
||||
// uuid_generate(id);
|
||||
// char *guid_string = new char[100];
|
||||
// uuid_unparse(id, guid_string);
|
||||
// string stringGUID = guid_string;
|
||||
// return stringGUID;
|
||||
|
||||
uuid_t uu;
|
||||
char uu_str[UUID_STR_LEN];
|
||||
|
||||
uuid_generate(uu);
|
||||
uuid_unparse(uu, uu_str);
|
||||
string stringGUID = uu_str;
|
||||
return stringGUID;
|
||||
}
|
||||
/** The name of the client's host computer*/
|
||||
string getClientHostName() {
|
||||
string stringHostName = "";
|
||||
const char * hostname;
|
||||
esp_netif_get_hostname(esp_netif_get_default_netif(), &hostname);
|
||||
if (hostname != nullptr) {
|
||||
stringHostName = hostname;
|
||||
}
|
||||
}
|
||||
void SPITSocket::setConnectionParams(string p_ServerIP, string p_ServerPort, string p_ClientIP, string p_ClientPort) {
|
||||
m_ServerIP = p_ServerIP;
|
||||
m_ServerPort = p_ServerPort;
|
||||
m_ClientIP = p_ClientIP;
|
||||
m_ClientPort = p_ClientPort;
|
||||
}
|
||||
string SPITSocket::getServerIP() {
|
||||
return m_ServerIP;
|
||||
}
|
||||
string SPITSocket::getServerPort(){
|
||||
return m_ServerPort;
|
||||
}
|
||||
string SPITSocket::getClientIP() {
|
||||
return m_ClientIP;
|
||||
}
|
||||
string SPITSocket::getClientPort() {
|
||||
return m_ClientPort;
|
||||
}
|
||||
string SPITSocket::getBoundClientPort() {
|
||||
return m_BoundClientPort;
|
||||
}
|
||||
void SPITSocket::setBoundClientPort(string p_Port) {
|
||||
m_BoundClientPort = p_Port;
|
||||
}
|
||||
int SPITSocket::getBoundClientFamily() {
|
||||
return m_BoundClientFamily;
|
||||
}
|
||||
void SPITSocket::setBoundClientFamily(int p_Family) {
|
||||
m_BoundClientFamily = p_Family;
|
||||
}
|
||||
|
||||
void SPITSocket::setIsBound(bool p_IsBound) {
|
||||
{
|
||||
fos::MutexGuard o_LockSocket(m_MutexSocket);
|
||||
m_IsBound = p_IsBound;
|
||||
}
|
||||
}
|
||||
bool SPITSocket::getIsBound() {
|
||||
return m_IsBound;
|
||||
}
|
||||
|
||||
int SPITSocket::sendMessage(const char* p_MessageBytes, int p_MessageLength) {
|
||||
if (m_ServerPort.length() <= 0) return -1;
|
||||
int intResult;
|
||||
{
|
||||
fos::MutexGuard o_LockSocket(m_MutexSocket);
|
||||
if (m_IsBound == false) return -1;
|
||||
intResult = sendMessageTo(m_BoundClientFamily, m_ServerIP, m_ServerPort, p_MessageBytes, p_MessageLength);
|
||||
}
|
||||
return intResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------- IP Adresses ---------
|
||||
void SPITSocket::addIPAddress(string p_IPAddress, string p_SubnetMask) {
|
||||
IPAddress* o_IPAddress;
|
||||
{
|
||||
fos::MutexGuard o_LockIP(s_MutexIPAddresses);
|
||||
auto i = s_IPAddresses.find(p_IPAddress);
|
||||
if (i != s_IPAddresses.end()) {
|
||||
o_IPAddress = i->second;
|
||||
}
|
||||
else {
|
||||
o_IPAddress = new IPAddress();
|
||||
}
|
||||
o_IPAddress->setIPAddress(p_IPAddress);
|
||||
o_IPAddress->setSubnetMask(p_SubnetMask);
|
||||
o_IPAddress->setFound(true);
|
||||
s_IPAddresses[o_IPAddress->getIPAddress()] = o_IPAddress;
|
||||
}
|
||||
}
|
||||
void SPITSocket::removeIPAddress(string p_IPAddress) {
|
||||
IPAddress* o_IPAddress;
|
||||
{
|
||||
fos::MutexGuard o_LockIP(s_MutexIPAddresses);
|
||||
auto i = s_IPAddresses.find(p_IPAddress);
|
||||
if (i != s_IPAddresses.end()) {
|
||||
o_IPAddress = i->second;
|
||||
i = s_IPAddresses.erase(i);
|
||||
delete o_IPAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
int SPITSocket::getIPAddressCount() {
|
||||
return s_IPAddresses.size();
|
||||
}
|
||||
SPITSocket::IPAddress* SPITSocket::getIPAddress(int p_Index) {
|
||||
IPAddress* ptr_IPAddress = NULL;
|
||||
{
|
||||
fos::MutexGuard o_LockIP(s_MutexIPAddresses);
|
||||
if (p_Index <= s_IPAddresses.size()) {
|
||||
unordered_map<string, IPAddress*>::iterator i = next(s_IPAddresses.begin(), p_Index);
|
||||
ptr_IPAddress = i->second;
|
||||
}
|
||||
return ptr_IPAddress;
|
||||
}
|
||||
}
|
||||
void SPITSocket::clearIPAddresses() {
|
||||
IPAddress* o_IPAddress;
|
||||
{
|
||||
fos::MutexGuard o_LockIP(s_MutexIPAddresses);
|
||||
for (auto i = s_IPAddresses.begin(); i != s_IPAddresses.end(); i++) {
|
||||
o_IPAddress = i->second;
|
||||
i = s_IPAddresses.erase(i);
|
||||
delete o_IPAddress;
|
||||
if (i == s_IPAddresses.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SPITSocket::resetFoundIPAddresses() {
|
||||
IPAddress* o_IPAddress;
|
||||
{
|
||||
fos::MutexGuard o_LockIP(s_MutexIPAddresses);
|
||||
for (auto i = s_IPAddresses.begin(); i != s_IPAddresses.end(); i++) {
|
||||
o_IPAddress = i->second;
|
||||
o_IPAddress->setFound(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
void SPITSocket::removeNotFoundIPAddresses() {
|
||||
IPAddress* o_IPAddress;
|
||||
{
|
||||
fos::MutexGuard o_LockIP(s_MutexIPAddresses);
|
||||
for (auto i = s_IPAddresses.begin(); i != s_IPAddresses.end(); i++) {
|
||||
o_IPAddress = i->second;
|
||||
if (o_IPAddress->getFound() == false) {
|
||||
i = s_IPAddresses.erase(i);
|
||||
delete o_IPAddress;
|
||||
if (i == s_IPAddresses.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------ IPAddress -------------------
|
||||
SPITSocket::IPAddress::IPAddress() {
|
||||
m_IPAddress = "";
|
||||
m_SubnetMask = "";
|
||||
m_Found = false;
|
||||
}
|
||||
SPITSocket::IPAddress::~IPAddress() {
|
||||
m_Found = false;
|
||||
}
|
||||
void SPITSocket::IPAddress::setIPAddress(const string& p_IPAddress) {
|
||||
m_IPAddress = p_IPAddress;
|
||||
}
|
||||
void SPITSocket::IPAddress::setSubnetMask(const string& p_SubnetMask) {
|
||||
m_SubnetMask = p_SubnetMask;
|
||||
}
|
||||
void SPITSocket::IPAddress::setFound(bool p_Found) {
|
||||
m_Found = p_Found;
|
||||
return stringHostName;;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user