Linux: Binds to MY_IP_ADDRESS in client mode (#849)

This commit is contained in:
Marcelo Aquino
2017-05-21 14:27:22 +02:00
committed by Olivier
parent abba1ec377
commit fb3d936d4c
5 changed files with 45 additions and 10 deletions
+30 -8
View File
@@ -43,11 +43,13 @@ EthernetClient::EthernetClient(int sock) : _sock(sock)
int EthernetClient::connect(const char* host, uint16_t port)
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
struct addrinfo hints, *servinfo, *localinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
char port_str[6];
bool use_bind = (_srcip != 0);
close();
memset(&hints, 0, sizeof hints);
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));
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
for (p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
if ((_sock = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
logError("socket: %s\n", strerror(errno));
continue;
}
if (::connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
::close(sockfd);
if (use_bind) {
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));
continue;
}
@@ -81,13 +97,14 @@ int EthernetClient::connect(const char* host, uint16_t port)
return -1;
}
_sock = sockfd;
void *addr = &(((struct sockaddr_in*)p->ai_addr)->sin_addr);
inet_ntop(p->ai_family, addr, s, sizeof s);
logDebug("connected to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
if (use_bind) {
freeaddrinfo(localinfo); // all done with this structure
}
return 1;
}
@@ -273,6 +290,11 @@ void EthernetClient::close()
}
}
void EthernetClient::bind(IPAddress ip)
{
_srcip = ip;
}
int EthernetClient::getSocketNumber()
{
return _sock;
+6 -1
View File
@@ -155,6 +155,10 @@ public:
* @brief Close the connection.
*/
void close();
/**
* @brief Bind the conection to the specified local ip.
*/
void bind(IPAddress ip);
/**
* @brief Get the internal socket file descriptor.
*
@@ -200,7 +204,8 @@ public:
friend class EthernetServer;
private:
int _sock; //!< @brief Network socket.
int _sock; //!< @brief Network socket file descriptor.
IPAddress _srcip; //!< @brief Local ip to bind to.
};
#endif
+5
View File
@@ -51,6 +51,11 @@ void EthernetServer::begin(IPAddress address)
char ipstr[INET_ADDRSTRLEN];
char portstr[6];
if (sockfd != -1) {
close(sockfd);
sockfd = -1;
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;