mbed-os5 only for TYBLE16
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
features/lwipstack/LWIPStack.cpp@1:9db0e321a9f4, 2019-12-31 (annotated)
- 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?
User | Revision | Line number | New 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 |