Skip to content

Commit 11544cd

Browse files
committed
Determine default interface
1 parent ddada8a commit 11544cd

File tree

1 file changed

+144
-121
lines changed

1 file changed

+144
-121
lines changed

ArduinoCore-Linux/cores/arduino/SocketImpl.cpp

Lines changed: 144 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -3,167 +3,190 @@
33
* Separate implementation class for the WIFI client to prevent import conflicts
44
***/
55

6+
#include <arpa/inet.h>
67
#include <cstring>
7-
#include <sys/socket.h>
8+
#include <fcntl.h>
89
#include <sys/ioctl.h>
10+
#include <sys/socket.h>
911
#include <unistd.h>
10-
#include <fcntl.h>
11-
#include <arpa/inet.h>
1212

13-
#include <sys/types.h>
13+
#include <arpa/inet.h>
1414
#include <ifaddrs.h>
15-
#include <netinet/in.h>
1615
#include <net/if.h>
1716
#include <netdb.h>
18-
#include <sys/types.h>
1917
#include <netinet/in.h>
20-
#include <arpa/inet.h>
18+
#include <sys/types.h>
2119

22-
#include "SocketImpl.h"
2320
#include "ArduinoLogger.h"
21+
#include "SocketImpl.h"
2422

2523
namespace arduino {
2624

27-
SocketImpl::SocketImpl(){
28-
}
25+
SocketImpl::SocketImpl() {}
2926

30-
const char* SOCKET_IMPL = "SocketImpl";
27+
const char *SOCKET_IMPL = "SocketImpl";
3128

3229
// checks if we are connected
3330
uint8_t SocketImpl::connected() {
34-
char buf[2];
35-
int result = ::recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT);
36-
// if peek is working we are connected - if not we do further checks
37-
is_connected = result >= 0;
38-
if (!is_connected){
39-
int error_code;
40-
socklen_t error_code_size;
41-
//int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);
42-
int result = getsockopt(sock, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size);
43-
if (result!=0){
44-
char msg[50];
45-
sprintf(msg,"%d",result);
46-
Logger.debug(SOCKET_IMPL,"getsockopt->",msg);
47-
}
48-
49-
is_connected = (result == 0);
31+
char buf[2];
32+
int result = ::recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT);
33+
// if peek is working we are connected - if not we do further checks
34+
is_connected = result >= 0;
35+
if (!is_connected) {
36+
int error_code;
37+
socklen_t error_code_size;
38+
// int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t
39+
// *optlen);
40+
int result =
41+
getsockopt(sock, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size);
42+
if (result != 0) {
43+
char msg[50];
44+
sprintf(msg, "%d", result);
45+
Logger.debug(SOCKET_IMPL, "getsockopt->", msg);
5046
}
5147

52-
return is_connected;
48+
is_connected = (result == 0);
49+
}
50+
51+
return is_connected;
5352
}
5453

5554
// opens a conection
56-
int SocketImpl::connect(const char* address, uint16_t port){
57-
if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) < 0) {
58-
Logger.error(SOCKET_IMPL,"could not create socket");
59-
return -1;
60-
}
61-
62-
serv_addr.sin_family = AF_INET;
63-
serv_addr.sin_port = htons(port);
64-
65-
const char* address_ip = address;
66-
hostent *host_entry = gethostbyname(address); //find host information
67-
if (host_entry!=nullptr){
68-
address_ip = inet_ntoa(*((struct in_addr*) host_entry->h_addr_list[0])); //Convert into IP string
69-
}
70-
71-
// Convert IPv4 and IPv6 addresses from text to binary form
72-
if(::inet_pton(AF_INET, address_ip, &serv_addr.sin_addr)<=0) {
73-
Logger.error(SOCKET_IMPL,"invalid address");
74-
return -2;
75-
}
76-
77-
if (::connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
78-
Logger.error(SOCKET_IMPL,"could not connect");
79-
return -3;
80-
}
81-
82-
is_connected = true;
83-
Logger.info(SOCKET_IMPL,"connected!");
84-
return 1;
55+
int SocketImpl::connect(const char *address, uint16_t port) {
56+
if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) < 0) {
57+
Logger.error(SOCKET_IMPL, "could not create socket");
58+
return -1;
59+
}
60+
61+
serv_addr.sin_family = AF_INET;
62+
serv_addr.sin_port = htons(port);
63+
64+
const char *address_ip = address;
65+
hostent *host_entry = gethostbyname(address); // find host information
66+
if (host_entry != nullptr) {
67+
address_ip =
68+
inet_ntoa(*((struct in_addr *)
69+
host_entry->h_addr_list[0])); // Convert into IP string
70+
}
71+
72+
// Convert IPv4 and IPv6 addresses from text to binary form
73+
if (::inet_pton(AF_INET, address_ip, &serv_addr.sin_addr) <= 0) {
74+
Logger.error(SOCKET_IMPL, "invalid address");
75+
return -2;
76+
}
77+
78+
if (::connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
79+
Logger.error(SOCKET_IMPL, "could not connect");
80+
return -3;
81+
}
82+
83+
is_connected = true;
84+
Logger.info(SOCKET_IMPL, "connected!");
85+
return 1;
8586
}
8687

87-
// send the data via the socket - returns the number of characters written or -1=>Error
88-
size_t SocketImpl::write(const uint8_t* str, size_t len){
89-
Logger.debug(SOCKET_IMPL,"write");
90-
return ::send(sock , str , len , 0 );
88+
// send the data via the socket - returns the number of characters written or
89+
// -1=>Error
90+
size_t SocketImpl::write(const uint8_t *str, size_t len) {
91+
Logger.debug(SOCKET_IMPL, "write");
92+
return ::send(sock, str, len, 0);
9193
}
9294

9395
// provides the available bytes
9496
size_t SocketImpl::available() {
95-
int bytes_available;
96-
ioctl(sock, FIONREAD, &bytes_available);
97-
char msg[50];
98-
sprintf(msg,"%d",bytes_available);
99-
Logger.debug(SOCKET_IMPL,"available->",msg);
100-
return bytes_available;
97+
int bytes_available;
98+
ioctl(sock, FIONREAD, &bytes_available);
99+
char msg[50];
100+
sprintf(msg, "%d", bytes_available);
101+
Logger.debug(SOCKET_IMPL, "available->", msg);
102+
return bytes_available;
101103
}
102104

103105
// direct read
104-
size_t SocketImpl::read(uint8_t* buffer, size_t len){
105-
size_t result = ::recv(sock, buffer, len, MSG_DONTWAIT );
106-
char lenStr[80];
107-
sprintf(lenStr,"%ld -> %ld",len, result);
108-
Logger.debug(SOCKET_IMPL,"read->", lenStr);
109-
return result;
106+
size_t SocketImpl::read(uint8_t *buffer, size_t len) {
107+
size_t result = ::recv(sock, buffer, len, MSG_DONTWAIT);
108+
char lenStr[80];
109+
sprintf(lenStr, "%ld -> %ld", len, result);
110+
Logger.debug(SOCKET_IMPL, "read->", lenStr);
111+
return result;
110112
}
111113

112114
// peeks one character
113-
int SocketImpl::peek(){
114-
Logger.debug(SOCKET_IMPL,"peek");
115-
char buf[1];
116-
int result = ::recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT);
117-
return result>0 ? buf[0] : -1;
115+
int SocketImpl::peek() {
116+
Logger.debug(SOCKET_IMPL, "peek");
117+
char buf[1];
118+
int result = ::recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT);
119+
return result > 0 ? buf[0] : -1;
118120
}
119121

120122
void SocketImpl::close() {
121-
Logger.info(SOCKET_IMPL,"close");
122-
::close(sock);
123+
Logger.info(SOCKET_IMPL, "close");
124+
::close(sock);
125+
}
126+
127+
char* defaultInterface() {
128+
FILE *f;
129+
char line[100], *p, *c;
130+
131+
f = fopen("/proc/net/route", "r");
132+
133+
while (fgets(line, 100, f)) {
134+
p = strtok(line, " \t");
135+
c = strtok(NULL, " \t");
136+
137+
if (p != NULL && c != NULL) {
138+
if (strcmp(c, "00000000") == 0) {
139+
static char defaultInterface[20];
140+
strcpy(defaultInterface, p);
141+
printf("Default interface is : %s \n", p);
142+
return defaultInterface;
143+
}
144+
}
145+
}
123146
}
124-
147+
125148
// determines the IP Adress
126-
const char* SocketImpl::getIPAddress(){
127-
Logger.info(SOCKET_IMPL,"getIPAddress");
128-
const char* valid[] = {"eth0", "en0","en1",nullptr};
129-
return getIPAddress(valid);
149+
const char *SocketImpl::getIPAddress() {
150+
Logger.info(SOCKET_IMPL, "getIPAddress");
151+
const char *valid[] = {"eth0", "en0", "en1", defaultInterface(), nullptr};
152+
return getIPAddress(valid);
130153
}
131-
132-
// determines the IP Adress
133-
const char* SocketImpl::getIPAddress(const char* validEntries[]){
134-
Logger.info(SOCKET_IMPL,"getIPAddress-1");
135-
struct ifaddrs *interfaces = NULL;
136-
struct ifaddrs *temp_addr = NULL;
137-
char* resultAddress = nullptr;
138-
int success = 0;
139-
// retrieve the current interfaces - returns 0 on success
140-
success = getifaddrs(&interfaces);
141-
if (success == 0) {
142-
// Loop through linked list of interfaces
143-
temp_addr = interfaces;
144-
while(temp_addr != NULL) {
145-
if(temp_addr->ifa_addr->sa_family == AF_INET && (temp_addr->ifa_flags & IFF_UP)) {
146-
// check if ifa_name is in the list of relevant names
147-
bool isValid = false;
148-
for(int j=0;validEntries[j]!=nullptr;j++){
149-
if (strcmp(temp_addr->ifa_name, validEntries[j])==0){
150-
isValid = true;
151-
break;
152-
}
153-
}
154-
if(isValid) {
155-
auto addr = ((struct sockaddr_in*)temp_addr->ifa_addr)->sin_addr;
156-
resultAddress = inet_ntoa(addr);
157-
break;
158-
}
159-
}
160-
temp_addr = temp_addr->ifa_next;
154+
155+
// determines the IP Adress
156+
const char *SocketImpl::getIPAddress(const char *validEntries[]) {
157+
Logger.info(SOCKET_IMPL, "getIPAddress-1");
158+
struct ifaddrs *interfaces = NULL;
159+
struct ifaddrs *temp_addr = NULL;
160+
char *resultAddress = nullptr;
161+
int success = 0;
162+
// retrieve the current interfaces - returns 0 on success
163+
success = getifaddrs(&interfaces);
164+
if (success == 0) {
165+
// Loop through linked list of interfaces
166+
temp_addr = interfaces;
167+
while (temp_addr != NULL) {
168+
if (temp_addr->ifa_addr->sa_family == AF_INET &&
169+
(temp_addr->ifa_flags & IFF_UP)) {
170+
// check if ifa_name is in the list of relevant names
171+
bool isValid = false;
172+
for (int j = 0; validEntries[j] != nullptr; j++) {
173+
if (strcmp(temp_addr->ifa_name, validEntries[j]) == 0) {
174+
isValid = true;
175+
break;
176+
}
177+
}
178+
if (isValid) {
179+
auto addr = ((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr;
180+
resultAddress = inet_ntoa(addr);
181+
break;
161182
}
183+
}
184+
temp_addr = temp_addr->ifa_next;
162185
}
163-
// Free memory
164-
freeifaddrs(interfaces);
165-
return resultAddress;
186+
}
187+
// Free memory
188+
freeifaddrs(interfaces);
189+
return resultAddress;
166190
}
167-
168-
169-
}
191+
192+
} // namespace arduino

0 commit comments

Comments
 (0)