esp_ot_tcp_socket.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: CC0-1.0
  5. *
  6. * OpenThread Command Line Example
  7. *
  8. * This example code is in the Public Domain (or CC0 licensed, at your option.)
  9. *
  10. * Unless required by applicable law or agreed to in writing, this
  11. * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  12. * CONDITIONS OF ANY KIND, either express or implied.
  13. */
  14. #include "esp_check.h"
  15. #include "esp_err.h"
  16. #include "esp_log.h"
  17. #include "esp_ot_tcp_socket.h"
  18. #include "lwip/err.h"
  19. #include "lwip/sockets.h"
  20. #define TAG "ot_socket"
  21. static void tcp_socket_server_task(void *pvParameters)
  22. {
  23. char addr_str[128];
  24. char rx_buffer[128];
  25. esp_err_t ret = ESP_OK;
  26. int err = 0;
  27. int len = 0;
  28. int listen_sock;
  29. int opt = 1;
  30. int port = CONFIG_OPENTHREAD_CLI_TCP_SERVER_PORT;
  31. int client_sock = 0;
  32. struct timeval timeout = { 0 };
  33. struct sockaddr_storage source_addr; // Large enough for both IPv6
  34. struct sockaddr_in6 listen_addr = { 0 };
  35. // The TCP server listen at the address "::", which means all addresses can be listened to.
  36. inet6_aton("::", &listen_addr.sin6_addr);
  37. listen_addr.sin6_family = AF_INET6;
  38. listen_addr.sin6_port = htons(port);
  39. listen_sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_IPV6);
  40. ESP_GOTO_ON_FALSE((listen_sock >= 0), ESP_OK, exit, TAG, "Unable to create socket: errno %d", errno);
  41. setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  42. // Note that by default IPV6 binds to both protocols, it is must be disabled
  43. // if both protocols used at the same time (used in CI)
  44. setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
  45. ESP_LOGI(TAG, "Socket created");
  46. err = bind(listen_sock, (struct sockaddr *)&listen_addr, sizeof(struct sockaddr_in6) );
  47. ESP_GOTO_ON_FALSE((err == 0), ESP_FAIL, exit, TAG, "Socket unable to bind: errno %d, IPPROTO: %d", errno, AF_INET6);
  48. ESP_LOGI(TAG, "Socket bound, port %d", port);
  49. err = listen(listen_sock, 1);
  50. ESP_GOTO_ON_FALSE((err == 0), ESP_FAIL, exit, TAG, "Error occurred during listen: errno %d", errno);
  51. //blocking-mode accept, set timeout 30 seconds
  52. timeout.tv_sec = 30;
  53. setsockopt(listen_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
  54. ESP_LOGI(TAG, "Socket listening, timeout is 30 seconds");
  55. socklen_t addr_len = sizeof(source_addr);
  56. client_sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
  57. ESP_GOTO_ON_FALSE((client_sock >= 0), ESP_FAIL, exit, TAG, "Unable to accept connection: errno %d", errno);
  58. ESP_GOTO_ON_FALSE((err >= 0), ESP_FAIL, exit, TAG, "Error occurred during sending: errno %d", errno);
  59. //blocking-mode receive, set timeout 30 seconds
  60. timeout.tv_sec = 30;
  61. setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
  62. len = recv(client_sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
  63. // Error occurred during receiving
  64. ESP_GOTO_ON_FALSE((len >= 0), ESP_FAIL, exit, TAG, "recv failed: errno %d", errno);
  65. // Data received
  66. rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
  67. ESP_LOGI(TAG, "Received %d bytes from client:", len);
  68. ESP_LOGI(TAG, "%s", rx_buffer);
  69. // Convert ip address to string
  70. inet6_ntoa_r(((struct sockaddr_in6 *)&source_addr)->sin6_addr, addr_str, sizeof(addr_str) - 1);
  71. ESP_LOGI(TAG, "Socket accepted ip address: %s", addr_str);
  72. exit:
  73. if (ret != ESP_OK || listen_sock != -1) {
  74. shutdown(listen_sock, 0);
  75. close(listen_sock);
  76. }
  77. if (client_sock != -1) {
  78. shutdown(client_sock, 0);
  79. close(client_sock);
  80. }
  81. ESP_LOGI(TAG, "Socket server is closed.");
  82. vTaskDelete(NULL);
  83. }
  84. static void tcp_socket_client_task(void *pvParameters)
  85. {
  86. char *host_ip = (char *)pvParameters;
  87. char *payload = "This message is from client\n";
  88. char rx_buffer[128];
  89. esp_err_t ret = ESP_OK;
  90. int client_sock;
  91. int err = 0;
  92. int len = 0;
  93. int port = CONFIG_OPENTHREAD_CLI_TCP_SERVER_PORT;
  94. struct sockaddr_in6 dest_addr = { 0 };
  95. inet6_aton(host_ip, &dest_addr.sin6_addr);
  96. dest_addr.sin6_family = AF_INET6;
  97. dest_addr.sin6_port = htons(port);
  98. client_sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_IPV6);
  99. ESP_GOTO_ON_FALSE((client_sock >= 0), ESP_OK, exit, TAG, "Unable to create socket: errno %d", errno);
  100. ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, port);
  101. err = connect(client_sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6));
  102. ESP_GOTO_ON_FALSE((err == 0), ESP_FAIL, exit, TAG, "Socket unable to connect: errno %d", errno);
  103. ESP_LOGI(TAG, "Successfully connected");
  104. len = send(client_sock, payload, strlen(payload), 0);
  105. ESP_GOTO_ON_FALSE((len >= 0), ESP_FAIL, exit, TAG, "Error occurred during sending: errno %d", errno);
  106. len = recv(client_sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
  107. // Error occurred during receiving
  108. ESP_GOTO_ON_FALSE((len >= 0), ESP_FAIL, exit, TAG, "recv failed: errno %d", errno);
  109. // Data received
  110. rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
  111. ESP_LOGI(TAG, "Received %d bytes from %s", len, host_ip);
  112. ESP_LOGI(TAG, "%s", rx_buffer);
  113. exit:
  114. if (ret != ESP_OK || client_sock != -1) {
  115. shutdown(client_sock, 0);
  116. close(client_sock);
  117. }
  118. ESP_LOGI(TAG, "Socket client is closed.");
  119. vTaskDelete(NULL);
  120. }
  121. void esp_ot_process_tcp_server(void *aContext, uint8_t aArgsLength, char *aArgs[])
  122. {
  123. (void)(aContext);
  124. (void)(aArgsLength);
  125. (void)(*aArgs);
  126. xTaskCreate(tcp_socket_server_task, "ot_tcp_scoket_server", 4096, xTaskGetCurrentTaskHandle(), 4, NULL);
  127. }
  128. void esp_ot_process_tcp_client(void *aContext, uint8_t aArgsLength, char *aArgs[])
  129. {
  130. (void)(aContext);
  131. (void)(aArgsLength);
  132. if (aArgsLength == 0) {
  133. ESP_LOGE(TAG, "Invalid arguments.");
  134. } else {
  135. xTaskCreate(tcp_socket_client_task, "ot_tcp_socket_client", 4096, aArgs[0], 4, NULL);
  136. }
  137. }