esp_netif_objects.c
1 // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "esp_netif.h" 16 #include "sys/queue.h" 17 #include "esp_log.h" 18 #include "freertos/FreeRTOS.h" 19 #include "freertos/semphr.h" 20 #include "esp_netif_private.h" 21 #include <string.h> 22 23 // 24 // Purpose of this module is to provide list of esp-netif structures 25 // - this module has no dependency on a specific network stack (lwip) 26 // 27 28 static const char *TAG = "esp_netif_objects"; 29 30 typedef struct slist_netifs_s slist_netifs_t; 31 struct slist_netifs_s { 32 esp_netif_t *netif; 33 SLIST_ENTRY(slist_netifs_s) next; 34 }; 35 36 SLIST_HEAD(slisthead, slist_netifs_s) s_head = { .slh_first = NULL, }; 37 38 static size_t s_esp_netif_counter = 0; 39 static xSemaphoreHandle s_list_lock = NULL; 40 41 ESP_EVENT_DEFINE_BASE(IP_EVENT); 42 43 esp_err_t esp_netif_list_lock(void) 44 { 45 if (s_list_lock == NULL) { 46 s_list_lock = xSemaphoreCreateMutex(); 47 if (s_list_lock == NULL) { 48 return ESP_ERR_NO_MEM; 49 } 50 } 51 xSemaphoreTake(s_list_lock, portMAX_DELAY); 52 return ESP_OK; 53 } 54 55 void esp_netif_list_unlock(void) 56 { 57 assert(s_list_lock); 58 xSemaphoreGive(s_list_lock); 59 if (s_esp_netif_counter == 0) { 60 vQueueDelete(s_list_lock); 61 s_list_lock = NULL; 62 } 63 } 64 65 // 66 // List manipulation functions 67 // 68 esp_err_t esp_netif_add_to_list(esp_netif_t *netif) 69 { 70 esp_err_t ret; 71 struct slist_netifs_s *item = calloc(1, sizeof(struct slist_netifs_s)); 72 ESP_LOGD(TAG, "%s %p", __func__, netif); 73 if (item == NULL) { 74 return ESP_ERR_NO_MEM; 75 } 76 item->netif = netif; 77 78 if ((ret = esp_netif_list_lock()) != ESP_OK) { 79 free(item); 80 return ret; 81 } 82 83 SLIST_INSERT_HEAD(&s_head, item, next); 84 ++s_esp_netif_counter; 85 ESP_LOGD(TAG, "%s netif added successfully (total netifs: %d)", __func__, s_esp_netif_counter); 86 esp_netif_list_unlock(); 87 return ESP_OK; 88 } 89 90 91 esp_err_t esp_netif_remove_from_list(esp_netif_t *netif) 92 { 93 struct slist_netifs_s *item; 94 esp_err_t ret; 95 if ((ret = esp_netif_list_lock()) != ESP_OK) { 96 return ret; 97 } 98 ESP_LOGV(TAG, "%s %p", __func__, netif); 99 100 SLIST_FOREACH(item, &s_head, next) { 101 if (item->netif == netif) { 102 SLIST_REMOVE(&s_head, item, slist_netifs_s, next); 103 assert(s_esp_netif_counter > 0); 104 --s_esp_netif_counter; 105 ESP_LOGD(TAG, "%s netif successfully removed (total netifs: %d)", __func__, s_esp_netif_counter); 106 free(item); 107 esp_netif_list_unlock(); 108 return ESP_OK; 109 } 110 } 111 esp_netif_list_unlock(); 112 return ESP_ERR_NOT_FOUND; 113 } 114 115 size_t esp_netif_get_nr_of_ifs(void) 116 { 117 return s_esp_netif_counter; 118 } 119 120 esp_netif_t* esp_netif_next(esp_netif_t* netif) 121 { 122 esp_err_t ret; 123 esp_netif_t* result; 124 if ((ret = esp_netif_list_lock()) != ESP_OK) { 125 ESP_LOGE(TAG, "Failed to lock esp-netif list with %d", ret); 126 return NULL; 127 } 128 result = esp_netif_next_unsafe(netif); 129 esp_netif_list_unlock(); 130 return result; 131 } 132 133 esp_netif_t* esp_netif_next_unsafe(esp_netif_t* netif) 134 { 135 ESP_LOGV(TAG, "%s %p", __func__, netif); 136 struct slist_netifs_s *item; 137 // Getting the first netif if argument is NULL 138 if (netif == NULL) { 139 item = SLIST_FIRST(&s_head); 140 return (item == NULL) ? NULL : item->netif; 141 } 142 // otherwise the next one (after the supplied netif) 143 SLIST_FOREACH(item, &s_head, next) { 144 if (item->netif == netif) { 145 item = SLIST_NEXT(item, next); 146 return (item == NULL) ? NULL : item->netif; 147 } 148 } 149 return NULL; 150 } 151 152 bool esp_netif_is_netif_listed(esp_netif_t *esp_netif) 153 { 154 esp_err_t ret; 155 if ((ret = esp_netif_list_lock()) != ESP_OK) { 156 ESP_LOGE(TAG, "Failed to lock esp-netif list with %d", ret); 157 return NULL; 158 } 159 160 // looking for the netif in the list of registered interfaces 161 esp_netif_t *it = esp_netif_next_unsafe(NULL); 162 do { 163 if (it && it == esp_netif) { 164 esp_netif_list_unlock(); 165 return true; 166 } 167 } while (NULL != (it = esp_netif_next_unsafe(it))); 168 esp_netif_list_unlock(); 169 return false; 170 } 171 172 esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key) 173 { 174 esp_err_t ret; 175 if ((ret = esp_netif_list_lock()) != ESP_OK) { 176 ESP_LOGE(TAG, "Failed to lock esp-netif list with %d", ret); 177 return NULL; 178 } 179 180 esp_netif_t *esp_netif = esp_netif_next_unsafe(NULL); 181 do { 182 if (esp_netif && strcmp(if_key, esp_netif_get_ifkey(esp_netif))==0) { 183 esp_netif_list_unlock(); 184 return esp_netif; 185 } 186 } while (NULL != (esp_netif = esp_netif_next_unsafe(esp_netif))); 187 esp_netif_list_unlock(); 188 return NULL; 189 }