1 /*
2 * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*
8 * After station connects to AP and gets IP address by smartconfig,
9 * it will use UDP to send 'ACK' to cellphone.
10 */
11
12 #include "freertos/FreeRTOS.h"
13 #include "freertos/task.h"
14 #include "esp_netif.h"
15 #include "esp_log.h"
16 #include "esp_wifi.h"
17 #include "esp_event.h"
18
19 #if CONFIG_ESP_NETIF_TCPIP_LWIP
20
21 #include <string.h>
22 #include "lwip/sockets.h"
23 #include "esp_smartconfig.h"
24 #include "smartconfig_ack.h"
25
26 #define SC_ACK_TASK_PRIORITY 2 /*!< Priority of sending smartconfig ACK task */
27 #define SC_ACK_TASK_STACK_SIZE 2048 /*!< Stack size of sending smartconfig ACK task */
28
29 #define SC_ACK_TOUCH_DEVICE_PORT 7001 /*!< ESPTouch UDP port of server on device */
30 #define SC_ACK_TOUCH_SERVER_PORT 18266 /*!< ESPTouch UDP port of server on cellphone */
31 #define SC_ACK_TOUCH_V2_SERVER_PORT(i) (18266+i*10000) /*!< ESPTouch v2 UDP port of server on cellphone */
32 #define SC_ACK_AIRKISS_SERVER_PORT 10000 /*!< Airkiss UDP port of server on cellphone */
33 #define SC_ACK_AIRKISS_DEVICE_PORT 10001 /*!< Airkiss UDP port of server on device */
34 #define SC_ACK_AIRKISS_TIMEOUT 1500 /*!< Airkiss read data timout millisecond */
35
36 #define SC_ACK_TOUCH_LEN 11 /*!< Length of ESPTouch ACK context */
37 #define SC_ACK_AIRKISS_LEN 7 /*!< Length of Airkiss ACK context */
38
39 #define SC_ACK_MAX_COUNT 30 /*!< Maximum count of sending smartconfig ACK */
40
41 /**
42 * @brief Smartconfig parameters passed to sc_ack_send call.
43 */
44 typedef struct sc_ack {
45 smartconfig_type_t type; /*!< Smartconfig type(ESPTouch or AirKiss) */
46 struct {
47 uint8_t token; /*!< Smartconfig token from the cellphone */
48 uint8_t mac[6]; /*!< MAC address of station */
49 uint8_t ip[4]; /*!< IP address of cellphone */
50 } ctx;
51 } sc_ack_t;
52
53 static const char *TAG = "smartconfig";
54
55 /* Flag to indicate sending smartconfig ACK or not. */
56 static bool s_sc_ack_send = false;
57
sc_ack_send_get_errno(int fd)58 static int sc_ack_send_get_errno(int fd)
59 {
60 int sock_errno = 0;
61 u32_t optlen = sizeof(sock_errno);
62
63 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen) < 0) {
64 return sock_errno;
65 }
66
67 return 0;
68 }
69
sc_ack_send_task(void * pvParameters)70 static void sc_ack_send_task(void *pvParameters)
71 {
72 sc_ack_t *ack = (sc_ack_t *)pvParameters;
73 esp_netif_ip_info_t local_ip;
74 uint8_t remote_ip[4];
75 memcpy(remote_ip, ack->ctx.ip, sizeof(remote_ip));
76 struct sockaddr_in server_addr;
77 socklen_t sin_size = sizeof(server_addr);
78 int send_sock = -1;
79 int optval = 1;
80 int sendlen;
81 int ack_len = (ack->type == SC_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_LEN : SC_ACK_AIRKISS_LEN;
82 uint8_t packet_count = 1;
83 int err;
84 int ret;
85
86 int remote_port = 0;
87 if (ack->type == SC_TYPE_ESPTOUCH) {
88 remote_port = SC_ACK_TOUCH_SERVER_PORT;
89 } else if (ack->type == SC_TYPE_ESPTOUCH_V2) {
90 uint8_t port_bit = ack->ctx.token;
91 if(port_bit > 3) {
92 port_bit = 0;
93 }
94 remote_port = SC_ACK_TOUCH_V2_SERVER_PORT(port_bit);
95 } else {
96 remote_port = SC_ACK_AIRKISS_SERVER_PORT;
97 }
98
99 bzero(&server_addr, sizeof(struct sockaddr_in));
100 server_addr.sin_family = AF_INET;
101 memcpy(&server_addr.sin_addr.s_addr, remote_ip, sizeof(remote_ip));
102 server_addr.sin_port = htons(remote_port);
103
104 esp_wifi_get_mac(WIFI_IF_STA, ack->ctx.mac);
105
106 vTaskDelay(200 / portTICK_RATE_MS);
107
108 while (s_sc_ack_send) {
109 /* Get local IP address of station */
110 ret = esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &local_ip);
111 if ((ESP_OK == ret) && (local_ip.ip.addr != INADDR_ANY)) {
112 /* If ESPTouch, smartconfig ACK contains local IP address. */
113 if (ack->type == SC_TYPE_ESPTOUCH) {
114 memcpy(ack->ctx.ip, &local_ip.ip.addr, 4);
115 }
116
117 /* Create UDP socket. */
118 send_sock = socket(AF_INET, SOCK_DGRAM, 0);
119 if ((send_sock < LWIP_SOCKET_OFFSET) || (send_sock > (FD_SETSIZE - 1))) {
120 ESP_LOGE(TAG, "Creat udp socket failed");
121 goto _end;
122 }
123
124 if (setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(int)) < 0) {
125 ESP_LOGE(TAG, "setsockopt SO_BROADCAST failed");
126 goto _end;
127 }
128
129 if (setsockopt(send_sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)) < 0) {
130 ESP_LOGE(TAG, "setsockopt SO_REUSEADDR failed");
131 goto _end;
132 }
133
134 if (ack->type == SC_TYPE_AIRKISS) {
135 char data = 0;
136 struct sockaddr_in local_addr, from;
137 socklen_t sockadd_len = sizeof(struct sockaddr);
138 struct timeval timeout = {
139 SC_ACK_AIRKISS_TIMEOUT / 1000,
140 SC_ACK_AIRKISS_TIMEOUT % 1000 * 1000
141 };
142
143 bzero(&local_addr, sizeof(struct sockaddr_in));
144 bzero(&from, sizeof(struct sockaddr_in));
145 local_addr.sin_family = AF_INET;
146 local_addr.sin_addr.s_addr = INADDR_ANY;
147 if (ack->type == SC_TYPE_AIRKISS) {
148 local_addr.sin_port = htons(SC_ACK_AIRKISS_DEVICE_PORT);
149 } else {
150 local_addr.sin_port = htons(SC_ACK_TOUCH_DEVICE_PORT);
151 }
152
153 if (bind(send_sock, (struct sockaddr *)&local_addr, sockadd_len) < 0) {
154 ESP_LOGE(TAG, "socket bind failed");
155 goto _end;
156 }
157 if (setsockopt(send_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
158 goto _end;
159 }
160
161 if (recvfrom(send_sock, &data, 1, 0, (struct sockaddr *)&from, &sockadd_len) < 0) {
162 goto _end;
163 }
164 if (from.sin_addr.s_addr != INADDR_ANY) {
165 memcpy(remote_ip, &from.sin_addr, 4);
166 server_addr.sin_addr.s_addr = from.sin_addr.s_addr;
167 } else {
168 goto _end;
169 }
170 }
171
172 while (s_sc_ack_send) {
173 /* Send smartconfig ACK every 100ms. */
174 vTaskDelay(100 / portTICK_RATE_MS);
175
176 sendlen = sendto(send_sock, &ack->ctx, ack_len, 0, (struct sockaddr*) &server_addr, sin_size);
177 if (sendlen <= 0) {
178 err = sc_ack_send_get_errno(send_sock);
179 ESP_LOGD(TAG, "send failed, errno %d", err);
180 vTaskDelay(100 / portTICK_RATE_MS);
181 }
182
183 /* Send 30 smartconfig ACKs. Then smartconfig is successful. */
184 if (packet_count++ >= SC_ACK_MAX_COUNT) {
185 esp_event_post(SC_EVENT, SC_EVENT_SEND_ACK_DONE, NULL, 0, portMAX_DELAY);
186 goto _end;
187 }
188 }
189 }
190 else {
191 vTaskDelay((portTickType)(100 / portTICK_RATE_MS));
192 }
193 }
194
195 _end:
196 close(send_sock);
197 free(ack);
198 vTaskDelete(NULL);
199 }
200
sc_send_ack_start(smartconfig_type_t type,uint8_t token,uint8_t * cellphone_ip)201 esp_err_t sc_send_ack_start(smartconfig_type_t type, uint8_t token, uint8_t *cellphone_ip)
202 {
203 sc_ack_t *ack = NULL;
204
205 if (cellphone_ip == NULL) {
206 ESP_LOGE(TAG, "Cellphone IP address is NULL");
207 return ESP_ERR_INVALID_ARG;
208 }
209
210 ack = malloc(sizeof(sc_ack_t));
211 if (ack == NULL) {
212 ESP_LOGE(TAG, "ACK parameter malloc fail");
213 return ESP_ERR_NO_MEM;
214 }
215 ack->type = type;
216 ack->ctx.token = token;
217 memcpy(ack->ctx.ip, cellphone_ip, 4);
218
219 s_sc_ack_send = true;
220
221 if (xTaskCreate(sc_ack_send_task, "sc_ack_send_task", SC_ACK_TASK_STACK_SIZE, ack, SC_ACK_TASK_PRIORITY, NULL) != pdPASS) {
222 ESP_LOGE(TAG, "Create sending smartconfig ACK task fail");
223 free(ack);
224 return ESP_ERR_NO_MEM;
225 }
226
227 return ESP_OK;
228 }
229
sc_send_ack_stop(void)230 void sc_send_ack_stop(void)
231 {
232 s_sc_ack_send = false;
233 }
234
235 #endif
236