Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ns_mdns_api.c Source File

ns_mdns_api.c

00001 /*
00002  * Copyright (c) 2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "fnet.h"
00019 #include "fnet_netif_prv.h"
00020 
00021 #include "ns_types.h"
00022 #include "ns_list.h"
00023 #include "nsdynmemLIB.h"
00024 #include "ns_mdns_api.h"
00025 #include "ns_fnet_events.h"
00026 #include "common_functions.h" // common_write
00027 #include "ns_trace.h"
00028 
00029 #define TRACE_GROUP "mDNS"
00030 
00031 /* Structure for list of services */
00032 typedef struct {
00033     fnet_mdns_service_t service_opt;        // service options holding service parameters
00034     fnet_mdns_service_desc_t service_desc;  // service descriptor received from fnet
00035     ns_list_link_t link;
00036 } ns_mdns_service_entry_t;
00037 
00038 typedef NS_LIST_HEAD (ns_mdns_service_entry_t, link) ns_mdns_service_entry_list;
00039 
00040 /* Structure for list of servers */
00041 typedef struct {
00042     fnet_netif_t *ns_netif;         // network interface
00043     fnet_mdns_desc_t mdns_desc;     // server descriptor from fnet
00044     ns_mdns_service_entry_list service_list;    // list of services added to this server
00045     ns_list_link_t link;
00046 } ns_mdns_server_entry_t;
00047 
00048 static NS_LIST_DEFINE(server_list, ns_mdns_server_entry_t, link);
00049 
00050 /*
00051  * Find service_entry from a server list based on service_descriptor
00052  */
00053 static ns_mdns_service_entry_t* ns_mdns_service_entry_find(fnet_mdns_service_desc_t service_desc)
00054 {
00055     ns_list_foreach(ns_mdns_server_entry_t, cur_server_entry_ptr, &server_list) {
00056         ns_list_foreach(ns_mdns_service_entry_t, cur_service__entry_ptr, &cur_server_entry_ptr->service_list) {
00057             if (cur_service__entry_ptr->service_desc == service_desc ) {
00058                 return cur_service__entry_ptr;
00059             }
00060         }
00061     }
00062     return NULL;
00063 }
00064 
00065 /*
00066  * Find server_entry based on service_entry
00067  */
00068 static ns_mdns_server_entry_t* ns_mdns_server_entry_find_by_service(ns_mdns_service_entry_t *service_entry)
00069 {
00070     ns_list_foreach(ns_mdns_server_entry_t, cur_server_entry_ptr, &server_list) {
00071         ns_list_foreach(ns_mdns_service_entry_t, cur_service_entry_ptr, &cur_server_entry_ptr->service_list) {
00072             if (cur_service_entry_ptr == service_entry ) {
00073                 return cur_server_entry_ptr;
00074             }
00075         }
00076     }
00077     return NULL;
00078 }
00079 
00080 /*
00081  * Find server entry based on server_descriptor
00082  */
00083 static ns_mdns_server_entry_t* ns_mdns_server_entry_find(fnet_mdns_desc_t mdns_desc)
00084 {
00085     ns_list_foreach(ns_mdns_server_entry_t, cur_server__entry_ptr, &server_list) {
00086         if (cur_server__entry_ptr->mdns_desc == mdns_desc ) {
00087             return cur_server__entry_ptr;
00088         }
00089     }
00090     return NULL;
00091 }
00092 
00093 static ns_mdns_service_entry_t* ns_mdns_service_entry_create(ns_mdns_server_entry_t *server_entry, ns_mdns_service_param_t *service)
00094 {
00095     if (!service || !service->service_type || !service->service_get_txt || !server_entry) {
00096         return NULL;
00097     }
00098 
00099     ns_mdns_service_entry_t *mdns_service = ns_dyn_mem_alloc(sizeof(ns_mdns_service_entry_t));
00100     if (!mdns_service) {
00101         return NULL;
00102     }
00103     mdns_service->service_opt.service_type = ns_dyn_mem_alloc(strlen(service->service_type) + 1);
00104     if (!mdns_service->service_opt.service_type) {
00105         ns_dyn_mem_free(mdns_service);
00106         return NULL;
00107     }
00108     strcpy((char*)mdns_service->service_opt.service_type, service->service_type);
00109     // change port to be in network byte order
00110     mdns_service->service_opt.service_port = FNET_HTONS(service->service_port);
00111     mdns_service->service_opt.service_get_txt = service->service_get_txt;
00112 
00113     ns_list_add_to_end(&server_entry->service_list, mdns_service);
00114     return mdns_service;
00115 }
00116 
00117 /*
00118  * Free service entry and remove it from the list
00119  */
00120 static void ns_mdns_service_entry_free(ns_mdns_server_entry_t *server_entry, ns_mdns_service_entry_t *service_entry)
00121 {
00122     if (service_entry) {
00123         ns_list_remove(&server_entry->service_list, service_entry);
00124         ns_dyn_mem_free((void*)service_entry->service_opt.service_type);
00125         ns_dyn_mem_free(service_entry);
00126     }
00127 }
00128 
00129 ns_mdns_t ns_mdns_server_start(const char *server_name, uint32_t ttl, uint32_t ttl_ip, int8_t interface_id)
00130 {
00131     FNET_DEBUG("ns_mdns_server_start(), interface=%d", interface_id);
00132     struct fnet_mdns_params params;
00133     fnet_netif_t *ns_netif;
00134     ns_mdns_server_entry_t *server_entry;
00135     fnet_mdns_desc_t mdns_desc;
00136 
00137     if (interface_id < 0) {
00138         return NULL;
00139     }
00140 
00141     server_entry = ns_dyn_mem_alloc(sizeof(ns_mdns_server_entry_t));
00142     if (!server_entry) {
00143        return NULL;
00144     }
00145 
00146     ns_netif = ns_dyn_mem_alloc(sizeof(fnet_netif_t));
00147     if (!ns_netif) {
00148         ns_dyn_mem_free(server_entry);
00149        return NULL;
00150     }
00151     ns_netif->scope_id = interface_id;
00152     server_entry->ns_netif = ns_netif;
00153 
00154     params.netif_desc = (fnet_mdns_desc_t)ns_netif;
00155     params.name = server_name;
00156     params.rr_ttl = ttl;
00157     params.rr_ttl_ip = ttl_ip;
00158     params.addr_family = AF_INET6;
00159 
00160     ns_fnet_events_start();
00161 
00162     /* Start mDNS server */
00163     mdns_desc = fnet_mdns_init(&params);
00164     if (!mdns_desc) {
00165         ns_dyn_mem_free(ns_netif);
00166         ns_dyn_mem_free(server_entry);
00167         tr_error("mdns init failure");
00168         return NULL;
00169     }
00170 
00171     server_entry->mdns_desc = mdns_desc;
00172 
00173     ns_list_init(&server_entry->service_list);
00174     ns_list_add_to_end(&server_list, server_entry);
00175     return mdns_desc;
00176 }
00177 
00178 void ns_mdns_server_stop(ns_mdns_t ns_mdns)
00179 {
00180     FNET_DEBUG("ns_mdns_server_stop()");
00181     ns_mdns_server_entry_t *server_entry;
00182 
00183     server_entry = ns_mdns_server_entry_find(ns_mdns);
00184     if (server_entry) {
00185         fnet_mdns_release((fnet_mdns_desc_t)ns_mdns);
00186         ns_list_remove(&server_list, server_entry);
00187 
00188         ns_list_foreach_safe(ns_mdns_service_entry_t, cur_service_entry_ptr, &server_entry->service_list) {
00189             // free all services from the current server
00190             ns_mdns_service_entry_free(server_entry, cur_service_entry_ptr);
00191         }
00192 
00193         ns_dyn_mem_free(server_entry->ns_netif);
00194         ns_dyn_mem_free(server_entry);
00195     }
00196 
00197    if (ns_list_is_empty(&server_list)) {
00198        // No more servers in the system, stop events
00199        ns_fnet_events_stop();
00200    }
00201 }
00202 
00203 ns_mdns_service_t ns_mdns_service_register(ns_mdns_t ns_mdns, ns_mdns_service_param_t *service)
00204 {
00205     ns_mdns_server_entry_t *server_entry = ns_mdns_server_entry_find(ns_mdns);
00206     ns_mdns_service_entry_t *mdns_service_entry = ns_mdns_service_entry_create(server_entry, service);
00207 
00208     if (!mdns_service_entry) {
00209         tr_error("Failed to create service entry");
00210         return NULL;
00211     }
00212 
00213     mdns_service_entry->service_desc = fnet_mdns_service_register((fnet_mdns_desc_t)ns_mdns, &mdns_service_entry->service_opt);
00214     return mdns_service_entry->service_desc;
00215 }
00216 
00217 void ns_mdns_service_unregister(ns_mdns_service_t service_desc)
00218 {
00219     ns_mdns_service_entry_t *service_entry;
00220     ns_mdns_server_entry_t *server_entry;
00221 
00222     // find service from a server
00223     service_entry = ns_mdns_service_entry_find(service_desc);
00224     // find server that holds current server
00225     server_entry = ns_mdns_server_entry_find_by_service(service_entry);
00226     if (service_entry && server_entry) {
00227         fnet_mdns_service_unregister(service_desc);
00228         ns_mdns_service_entry_free(server_entry, service_entry);
00229     }
00230 }
00231 
00232 void ns_mdns_announcement_send(ns_mdns_t ns_mdns)
00233 {
00234     FNET_DEBUG("ns_mdns_announcement_send()");
00235     if (ns_mdns_server_entry_find(ns_mdns)) {
00236         fnet_mdns_announce((fnet_mdns_desc_t)ns_mdns);
00237     }
00238 }