Linux: Binds to MY_IP_ADDRESS in client mode (#849)
This commit is contained in:
@@ -138,6 +138,9 @@ bool gatewayTransportInit(void)
|
|||||||
#endif /* MY_GATEWAY_ESP8266 */
|
#endif /* MY_GATEWAY_ESP8266 */
|
||||||
|
|
||||||
#if defined(MY_GATEWAY_CLIENT_MODE)
|
#if defined(MY_GATEWAY_CLIENT_MODE)
|
||||||
|
#if defined(MY_GATEWAY_LINUX) && defined(MY_IP_ADDRESS)
|
||||||
|
client.bind(_ethernetGatewayIP);
|
||||||
|
#endif
|
||||||
#if defined(MY_CONTROLLER_URL_ADDRESS)
|
#if defined(MY_CONTROLLER_URL_ADDRESS)
|
||||||
if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) {
|
if (client.connect(MY_CONTROLLER_URL_ADDRESS, MY_PORT)) {
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ bool gatewayTransportConnect(void)
|
|||||||
MY_SERIALDEVICE.println(WiFi.localIP());
|
MY_SERIALDEVICE.println(WiFi.localIP());
|
||||||
#elif defined(MY_GATEWAY_LINUX)
|
#elif defined(MY_GATEWAY_LINUX)
|
||||||
#if defined(MY_IP_ADDRESS)
|
#if defined(MY_IP_ADDRESS)
|
||||||
//TODO
|
_MQTT_ethClient.bind(_MQTT_clientIp);
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#ifdef MY_IP_ADDRESS
|
#ifdef MY_IP_ADDRESS
|
||||||
|
|||||||
@@ -43,11 +43,13 @@ EthernetClient::EthernetClient(int sock) : _sock(sock)
|
|||||||
|
|
||||||
int EthernetClient::connect(const char* host, uint16_t port)
|
int EthernetClient::connect(const char* host, uint16_t port)
|
||||||
{
|
{
|
||||||
int sockfd;
|
struct addrinfo hints, *servinfo, *localinfo, *p;
|
||||||
struct addrinfo hints, *servinfo, *p;
|
|
||||||
int rv;
|
int rv;
|
||||||
char s[INET6_ADDRSTRLEN];
|
char s[INET6_ADDRSTRLEN];
|
||||||
char port_str[6];
|
char port_str[6];
|
||||||
|
bool use_bind = (_srcip != 0);
|
||||||
|
|
||||||
|
close();
|
||||||
|
|
||||||
memset(&hints, 0, sizeof hints);
|
memset(&hints, 0, sizeof hints);
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
@@ -58,17 +60,31 @@ int EthernetClient::connect(const char* host, uint16_t port)
|
|||||||
logError("getaddrinfo: %s\n", gai_strerror(rv));
|
logError("getaddrinfo: %s\n", gai_strerror(rv));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (use_bind) {
|
||||||
|
if ((rv = getaddrinfo(_srcip.toString().c_str(), port_str, &hints, &localinfo)) != 0) {
|
||||||
|
logError("getaddrinfo: %s\n", gai_strerror(rv));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// loop through all the results and connect to the first we can
|
// loop through all the results and connect to the first we can
|
||||||
for (p = servinfo; p != NULL; p = p->ai_next) {
|
for (p = servinfo; p != NULL; p = p->ai_next) {
|
||||||
if ((sockfd = socket(p->ai_family, p->ai_socktype,
|
if ((_sock = socket(p->ai_family, p->ai_socktype,
|
||||||
p->ai_protocol)) == -1) {
|
p->ai_protocol)) == -1) {
|
||||||
logError("socket: %s\n", strerror(errno));
|
logError("socket: %s\n", strerror(errno));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (::connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
|
if (use_bind) {
|
||||||
::close(sockfd);
|
if (::bind(_sock, localinfo->ai_addr, localinfo->ai_addrlen) == -1) {
|
||||||
|
close();
|
||||||
|
logError("bind: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (::connect(_sock, p->ai_addr, p->ai_addrlen) == -1) {
|
||||||
|
close();
|
||||||
logError("connect: %s\n", strerror(errno));
|
logError("connect: %s\n", strerror(errno));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -81,13 +97,14 @@ int EthernetClient::connect(const char* host, uint16_t port)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_sock = sockfd;
|
|
||||||
|
|
||||||
void *addr = &(((struct sockaddr_in*)p->ai_addr)->sin_addr);
|
void *addr = &(((struct sockaddr_in*)p->ai_addr)->sin_addr);
|
||||||
inet_ntop(p->ai_family, addr, s, sizeof s);
|
inet_ntop(p->ai_family, addr, s, sizeof s);
|
||||||
logDebug("connected to %s\n", s);
|
logDebug("connected to %s\n", s);
|
||||||
|
|
||||||
freeaddrinfo(servinfo); // all done with this structure
|
freeaddrinfo(servinfo); // all done with this structure
|
||||||
|
if (use_bind) {
|
||||||
|
freeaddrinfo(localinfo); // all done with this structure
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -273,6 +290,11 @@ void EthernetClient::close()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EthernetClient::bind(IPAddress ip)
|
||||||
|
{
|
||||||
|
_srcip = ip;
|
||||||
|
}
|
||||||
|
|
||||||
int EthernetClient::getSocketNumber()
|
int EthernetClient::getSocketNumber()
|
||||||
{
|
{
|
||||||
return _sock;
|
return _sock;
|
||||||
|
|||||||
@@ -155,6 +155,10 @@ public:
|
|||||||
* @brief Close the connection.
|
* @brief Close the connection.
|
||||||
*/
|
*/
|
||||||
void close();
|
void close();
|
||||||
|
/**
|
||||||
|
* @brief Bind the conection to the specified local ip.
|
||||||
|
*/
|
||||||
|
void bind(IPAddress ip);
|
||||||
/**
|
/**
|
||||||
* @brief Get the internal socket file descriptor.
|
* @brief Get the internal socket file descriptor.
|
||||||
*
|
*
|
||||||
@@ -200,7 +204,8 @@ public:
|
|||||||
friend class EthernetServer;
|
friend class EthernetServer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _sock; //!< @brief Network socket.
|
int _sock; //!< @brief Network socket file descriptor.
|
||||||
|
IPAddress _srcip; //!< @brief Local ip to bind to.
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ void EthernetServer::begin(IPAddress address)
|
|||||||
char ipstr[INET_ADDRSTRLEN];
|
char ipstr[INET_ADDRSTRLEN];
|
||||||
char portstr[6];
|
char portstr[6];
|
||||||
|
|
||||||
|
if (sockfd != -1) {
|
||||||
|
close(sockfd);
|
||||||
|
sockfd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&hints, 0, sizeof hints);
|
memset(&hints, 0, sizeof hints);
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|||||||
Reference in New Issue
Block a user