Implementation of the NetworkSocketAPI for LWIP

Dependencies:   lwip-eth lwip-sys lwip

Dependents:   HelloLWIPInterface HelloLWIPInterfaceNonBlocking LWIPInterfaceTests SimpleHTTPExample ... more

Committer:
geky
Date:
Wed Apr 06 10:45:34 2016 +0000
Revision:
16:1efb0d91c223
Parent:
15:0d8d1dafe064
Child:
17:7db2f5d503d4
Added support for bind call

Who changed what in which revision?

UserRevisionLine numberNew contents of line
geky 1:2fbcfc9c12dd 1 /* LWIP implementation of NetworkInterfaceAPI
geky 1:2fbcfc9c12dd 2 * Copyright (c) 2015 ARM Limited
geky 1:2fbcfc9c12dd 3 *
geky 1:2fbcfc9c12dd 4 * Licensed under the Apache License, Version 2.0 (the "License");
geky 1:2fbcfc9c12dd 5 * you may not use this file except in compliance with the License.
geky 1:2fbcfc9c12dd 6 * You may obtain a copy of the License at
geky 1:2fbcfc9c12dd 7 *
geky 1:2fbcfc9c12dd 8 * http://www.apache.org/licenses/LICENSE-2.0
geky 1:2fbcfc9c12dd 9 *
geky 1:2fbcfc9c12dd 10 * Unless required by applicable law or agreed to in writing, software
geky 1:2fbcfc9c12dd 11 * distributed under the License is distributed on an "AS IS" BASIS,
geky 1:2fbcfc9c12dd 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
geky 1:2fbcfc9c12dd 13 * See the License for the specific language governing permissions and
geky 1:2fbcfc9c12dd 14 * limitations under the License.
geky 1:2fbcfc9c12dd 15 */
sam_grove 8:cef01e812975 16
Christopher Haster 13:57d9e1721826 17 #include "mbed.h"
Christopher Haster 2:7fb7e78cb17f 18 #include "LWIPInterface.h"
Christopher Haster 2:7fb7e78cb17f 19
Christopher Haster 2:7fb7e78cb17f 20 #include "lwip/inet.h"
Christopher Haster 2:7fb7e78cb17f 21 #include "lwip/netif.h"
Christopher Haster 2:7fb7e78cb17f 22 #include "lwip/dhcp.h"
Christopher Haster 2:7fb7e78cb17f 23 #include "lwip/tcpip.h"
Christopher Haster 2:7fb7e78cb17f 24 #include "lwip/sockets.h"
Christopher Haster 2:7fb7e78cb17f 25 #include "lwip/netdb.h"
Christopher Haster 2:7fb7e78cb17f 26 #include "netif/etharp.h"
Christopher Haster 2:7fb7e78cb17f 27 #include "eth_arch.h"
Christopher Haster 2:7fb7e78cb17f 28
Christopher Haster 2:7fb7e78cb17f 29 /* TCP/IP and Network Interface Initialisation */
Christopher Haster 2:7fb7e78cb17f 30 static struct netif netif;
Christopher Haster 2:7fb7e78cb17f 31
geky 15:0d8d1dafe064 32 static char ip_addr[NSAPI_IP_SIZE] = "\0";
geky 15:0d8d1dafe064 33 static char mac_addr[NSAPI_MAC_SIZE] = "\0";
Christopher Haster 2:7fb7e78cb17f 34
Christopher Haster 2:7fb7e78cb17f 35 static Semaphore tcpip_inited(0);
Christopher Haster 2:7fb7e78cb17f 36 static Semaphore netif_linked(0);
Christopher Haster 2:7fb7e78cb17f 37 static Semaphore netif_up(0);
Christopher Haster 2:7fb7e78cb17f 38
sam_grove 8:cef01e812975 39 static void tcpip_init_done(void *)
sam_grove 8:cef01e812975 40 {
Christopher Haster 2:7fb7e78cb17f 41 tcpip_inited.release();
Christopher Haster 2:7fb7e78cb17f 42 }
Christopher Haster 2:7fb7e78cb17f 43
sam_grove 8:cef01e812975 44 static void netif_link_callback(struct netif *netif)
sam_grove 8:cef01e812975 45 {
Christopher Haster 2:7fb7e78cb17f 46 if (netif_is_link_up(netif)) {
Christopher Haster 2:7fb7e78cb17f 47 netif_linked.release();
Christopher Haster 2:7fb7e78cb17f 48 }
Christopher Haster 2:7fb7e78cb17f 49 }
Christopher Haster 2:7fb7e78cb17f 50
sam_grove 8:cef01e812975 51 static void netif_status_callback(struct netif *netif)
sam_grove 8:cef01e812975 52 {
Christopher Haster 2:7fb7e78cb17f 53 if (netif_is_up(netif)) {
geky 5:2c7d2186543c 54 strcpy(ip_addr, inet_ntoa(netif->ip_addr));
Christopher Haster 2:7fb7e78cb17f 55 netif_up.release();
Christopher Haster 2:7fb7e78cb17f 56 }
Christopher Haster 2:7fb7e78cb17f 57 }
Christopher Haster 2:7fb7e78cb17f 58
sam_grove 8:cef01e812975 59 static void init_netif(ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw)
sam_grove 8:cef01e812975 60 {
Christopher Haster 2:7fb7e78cb17f 61 tcpip_init(tcpip_init_done, NULL);
Christopher Haster 2:7fb7e78cb17f 62 tcpip_inited.wait();
sam_grove 8:cef01e812975 63
Christopher Haster 2:7fb7e78cb17f 64 memset((void*) &netif, 0, sizeof(netif));
Christopher Haster 2:7fb7e78cb17f 65 netif_add(&netif, ipaddr, netmask, gw, NULL, eth_arch_enetif_init, tcpip_input);
Christopher Haster 2:7fb7e78cb17f 66 netif_set_default(&netif);
sam_grove 8:cef01e812975 67
Christopher Haster 2:7fb7e78cb17f 68 netif_set_link_callback (&netif, netif_link_callback);
Christopher Haster 2:7fb7e78cb17f 69 netif_set_status_callback(&netif, netif_status_callback);
Christopher Haster 2:7fb7e78cb17f 70 }
Christopher Haster 2:7fb7e78cb17f 71
sam_grove 8:cef01e812975 72 static void set_mac_address(void)
sam_grove 8:cef01e812975 73 {
Christopher Haster 2:7fb7e78cb17f 74 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
Christopher Haster 2:7fb7e78cb17f 75 snprintf(mac_addr, 19, "%02x:%02x:%02x:%02x:%02x:%02x", MBED_MAC_ADDR_0, MBED_MAC_ADDR_1, MBED_MAC_ADDR_2,
Christopher Haster 2:7fb7e78cb17f 76 MBED_MAC_ADDR_3, MBED_MAC_ADDR_4, MBED_MAC_ADDR_5);
Christopher Haster 2:7fb7e78cb17f 77 #else
Christopher Haster 2:7fb7e78cb17f 78 char mac[6];
Christopher Haster 2:7fb7e78cb17f 79 mbed_mac_address(mac);
Christopher Haster 2:7fb7e78cb17f 80 snprintf(mac_addr, 19, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Christopher Haster 2:7fb7e78cb17f 81 #endif
Christopher Haster 2:7fb7e78cb17f 82 }
Christopher Haster 2:7fb7e78cb17f 83
Christopher Haster 13:57d9e1721826 84
Christopher Haster 13:57d9e1721826 85 int LWIPInterface::connect()
Christopher Haster 2:7fb7e78cb17f 86 {
Christopher Haster 2:7fb7e78cb17f 87 // Set up network
Christopher Haster 2:7fb7e78cb17f 88 set_mac_address();
geky 5:2c7d2186543c 89 init_netif(0, 0, 0);
Christopher Haster 2:7fb7e78cb17f 90
Christopher Haster 2:7fb7e78cb17f 91 // Connect to network
Christopher Haster 2:7fb7e78cb17f 92 eth_arch_enable_interrupts();
Christopher Haster 2:7fb7e78cb17f 93
geky 5:2c7d2186543c 94 dhcp_start(&netif);
sam_grove 8:cef01e812975 95
geky 5:2c7d2186543c 96 // Wait for an IP Address
geky 5:2c7d2186543c 97 // -1: error, 0: timeout
Christopher Haster 13:57d9e1721826 98 if (netif_up.wait(1500) < 0) {
Christopher Haster 13:57d9e1721826 99 return NSAPI_ERROR_DHCP_FAILURE;
Christopher Haster 2:7fb7e78cb17f 100 }
Christopher Haster 2:7fb7e78cb17f 101
Christopher Haster 2:7fb7e78cb17f 102 return 0;
Christopher Haster 2:7fb7e78cb17f 103 }
Christopher Haster 2:7fb7e78cb17f 104
Christopher Haster 13:57d9e1721826 105 int LWIPInterface::disconnect()
Christopher Haster 2:7fb7e78cb17f 106 {
geky 5:2c7d2186543c 107 dhcp_release(&netif);
geky 5:2c7d2186543c 108 dhcp_stop(&netif);
sam_grove 8:cef01e812975 109
Christopher Haster 2:7fb7e78cb17f 110 eth_arch_disable_interrupts();
sam_grove 8:cef01e812975 111
Christopher Haster 2:7fb7e78cb17f 112 return 0;
Christopher Haster 2:7fb7e78cb17f 113 }
Christopher Haster 2:7fb7e78cb17f 114
Christopher Haster 13:57d9e1721826 115 const char *LWIPInterface::get_ip_address()
geky 5:2c7d2186543c 116 {
geky 5:2c7d2186543c 117 return ip_addr;
geky 5:2c7d2186543c 118 }
geky 5:2c7d2186543c 119
Christopher Haster 13:57d9e1721826 120 const char *LWIPInterface::get_mac_address()
Christopher Haster 2:7fb7e78cb17f 121 {
Christopher Haster 2:7fb7e78cb17f 122 return mac_addr;
Christopher Haster 2:7fb7e78cb17f 123 }
Christopher Haster 2:7fb7e78cb17f 124
geky 15:0d8d1dafe064 125 void *LWIPInterface::socket_create(nsapi_protocol_t proto)
Christopher Haster 2:7fb7e78cb17f 126 {
geky 15:0d8d1dafe064 127 int type = (proto == NSAPI_UDP) ? SOCK_DGRAM : SOCK_STREAM;
Christopher Haster 2:7fb7e78cb17f 128 int fd = lwip_socket(AF_INET, type, 0);
Christopher Haster 2:7fb7e78cb17f 129 if (fd < 0) {
Christopher Haster 2:7fb7e78cb17f 130 return 0;
Christopher Haster 2:7fb7e78cb17f 131 }
Christopher Haster 2:7fb7e78cb17f 132
geky 14:67b325c56cde 133 return (void *)(fd+1);
Christopher Haster 2:7fb7e78cb17f 134 }
Christopher Haster 2:7fb7e78cb17f 135
Christopher Haster 13:57d9e1721826 136 void LWIPInterface::socket_destroy(void *handle)
Christopher Haster 2:7fb7e78cb17f 137 {
geky 14:67b325c56cde 138 int fd = (int)handle-1;
Christopher Haster 13:57d9e1721826 139 lwip_close(fd);
Christopher Haster 13:57d9e1721826 140
Christopher Haster 13:57d9e1721826 141 }
Christopher Haster 2:7fb7e78cb17f 142
Christopher Haster 13:57d9e1721826 143 int LWIPInterface::socket_set_option(void *handle, int optname, const void *optval, unsigned optlen)
Christopher Haster 13:57d9e1721826 144 {
geky 14:67b325c56cde 145 int fd = (int)handle-1;
geky 14:67b325c56cde 146 return lwip_setsockopt(fd, SOL_SOCKET, optname, optval, (socklen_t)optlen);
Christopher Haster 13:57d9e1721826 147 }
Christopher Haster 13:57d9e1721826 148
Christopher Haster 13:57d9e1721826 149 int LWIPInterface::socket_get_option(void *handle, int optname, void *optval, unsigned *optlen)
Christopher Haster 13:57d9e1721826 150 {
geky 14:67b325c56cde 151 int fd = (int)handle-1;
geky 14:67b325c56cde 152 return lwip_getsockopt(fd, SOL_SOCKET, optname, optval, (socklen_t*)optlen);
Christopher Haster 2:7fb7e78cb17f 153 }
Christopher Haster 2:7fb7e78cb17f 154
Christopher Haster 13:57d9e1721826 155 int LWIPInterface::socket_bind(void *handle, int port)
Christopher Haster 13:57d9e1721826 156 {
geky 16:1efb0d91c223 157 int fd = (int)handle-1;
geky 16:1efb0d91c223 158 struct sockaddr_in sa;
geky 16:1efb0d91c223 159 memset(&sa, 0, sizeof sa);
geky 16:1efb0d91c223 160
geky 16:1efb0d91c223 161 sa.sin_family = AF_INET;
geky 16:1efb0d91c223 162 sa.sin_port = htons(port);
geky 16:1efb0d91c223 163 sa.sin_addr.s_addr = INADDR_ANY;
geky 16:1efb0d91c223 164
geky 16:1efb0d91c223 165 if (lwip_bind(fd, (const struct sockaddr *)&sa, sizeof sa) < 0) {
geky 16:1efb0d91c223 166 return NSAPI_ERROR_DEVICE_ERROR;
geky 16:1efb0d91c223 167 }
geky 16:1efb0d91c223 168
geky 16:1efb0d91c223 169 return 0;
Christopher Haster 13:57d9e1721826 170 }
Christopher Haster 2:7fb7e78cb17f 171
Christopher Haster 13:57d9e1721826 172 int LWIPInterface::socket_listen(void *handle, int backlog)
Christopher Haster 2:7fb7e78cb17f 173 {
Christopher Haster 13:57d9e1721826 174 return NSAPI_ERROR_UNSUPPORTED;
Christopher Haster 13:57d9e1721826 175 }
Christopher Haster 2:7fb7e78cb17f 176
Christopher Haster 13:57d9e1721826 177 int LWIPInterface::socket_connect(void *handle, const SocketAddress &addr)
Christopher Haster 13:57d9e1721826 178 {
geky 14:67b325c56cde 179 int fd = (int)handle-1;
Christopher Haster 13:57d9e1721826 180 struct sockaddr_in sa;
Christopher Haster 13:57d9e1721826 181 memset(&sa, 0, sizeof sa);
Christopher Haster 13:57d9e1721826 182 inet_aton(addr.get_ip_address(), &sa.sin_addr);
Christopher Haster 13:57d9e1721826 183 sa.sin_family = AF_INET;
Christopher Haster 13:57d9e1721826 184 sa.sin_port = htons(addr.get_port());
Christopher Haster 13:57d9e1721826 185
Christopher Haster 13:57d9e1721826 186 if (lwip_connect(fd, (const struct sockaddr *)&sa, sizeof sa) < 0) {
Christopher Haster 13:57d9e1721826 187 return NSAPI_ERROR_NO_CONNECTION;
Christopher Haster 2:7fb7e78cb17f 188 }
Christopher Haster 2:7fb7e78cb17f 189
Christopher Haster 2:7fb7e78cb17f 190 return 0;
Christopher Haster 2:7fb7e78cb17f 191 }
Christopher Haster 13:57d9e1721826 192
Christopher Haster 13:57d9e1721826 193 bool LWIPInterface::socket_is_connected(void *handle)
Christopher Haster 13:57d9e1721826 194 {
Christopher Haster 13:57d9e1721826 195 return true;
Christopher Haster 13:57d9e1721826 196 }
Christopher Haster 2:7fb7e78cb17f 197
Christopher Haster 13:57d9e1721826 198 int LWIPInterface::socket_accept(void *handle, void **connection)
Christopher Haster 2:7fb7e78cb17f 199 {
Christopher Haster 13:57d9e1721826 200 return NSAPI_ERROR_UNSUPPORTED;
Christopher Haster 2:7fb7e78cb17f 201 }
Christopher Haster 2:7fb7e78cb17f 202
Christopher Haster 13:57d9e1721826 203 int LWIPInterface::socket_send(void *handle, const void *p, unsigned size)
Christopher Haster 2:7fb7e78cb17f 204 {
geky 14:67b325c56cde 205 int fd = (int)handle-1;
Christopher Haster 13:57d9e1721826 206 uint8_t *data = (uint8_t *)p;
Christopher Haster 13:57d9e1721826 207 unsigned written = 0;
Christopher Haster 2:7fb7e78cb17f 208
Christopher Haster 13:57d9e1721826 209 while (written < size) {
Christopher Haster 13:57d9e1721826 210 int ret = lwip_send(fd, data + written, size - written, 0);
Christopher Haster 2:7fb7e78cb17f 211
Christopher Haster 2:7fb7e78cb17f 212 if (ret > 0) {
Christopher Haster 13:57d9e1721826 213 written += ret;
Christopher Haster 2:7fb7e78cb17f 214 } else if (ret == 0) {
Christopher Haster 13:57d9e1721826 215 return NSAPI_ERROR_NO_CONNECTION;
Christopher Haster 2:7fb7e78cb17f 216 } else {
Christopher Haster 13:57d9e1721826 217 return NSAPI_ERROR_DEVICE_ERROR;
Christopher Haster 2:7fb7e78cb17f 218 }
Christopher Haster 2:7fb7e78cb17f 219 }
Christopher Haster 2:7fb7e78cb17f 220
Christopher Haster 13:57d9e1721826 221 return written;
Christopher Haster 2:7fb7e78cb17f 222 }
Christopher Haster 2:7fb7e78cb17f 223
Christopher Haster 13:57d9e1721826 224 int LWIPInterface::socket_recv(void *handle, void *data, unsigned size)
Christopher Haster 2:7fb7e78cb17f 225 {
geky 14:67b325c56cde 226 int fd = (int)handle-1;
Christopher Haster 2:7fb7e78cb17f 227 int ret = lwip_recv(fd, data, size, MSG_DONTWAIT);
Christopher Haster 2:7fb7e78cb17f 228
Christopher Haster 2:7fb7e78cb17f 229 if (ret > 0) {
Christopher Haster 2:7fb7e78cb17f 230 return ret;
Christopher Haster 2:7fb7e78cb17f 231 } else if (ret == 0) {
Christopher Haster 13:57d9e1721826 232 return NSAPI_ERROR_NO_CONNECTION;
Christopher Haster 2:7fb7e78cb17f 233 } else if (ret == -1) {
Christopher Haster 13:57d9e1721826 234 return NSAPI_ERROR_WOULD_BLOCK;
Christopher Haster 2:7fb7e78cb17f 235 } else {
Christopher Haster 13:57d9e1721826 236 return NSAPI_ERROR_DEVICE_ERROR;
Christopher Haster 2:7fb7e78cb17f 237 }
Christopher Haster 2:7fb7e78cb17f 238 }
Christopher Haster 2:7fb7e78cb17f 239
Christopher Haster 13:57d9e1721826 240 int LWIPInterface::socket_sendto(void *handle, const SocketAddress &addr, const void *p, unsigned size)
geky 12:899403b675fe 241 {
geky 14:67b325c56cde 242 int fd = (int)handle-1;
Christopher Haster 13:57d9e1721826 243 uint8_t *data = (uint8_t *)p;
Christopher Haster 13:57d9e1721826 244 unsigned written = 0;
geky 12:899403b675fe 245
Christopher Haster 13:57d9e1721826 246 struct sockaddr_in sa;
Christopher Haster 13:57d9e1721826 247 memset(&sa, 0, sizeof sa);
Christopher Haster 13:57d9e1721826 248 inet_aton(addr.get_ip_address(), &sa.sin_addr);
Christopher Haster 13:57d9e1721826 249 sa.sin_family = AF_INET;
Christopher Haster 13:57d9e1721826 250 sa.sin_port = htons(addr.get_port());
geky 12:899403b675fe 251
Christopher Haster 13:57d9e1721826 252 while (written < size) {
Christopher Haster 13:57d9e1721826 253 int ret = lwip_sendto(fd, data + written, size - written, 0,
Christopher Haster 13:57d9e1721826 254 (const struct sockaddr *)&sa, sizeof sa);
geky 12:899403b675fe 255
Christopher Haster 13:57d9e1721826 256 if (ret > 0) {
Christopher Haster 13:57d9e1721826 257 written += ret;
Christopher Haster 13:57d9e1721826 258 } else if (ret == 0) {
Christopher Haster 13:57d9e1721826 259 return NSAPI_ERROR_NO_CONNECTION;
Christopher Haster 13:57d9e1721826 260 } else {
Christopher Haster 13:57d9e1721826 261 return NSAPI_ERROR_DEVICE_ERROR;
Christopher Haster 13:57d9e1721826 262 }
geky 12:899403b675fe 263 }
geky 12:899403b675fe 264
Christopher Haster 13:57d9e1721826 265 return written;
Christopher Haster 13:57d9e1721826 266 }
geky 12:899403b675fe 267
Christopher Haster 13:57d9e1721826 268 int LWIPInterface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
Christopher Haster 13:57d9e1721826 269 {
geky 14:67b325c56cde 270 int fd = (int)handle-1;
Christopher Haster 13:57d9e1721826 271 struct sockaddr_in sa;
Christopher Haster 13:57d9e1721826 272 socklen_t sa_len = sizeof sa;
geky 12:899403b675fe 273
Christopher Haster 13:57d9e1721826 274 int ret = lwip_recvfrom(fd, data, size, MSG_DONTWAIT,
Christopher Haster 13:57d9e1721826 275 (struct sockaddr *)&sa, &sa_len);
geky 12:899403b675fe 276
Christopher Haster 13:57d9e1721826 277 if (ret > 0 && addr) {
Christopher Haster 13:57d9e1721826 278 addr->set_ip_address(inet_ntoa(sa.sin_addr));
Christopher Haster 13:57d9e1721826 279 addr->set_port(ntohs(sa.sin_port));
Christopher Haster 13:57d9e1721826 280 }
geky 12:899403b675fe 281
geky 14:67b325c56cde 282 if (ret > 0) {
Christopher Haster 13:57d9e1721826 283 return ret;
Christopher Haster 13:57d9e1721826 284 } else if (ret == 0) {
Christopher Haster 13:57d9e1721826 285 return NSAPI_ERROR_NO_CONNECTION;
Christopher Haster 13:57d9e1721826 286 } else if (ret == -1) {
Christopher Haster 13:57d9e1721826 287 return NSAPI_ERROR_WOULD_BLOCK;
Christopher Haster 13:57d9e1721826 288 } else {
Christopher Haster 13:57d9e1721826 289 return NSAPI_ERROR_DEVICE_ERROR;
Christopher Haster 13:57d9e1721826 290 }
Christopher Haster 13:57d9e1721826 291 }
geky 12:899403b675fe 292
Christopher Haster 13:57d9e1721826 293 int LWIPInterface::socket_close(void *handle, bool shutdown)
Christopher Haster 13:57d9e1721826 294 {
geky 14:67b325c56cde 295 int fd = (int)handle-1;
Christopher Haster 13:57d9e1721826 296 if (shutdown) {
Christopher Haster 13:57d9e1721826 297 lwip_shutdown(fd, SHUT_RDWR);
Christopher Haster 13:57d9e1721826 298 }
geky 12:899403b675fe 299
Christopher Haster 13:57d9e1721826 300 lwip_close(fd);
Christopher Haster 13:57d9e1721826 301 return 0;
Christopher Haster 13:57d9e1721826 302 }
geky 12:899403b675fe 303
Christopher Haster 13:57d9e1721826 304 void LWIPInterface::socket_attach_accept(void *handle, void (*callback)(void *), void *id)
Christopher Haster 13:57d9e1721826 305 {
Christopher Haster 13:57d9e1721826 306 }
geky 12:899403b675fe 307
Christopher Haster 13:57d9e1721826 308 void LWIPInterface::socket_attach_send(void *handle, void (*callback)(void *), void *id)
Christopher Haster 13:57d9e1721826 309 {
Christopher Haster 13:57d9e1721826 310 }
geky 12:899403b675fe 311
Christopher Haster 13:57d9e1721826 312 void LWIPInterface::socket_attach_recv(void *handle, void (*callback)(void *), void *id)
Christopher Haster 13:57d9e1721826 313 {
Christopher Haster 13:57d9e1721826 314 }
geky 12:899403b675fe 315