Nicolas Borla / Mbed OS BBR_1Ebene
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, 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/address.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     }
00076 
00077     FNET_DEBUG("fnet_netif_get_ip6_addr(), if=%d: %s", (int8_t)netif->scope_id, trace_ipv6(addr_info->address.addr));
00078 
00079     return result;
00080 }
00081 
00082 fnet_bool_t fnet_netif_is_my_ip6_addr(fnet_netif_t *netif, const fnet_ip6_addr_t *ip_addr)
00083 {
00084     int i = 0;
00085     uint8_t address_buffer[16];
00086     int8_t interface_id = (int8_t)netif->scope_id;
00087     int8_t addr_available = 0;
00088 
00089     do {
00090         addr_available = arm_net_address_list_get_next(interface_id, &i, address_buffer);
00091         if (addr_available < 0) {
00092             return FNET_FALSE;
00093         }
00094         if (addr_ipv6_equal(address_buffer, ip_addr->addr)) {
00095             return FNET_TRUE;
00096         }
00097     } while (addr_available);
00098 
00099     return FNET_FALSE;
00100 }
00101 
00102 static void fnet_nanostack_port_ns_socket_recv(void *socket_cb)
00103 {
00104     (void)socket_cb;
00105     // socket event received, run service again to achieve faster response time
00106     ns_fnet_events_fast_poll();
00107 }
00108 
00109 fnet_socket_t fnet_socket(fnet_address_family_t family, fnet_socket_type_t type, fnet_uint32_t protocol)
00110 {
00111     int8_t socket_id = 0;
00112     (void)protocol;
00113 
00114     if (type != SOCK_DGRAM || family != AF_INET6) {
00115         return FNET_NULL;
00116     }
00117 
00118     socket_id = socket_open(SOCKET_UDP, 0, fnet_nanostack_port_ns_socket_recv);
00119     if (socket_id < 0) {
00120         return FNET_NULL;
00121     }
00122 
00123     // Socket contains buffer for the received data, enable the feature using socket options
00124     static const int32_t rcvbuf_size = 1024*4;
00125     socket_setsockopt(socket_id, SOCKET_SOL_SOCKET, SOCKET_SO_RCVBUF, &rcvbuf_size, sizeof rcvbuf_size);
00126 
00127     FNET_DEBUG("fnet_socket_open, socket:%d", socket_id);
00128     return (fnet_socket_t)(long)socket_id;
00129 }
00130 
00131 fnet_return_t fnet_socket_bind( fnet_socket_t s, const struct sockaddr *name, fnet_size_t namelen )
00132 {
00133     (void)namelen;
00134     ns_address_t ns_source_addr = {0};
00135     int8_t socket_id = (int8_t)(long)s;
00136     fnet_return_t fnet_ret_val = FNET_ERR;
00137     const struct sockaddr_in6 *namein6 = (const struct sockaddr_in6 *) name;
00138     memcpy(ns_source_addr.address, &namein6->sin6_addr, 16);
00139     ns_source_addr.identifier = FNET_NTOHS(namein6->sin6_port);
00140     ns_source_addr.type = ADDRESS_IPV6;
00141 
00142     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));
00143 
00144     int8_t status = socket_bind(socket_id, &ns_source_addr);
00145     if (status == 0) {
00146         fnet_ret_val = FNET_OK;
00147     }
00148 
00149     return fnet_ret_val;
00150 }
00151 
00152 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 )
00153 {
00154     (void) level;
00155     (void) optvallen;
00156     int8_t socket_id;
00157     int8_t ret_val = -1;
00158 
00159     socket_id = (int8_t)(long)s;
00160 
00161     if (optname == IPV6_JOIN_GROUP) {
00162         const struct ipv6_mreq *mreq6 = optval; /* Multicast group information.*/
00163 
00164         int8_t interface_id = (int8_t)mreq6->ipv6imr_interface; // scope_id holds interface_id
00165         ret_val = socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, SOCKET_INTERFACE_SELECT, &interface_id, sizeof(interface_id));
00166 
00167         if (ret_val == 0) {
00168             ns_ipv6_mreq_t ns_ipv6_mreq;
00169             ns_ipv6_mreq.ipv6mr_interface = interface_id;
00170             memcpy(ns_ipv6_mreq.ipv6mr_multiaddr, ADDR_LINK_LOCAL_MDNS, 16);
00171             // Join multicast group
00172             ret_val = socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_JOIN_GROUP, &ns_ipv6_mreq, sizeof(ns_ipv6_mreq));
00173         }
00174 
00175         if (ret_val == 0) {
00176             bool loopback = false;
00177             // Ignore loopback from own multicasts
00178             ret_val = socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_MULTICAST_LOOP, &loopback, sizeof(loopback));
00179         }
00180     }
00181     else if (optname == IPV6_MULTICAST_HOPS) {
00182         // Both FNET and Nanostack use int16_t, so can pass straight through
00183         ret_val = socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_MULTICAST_HOPS, optval, optvallen);
00184     }
00185 
00186     if (ret_val == 0) {
00187         return FNET_OK;
00188     }
00189 
00190     return FNET_ERR;
00191 }
00192 
00193 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 )
00194 {
00195     (void)tolen; // ipv6 address expected
00196     (void)flags; //
00197     int8_t socket_id = (int8_t)(long)s;
00198     ns_address_t ns_address;
00199 
00200     ns_address.type = ADDRESS_IPV6;
00201     memcpy(ns_address.address, &((struct sockaddr_in6 *)to)->sin6_addr.s6_addr, 16);
00202     // Note! Port is already in network byte order, transfer it back as nanostack will convert it again to network byte order
00203     ns_address.identifier = FNET_NTOHS(to->sa_port);
00204     FNET_DEBUG("fnet_socket_sendto, %d bytes, port:%d, socket:%d", (int)len, (int)ns_address.identifier, socket_id);
00205     return (fnet_int32_t)socket_sendto(socket_id, &ns_address, buf, len);
00206 }
00207 
00208 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 )
00209 {
00210     (void)flags; // mdns does not use flags
00211     (void)fromlen;  // address is ipv6
00212     int8_t socket_id = (int8_t)(long)s;
00213     int16_t data_len;
00214     ns_address_t source_address;
00215     data_len = socket_read(socket_id, &source_address, buf, len);
00216 
00217     if (data_len >= 0) {
00218         if (from) {
00219             struct sockaddr_in6 *fromin6 = (struct sockaddr_in6 *) from;
00220             memcpy(&fromin6->sin6_addr.s6_addr, source_address.address, 16);
00221             //addrin6.sin6_scope_id = interface_id; where to get interface_id here?
00222             fromin6->sin6_family = AF_INET6;
00223             // port is in native byte order,, convert to network byte order
00224             fromin6->sin6_port = FNET_HTONS(source_address.identifier);
00225             *fromlen = sizeof(struct sockaddr_in6);
00226         }
00227     } else {
00228         tr_error("Socket recv failed: socket:%d, err:%d", socket_id, data_len);
00229         data_len = (int16_t) FNET_ERR;
00230     }
00231 
00232     return data_len;
00233 }
00234 
00235 fnet_return_t fnet_socket_close( fnet_socket_t s )
00236 {
00237     int8_t socket_id = (int8_t)(long)s;
00238 
00239     FNET_DEBUG("fnet_socket_close, socket:%d", socket_id);
00240 
00241     socket_close(socket_id);
00242 
00243     return FNET_OK;
00244 }