Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ns_fnet_port.c Source File

ns_fnet_port.c

00001 /*
00002  * Copyright (c) 2017-2019, 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 /**
00019  * FNET porting to Nanostack environment
00020  */
00021 
00022 #include "fnet.h"
00023 #include "fnet_netif.h"
00024 #include "fnet_netif_prv.h"
00025 #include "fnet_timer.h"
00026 #include "fnet_serial.h"
00027 #include "fnet_socket.h"
00028 
00029 #include "ns_types.h"
00030 #include "ns_list.h"
00031 #include "common_functions.h" // common_write
00032 #include "ns_trace.h"
00033 #include "socket_api.h"
00034 #include "net_interface.h"
00035 #include "nsdynmemLIB.h"
00036 #include "Core/include/ns_address_internal.h"
00037 
00038 #include "ns_fnet_events.h"
00039 
00040 #define TRACE_GROUP "mDNS"
00041 
00042 
00043 fnet_time_t fnet_timer_get_ms(void)
00044 {
00045     return ns_fnet_time_in_ms_get();
00046 }
00047 
00048 fnet_scope_id_t fnet_netif_get_scope_id(fnet_netif_desc_t netif_desc)
00049 {
00050     fnet_netif_t *netif = (fnet_netif_t *)netif_desc;
00051     FNET_DEBUG("fnet_netif_get_scope_id() scope_id=%d", (int)netif->scope_id);
00052     return netif->scope_id;
00053 }
00054 
00055 fnet_ip4_addr_t fnet_netif_get_ip4_addr(fnet_netif_desc_t netif_desc)
00056 {
00057     (void)netif_desc;
00058     return 0u;
00059 }
00060 
00061 fnet_bool_t fnet_netif_get_ip6_addr(fnet_netif_desc_t netif_desc, fnet_index_t n, fnet_netif_ip6_addr_info_t *addr_info)
00062 {
00063     fnet_bool_t     result = FNET_FALSE;
00064     fnet_netif_t    *netif = (fnet_netif_t *)netif_desc;
00065     uint8_t         global_address[16] = {0};
00066     (void)n;
00067 
00068     if (netif && addr_info) {
00069         if (0 == arm_net_address_get((int8_t)netif->scope_id, ADDR_IPV6_GP, global_address)) {
00070             memcpy(&addr_info->address.addr, global_address, 16);   /* IPv6 address.*/
00071             addr_info->state = FNET_NETIF_IP6_ADDR_STATE_PREFERRED;     /* Address current state.*/
00072             addr_info->type = FNET_NETIF_IP_ADDR_TYPE_AUTOCONFIGURABLE; /* How the address was acquired.*/
00073             result = FNET_TRUE;
00074         }
00075         FNET_DEBUG("fnet_netif_get_ip6_addr(), if=%d: %s", (int8_t)netif->scope_id, trace_ipv6(addr_info->address.addr));
00076     }
00077 
00078     return result;
00079 }
00080 
00081 fnet_bool_t fnet_netif_is_my_ip6_addr(fnet_netif_t *netif, const fnet_ip6_addr_t *ip_addr)
00082 {
00083     int i = 0;
00084     uint8_t address_buffer[16];
00085     int8_t interface_id = (int8_t)netif->scope_id;
00086     int8_t addr_available = 0;
00087 
00088     do {
00089         addr_available = arm_net_address_list_get_next(interface_id, &i, address_buffer);
00090         if (addr_available < 0) {
00091             return FNET_FALSE;
00092         }
00093         if (addr_ipv6_equal(address_buffer, ip_addr->addr)) {
00094             return FNET_TRUE;
00095         }
00096     } while (addr_available);
00097 
00098     return FNET_FALSE;
00099 }
00100 
00101 static void fnet_nanostack_port_ns_socket_recv(void *socket_cb)
00102 {
00103     (void)socket_cb;
00104     // socket event received, run service again to achieve faster response time
00105     ns_fnet_events_fast_poll();
00106 }
00107 
00108 fnet_socket_t fnet_socket(fnet_address_family_t family, fnet_socket_type_t type, fnet_uint32_t protocol)
00109 {
00110     int8_t socket_id = 0;
00111     (void)protocol;
00112 
00113     if (type != SOCK_DGRAM || family != AF_INET6) {
00114         return FNET_NULL;
00115     }
00116 
00117     socket_id = socket_open(SOCKET_UDP, 0, fnet_nanostack_port_ns_socket_recv);
00118     if (socket_id < 0) {
00119         return FNET_NULL;
00120     }
00121 
00122     // Socket contains buffer for the received data, enable the feature using socket options
00123     static const int32_t rcvbuf_size = 1024 * 4;
00124     socket_setsockopt(socket_id, SOCKET_SOL_SOCKET, SOCKET_SO_RCVBUF, &rcvbuf_size, sizeof rcvbuf_size);
00125 
00126     FNET_DEBUG("fnet_socket_open, socket:%d", socket_id);
00127     return (fnet_socket_t)(long)socket_id;
00128 }
00129 
00130 fnet_return_t fnet_socket_bind(fnet_socket_t s, const struct sockaddr *name, fnet_size_t namelen)
00131 {
00132     (void)namelen;
00133     ns_address_t ns_source_addr;
00134     int8_t socket_id = (int8_t)(long)s;
00135     fnet_return_t fnet_ret_val = FNET_ERR;
00136     const struct sockaddr_in6 *namein6 = (const struct sockaddr_in6 *) name;
00137     memcpy(ns_source_addr.address, &namein6->sin6_addr, 16);
00138     ns_source_addr.identifier = FNET_NTOHS(namein6->sin6_port);
00139     ns_source_addr.type = ADDRESS_IPV6;
00140 
00141     FNET_DEBUG("fnet_socket_bind socket:%d to port %d address %s", socket_id, (int)ns_source_addr.identifier, trace_ipv6(ns_source_addr.address));
00142 
00143     int8_t status = socket_bind(socket_id, &ns_source_addr);
00144     if (status == 0) {
00145         fnet_ret_val = FNET_OK;
00146     }
00147 
00148     return fnet_ret_val;
00149 }
00150 
00151 fnet_return_t fnet_socket_setopt(fnet_socket_t s, fnet_protocol_t level, fnet_socket_options_t optname, const void *optval, fnet_size_t optvallen)
00152 {
00153     (void) level;
00154     (void) optvallen;
00155     int8_t socket_id;
00156     int8_t ret_val = -1;
00157 
00158     socket_id = (int8_t)(long)s;
00159 
00160     if (optname == IPV6_JOIN_GROUP) {
00161         const struct ipv6_mreq *mreq6 = optval; /* Multicast group information.*/
00162 
00163         int8_t interface_id = (int8_t)mreq6->ipv6imr_interface; // scope_id holds interface_id
00164         ret_val = socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, SOCKET_INTERFACE_SELECT, &interface_id, sizeof(interface_id));
00165 
00166         if (ret_val == 0) {
00167             ns_ipv6_mreq_t ns_ipv6_mreq;
00168             ns_ipv6_mreq.ipv6mr_interface = interface_id;
00169             memcpy(ns_ipv6_mreq.ipv6mr_multiaddr, ADDR_LINK_LOCAL_MDNS, 16);
00170             // Join multicast group
00171             ret_val = socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_JOIN_GROUP, &ns_ipv6_mreq, sizeof(ns_ipv6_mreq));
00172         }
00173 
00174         if (ret_val == 0) {
00175             bool loopback = false;
00176             // Ignore loopback from own multicasts
00177             ret_val = socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_MULTICAST_LOOP, &loopback, sizeof(loopback));
00178         }
00179     } else if (optname == IPV6_MULTICAST_HOPS) {
00180         // Both FNET and Nanostack use int16_t, so can pass straight through
00181         ret_val = socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_MULTICAST_HOPS, optval, optvallen);
00182     }
00183 
00184     if (ret_val == 0) {
00185         return FNET_OK;
00186     }
00187 
00188     return FNET_ERR;
00189 }
00190 
00191 fnet_int32_t fnet_socket_sendto(fnet_socket_t s, fnet_uint8_t *buf, fnet_size_t len, fnet_flag_t flags, const struct sockaddr *to, fnet_size_t tolen)
00192 {
00193     (void)tolen; // ipv6 address expected
00194     (void)flags; //
00195     int8_t socket_id = (int8_t)(long)s;
00196     ns_address_t ns_address;
00197 
00198     ns_address.type = ADDRESS_IPV6;
00199     memcpy(ns_address.address, &((struct sockaddr_in6 *)to)->sin6_addr.s6_addr, 16);
00200     // Note! Port is already in network byte order, transfer it back as nanostack will convert it again to network byte order
00201     ns_address.identifier = FNET_NTOHS(to->sa_port);
00202     FNET_DEBUG("fnet_socket_sendto, %d bytes, port:%d, socket:%d", (int)len, (int)ns_address.identifier, socket_id);
00203     return (fnet_int32_t)socket_sendto(socket_id, &ns_address, buf, len);
00204 }
00205 
00206 fnet_int32_t fnet_socket_recvfrom(fnet_socket_t s, fnet_uint8_t *buf, fnet_size_t len, fnet_flag_t flags, struct sockaddr *from, fnet_size_t *fromlen)
00207 {
00208     (void)flags; // mdns does not use flags
00209     (void)fromlen;  // address is ipv6
00210     int8_t socket_id = (int8_t)(long)s;
00211     int16_t data_len;
00212     ns_address_t source_address;
00213     data_len = socket_read(socket_id, &source_address, buf, len);
00214 
00215     if (data_len >= 0) {
00216         if (from) {
00217             struct sockaddr_in6 *fromin6 = (struct sockaddr_in6 *) from;
00218             memcpy(&fromin6->sin6_addr.s6_addr, source_address.address, 16);
00219             //addrin6.sin6_scope_id = interface_id; where to get interface_id here?
00220             fromin6->sin6_family = AF_INET6;
00221             // port is in native byte order,, convert to network byte order
00222             fromin6->sin6_port = FNET_HTONS(source_address.identifier);
00223             *fromlen = sizeof(struct sockaddr_in6);
00224         }
00225     } else {
00226         tr_error("Socket recv failed: socket:%d, err:%d", socket_id, data_len);
00227         data_len = (int16_t) FNET_ERR;
00228     }
00229 
00230     return data_len;
00231 }
00232 
00233 fnet_return_t fnet_socket_close(fnet_socket_t s)
00234 {
00235     int8_t socket_id = (int8_t)(long)s;
00236 
00237     FNET_DEBUG("fnet_socket_close, socket:%d", socket_id);
00238 
00239     socket_close(socket_id);
00240 
00241     return FNET_OK;
00242 }