mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 31 06:02:27 2019 +0000
Revision:
1:9db0e321a9f4
Parent:
0:5b88d5760320
updated based on mbed-os5.15.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /* LWIP implementation of NSAPI NetworkStack
kenjiArai 0:5b88d5760320 2 * Copyright (c) 2017 ARM Limited
kenjiArai 0:5b88d5760320 3 *
kenjiArai 0:5b88d5760320 4 * Licensed under the Apache License, Version 2.0 (the "License");
kenjiArai 0:5b88d5760320 5 * you may not use this file except in compliance with the License.
kenjiArai 0:5b88d5760320 6 * You may obtain a copy of the License at
kenjiArai 0:5b88d5760320 7 *
kenjiArai 0:5b88d5760320 8 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 0:5b88d5760320 9 *
kenjiArai 0:5b88d5760320 10 * Unless required by applicable law or agreed to in writing, software
kenjiArai 0:5b88d5760320 11 * distributed under the License is distributed on an "AS IS" BASIS,
kenjiArai 0:5b88d5760320 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 0:5b88d5760320 13 * See the License for the specific language governing permissions and
kenjiArai 0:5b88d5760320 14 * limitations under the License.
kenjiArai 0:5b88d5760320 15 */
kenjiArai 0:5b88d5760320 16 #include "nsapi.h"
kenjiArai 0:5b88d5760320 17 #include "mbed_interface.h"
kenjiArai 0:5b88d5760320 18 #include "mbed_assert.h"
kenjiArai 0:5b88d5760320 19 #include "Semaphore.h"
kenjiArai 0:5b88d5760320 20 #include <stdio.h>
kenjiArai 0:5b88d5760320 21 #include <stdbool.h>
kenjiArai 0:5b88d5760320 22 #include <string.h>
kenjiArai 0:5b88d5760320 23
kenjiArai 0:5b88d5760320 24 #include "lwip/opt.h"
kenjiArai 0:5b88d5760320 25 #include "lwip/api.h"
kenjiArai 0:5b88d5760320 26 #include "lwip/inet.h"
kenjiArai 0:5b88d5760320 27 #include "lwip/netif.h"
kenjiArai 0:5b88d5760320 28 #include "lwip/dhcp.h"
kenjiArai 0:5b88d5760320 29 #include "lwip/tcpip.h"
kenjiArai 0:5b88d5760320 30 #include "lwip/tcp.h"
kenjiArai 0:5b88d5760320 31 #include "lwip/ip.h"
kenjiArai 0:5b88d5760320 32 #include "lwip/mld6.h"
kenjiArai 0:5b88d5760320 33 #include "lwip/igmp.h"
kenjiArai 0:5b88d5760320 34 #include "lwip/dns.h"
kenjiArai 0:5b88d5760320 35 #include "lwip/udp.h"
kenjiArai 0:5b88d5760320 36 #include "lwip/raw.h"
kenjiArai 0:5b88d5760320 37 #include "lwip/netif.h"
kenjiArai 0:5b88d5760320 38 #include "lwip/lwip_errno.h"
kenjiArai 0:5b88d5760320 39 #include "lwip-sys/arch/sys_arch.h"
kenjiArai 0:5b88d5760320 40
kenjiArai 0:5b88d5760320 41 #include "LWIPStack.h"
kenjiArai 1:9db0e321a9f4 42 #include "lwip_tools.h"
kenjiArai 0:5b88d5760320 43
kenjiArai 0:5b88d5760320 44 #ifndef LWIP_SOCKET_MAX_MEMBERSHIPS
kenjiArai 0:5b88d5760320 45 #define LWIP_SOCKET_MAX_MEMBERSHIPS 4
kenjiArai 0:5b88d5760320 46 #endif
kenjiArai 0:5b88d5760320 47
kenjiArai 0:5b88d5760320 48 void LWIP::socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len)
kenjiArai 0:5b88d5760320 49 {
kenjiArai 0:5b88d5760320 50 // Filter send minus events
kenjiArai 0:5b88d5760320 51 if (eh == NETCONN_EVT_SENDMINUS && nc->state == NETCONN_WRITE) {
kenjiArai 0:5b88d5760320 52 return;
kenjiArai 0:5b88d5760320 53 }
kenjiArai 0:5b88d5760320 54
kenjiArai 0:5b88d5760320 55 LWIP &lwip = LWIP::get_instance();
kenjiArai 0:5b88d5760320 56 lwip.adaptation.lock();
kenjiArai 0:5b88d5760320 57
kenjiArai 0:5b88d5760320 58 if (eh == NETCONN_EVT_RCVPLUS && nc->state == NETCONN_NONE) {
kenjiArai 0:5b88d5760320 59 lwip._event_flag.set(TCP_CLOSED_FLAG);
kenjiArai 0:5b88d5760320 60 }
kenjiArai 0:5b88d5760320 61
kenjiArai 0:5b88d5760320 62 for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
kenjiArai 0:5b88d5760320 63 if (lwip.arena[i].in_use
kenjiArai 0:5b88d5760320 64 && lwip.arena[i].conn == nc
kenjiArai 0:5b88d5760320 65 && lwip.arena[i].cb) {
kenjiArai 0:5b88d5760320 66 lwip.arena[i].cb(lwip.arena[i].data);
kenjiArai 0:5b88d5760320 67 }
kenjiArai 0:5b88d5760320 68 }
kenjiArai 0:5b88d5760320 69
kenjiArai 0:5b88d5760320 70 lwip.adaptation.unlock();
kenjiArai 0:5b88d5760320 71 }
kenjiArai 0:5b88d5760320 72
kenjiArai 0:5b88d5760320 73 void LWIP::tcpip_init_irq(void *eh)
kenjiArai 0:5b88d5760320 74 {
kenjiArai 0:5b88d5760320 75 static_cast<rtos::Semaphore *>(eh)->release();
kenjiArai 0:5b88d5760320 76 sys_tcpip_thread_set();
kenjiArai 0:5b88d5760320 77 }
kenjiArai 0:5b88d5760320 78
kenjiArai 0:5b88d5760320 79 /* LWIP network stack implementation */
kenjiArai 0:5b88d5760320 80 LWIP::LWIP()
kenjiArai 0:5b88d5760320 81 {
kenjiArai 0:5b88d5760320 82 default_interface = NULL;
kenjiArai 1:9db0e321a9f4 83 tcpip_thread_id = NULL;
kenjiArai 0:5b88d5760320 84
kenjiArai 0:5b88d5760320 85 // Seed lwip random
kenjiArai 0:5b88d5760320 86 lwip_seed_random();
kenjiArai 0:5b88d5760320 87
kenjiArai 0:5b88d5760320 88 // Initialise TCP sequence number
kenjiArai 0:5b88d5760320 89 uint32_t tcp_isn_secret[4];
kenjiArai 0:5b88d5760320 90 for (int i = 0; i < 4; i++) {
kenjiArai 0:5b88d5760320 91 tcp_isn_secret[i] = LWIP_RAND();
kenjiArai 0:5b88d5760320 92 }
kenjiArai 0:5b88d5760320 93 lwip_init_tcp_isn(0, (u8_t *) &tcp_isn_secret);
kenjiArai 0:5b88d5760320 94
kenjiArai 0:5b88d5760320 95 rtos::Semaphore tcpip_inited;
kenjiArai 0:5b88d5760320 96
kenjiArai 0:5b88d5760320 97 tcpip_init(&LWIP::tcpip_init_irq, &tcpip_inited);
kenjiArai 0:5b88d5760320 98 tcpip_inited.acquire();
kenjiArai 0:5b88d5760320 99
kenjiArai 0:5b88d5760320 100 // Zero out socket set
kenjiArai 0:5b88d5760320 101 arena_init();
kenjiArai 0:5b88d5760320 102 }
kenjiArai 0:5b88d5760320 103
kenjiArai 0:5b88d5760320 104 nsapi_error_t LWIP::get_dns_server(int index, SocketAddress *address, const char *interface_name)
kenjiArai 0:5b88d5760320 105 {
kenjiArai 0:5b88d5760320 106 int dns_entries = 0;
kenjiArai 0:5b88d5760320 107
kenjiArai 0:5b88d5760320 108 for (int i = 0; i < DNS_MAX_SERVERS; i++) {
kenjiArai 0:5b88d5760320 109 const ip_addr_t *ip_addr = dns_getserver(i, interface_name);
kenjiArai 0:5b88d5760320 110 if (!ip_addr_isany(ip_addr)) {
kenjiArai 0:5b88d5760320 111 if (index == dns_entries) {
kenjiArai 0:5b88d5760320 112 nsapi_addr_t addr;
kenjiArai 0:5b88d5760320 113 convert_lwip_addr_to_mbed(&addr, ip_addr);
kenjiArai 0:5b88d5760320 114 address->set_addr(addr);
kenjiArai 0:5b88d5760320 115 return NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 116 }
kenjiArai 0:5b88d5760320 117 dns_entries++;
kenjiArai 0:5b88d5760320 118 }
kenjiArai 0:5b88d5760320 119 }
kenjiArai 0:5b88d5760320 120 return NSAPI_ERROR_NO_ADDRESS;
kenjiArai 0:5b88d5760320 121 }
kenjiArai 0:5b88d5760320 122
kenjiArai 0:5b88d5760320 123 nsapi_error_t LWIP::add_dns_server(const SocketAddress &address, const char *interface_name)
kenjiArai 0:5b88d5760320 124 {
kenjiArai 0:5b88d5760320 125 int index;
kenjiArai 0:5b88d5760320 126 nsapi_addr_t addr = address.get_addr();
kenjiArai 0:5b88d5760320 127 const ip_addr_t *ip_addr_move;
kenjiArai 0:5b88d5760320 128 ip_addr_t ip_addr;
kenjiArai 0:5b88d5760320 129
kenjiArai 1:9db0e321a9f4 130 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
kenjiArai 1:9db0e321a9f4 131 return NSAPI_ERROR_PARAMETER;
kenjiArai 1:9db0e321a9f4 132 }
kenjiArai 0:5b88d5760320 133
kenjiArai 0:5b88d5760320 134 if (ip_addr_isany(&ip_addr)) {
kenjiArai 0:5b88d5760320 135 return NSAPI_ERROR_NO_ADDRESS;
kenjiArai 0:5b88d5760320 136 }
kenjiArai 0:5b88d5760320 137
kenjiArai 0:5b88d5760320 138 if (interface_name == NULL) {
kenjiArai 0:5b88d5760320 139 for (index = DNS_MAX_SERVERS - 1; index > 0; index--) {
kenjiArai 0:5b88d5760320 140 ip_addr_move = dns_getserver(index - 1, NULL);
kenjiArai 0:5b88d5760320 141 if (!ip_addr_isany(ip_addr_move)) {
kenjiArai 0:5b88d5760320 142 dns_setserver(index, ip_addr_move, NULL);
kenjiArai 0:5b88d5760320 143 }
kenjiArai 0:5b88d5760320 144 }
kenjiArai 0:5b88d5760320 145 dns_setserver(0, &ip_addr, NULL);
kenjiArai 0:5b88d5760320 146 } else {
kenjiArai 0:5b88d5760320 147 for (index = DNS_MAX_SERVERS - 1; index > 0; index--) {
kenjiArai 0:5b88d5760320 148 ip_addr_move = dns_get_interface_server(index - 1, interface_name);
kenjiArai 0:5b88d5760320 149 if (!ip_addr_isany(ip_addr_move)) {
kenjiArai 0:5b88d5760320 150 dns_add_interface_server(index, interface_name, ip_addr_move);
kenjiArai 0:5b88d5760320 151 }
kenjiArai 0:5b88d5760320 152 }
kenjiArai 0:5b88d5760320 153 dns_add_interface_server(0, interface_name, &ip_addr);
kenjiArai 0:5b88d5760320 154 }
kenjiArai 0:5b88d5760320 155 return NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 156 }
kenjiArai 0:5b88d5760320 157
kenjiArai 0:5b88d5760320 158 void LWIP::tcpip_thread_callback(void *ptr)
kenjiArai 0:5b88d5760320 159 {
kenjiArai 0:5b88d5760320 160 lwip_callback *cb = static_cast<lwip_callback *>(ptr);
kenjiArai 0:5b88d5760320 161
kenjiArai 0:5b88d5760320 162 if (cb->delay) {
kenjiArai 0:5b88d5760320 163 sys_timeout(cb->delay, LWIP::tcpip_thread_callback, ptr);
kenjiArai 0:5b88d5760320 164 cb->delay = 0;
kenjiArai 0:5b88d5760320 165 } else {
kenjiArai 0:5b88d5760320 166 cb->callback();
kenjiArai 0:5b88d5760320 167 delete cb;
kenjiArai 0:5b88d5760320 168 }
kenjiArai 0:5b88d5760320 169 }
kenjiArai 0:5b88d5760320 170
kenjiArai 0:5b88d5760320 171 nsapi_error_t LWIP::call_in(int delay, mbed::Callback<void()> func)
kenjiArai 0:5b88d5760320 172 {
kenjiArai 0:5b88d5760320 173 lwip_callback *cb = new (std::nothrow) lwip_callback;
kenjiArai 0:5b88d5760320 174 if (!cb) {
kenjiArai 0:5b88d5760320 175 return NSAPI_ERROR_NO_MEMORY;
kenjiArai 0:5b88d5760320 176 }
kenjiArai 0:5b88d5760320 177
kenjiArai 0:5b88d5760320 178 cb->delay = delay;
kenjiArai 0:5b88d5760320 179 cb->callback = func;
kenjiArai 0:5b88d5760320 180
kenjiArai 0:5b88d5760320 181 if (tcpip_callback_with_block(LWIP::tcpip_thread_callback, cb, 1) != ERR_OK) {
kenjiArai 0:5b88d5760320 182 return NSAPI_ERROR_NO_MEMORY;
kenjiArai 0:5b88d5760320 183 }
kenjiArai 0:5b88d5760320 184
kenjiArai 0:5b88d5760320 185 return NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 186 }
kenjiArai 0:5b88d5760320 187
kenjiArai 0:5b88d5760320 188 LWIP::call_in_callback_cb_t LWIP::get_call_in_callback()
kenjiArai 0:5b88d5760320 189 {
kenjiArai 0:5b88d5760320 190 call_in_callback_cb_t cb(this, &LWIP::call_in);
kenjiArai 0:5b88d5760320 191 return cb;
kenjiArai 0:5b88d5760320 192 }
kenjiArai 0:5b88d5760320 193
kenjiArai 0:5b88d5760320 194 const char *LWIP::get_ip_address()
kenjiArai 0:5b88d5760320 195 {
kenjiArai 0:5b88d5760320 196 if (!default_interface) {
kenjiArai 0:5b88d5760320 197 return NULL;
kenjiArai 0:5b88d5760320 198 }
kenjiArai 0:5b88d5760320 199
kenjiArai 0:5b88d5760320 200 const ip_addr_t *addr = get_ip_addr(true, &default_interface->netif);
kenjiArai 0:5b88d5760320 201
kenjiArai 0:5b88d5760320 202 if (!addr) {
kenjiArai 0:5b88d5760320 203 return NULL;
kenjiArai 0:5b88d5760320 204 }
kenjiArai 0:5b88d5760320 205 #if LWIP_IPV6
kenjiArai 0:5b88d5760320 206 if (IP_IS_V6(addr)) {
kenjiArai 0:5b88d5760320 207 return ip6addr_ntoa_r(ip_2_ip6(addr), ip_address, sizeof(ip_address));
kenjiArai 0:5b88d5760320 208 }
kenjiArai 0:5b88d5760320 209 #endif
kenjiArai 0:5b88d5760320 210 #if LWIP_IPV4
kenjiArai 0:5b88d5760320 211 if (IP_IS_V4(addr)) {
kenjiArai 0:5b88d5760320 212 return ip4addr_ntoa_r(ip_2_ip4(addr), ip_address, sizeof(ip_address));
kenjiArai 0:5b88d5760320 213 }
kenjiArai 0:5b88d5760320 214 #endif
kenjiArai 0:5b88d5760320 215 #if LWIP_IPV6 && LWIP_IPV4
kenjiArai 0:5b88d5760320 216 return NULL;
kenjiArai 0:5b88d5760320 217 #endif
kenjiArai 0:5b88d5760320 218 }
kenjiArai 0:5b88d5760320 219
kenjiArai 1:9db0e321a9f4 220 nsapi_error_t LWIP::get_ip_address_if(SocketAddress *address, const char *interface_name)
kenjiArai 1:9db0e321a9f4 221 {
kenjiArai 1:9db0e321a9f4 222 if (!address) {
kenjiArai 1:9db0e321a9f4 223 return NSAPI_ERROR_PARAMETER;
kenjiArai 1:9db0e321a9f4 224 }
kenjiArai 1:9db0e321a9f4 225
kenjiArai 1:9db0e321a9f4 226 const ip_addr_t *addr;
kenjiArai 1:9db0e321a9f4 227
kenjiArai 1:9db0e321a9f4 228 if (interface_name == NULL) {
kenjiArai 1:9db0e321a9f4 229 addr = get_ip_addr(true, &default_interface->netif);
kenjiArai 1:9db0e321a9f4 230 } else {
kenjiArai 1:9db0e321a9f4 231 addr = get_ip_addr(true, netif_find(interface_name));
kenjiArai 1:9db0e321a9f4 232 }
kenjiArai 1:9db0e321a9f4 233 #if LWIP_IPV6
kenjiArai 1:9db0e321a9f4 234 if (IP_IS_V6(addr)) {
kenjiArai 1:9db0e321a9f4 235 char buf[NSAPI_IPv6_SIZE];
kenjiArai 1:9db0e321a9f4 236 address->set_ip_address(ip6addr_ntoa_r(ip_2_ip6(addr), buf, NSAPI_IPv6_SIZE));
kenjiArai 1:9db0e321a9f4 237 return NSAPI_ERROR_OK;
kenjiArai 1:9db0e321a9f4 238 }
kenjiArai 1:9db0e321a9f4 239 #endif
kenjiArai 1:9db0e321a9f4 240 #if LWIP_IPV4
kenjiArai 1:9db0e321a9f4 241 if (IP_IS_V4(addr)) {
kenjiArai 1:9db0e321a9f4 242 char buf[NSAPI_IPv4_SIZE];
kenjiArai 1:9db0e321a9f4 243 address->set_ip_address(ip4addr_ntoa_r(ip_2_ip4(addr), buf, NSAPI_IPv4_SIZE));
kenjiArai 1:9db0e321a9f4 244 return NSAPI_ERROR_OK;
kenjiArai 1:9db0e321a9f4 245 }
kenjiArai 1:9db0e321a9f4 246 #endif
kenjiArai 1:9db0e321a9f4 247 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 1:9db0e321a9f4 248 }
kenjiArai 1:9db0e321a9f4 249
kenjiArai 0:5b88d5760320 250 nsapi_error_t LWIP::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
kenjiArai 0:5b88d5760320 251 {
kenjiArai 0:5b88d5760320 252 // check if network is connected
kenjiArai 0:5b88d5760320 253 // if (lwip_connected == NSAPI_STATUS_DISCONNECTED) {
kenjiArai 0:5b88d5760320 254 // return NSAPI_ERROR_NO_CONNECTION;
kenjiArai 0:5b88d5760320 255 // }
kenjiArai 0:5b88d5760320 256
kenjiArai 0:5b88d5760320 257 // allocate a socket
kenjiArai 0:5b88d5760320 258 struct mbed_lwip_socket *s = arena_alloc();
kenjiArai 0:5b88d5760320 259 if (!s) {
kenjiArai 0:5b88d5760320 260 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 261 }
kenjiArai 0:5b88d5760320 262
kenjiArai 1:9db0e321a9f4 263 enum netconn_type netconntype;
kenjiArai 1:9db0e321a9f4 264 if (proto == NSAPI_TCP) {
kenjiArai 1:9db0e321a9f4 265 netconntype = NETCONN_TCP;
kenjiArai 1:9db0e321a9f4 266 } else if (proto == NSAPI_UDP) {
kenjiArai 1:9db0e321a9f4 267 netconntype = NETCONN_UDP;
kenjiArai 1:9db0e321a9f4 268 } else if (proto == NSAPI_ICMP) {
kenjiArai 1:9db0e321a9f4 269 netconntype = NETCONN_RAW;
kenjiArai 1:9db0e321a9f4 270 } else {
kenjiArai 1:9db0e321a9f4 271 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 1:9db0e321a9f4 272 }
kenjiArai 0:5b88d5760320 273
kenjiArai 0:5b88d5760320 274 #if LWIP_IPV6
kenjiArai 0:5b88d5760320 275 // Enable IPv6 (or dual-stack)
kenjiArai 1:9db0e321a9f4 276 netconntype = (enum netconn_type)(netconntype | NETCONN_TYPE_IPV6);
kenjiArai 0:5b88d5760320 277 #endif
kenjiArai 0:5b88d5760320 278
kenjiArai 1:9db0e321a9f4 279 if (proto == NSAPI_ICMP) {
kenjiArai 1:9db0e321a9f4 280 s->conn = netconn_new_with_proto_and_callback(NETCONN_RAW,
kenjiArai 1:9db0e321a9f4 281 (u8_t)IP_PROTO_ICMP, &LWIP::socket_callback);
kenjiArai 1:9db0e321a9f4 282 } else {
kenjiArai 1:9db0e321a9f4 283 s->conn = netconn_new_with_callback(netconntype, &LWIP::socket_callback);
kenjiArai 1:9db0e321a9f4 284 }
kenjiArai 0:5b88d5760320 285
kenjiArai 0:5b88d5760320 286 if (!s->conn) {
kenjiArai 0:5b88d5760320 287 arena_dealloc(s);
kenjiArai 0:5b88d5760320 288 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 289 }
kenjiArai 0:5b88d5760320 290
kenjiArai 0:5b88d5760320 291 netconn_set_recvtimeout(s->conn, 1);
kenjiArai 0:5b88d5760320 292 *(struct mbed_lwip_socket **)handle = s;
kenjiArai 0:5b88d5760320 293 return 0;
kenjiArai 0:5b88d5760320 294 }
kenjiArai 0:5b88d5760320 295
kenjiArai 0:5b88d5760320 296 nsapi_error_t LWIP::socket_close(nsapi_socket_t handle)
kenjiArai 0:5b88d5760320 297 {
kenjiArai 0:5b88d5760320 298 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
kenjiArai 0:5b88d5760320 299 #if LWIP_TCP
kenjiArai 0:5b88d5760320 300 /* Check if TCP FSM is in ESTABLISHED state.
kenjiArai 0:5b88d5760320 301 * Then give extra time for connection close handshaking until TIME_WAIT state.
kenjiArai 0:5b88d5760320 302 * The purpose is to prevent eth/wifi driver stop and FIN ACK corrupt.
kenjiArai 0:5b88d5760320 303 * This may happend if network interface disconnect follows immediately after socket_close.*/
kenjiArai 0:5b88d5760320 304 if (NETCONNTYPE_GROUP(s->conn->type) == NETCONN_TCP && s->conn->pcb.tcp->state == ESTABLISHED) {
kenjiArai 0:5b88d5760320 305 _event_flag.clear(TCP_CLOSED_FLAG);
kenjiArai 0:5b88d5760320 306 netconn_shutdown(s->conn, false, true);
kenjiArai 0:5b88d5760320 307 _event_flag.wait_any(TCP_CLOSED_FLAG, TCP_CLOSE_TIMEOUT);
kenjiArai 0:5b88d5760320 308 }
kenjiArai 0:5b88d5760320 309 #endif
kenjiArai 0:5b88d5760320 310 pbuf_free(s->buf);
kenjiArai 0:5b88d5760320 311 err_t err = netconn_delete(s->conn);
kenjiArai 0:5b88d5760320 312 arena_dealloc(s);
kenjiArai 0:5b88d5760320 313 return err_remap(err);
kenjiArai 0:5b88d5760320 314 }
kenjiArai 0:5b88d5760320 315
kenjiArai 0:5b88d5760320 316 nsapi_error_t LWIP::socket_bind(nsapi_socket_t handle, const SocketAddress &address)
kenjiArai 0:5b88d5760320 317 {
kenjiArai 0:5b88d5760320 318 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
kenjiArai 0:5b88d5760320 319 ip_addr_t ip_addr;
kenjiArai 0:5b88d5760320 320
kenjiArai 0:5b88d5760320 321 if (
kenjiArai 0:5b88d5760320 322 #if LWIP_TCP
kenjiArai 0:5b88d5760320 323 (NETCONNTYPE_GROUP(s->conn->type) == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) ||
kenjiArai 0:5b88d5760320 324 #endif
kenjiArai 0:5b88d5760320 325 (NETCONNTYPE_GROUP(s->conn->type) == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) {
kenjiArai 0:5b88d5760320 326 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 327 }
kenjiArai 0:5b88d5760320 328
kenjiArai 0:5b88d5760320 329 nsapi_addr_t addr = address.get_addr();
kenjiArai 0:5b88d5760320 330 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
kenjiArai 0:5b88d5760320 331 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 332 }
kenjiArai 0:5b88d5760320 333
kenjiArai 0:5b88d5760320 334 if (!ip_addr_isany_val(ip_addr) && !is_local_addr(&ip_addr)) {
kenjiArai 0:5b88d5760320 335 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 336 }
kenjiArai 0:5b88d5760320 337
kenjiArai 0:5b88d5760320 338 err_t err = netconn_bind(s->conn, &ip_addr, address.get_port());
kenjiArai 0:5b88d5760320 339 return err_remap(err);
kenjiArai 0:5b88d5760320 340 }
kenjiArai 0:5b88d5760320 341
kenjiArai 0:5b88d5760320 342 nsapi_error_t LWIP::socket_listen(nsapi_socket_t handle, int backlog)
kenjiArai 0:5b88d5760320 343 {
kenjiArai 0:5b88d5760320 344 #if LWIP_TCP
kenjiArai 0:5b88d5760320 345 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
kenjiArai 0:5b88d5760320 346
kenjiArai 0:5b88d5760320 347 if (s->conn->pcb.tcp->local_port == 0) {
kenjiArai 0:5b88d5760320 348 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 349 }
kenjiArai 0:5b88d5760320 350
kenjiArai 0:5b88d5760320 351 err_t err = netconn_listen_with_backlog(s->conn, backlog);
kenjiArai 0:5b88d5760320 352 return err_remap(err);
kenjiArai 0:5b88d5760320 353 #else
kenjiArai 0:5b88d5760320 354 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 355 #endif
kenjiArai 0:5b88d5760320 356 }
kenjiArai 0:5b88d5760320 357
kenjiArai 0:5b88d5760320 358 nsapi_error_t LWIP::socket_connect(nsapi_socket_t handle, const SocketAddress &address)
kenjiArai 0:5b88d5760320 359 {
kenjiArai 0:5b88d5760320 360 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
kenjiArai 0:5b88d5760320 361 ip_addr_t ip_addr;
kenjiArai 0:5b88d5760320 362
kenjiArai 0:5b88d5760320 363 nsapi_addr_t addr = address.get_addr();
kenjiArai 0:5b88d5760320 364 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
kenjiArai 0:5b88d5760320 365 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 366 }
kenjiArai 0:5b88d5760320 367
kenjiArai 0:5b88d5760320 368 netconn_set_nonblocking(s->conn, false);
kenjiArai 0:5b88d5760320 369 err_t err = netconn_connect(s->conn, &ip_addr, address.get_port());
kenjiArai 0:5b88d5760320 370 netconn_set_nonblocking(s->conn, true);
kenjiArai 0:5b88d5760320 371
kenjiArai 0:5b88d5760320 372 return err_remap(err);
kenjiArai 0:5b88d5760320 373 }
kenjiArai 0:5b88d5760320 374
kenjiArai 0:5b88d5760320 375 nsapi_error_t LWIP::socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address)
kenjiArai 0:5b88d5760320 376 {
kenjiArai 0:5b88d5760320 377 #if LWIP_TCP
kenjiArai 0:5b88d5760320 378 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)server;
kenjiArai 0:5b88d5760320 379 struct mbed_lwip_socket *ns = arena_alloc();
kenjiArai 0:5b88d5760320 380 if (!ns) {
kenjiArai 0:5b88d5760320 381 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 382 }
kenjiArai 0:5b88d5760320 383
kenjiArai 0:5b88d5760320 384 if (s->conn->pcb.tcp->state != LISTEN) {
kenjiArai 0:5b88d5760320 385 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 386 }
kenjiArai 0:5b88d5760320 387
kenjiArai 0:5b88d5760320 388 err_t err = netconn_accept(s->conn, &ns->conn);
kenjiArai 0:5b88d5760320 389 if (err != ERR_OK) {
kenjiArai 0:5b88d5760320 390 arena_dealloc(ns);
kenjiArai 0:5b88d5760320 391 return err_remap(err);
kenjiArai 0:5b88d5760320 392 }
kenjiArai 0:5b88d5760320 393
kenjiArai 0:5b88d5760320 394 netconn_set_recvtimeout(ns->conn, 1);
kenjiArai 0:5b88d5760320 395 *(struct mbed_lwip_socket **)handle = ns;
kenjiArai 0:5b88d5760320 396
kenjiArai 0:5b88d5760320 397 ip_addr_t peer_addr;
kenjiArai 0:5b88d5760320 398 nsapi_addr_t addr;
kenjiArai 0:5b88d5760320 399 u16_t port;
kenjiArai 0:5b88d5760320 400 (void) netconn_peer(ns->conn, &peer_addr, &port);
kenjiArai 0:5b88d5760320 401 convert_lwip_addr_to_mbed(&addr, &peer_addr);
kenjiArai 0:5b88d5760320 402
kenjiArai 0:5b88d5760320 403 if (address) {
kenjiArai 0:5b88d5760320 404 address->set_addr(addr);
kenjiArai 0:5b88d5760320 405 address->set_port(port);
kenjiArai 0:5b88d5760320 406 }
kenjiArai 0:5b88d5760320 407
kenjiArai 0:5b88d5760320 408 netconn_set_nonblocking(ns->conn, true);
kenjiArai 0:5b88d5760320 409
kenjiArai 0:5b88d5760320 410 return 0;
kenjiArai 0:5b88d5760320 411 #else
kenjiArai 0:5b88d5760320 412 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 413 #endif
kenjiArai 0:5b88d5760320 414 }
kenjiArai 0:5b88d5760320 415
kenjiArai 0:5b88d5760320 416 nsapi_size_or_error_t LWIP::socket_send(nsapi_socket_t handle, const void *data, nsapi_size_t size)
kenjiArai 0:5b88d5760320 417 {
kenjiArai 0:5b88d5760320 418 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
kenjiArai 0:5b88d5760320 419 size_t bytes_written = 0;
kenjiArai 0:5b88d5760320 420
kenjiArai 0:5b88d5760320 421 err_t err = netconn_write_partly(s->conn, data, size, NETCONN_COPY, &bytes_written);
kenjiArai 0:5b88d5760320 422 if (err != ERR_OK) {
kenjiArai 0:5b88d5760320 423 return err_remap(err);
kenjiArai 0:5b88d5760320 424 }
kenjiArai 0:5b88d5760320 425
kenjiArai 0:5b88d5760320 426 return (nsapi_size_or_error_t)bytes_written;
kenjiArai 0:5b88d5760320 427 }
kenjiArai 0:5b88d5760320 428
kenjiArai 0:5b88d5760320 429 nsapi_size_or_error_t LWIP::socket_recv(nsapi_socket_t handle, void *data, nsapi_size_t size)
kenjiArai 0:5b88d5760320 430 {
kenjiArai 0:5b88d5760320 431 #if LWIP_TCP
kenjiArai 0:5b88d5760320 432 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
kenjiArai 0:5b88d5760320 433
kenjiArai 0:5b88d5760320 434 if (!s->buf) {
kenjiArai 0:5b88d5760320 435 err_t err = netconn_recv_tcp_pbuf(s->conn, &s->buf);
kenjiArai 0:5b88d5760320 436 s->offset = 0;
kenjiArai 0:5b88d5760320 437
kenjiArai 0:5b88d5760320 438 if (err != ERR_OK) {
kenjiArai 0:5b88d5760320 439 return err_remap(err);
kenjiArai 0:5b88d5760320 440 }
kenjiArai 0:5b88d5760320 441 }
kenjiArai 0:5b88d5760320 442
kenjiArai 0:5b88d5760320 443 u16_t recv = pbuf_copy_partial(s->buf, data, (u16_t)size, s->offset);
kenjiArai 0:5b88d5760320 444 s->offset += recv;
kenjiArai 0:5b88d5760320 445
kenjiArai 0:5b88d5760320 446 if (s->offset >= s->buf->tot_len) {
kenjiArai 0:5b88d5760320 447 pbuf_free(s->buf);
kenjiArai 0:5b88d5760320 448 s->buf = 0;
kenjiArai 0:5b88d5760320 449 }
kenjiArai 0:5b88d5760320 450
kenjiArai 0:5b88d5760320 451 return recv;
kenjiArai 0:5b88d5760320 452 #else
kenjiArai 0:5b88d5760320 453 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 454 #endif
kenjiArai 0:5b88d5760320 455 }
kenjiArai 0:5b88d5760320 456
kenjiArai 0:5b88d5760320 457 nsapi_size_or_error_t LWIP::socket_sendto(nsapi_socket_t handle, const SocketAddress &address, const void *data, nsapi_size_t size)
kenjiArai 0:5b88d5760320 458 {
kenjiArai 0:5b88d5760320 459 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
kenjiArai 0:5b88d5760320 460 ip_addr_t ip_addr;
kenjiArai 0:5b88d5760320 461
kenjiArai 0:5b88d5760320 462 nsapi_addr_t addr = address.get_addr();
kenjiArai 0:5b88d5760320 463 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
kenjiArai 0:5b88d5760320 464 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 465 }
kenjiArai 0:5b88d5760320 466 struct netif *netif_ = netif_get_by_index(s->conn->pcb.ip->netif_idx);
kenjiArai 0:5b88d5760320 467 if (!netif_) {
kenjiArai 0:5b88d5760320 468 netif_ = &default_interface->netif;
kenjiArai 0:5b88d5760320 469 }
kenjiArai 0:5b88d5760320 470 if (netif_) {
kenjiArai 0:5b88d5760320 471 if ((addr.version == NSAPI_IPv4 && !get_ipv4_addr(netif_)) ||
kenjiArai 1:9db0e321a9f4 472 (addr.version == NSAPI_IPv6 && !get_ipv6_addr(netif_) && !get_ipv6_link_local_addr(netif_))) {
kenjiArai 0:5b88d5760320 473 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 474 }
kenjiArai 0:5b88d5760320 475 }
kenjiArai 0:5b88d5760320 476 struct netbuf *buf = netbuf_new();
kenjiArai 0:5b88d5760320 477
kenjiArai 0:5b88d5760320 478 err_t err = netbuf_ref(buf, data, (u16_t)size);
kenjiArai 0:5b88d5760320 479 if (err != ERR_OK) {
kenjiArai 0:5b88d5760320 480 netbuf_free(buf);
kenjiArai 0:5b88d5760320 481 return err_remap(err);
kenjiArai 0:5b88d5760320 482 }
kenjiArai 0:5b88d5760320 483
kenjiArai 0:5b88d5760320 484 err = netconn_sendto(s->conn, buf, &ip_addr, address.get_port());
kenjiArai 0:5b88d5760320 485 netbuf_delete(buf);
kenjiArai 0:5b88d5760320 486 if (err != ERR_OK) {
kenjiArai 0:5b88d5760320 487 return err_remap(err);
kenjiArai 0:5b88d5760320 488 }
kenjiArai 0:5b88d5760320 489
kenjiArai 0:5b88d5760320 490 return size;
kenjiArai 0:5b88d5760320 491 }
kenjiArai 0:5b88d5760320 492
kenjiArai 0:5b88d5760320 493 nsapi_size_or_error_t LWIP::socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size)
kenjiArai 0:5b88d5760320 494 {
kenjiArai 0:5b88d5760320 495 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
kenjiArai 0:5b88d5760320 496 struct netbuf *buf;
kenjiArai 0:5b88d5760320 497
kenjiArai 0:5b88d5760320 498 err_t err = netconn_recv(s->conn, &buf);
kenjiArai 0:5b88d5760320 499 if (err != ERR_OK) {
kenjiArai 0:5b88d5760320 500 return err_remap(err);
kenjiArai 0:5b88d5760320 501 }
kenjiArai 0:5b88d5760320 502
kenjiArai 0:5b88d5760320 503 if (address) {
kenjiArai 0:5b88d5760320 504 nsapi_addr_t addr;
kenjiArai 0:5b88d5760320 505 convert_lwip_addr_to_mbed(&addr, netbuf_fromaddr(buf));
kenjiArai 0:5b88d5760320 506 address->set_addr(addr);
kenjiArai 0:5b88d5760320 507 address->set_port(netbuf_fromport(buf));
kenjiArai 0:5b88d5760320 508 }
kenjiArai 0:5b88d5760320 509
kenjiArai 0:5b88d5760320 510 u16_t recv = netbuf_copy(buf, data, (u16_t)size);
kenjiArai 0:5b88d5760320 511 netbuf_delete(buf);
kenjiArai 0:5b88d5760320 512
kenjiArai 0:5b88d5760320 513 return recv;
kenjiArai 0:5b88d5760320 514 }
kenjiArai 0:5b88d5760320 515
kenjiArai 0:5b88d5760320 516 int32_t LWIP::find_multicast_member(const struct mbed_lwip_socket *s, const nsapi_ip_mreq_t *imr)
kenjiArai 0:5b88d5760320 517 {
kenjiArai 0:5b88d5760320 518 uint32_t count = 0;
kenjiArai 0:5b88d5760320 519 uint32_t index = 0;
kenjiArai 0:5b88d5760320 520 // Set upper limit on while loop, should break out when the membership pair is found
kenjiArai 0:5b88d5760320 521 while (count < s->multicast_memberships_count) {
kenjiArai 0:5b88d5760320 522 index = next_registered_multicast_member(s, index);
kenjiArai 0:5b88d5760320 523
kenjiArai 0:5b88d5760320 524 if (memcmp(&s->multicast_memberships[index].imr_multiaddr, &imr->imr_multiaddr, sizeof(nsapi_addr_t)) == 0 &&
kenjiArai 0:5b88d5760320 525 memcmp(&s->multicast_memberships[index].imr_interface, &imr->imr_interface, sizeof(nsapi_addr_t)) == 0) {
kenjiArai 0:5b88d5760320 526 return index;
kenjiArai 0:5b88d5760320 527 }
kenjiArai 0:5b88d5760320 528 count++;
kenjiArai 0:5b88d5760320 529 index++;
kenjiArai 0:5b88d5760320 530 }
kenjiArai 0:5b88d5760320 531
kenjiArai 0:5b88d5760320 532 return -1;
kenjiArai 0:5b88d5760320 533 }
kenjiArai 0:5b88d5760320 534
kenjiArai 0:5b88d5760320 535 nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen)
kenjiArai 0:5b88d5760320 536 {
kenjiArai 0:5b88d5760320 537 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
kenjiArai 0:5b88d5760320 538
kenjiArai 0:5b88d5760320 539 switch (optname) {
kenjiArai 0:5b88d5760320 540 case NSAPI_BIND_TO_DEVICE:
kenjiArai 0:5b88d5760320 541 if (optlen > NSAPI_INTERFACE_NAME_MAX_SIZE) {
kenjiArai 0:5b88d5760320 542 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 543 }
kenjiArai 0:5b88d5760320 544
kenjiArai 0:5b88d5760320 545 netconn_bind_if(s->conn, netif_name_to_index((const char *)optval));
kenjiArai 0:5b88d5760320 546
kenjiArai 0:5b88d5760320 547 return 0;
kenjiArai 0:5b88d5760320 548 #if LWIP_TCP
kenjiArai 0:5b88d5760320 549 case NSAPI_KEEPALIVE:
kenjiArai 0:5b88d5760320 550 if (optlen != sizeof(int) || NETCONNTYPE_GROUP(s->conn->type) != NETCONN_TCP) {
kenjiArai 0:5b88d5760320 551 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 552 }
kenjiArai 0:5b88d5760320 553
kenjiArai 0:5b88d5760320 554 s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE;
kenjiArai 0:5b88d5760320 555 return 0;
kenjiArai 0:5b88d5760320 556
kenjiArai 0:5b88d5760320 557 case NSAPI_KEEPIDLE:
kenjiArai 0:5b88d5760320 558 if (optlen != sizeof(int) || NETCONNTYPE_GROUP(s->conn->type) != NETCONN_TCP) {
kenjiArai 0:5b88d5760320 559 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 560 }
kenjiArai 0:5b88d5760320 561
kenjiArai 0:5b88d5760320 562 s->conn->pcb.tcp->keep_idle = *(int *)optval;
kenjiArai 0:5b88d5760320 563 return 0;
kenjiArai 0:5b88d5760320 564
kenjiArai 0:5b88d5760320 565 case NSAPI_KEEPINTVL:
kenjiArai 0:5b88d5760320 566 if (optlen != sizeof(int) || NETCONNTYPE_GROUP(s->conn->type) != NETCONN_TCP) {
kenjiArai 0:5b88d5760320 567 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 568 }
kenjiArai 0:5b88d5760320 569
kenjiArai 0:5b88d5760320 570 s->conn->pcb.tcp->keep_intvl = *(int *)optval;
kenjiArai 0:5b88d5760320 571 return 0;
kenjiArai 0:5b88d5760320 572 #endif
kenjiArai 0:5b88d5760320 573
kenjiArai 0:5b88d5760320 574 case NSAPI_REUSEADDR:
kenjiArai 0:5b88d5760320 575 if (optlen != sizeof(int)) {
kenjiArai 0:5b88d5760320 576 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 577 }
kenjiArai 0:5b88d5760320 578
kenjiArai 0:5b88d5760320 579 if (*(int *)optval) {
kenjiArai 0:5b88d5760320 580 ip_set_option(s->conn->pcb.ip, SOF_REUSEADDR);
kenjiArai 0:5b88d5760320 581 } else {
kenjiArai 0:5b88d5760320 582 ip_reset_option(s->conn->pcb.ip, SOF_REUSEADDR);
kenjiArai 0:5b88d5760320 583 }
kenjiArai 0:5b88d5760320 584 return 0;
kenjiArai 0:5b88d5760320 585
kenjiArai 0:5b88d5760320 586 case NSAPI_ADD_MEMBERSHIP:
kenjiArai 0:5b88d5760320 587 case NSAPI_DROP_MEMBERSHIP: {
kenjiArai 0:5b88d5760320 588 if (optlen != sizeof(nsapi_ip_mreq_t)) {
kenjiArai 0:5b88d5760320 589 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 590 }
kenjiArai 0:5b88d5760320 591 err_t igmp_err;
kenjiArai 0:5b88d5760320 592 const nsapi_ip_mreq_t *imr = static_cast<const nsapi_ip_mreq_t *>(optval);
kenjiArai 0:5b88d5760320 593
kenjiArai 0:5b88d5760320 594 /* Check interface address type matches group, or is unspecified */
kenjiArai 0:5b88d5760320 595 if (imr->imr_interface.version != NSAPI_UNSPEC && imr->imr_interface.version != imr->imr_multiaddr.version) {
kenjiArai 0:5b88d5760320 596 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 597 }
kenjiArai 0:5b88d5760320 598
kenjiArai 0:5b88d5760320 599 ip_addr_t if_addr;
kenjiArai 0:5b88d5760320 600 ip_addr_t multi_addr;
kenjiArai 0:5b88d5760320 601
kenjiArai 0:5b88d5760320 602 /* Convert the group address */
kenjiArai 0:5b88d5760320 603 if (!convert_mbed_addr_to_lwip(&multi_addr, &imr->imr_multiaddr)) {
kenjiArai 0:5b88d5760320 604 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 605 }
kenjiArai 0:5b88d5760320 606
kenjiArai 0:5b88d5760320 607 if (imr->imr_interface.version != NSAPI_UNSPEC) {
kenjiArai 1:9db0e321a9f4 608 /* Convert the interface address */
kenjiArai 0:5b88d5760320 609 if (!convert_mbed_addr_to_lwip(&if_addr, &imr->imr_interface)) {
kenjiArai 0:5b88d5760320 610 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 611 }
kenjiArai 0:5b88d5760320 612 } else {
kenjiArai 1:9db0e321a9f4 613 /* Set interface address to "any", matching the group address type */
kenjiArai 1:9db0e321a9f4 614 ip_addr_set_any(IP_IS_V6(&multi_addr), &if_addr);
kenjiArai 0:5b88d5760320 615 }
kenjiArai 0:5b88d5760320 616
kenjiArai 0:5b88d5760320 617 igmp_err = ERR_USE; // Maps to NSAPI_ERROR_UNSUPPORTED
kenjiArai 0:5b88d5760320 618 int32_t member_pair_index = find_multicast_member(s, imr);
kenjiArai 0:5b88d5760320 619
kenjiArai 0:5b88d5760320 620 if (optname == NSAPI_ADD_MEMBERSHIP) {
kenjiArai 0:5b88d5760320 621 if (!s->multicast_memberships) {
kenjiArai 0:5b88d5760320 622 // First multicast join on this socket, allocate space for membership tracking
kenjiArai 0:5b88d5760320 623 s->multicast_memberships = (nsapi_ip_mreq_t *)malloc(sizeof(nsapi_ip_mreq_t) * LWIP_SOCKET_MAX_MEMBERSHIPS);
kenjiArai 0:5b88d5760320 624 if (!s->multicast_memberships) {
kenjiArai 0:5b88d5760320 625 return NSAPI_ERROR_NO_MEMORY;
kenjiArai 0:5b88d5760320 626 }
kenjiArai 0:5b88d5760320 627 } else if (s->multicast_memberships_count == LWIP_SOCKET_MAX_MEMBERSHIPS) {
kenjiArai 0:5b88d5760320 628 return NSAPI_ERROR_NO_MEMORY;
kenjiArai 0:5b88d5760320 629 }
kenjiArai 0:5b88d5760320 630
kenjiArai 0:5b88d5760320 631 if (member_pair_index != -1) {
kenjiArai 0:5b88d5760320 632 return NSAPI_ERROR_ADDRESS_IN_USE;
kenjiArai 0:5b88d5760320 633 }
kenjiArai 0:5b88d5760320 634
kenjiArai 0:5b88d5760320 635 member_pair_index = next_free_multicast_member(s, 0);
kenjiArai 0:5b88d5760320 636
kenjiArai 0:5b88d5760320 637 adaptation.lock();
kenjiArai 0:5b88d5760320 638
kenjiArai 0:5b88d5760320 639 #if LWIP_IPV4
kenjiArai 0:5b88d5760320 640 if (IP_IS_V4(&if_addr)) {
kenjiArai 0:5b88d5760320 641 igmp_err = igmp_joingroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr));
kenjiArai 0:5b88d5760320 642 }
kenjiArai 0:5b88d5760320 643 #endif
kenjiArai 0:5b88d5760320 644 #if LWIP_IPV6
kenjiArai 0:5b88d5760320 645 if (IP_IS_V6(&if_addr)) {
kenjiArai 0:5b88d5760320 646 igmp_err = mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr));
kenjiArai 0:5b88d5760320 647 }
kenjiArai 0:5b88d5760320 648 #endif
kenjiArai 0:5b88d5760320 649
kenjiArai 0:5b88d5760320 650 adaptation.unlock();
kenjiArai 0:5b88d5760320 651
kenjiArai 0:5b88d5760320 652 if (igmp_err == ERR_OK) {
kenjiArai 0:5b88d5760320 653 set_multicast_member_registry_bit(s, member_pair_index);
kenjiArai 0:5b88d5760320 654 s->multicast_memberships[member_pair_index] = *imr;
kenjiArai 0:5b88d5760320 655 s->multicast_memberships_count++;
kenjiArai 0:5b88d5760320 656 }
kenjiArai 0:5b88d5760320 657 } else {
kenjiArai 0:5b88d5760320 658 if (member_pair_index == -1) {
kenjiArai 0:5b88d5760320 659 return NSAPI_ERROR_NO_ADDRESS;
kenjiArai 0:5b88d5760320 660 }
kenjiArai 0:5b88d5760320 661
kenjiArai 0:5b88d5760320 662 clear_multicast_member_registry_bit(s, member_pair_index);
kenjiArai 0:5b88d5760320 663 s->multicast_memberships_count--;
kenjiArai 0:5b88d5760320 664
kenjiArai 0:5b88d5760320 665 adaptation.lock();
kenjiArai 0:5b88d5760320 666
kenjiArai 0:5b88d5760320 667 #if LWIP_IPV4
kenjiArai 0:5b88d5760320 668 if (IP_IS_V4(&if_addr)) {
kenjiArai 0:5b88d5760320 669 igmp_err = igmp_leavegroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr));
kenjiArai 0:5b88d5760320 670 }
kenjiArai 0:5b88d5760320 671 #endif
kenjiArai 0:5b88d5760320 672 #if LWIP_IPV6
kenjiArai 0:5b88d5760320 673 if (IP_IS_V6(&if_addr)) {
kenjiArai 0:5b88d5760320 674 igmp_err = mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr));
kenjiArai 0:5b88d5760320 675 }
kenjiArai 0:5b88d5760320 676 #endif
kenjiArai 0:5b88d5760320 677
kenjiArai 0:5b88d5760320 678 adaptation.unlock();
kenjiArai 0:5b88d5760320 679 }
kenjiArai 0:5b88d5760320 680
kenjiArai 0:5b88d5760320 681 return err_remap(igmp_err);
kenjiArai 0:5b88d5760320 682 }
kenjiArai 0:5b88d5760320 683
kenjiArai 0:5b88d5760320 684 default:
kenjiArai 0:5b88d5760320 685 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 686 }
kenjiArai 0:5b88d5760320 687 }
kenjiArai 0:5b88d5760320 688
kenjiArai 0:5b88d5760320 689 nsapi_error_t LWIP::getsockopt(nsapi_socket_t handle, int level, int optname, void *optval, unsigned *optlen)
kenjiArai 0:5b88d5760320 690 {
kenjiArai 0:5b88d5760320 691 return NSAPI_ERROR_UNSUPPORTED;
kenjiArai 0:5b88d5760320 692 }
kenjiArai 0:5b88d5760320 693
kenjiArai 0:5b88d5760320 694
kenjiArai 0:5b88d5760320 695 void LWIP::socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data)
kenjiArai 0:5b88d5760320 696 {
kenjiArai 0:5b88d5760320 697 struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
kenjiArai 0:5b88d5760320 698
kenjiArai 0:5b88d5760320 699 s->cb = callback;
kenjiArai 0:5b88d5760320 700 s->data = data;
kenjiArai 0:5b88d5760320 701 }
kenjiArai 0:5b88d5760320 702
kenjiArai 0:5b88d5760320 703 LWIP &LWIP::get_instance()
kenjiArai 0:5b88d5760320 704 {
kenjiArai 0:5b88d5760320 705 static LWIP lwip;
kenjiArai 0:5b88d5760320 706 return lwip;
kenjiArai 0:5b88d5760320 707 }
kenjiArai 0:5b88d5760320 708
kenjiArai 0:5b88d5760320 709 // This works as long as it's not ever set to something which corresponds to
kenjiArai 0:5b88d5760320 710 // a macro defined as a non-integer. Eg `#define Nanostack "Foo"`
kenjiArai 0:5b88d5760320 711 #define LWIP 0x11991199
kenjiArai 0:5b88d5760320 712 #if MBED_CONF_NSAPI_DEFAULT_STACK == LWIP
kenjiArai 0:5b88d5760320 713 #undef LWIP
kenjiArai 0:5b88d5760320 714 OnboardNetworkStack &OnboardNetworkStack::get_default_instance()
kenjiArai 0:5b88d5760320 715 {
kenjiArai 0:5b88d5760320 716 return LWIP::get_instance();
kenjiArai 0:5b88d5760320 717 }
kenjiArai 0:5b88d5760320 718 #endif