tcp_client_v6.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Unlicense OR CC0-1.0
  5. */
  6. #include "sdkconfig.h"
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include <sys/socket.h>
  10. #include <errno.h>
  11. #include <netdb.h> // struct addrinfo
  12. #include <arpa/inet.h>
  13. #include "esp_netif.h"
  14. #include "esp_log.h"
  15. #if defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN)
  16. #include "addr_from_stdin.h"
  17. #endif
  18. #if defined(CONFIG_EXAMPLE_IPV6_ADDR)
  19. #define HOST_IP_ADDR CONFIG_EXAMPLE_IPV6_ADDR
  20. #else
  21. #define HOST_IP_ADDR ""
  22. #endif
  23. #define PORT CONFIG_EXAMPLE_PORT
  24. static const char *TAG = "example";
  25. static const char *payload = "Message from ESP32 ";
  26. #if defined(CONFIG_IDF_TARGET_LINUX)
  27. // Checks for Global address, Unique Unicast(RFC4193) and link-local address.
  28. #define ip6_addr_isglobal(ip6addr) ((((ip6addr)->sin6_addr.s6_addr[0] & htonl(0xe0000000UL)) & htonl(0x20000000UL)) || \
  29. (((ip6addr)->sin6_addr.s6_addr[0] & htonl(0xff000000UL)) & htonl(0xfc000000UL)) || \
  30. (((ip6addr)->sin6_addr.s6_addr[0] & htonl(0xff000000UL)) & htonl(0xfe800000UL)))
  31. /**
  32. * @brief In case of Auto mode returns the interface name with a valid IPv6 address or
  33. * In case the user has specified interface, validates and returns the interface name.
  34. *
  35. * @param[out] interface Name of the interface in as a string.
  36. *
  37. * @return 0 incase of success.
  38. */
  39. static int get_src_iface(char *interface)
  40. {
  41. struct ifaddrs *ifap, *ifa;
  42. char src_addr_str[INET6_ADDRSTRLEN];
  43. if (getifaddrs(&ifap) == -1) {
  44. ESP_LOGE(TAG, "getifaddrs failed");
  45. return -1;
  46. }
  47. for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
  48. if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6) {
  49. #if defined(CONFIG_EXAMPLE_USER_SPECIFIED_IFACE)
  50. if (0 == strcmp(CONFIG_EXAMPLE_USER_SPECIFIED_IFACE_NAME, ifa->ifa_name)) {
  51. strcpy(interface, ifa->ifa_name);
  52. freeifaddrs(ifap);
  53. ESP_LOGI(TAG, "Interface: %s", interface);
  54. return 0;
  55. }
  56. #else
  57. strcpy(interface, ifa->ifa_name);
  58. getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), src_addr_str,
  59. sizeof(src_addr_str), NULL, 0, NI_NUMERICHOST);
  60. struct sockaddr_in6 *src_addr = (struct sockaddr_in6 *) ifa->ifa_addr;
  61. inet_ntop(AF_INET6, &(src_addr->sin6_addr), src_addr_str, INET6_ADDRSTRLEN);
  62. if (ip6_addr_isglobal(src_addr)) {
  63. //Return as we have the source address
  64. freeifaddrs(ifap);
  65. ESP_LOGI(TAG, "Interface: %s", interface);
  66. return 0;
  67. }
  68. #endif // #if defined(CONFIG_EXAMPLE_USER_SPECIFIED_IFACE)
  69. }
  70. }
  71. freeifaddrs(ifap);
  72. return -1;
  73. }
  74. #else
  75. /**
  76. * @brief In case of Auto mode returns the interface name with a valid IPv6 address or
  77. * In case the user has specified interface, validates and returns the interface name.
  78. *
  79. * This function is a predicate for esp_netif_find_if() API, and it uses the underlying
  80. * network interface name as a context parameter
  81. *
  82. * @return true if we found the appropriate interface, false if not
  83. */
  84. static bool choose_netif(esp_netif_t *netif, void* ctx)
  85. {
  86. char *interface = ctx;
  87. esp_ip6_addr_t ip6[LWIP_IPV6_NUM_ADDRESSES];
  88. esp_err_t ret = esp_netif_get_netif_impl_name(netif, interface);
  89. if ((ESP_FAIL == ret) || (NULL == netif)) {
  90. ESP_LOGE(TAG, "No interface available");
  91. return false;
  92. }
  93. #if defined(CONFIG_EXAMPLE_USER_SPECIFIED_IFACE)
  94. if (!strcmp(CONFIG_EXAMPLE_USER_SPECIFIED_IFACE_NAME, interface)) {
  95. ESP_LOGI(TAG, "Interface: %s", interface);
  96. return true;
  97. }
  98. #else
  99. int ip6_addrs_count = esp_netif_get_all_ip6(netif, ip6);
  100. for (int j = 0; j < ip6_addrs_count; ++j) {
  101. esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&(ip6[j]));
  102. if ((ESP_IP6_ADDR_IS_GLOBAL == ipv6_type) ||
  103. (ESP_IP6_ADDR_IS_UNIQUE_LOCAL == ipv6_type) ||
  104. (ESP_IP6_ADDR_IS_LINK_LOCAL == ipv6_type)) {
  105. // Break as we have the source address
  106. ESP_LOGI(TAG, "Interface: %s", interface);
  107. return true;
  108. }
  109. }
  110. #endif // #if defined(CONFIG_EXAMPLE_USER_SPECIFIED_IFACE)
  111. return false;
  112. }
  113. #endif // #if defined(CONFIG_IDF_TARGET_LINUX)
  114. void tcp_client(void)
  115. {
  116. char rx_buffer[128];
  117. char host_ip[] = HOST_IP_ADDR;
  118. int addr_family = 0;
  119. int ip_protocol = 0;
  120. char interface[10];
  121. #if defined(CONFIG_IDF_TARGET_LINUX)
  122. struct ifreq ifr;
  123. #else
  124. esp_netif_t *netif = NULL;
  125. #endif
  126. while (1) {
  127. #if defined(CONFIG_EXAMPLE_IPV6)
  128. struct sockaddr_in6 dest_addr = { 0 };
  129. inet_pton(AF_INET6, host_ip, &dest_addr.sin6_addr);
  130. dest_addr.sin6_family = AF_INET6;
  131. dest_addr.sin6_port = htons(PORT);
  132. addr_family = AF_INET6;
  133. ip_protocol = IPPROTO_TCP;
  134. #elif defined(CONFIG_EXAMPLE_SOCKET_IP_INPUT_STDIN)
  135. struct sockaddr_storage dest_addr = { 0 };
  136. ESP_ERROR_CHECK(get_addr_from_stdin(PORT, SOCK_STREAM, &ip_protocol, &addr_family, &dest_addr));
  137. #endif
  138. int sock = socket(addr_family, SOCK_STREAM, ip_protocol);
  139. if (sock < 0) {
  140. ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
  141. break;
  142. }
  143. ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, PORT);
  144. #if defined(CONFIG_IDF_TARGET_LINUX)
  145. if (0 != get_src_iface(interface)) {
  146. ESP_LOGE(TAG, "Interface: Unavailable");
  147. break;
  148. }
  149. memset (&ifr, 0, sizeof(ifr));
  150. snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
  151. if (ioctl (sock, SIOCGIFINDEX, &ifr) < 0) {
  152. ESP_LOGE(TAG, "ioctl() failed to find interface ");
  153. break;
  154. }
  155. #if defined(CONFIG_EXAMPLE_IPV6)
  156. dest_addr.sin6_scope_id = ifr.ifr_ifindex;
  157. ESP_LOGI(TAG, "Interface index: %d", dest_addr.sin6_scope_id);
  158. #endif
  159. #else
  160. if (NULL == (netif = esp_netif_find_if(choose_netif, interface))) {
  161. ESP_LOGE(TAG, "Failed to find interface ");
  162. break;
  163. }
  164. #if defined(CONFIG_EXAMPLE_IPV6)
  165. dest_addr.sin6_scope_id = esp_netif_get_netif_impl_index(netif);
  166. ESP_LOGI(TAG, "Interface index: %" PRIu32, dest_addr.sin6_scope_id);
  167. #endif
  168. #endif
  169. int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
  170. if (err != 0) {
  171. ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
  172. break;
  173. }
  174. ESP_LOGI(TAG, "Successfully connected");
  175. while (1) {
  176. int err = send(sock, payload, strlen(payload), 0);
  177. if (err < 0) {
  178. ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
  179. break;
  180. }
  181. int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
  182. // Error occurred during receiving
  183. if (len < 0) {
  184. ESP_LOGE(TAG, "recv failed: errno %d", errno);
  185. break;
  186. }
  187. // Data received
  188. else {
  189. rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
  190. ESP_LOGI(TAG, "Received %d bytes from %s:", len, host_ip);
  191. ESP_LOGI(TAG, "%s", rx_buffer);
  192. }
  193. }
  194. if (sock != -1) {
  195. ESP_LOGE(TAG, "Shutting down socket and restarting...");
  196. shutdown(sock, 0);
  197. close(sock);
  198. }
  199. }
  200. }