sandbox / LWIPInterface

Dependencies:   lwip-eth lwip-sys lwip

Fork of LWIPInterface by Christopher Haster

Committer:
geky
Date:
Wed Apr 20 00:48:19 2016 +0000
Revision:
18:5890b186a607
Parent:
17:7db2f5d503d4
Remove is_connect function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Christopher Haster 17:7db2f5d503d4 1 /* LWIP implementation of NetworkInterfaceAPI
Christopher Haster 17:7db2f5d503d4 2 * Copyright (c) 2015 ARM Limited
Christopher Haster 17:7db2f5d503d4 3 *
Christopher Haster 17:7db2f5d503d4 4 * Licensed under the Apache License, Version 2.0 (the "License");
Christopher Haster 17:7db2f5d503d4 5 * you may not use this file except in compliance with the License.
Christopher Haster 17:7db2f5d503d4 6 * You may obtain a copy of the License at
Christopher Haster 17:7db2f5d503d4 7 *
Christopher Haster 17:7db2f5d503d4 8 * http://www.apache.org/licenses/LICENSE-2.0
Christopher Haster 17:7db2f5d503d4 9 *
Christopher Haster 17:7db2f5d503d4 10 * Unless required by applicable law or agreed to in writing, software
Christopher Haster 17:7db2f5d503d4 11 * distributed under the License is distributed on an "AS IS" BASIS,
Christopher Haster 17:7db2f5d503d4 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Christopher Haster 17:7db2f5d503d4 13 * See the License for the specific language governing permissions and
Christopher Haster 17:7db2f5d503d4 14 * limitations under the License.
Christopher Haster 17:7db2f5d503d4 15 */
Christopher Haster 17:7db2f5d503d4 16
Christopher Haster 17:7db2f5d503d4 17 #include "mbed.h"
Christopher Haster 17:7db2f5d503d4 18 #include "LWIPInterface.h"
Christopher Haster 17:7db2f5d503d4 19
Christopher Haster 17:7db2f5d503d4 20 #include "lwip/inet.h"
Christopher Haster 17:7db2f5d503d4 21 #include "lwip/netif.h"
Christopher Haster 17:7db2f5d503d4 22 #include "lwip/dhcp.h"
Christopher Haster 17:7db2f5d503d4 23 #include "lwip/tcpip.h"
Christopher Haster 17:7db2f5d503d4 24 #include "lwip/sockets.h"
Christopher Haster 17:7db2f5d503d4 25 #include "lwip/netdb.h"
Christopher Haster 17:7db2f5d503d4 26 #include "netif/etharp.h"
Christopher Haster 17:7db2f5d503d4 27 #include "eth_arch.h"
Christopher Haster 17:7db2f5d503d4 28 #include "lwip/netif.h"
Christopher Haster 17:7db2f5d503d4 29 #include "lwip/udp.h"
Christopher Haster 17:7db2f5d503d4 30 #include "lwip/tcp.h"
Christopher Haster 17:7db2f5d503d4 31 #include "lwip/tcp_impl.h"
Christopher Haster 17:7db2f5d503d4 32 #include "lwip/timers.h"
Christopher Haster 17:7db2f5d503d4 33 #include "lwip/dns.h"
Christopher Haster 17:7db2f5d503d4 34 #include "lwip/def.h"
Christopher Haster 17:7db2f5d503d4 35 #include "lwip/ip_addr.h"
Christopher Haster 17:7db2f5d503d4 36
Christopher Haster 17:7db2f5d503d4 37
Christopher Haster 17:7db2f5d503d4 38 /* TCP/IP and Network Interface Initialisation */
Christopher Haster 17:7db2f5d503d4 39 static struct netif netif;
Christopher Haster 17:7db2f5d503d4 40
Christopher Haster 17:7db2f5d503d4 41 static char ip_addr[NSAPI_IP_SIZE] = "\0";
Christopher Haster 17:7db2f5d503d4 42 static char mac_addr[NSAPI_MAC_SIZE] = "\0";
Christopher Haster 17:7db2f5d503d4 43
Christopher Haster 17:7db2f5d503d4 44 static Semaphore tcpip_inited(0);
Christopher Haster 17:7db2f5d503d4 45 static Semaphore netif_linked(0);
Christopher Haster 17:7db2f5d503d4 46 static Semaphore netif_up(0);
Christopher Haster 17:7db2f5d503d4 47
Christopher Haster 17:7db2f5d503d4 48 static void tcpip_init_irq(void *)
Christopher Haster 17:7db2f5d503d4 49 {
Christopher Haster 17:7db2f5d503d4 50 tcpip_inited.release();
Christopher Haster 17:7db2f5d503d4 51 }
Christopher Haster 17:7db2f5d503d4 52
Christopher Haster 17:7db2f5d503d4 53 static void netif_link_irq(struct netif *netif)
Christopher Haster 17:7db2f5d503d4 54 {
Christopher Haster 17:7db2f5d503d4 55 if (netif_is_link_up(netif)) {
Christopher Haster 17:7db2f5d503d4 56 netif_linked.release();
Christopher Haster 17:7db2f5d503d4 57 }
Christopher Haster 17:7db2f5d503d4 58 }
Christopher Haster 17:7db2f5d503d4 59
Christopher Haster 17:7db2f5d503d4 60 static void netif_status_irq(struct netif *netif)
Christopher Haster 17:7db2f5d503d4 61 {
Christopher Haster 17:7db2f5d503d4 62 if (netif_is_up(netif)) {
Christopher Haster 17:7db2f5d503d4 63 strcpy(ip_addr, inet_ntoa(netif->ip_addr));
Christopher Haster 17:7db2f5d503d4 64 netif_up.release();
Christopher Haster 17:7db2f5d503d4 65 }
Christopher Haster 17:7db2f5d503d4 66 }
Christopher Haster 17:7db2f5d503d4 67
Christopher Haster 17:7db2f5d503d4 68 static void init_netif(ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw)
Christopher Haster 17:7db2f5d503d4 69 {
Christopher Haster 17:7db2f5d503d4 70 tcpip_init(tcpip_init_irq, NULL);
Christopher Haster 17:7db2f5d503d4 71 tcpip_inited.wait();
Christopher Haster 17:7db2f5d503d4 72
Christopher Haster 17:7db2f5d503d4 73 memset((void*) &netif, 0, sizeof(netif));
Christopher Haster 17:7db2f5d503d4 74 netif_add(&netif, ipaddr, netmask, gw, NULL, eth_arch_enetif_init, tcpip_input);
Christopher Haster 17:7db2f5d503d4 75 netif_set_default(&netif);
Christopher Haster 17:7db2f5d503d4 76
Christopher Haster 17:7db2f5d503d4 77 netif_set_link_callback (&netif, netif_link_irq);
Christopher Haster 17:7db2f5d503d4 78 netif_set_status_callback(&netif, netif_status_irq);
Christopher Haster 17:7db2f5d503d4 79 }
Christopher Haster 17:7db2f5d503d4 80
Christopher Haster 17:7db2f5d503d4 81 static void set_mac_address(void)
Christopher Haster 17:7db2f5d503d4 82 {
Christopher Haster 17:7db2f5d503d4 83 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
Christopher Haster 17:7db2f5d503d4 84 snprintf(mac_addr, 19, "%02x:%02x:%02x:%02x:%02x:%02x", MBED_MAC_ADDR_0, MBED_MAC_ADDR_1, MBED_MAC_ADDR_2,
Christopher Haster 17:7db2f5d503d4 85 MBED_MAC_ADDR_3, MBED_MAC_ADDR_4, MBED_MAC_ADDR_5);
Christopher Haster 17:7db2f5d503d4 86 #else
Christopher Haster 17:7db2f5d503d4 87 char mac[6];
Christopher Haster 17:7db2f5d503d4 88 mbed_mac_address(mac);
Christopher Haster 17:7db2f5d503d4 89 snprintf(mac_addr, 19, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Christopher Haster 17:7db2f5d503d4 90 #endif
Christopher Haster 17:7db2f5d503d4 91 }
Christopher Haster 17:7db2f5d503d4 92
Christopher Haster 17:7db2f5d503d4 93
Christopher Haster 17:7db2f5d503d4 94 /* Interface implementation */
Christopher Haster 17:7db2f5d503d4 95 int LWIPInterface::connect()
Christopher Haster 17:7db2f5d503d4 96 {
Christopher Haster 17:7db2f5d503d4 97 // Set up network
Christopher Haster 17:7db2f5d503d4 98 set_mac_address();
Christopher Haster 17:7db2f5d503d4 99 init_netif(0, 0, 0);
Christopher Haster 17:7db2f5d503d4 100
Christopher Haster 17:7db2f5d503d4 101 // Connect to network
Christopher Haster 17:7db2f5d503d4 102 eth_arch_enable_interrupts();
Christopher Haster 17:7db2f5d503d4 103
Christopher Haster 17:7db2f5d503d4 104 dhcp_start(&netif);
Christopher Haster 17:7db2f5d503d4 105
Christopher Haster 17:7db2f5d503d4 106 // Wait for an IP Address
Christopher Haster 17:7db2f5d503d4 107 // -1: error, 0: timeout
Christopher Haster 17:7db2f5d503d4 108 if (netif_up.wait(1500) < 0) {
Christopher Haster 17:7db2f5d503d4 109 return NSAPI_ERROR_DHCP_FAILURE;
Christopher Haster 17:7db2f5d503d4 110 }
Christopher Haster 17:7db2f5d503d4 111
Christopher Haster 17:7db2f5d503d4 112 return 0;
Christopher Haster 17:7db2f5d503d4 113 }
Christopher Haster 17:7db2f5d503d4 114
Christopher Haster 17:7db2f5d503d4 115 int LWIPInterface::disconnect()
Christopher Haster 17:7db2f5d503d4 116 {
Christopher Haster 17:7db2f5d503d4 117 dhcp_release(&netif);
Christopher Haster 17:7db2f5d503d4 118 dhcp_stop(&netif);
Christopher Haster 17:7db2f5d503d4 119
Christopher Haster 17:7db2f5d503d4 120 eth_arch_disable_interrupts();
Christopher Haster 17:7db2f5d503d4 121
Christopher Haster 17:7db2f5d503d4 122 return 0;
Christopher Haster 17:7db2f5d503d4 123 }
Christopher Haster 17:7db2f5d503d4 124
Christopher Haster 17:7db2f5d503d4 125 const char *LWIPInterface::get_ip_address()
Christopher Haster 17:7db2f5d503d4 126 {
Christopher Haster 17:7db2f5d503d4 127 return ip_addr;
Christopher Haster 17:7db2f5d503d4 128 }
Christopher Haster 17:7db2f5d503d4 129
Christopher Haster 17:7db2f5d503d4 130 const char *LWIPInterface::get_mac_address()
Christopher Haster 17:7db2f5d503d4 131 {
Christopher Haster 17:7db2f5d503d4 132 return mac_addr;
Christopher Haster 17:7db2f5d503d4 133 }
Christopher Haster 17:7db2f5d503d4 134
Christopher Haster 17:7db2f5d503d4 135 struct lwip_socket {
Christopher Haster 17:7db2f5d503d4 136 nsapi_protocol_t proto;
Christopher Haster 17:7db2f5d503d4 137 union {
Christopher Haster 17:7db2f5d503d4 138 struct udp_pcb *udp;
Christopher Haster 17:7db2f5d503d4 139 struct tcp_pcb *tcp;
Christopher Haster 17:7db2f5d503d4 140 };
Christopher Haster 17:7db2f5d503d4 141
Christopher Haster 17:7db2f5d503d4 142 struct pbuf *rx_chain;
Christopher Haster 17:7db2f5d503d4 143 Semaphore *sem;
Christopher Haster 17:7db2f5d503d4 144
Christopher Haster 17:7db2f5d503d4 145 void (*callback)(void *);
Christopher Haster 17:7db2f5d503d4 146 void *data;
Christopher Haster 17:7db2f5d503d4 147 };
Christopher Haster 17:7db2f5d503d4 148
Christopher Haster 17:7db2f5d503d4 149 static void udp_recv_irq(
Christopher Haster 17:7db2f5d503d4 150 void *arg, struct udp_pcb *upcb, struct pbuf *p,
Christopher Haster 17:7db2f5d503d4 151 struct ip_addr *addr, uint16_t port);
Christopher Haster 17:7db2f5d503d4 152
Christopher Haster 17:7db2f5d503d4 153 int LWIPInterface::socket_open(void **handle, nsapi_protocol_t proto)
Christopher Haster 17:7db2f5d503d4 154 {
Christopher Haster 17:7db2f5d503d4 155 struct lwip_socket *s = new struct lwip_socket;
Christopher Haster 17:7db2f5d503d4 156 if (!s) {
Christopher Haster 17:7db2f5d503d4 157 return NSAPI_ERROR_NO_SOCKET;
Christopher Haster 17:7db2f5d503d4 158 }
Christopher Haster 17:7db2f5d503d4 159
Christopher Haster 17:7db2f5d503d4 160 memset(s, 0, sizeof *s);
Christopher Haster 17:7db2f5d503d4 161
Christopher Haster 17:7db2f5d503d4 162 switch (proto) {
Christopher Haster 17:7db2f5d503d4 163 case NSAPI_UDP:
Christopher Haster 17:7db2f5d503d4 164 s->proto = proto;
Christopher Haster 17:7db2f5d503d4 165 s->udp = udp_new();
Christopher Haster 17:7db2f5d503d4 166 if (!s->udp) {
Christopher Haster 17:7db2f5d503d4 167 return NSAPI_ERROR_NO_SOCKET;
Christopher Haster 17:7db2f5d503d4 168 }
Christopher Haster 17:7db2f5d503d4 169
Christopher Haster 17:7db2f5d503d4 170 udp_recv(s->udp, udp_recv_irq, s);
Christopher Haster 17:7db2f5d503d4 171 *handle = s;
geky 18:5890b186a607 172 return 0;
Christopher Haster 17:7db2f5d503d4 173
Christopher Haster 17:7db2f5d503d4 174 case NSAPI_TCP:
Christopher Haster 17:7db2f5d503d4 175 s->proto = proto;
Christopher Haster 17:7db2f5d503d4 176 s->tcp = tcp_new();
Christopher Haster 17:7db2f5d503d4 177 if (!s->tcp) {
Christopher Haster 17:7db2f5d503d4 178 return NSAPI_ERROR_NO_SOCKET;
Christopher Haster 17:7db2f5d503d4 179 }
Christopher Haster 17:7db2f5d503d4 180
Christopher Haster 17:7db2f5d503d4 181 tcp_arg(s->tcp, s);
Christopher Haster 17:7db2f5d503d4 182 //tcp_err(s->tcp, tcp_error_irq);
Christopher Haster 17:7db2f5d503d4 183 *handle = s;
geky 18:5890b186a607 184 return 0;
Christopher Haster 17:7db2f5d503d4 185 }
Christopher Haster 17:7db2f5d503d4 186
Christopher Haster 17:7db2f5d503d4 187 return NSAPI_ERROR_DEVICE_ERROR;
Christopher Haster 17:7db2f5d503d4 188 }
Christopher Haster 17:7db2f5d503d4 189
Christopher Haster 17:7db2f5d503d4 190 int LWIPInterface::socket_close(void *handle)
Christopher Haster 17:7db2f5d503d4 191 {
Christopher Haster 17:7db2f5d503d4 192 struct lwip_socket *s = (struct lwip_socket *)handle;
Christopher Haster 17:7db2f5d503d4 193 int err = 0;
Christopher Haster 17:7db2f5d503d4 194
Christopher Haster 17:7db2f5d503d4 195 switch (s->proto) {
Christopher Haster 17:7db2f5d503d4 196 case NSAPI_UDP:
Christopher Haster 17:7db2f5d503d4 197 udp_disconnect(s->udp);
Christopher Haster 17:7db2f5d503d4 198 break;
Christopher Haster 17:7db2f5d503d4 199
Christopher Haster 17:7db2f5d503d4 200 case NSAPI_TCP:
Christopher Haster 17:7db2f5d503d4 201 if (tcp_close(s->tcp)) {
Christopher Haster 17:7db2f5d503d4 202 err = NSAPI_ERROR_DEVICE_ERROR;
Christopher Haster 17:7db2f5d503d4 203 }
Christopher Haster 17:7db2f5d503d4 204 break;
Christopher Haster 17:7db2f5d503d4 205 }
Christopher Haster 17:7db2f5d503d4 206
Christopher Haster 17:7db2f5d503d4 207 if (s->rx_chain) {
Christopher Haster 17:7db2f5d503d4 208 pbuf_free(s->rx_chain);
Christopher Haster 17:7db2f5d503d4 209 s->rx_chain = 0;
Christopher Haster 17:7db2f5d503d4 210 }
Christopher Haster 17:7db2f5d503d4 211
Christopher Haster 17:7db2f5d503d4 212 delete s;
Christopher Haster 17:7db2f5d503d4 213
Christopher Haster 17:7db2f5d503d4 214 return err;
Christopher Haster 17:7db2f5d503d4 215 }
Christopher Haster 17:7db2f5d503d4 216
Christopher Haster 17:7db2f5d503d4 217
Christopher Haster 17:7db2f5d503d4 218 int LWIPInterface::socket_bind(void *handle, const SocketAddress &address)
Christopher Haster 17:7db2f5d503d4 219 {
Christopher Haster 17:7db2f5d503d4 220 struct lwip_socket *s = (struct lwip_socket *)handle;
Christopher Haster 17:7db2f5d503d4 221 ip_addr_t ip_addr = ip_addr_any; // TODO use address
Christopher Haster 17:7db2f5d503d4 222
Christopher Haster 17:7db2f5d503d4 223 switch (s->proto) {
Christopher Haster 17:7db2f5d503d4 224 case NSAPI_UDP:
Christopher Haster 17:7db2f5d503d4 225 if (udp_bind(s->udp, &ip_addr, address.get_port())) {
Christopher Haster 17:7db2f5d503d4 226 return NSAPI_ERROR_DEVICE_ERROR;
Christopher Haster 17:7db2f5d503d4 227 }
Christopher Haster 17:7db2f5d503d4 228 return 0;
Christopher Haster 17:7db2f5d503d4 229
Christopher Haster 17:7db2f5d503d4 230 case NSAPI_TCP:
Christopher Haster 17:7db2f5d503d4 231 if (tcp_bind(s->tcp, &ip_addr, address.get_port())) {
Christopher Haster 17:7db2f5d503d4 232 return NSAPI_ERROR_DEVICE_ERROR;
Christopher Haster 17:7db2f5d503d4 233 }
Christopher Haster 17:7db2f5d503d4 234 return 0;
Christopher Haster 17:7db2f5d503d4 235 }
Christopher Haster 17:7db2f5d503d4 236
Christopher Haster 17:7db2f5d503d4 237 return NSAPI_ERROR_DEVICE_ERROR;
Christopher Haster 17:7db2f5d503d4 238 }
Christopher Haster 17:7db2f5d503d4 239
Christopher Haster 17:7db2f5d503d4 240 int LWIPInterface::socket_listen(void *handle, int backlog)
Christopher Haster 17:7db2f5d503d4 241 {
Christopher Haster 17:7db2f5d503d4 242 return NSAPI_ERROR_UNSUPPORTED;
Christopher Haster 17:7db2f5d503d4 243 }
Christopher Haster 17:7db2f5d503d4 244
Christopher Haster 17:7db2f5d503d4 245 static err_t tcp_sent_irq(void *arg, struct tcp_pcb *tpcb, uint16_t len);
Christopher Haster 17:7db2f5d503d4 246 static err_t tcp_recv_irq(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
Christopher Haster 17:7db2f5d503d4 247
Christopher Haster 17:7db2f5d503d4 248 static err_t tcp_connect_irq(void *handle, struct tcp_pcb *tpcb, err_t err)
Christopher Haster 17:7db2f5d503d4 249 {
Christopher Haster 17:7db2f5d503d4 250 struct lwip_socket *s = (struct lwip_socket *)handle;
Christopher Haster 17:7db2f5d503d4 251 tcp_sent(tpcb, tcp_sent_irq);
Christopher Haster 17:7db2f5d503d4 252 tcp_recv(tpcb, tcp_recv_irq);
Christopher Haster 17:7db2f5d503d4 253
Christopher Haster 17:7db2f5d503d4 254 s->sem->release();
Christopher Haster 17:7db2f5d503d4 255
Christopher Haster 17:7db2f5d503d4 256 return ERR_OK;
Christopher Haster 17:7db2f5d503d4 257 }
Christopher Haster 17:7db2f5d503d4 258
Christopher Haster 17:7db2f5d503d4 259 int LWIPInterface::socket_connect(void *handle, const SocketAddress &addr)
Christopher Haster 17:7db2f5d503d4 260 {
Christopher Haster 17:7db2f5d503d4 261 struct lwip_socket *s = (struct lwip_socket *)handle;
Christopher Haster 17:7db2f5d503d4 262
Christopher Haster 17:7db2f5d503d4 263 ip_addr_t ip_addr;
Christopher Haster 17:7db2f5d503d4 264 inet_aton(addr.get_ip_address(), &ip_addr);
Christopher Haster 17:7db2f5d503d4 265
Christopher Haster 17:7db2f5d503d4 266 Semaphore connected(0);
Christopher Haster 17:7db2f5d503d4 267 s->sem = &connected;
Christopher Haster 17:7db2f5d503d4 268
Christopher Haster 17:7db2f5d503d4 269 tcp_connect(s->tcp, &ip_addr, addr.get_port(), tcp_connect_irq);
Christopher Haster 17:7db2f5d503d4 270
Christopher Haster 17:7db2f5d503d4 271 // Wait for connection
Christopher Haster 17:7db2f5d503d4 272 if (connected.wait(1500) < 0) {
Christopher Haster 17:7db2f5d503d4 273 return NSAPI_ERROR_NO_CONNECTION;
Christopher Haster 17:7db2f5d503d4 274 }
Christopher Haster 17:7db2f5d503d4 275
Christopher Haster 17:7db2f5d503d4 276 return 0;
Christopher Haster 17:7db2f5d503d4 277 }
Christopher Haster 17:7db2f5d503d4 278
Christopher Haster 17:7db2f5d503d4 279 int LWIPInterface::socket_accept(void **handle, void *server)
Christopher Haster 17:7db2f5d503d4 280 {
Christopher Haster 17:7db2f5d503d4 281 return NSAPI_ERROR_UNSUPPORTED;
Christopher Haster 17:7db2f5d503d4 282 }
Christopher Haster 17:7db2f5d503d4 283
Christopher Haster 17:7db2f5d503d4 284 static struct pbuf *pbuf_consume(struct pbuf *p, size_t consume, bool free_partial)
Christopher Haster 17:7db2f5d503d4 285 {
Christopher Haster 17:7db2f5d503d4 286 do {
Christopher Haster 17:7db2f5d503d4 287 if (consume <= p->len) {
Christopher Haster 17:7db2f5d503d4 288 // advance the payload pointer by the number of bytes copied
Christopher Haster 17:7db2f5d503d4 289 p->payload = (char *)p->payload + consume;
Christopher Haster 17:7db2f5d503d4 290 // reduce the length by the number of bytes copied
Christopher Haster 17:7db2f5d503d4 291 p->len -= consume;
Christopher Haster 17:7db2f5d503d4 292 // break out of the loop
Christopher Haster 17:7db2f5d503d4 293 consume = 0;
Christopher Haster 17:7db2f5d503d4 294 }
Christopher Haster 17:7db2f5d503d4 295 if (p->len == 0 || consume > p->len || (consume == 0 && free_partial)) {
Christopher Haster 17:7db2f5d503d4 296 struct pbuf *q;
Christopher Haster 17:7db2f5d503d4 297 q = p->next;
Christopher Haster 17:7db2f5d503d4 298 // decrement the number of bytes copied by the length of the buffer
Christopher Haster 17:7db2f5d503d4 299 if(consume > p->len)
Christopher Haster 17:7db2f5d503d4 300 consume -= p->len;
Christopher Haster 17:7db2f5d503d4 301 // Free the current pbuf
Christopher Haster 17:7db2f5d503d4 302 // NOTE: This operation is interrupt safe, but not thread safe.
Christopher Haster 17:7db2f5d503d4 303 if (q != NULL) {
Christopher Haster 17:7db2f5d503d4 304 pbuf_ref(q);
Christopher Haster 17:7db2f5d503d4 305 }
Christopher Haster 17:7db2f5d503d4 306 pbuf_free(p);
Christopher Haster 17:7db2f5d503d4 307 p = q;
Christopher Haster 17:7db2f5d503d4 308 }
Christopher Haster 17:7db2f5d503d4 309 } while (consume);
Christopher Haster 17:7db2f5d503d4 310 return p;
Christopher Haster 17:7db2f5d503d4 311 }
Christopher Haster 17:7db2f5d503d4 312
Christopher Haster 17:7db2f5d503d4 313 static err_t tcp_sent_irq(void *handle, struct tcp_pcb *tpcb, uint16_t len)
Christopher Haster 17:7db2f5d503d4 314 {
Christopher Haster 17:7db2f5d503d4 315 struct lwip_socket *s = (struct lwip_socket *)handle;
Christopher Haster 17:7db2f5d503d4 316 if (s->callback) {
Christopher Haster 17:7db2f5d503d4 317 s->callback(s->data);
Christopher Haster 17:7db2f5d503d4 318 }
Christopher Haster 17:7db2f5d503d4 319
Christopher Haster 17:7db2f5d503d4 320 return ERR_OK;
Christopher Haster 17:7db2f5d503d4 321 }
Christopher Haster 17:7db2f5d503d4 322
Christopher Haster 17:7db2f5d503d4 323 int LWIPInterface::socket_send(void *handle, const void *buf, unsigned size)
Christopher Haster 17:7db2f5d503d4 324 {
Christopher Haster 17:7db2f5d503d4 325 struct lwip_socket *s = (struct lwip_socket *)handle;
Christopher Haster 17:7db2f5d503d4 326
Christopher Haster 17:7db2f5d503d4 327 if (tcp_write(s->tcp, buf, size, TCP_WRITE_FLAG_COPY)) {
Christopher Haster 17:7db2f5d503d4 328 return NSAPI_ERROR_DEVICE_ERROR;
Christopher Haster 17:7db2f5d503d4 329 }
Christopher Haster 17:7db2f5d503d4 330
Christopher Haster 17:7db2f5d503d4 331 tcp_output(s->tcp);
Christopher Haster 17:7db2f5d503d4 332
Christopher Haster 17:7db2f5d503d4 333 return size;
Christopher Haster 17:7db2f5d503d4 334 }
Christopher Haster 17:7db2f5d503d4 335
Christopher Haster 17:7db2f5d503d4 336 static err_t tcp_recv_irq(void *handle, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
Christopher Haster 17:7db2f5d503d4 337 {
Christopher Haster 17:7db2f5d503d4 338 struct lwip_socket *s = (struct lwip_socket *)handle;
Christopher Haster 17:7db2f5d503d4 339
Christopher Haster 17:7db2f5d503d4 340 // Check for disconnect
Christopher Haster 17:7db2f5d503d4 341 if (!p) {
Christopher Haster 17:7db2f5d503d4 342 // Zero pcb during disconnect, since disconnect will cause a free
Christopher Haster 17:7db2f5d503d4 343 switch (tpcb->state) {
Christopher Haster 17:7db2f5d503d4 344 case FIN_WAIT_1:
Christopher Haster 17:7db2f5d503d4 345 case FIN_WAIT_2:
Christopher Haster 17:7db2f5d503d4 346 case TIME_WAIT:
Christopher Haster 17:7db2f5d503d4 347 s->tcp = 0;
Christopher Haster 17:7db2f5d503d4 348 break;
Christopher Haster 17:7db2f5d503d4 349 default:
Christopher Haster 17:7db2f5d503d4 350 break;
Christopher Haster 17:7db2f5d503d4 351 }
Christopher Haster 17:7db2f5d503d4 352 return ERR_OK;
Christopher Haster 17:7db2f5d503d4 353 }
Christopher Haster 17:7db2f5d503d4 354
Christopher Haster 17:7db2f5d503d4 355 __disable_irq();
Christopher Haster 17:7db2f5d503d4 356 if (!s->rx_chain) {
Christopher Haster 17:7db2f5d503d4 357 s->rx_chain = p;
Christopher Haster 17:7db2f5d503d4 358 } else {
Christopher Haster 17:7db2f5d503d4 359 pbuf_cat(s->rx_chain, p);
Christopher Haster 17:7db2f5d503d4 360 }
Christopher Haster 17:7db2f5d503d4 361 __enable_irq();
Christopher Haster 17:7db2f5d503d4 362
Christopher Haster 17:7db2f5d503d4 363 if (s->callback) {
Christopher Haster 17:7db2f5d503d4 364 s->callback(s->data);
Christopher Haster 17:7db2f5d503d4 365 }
Christopher Haster 17:7db2f5d503d4 366
Christopher Haster 17:7db2f5d503d4 367 return ERR_OK;
Christopher Haster 17:7db2f5d503d4 368 }
Christopher Haster 17:7db2f5d503d4 369
Christopher Haster 17:7db2f5d503d4 370 int LWIPInterface::socket_recv(void *handle, void *buf, unsigned size)
Christopher Haster 17:7db2f5d503d4 371 {
Christopher Haster 17:7db2f5d503d4 372 struct lwip_socket *s = (struct lwip_socket *)handle;
Christopher Haster 17:7db2f5d503d4 373
Christopher Haster 17:7db2f5d503d4 374 // Disconnected
Christopher Haster 17:7db2f5d503d4 375 if (!s->tcp && !s->rx_chain) {
Christopher Haster 17:7db2f5d503d4 376 return NSAPI_ERROR_NO_CONNECTION;
Christopher Haster 17:7db2f5d503d4 377 }
Christopher Haster 17:7db2f5d503d4 378
Christopher Haster 17:7db2f5d503d4 379 // Nothing ready
Christopher Haster 17:7db2f5d503d4 380 if (!s->rx_chain) {
Christopher Haster 17:7db2f5d503d4 381 return NSAPI_ERROR_WOULD_BLOCK;
Christopher Haster 17:7db2f5d503d4 382 }
Christopher Haster 17:7db2f5d503d4 383
Christopher Haster 17:7db2f5d503d4 384 // Copy out pbuf
Christopher Haster 17:7db2f5d503d4 385 struct pbuf *p = s->rx_chain;
Christopher Haster 17:7db2f5d503d4 386 int copied = pbuf_copy_partial(p, buf, size, 0);
Christopher Haster 17:7db2f5d503d4 387 s->rx_chain = pbuf_consume(p, copied, false);
Christopher Haster 17:7db2f5d503d4 388
Christopher Haster 17:7db2f5d503d4 389 // Update TCP window
Christopher Haster 17:7db2f5d503d4 390 tcp_recved(s->tcp, copied);
Christopher Haster 17:7db2f5d503d4 391 return copied;
Christopher Haster 17:7db2f5d503d4 392 }
Christopher Haster 17:7db2f5d503d4 393
Christopher Haster 17:7db2f5d503d4 394 int LWIPInterface::socket_sendto(void *handle, const SocketAddress &addr, const void *buf, unsigned size)
Christopher Haster 17:7db2f5d503d4 395 {
Christopher Haster 17:7db2f5d503d4 396 struct lwip_socket *s = (struct lwip_socket *)handle;
Christopher Haster 17:7db2f5d503d4 397
Christopher Haster 17:7db2f5d503d4 398 struct pbuf *pb = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
Christopher Haster 17:7db2f5d503d4 399 if (pbuf_take(pb, buf, size)) {
Christopher Haster 17:7db2f5d503d4 400 return NSAPI_ERROR_DEVICE_ERROR;
Christopher Haster 17:7db2f5d503d4 401 }
Christopher Haster 17:7db2f5d503d4 402
Christopher Haster 17:7db2f5d503d4 403 ip_addr_t id_addr;
Christopher Haster 17:7db2f5d503d4 404 inet_aton(addr.get_ip_address(), &id_addr);
Christopher Haster 17:7db2f5d503d4 405
Christopher Haster 17:7db2f5d503d4 406 err_t err = udp_sendto(s->udp, pb, &id_addr, addr.get_port());
Christopher Haster 17:7db2f5d503d4 407 pbuf_free(pb);
Christopher Haster 17:7db2f5d503d4 408 if (err) {
Christopher Haster 17:7db2f5d503d4 409 return NSAPI_ERROR_DEVICE_ERROR;
Christopher Haster 17:7db2f5d503d4 410 }
Christopher Haster 17:7db2f5d503d4 411
Christopher Haster 17:7db2f5d503d4 412 if (s->callback) {
Christopher Haster 17:7db2f5d503d4 413 s->callback(s->data);
Christopher Haster 17:7db2f5d503d4 414 }
Christopher Haster 17:7db2f5d503d4 415
Christopher Haster 17:7db2f5d503d4 416 return size;
Christopher Haster 17:7db2f5d503d4 417 }
Christopher Haster 17:7db2f5d503d4 418
Christopher Haster 17:7db2f5d503d4 419 static void udp_recv_irq(
Christopher Haster 17:7db2f5d503d4 420 void *handle, struct udp_pcb *upcb, struct pbuf *p,
Christopher Haster 17:7db2f5d503d4 421 struct ip_addr *addr, uint16_t port)
Christopher Haster 17:7db2f5d503d4 422 {
Christopher Haster 17:7db2f5d503d4 423 struct lwip_socket *s = (struct lwip_socket *)handle;
Christopher Haster 17:7db2f5d503d4 424
Christopher Haster 17:7db2f5d503d4 425 __disable_irq();
Christopher Haster 17:7db2f5d503d4 426 if (!s->rx_chain) {
Christopher Haster 17:7db2f5d503d4 427 s->rx_chain = p;
Christopher Haster 17:7db2f5d503d4 428 } else {
Christopher Haster 17:7db2f5d503d4 429 // Attach p to buffer chain without changing the tot_len
Christopher Haster 17:7db2f5d503d4 430 // NOTE: This is not how pbufs are intended to work, but it is necessary to deal with
Christopher Haster 17:7db2f5d503d4 431 // a) fragmentation and b) packet queueing
Christopher Haster 17:7db2f5d503d4 432 struct pbuf *q = s->rx_chain;
Christopher Haster 17:7db2f5d503d4 433 while (q->next) { q = q->next; }
Christopher Haster 17:7db2f5d503d4 434 q->next = p;
Christopher Haster 17:7db2f5d503d4 435 }
Christopher Haster 17:7db2f5d503d4 436 __enable_irq();
Christopher Haster 17:7db2f5d503d4 437
Christopher Haster 17:7db2f5d503d4 438 if (s->callback) {
Christopher Haster 17:7db2f5d503d4 439 s->callback(s->data);
Christopher Haster 17:7db2f5d503d4 440 }
Christopher Haster 17:7db2f5d503d4 441 }
Christopher Haster 17:7db2f5d503d4 442
Christopher Haster 17:7db2f5d503d4 443 int LWIPInterface::socket_recvfrom(void *handle, SocketAddress *addr, void *buf, unsigned size)
Christopher Haster 17:7db2f5d503d4 444 {
Christopher Haster 17:7db2f5d503d4 445 struct lwip_socket *s = (struct lwip_socket *)handle;
Christopher Haster 17:7db2f5d503d4 446
Christopher Haster 17:7db2f5d503d4 447 // Disconnected
Christopher Haster 17:7db2f5d503d4 448 if (!s->udp && !s->rx_chain) {
Christopher Haster 17:7db2f5d503d4 449 return NSAPI_ERROR_NO_CONNECTION;
Christopher Haster 17:7db2f5d503d4 450 }
Christopher Haster 17:7db2f5d503d4 451
Christopher Haster 17:7db2f5d503d4 452 // Nothing ready
Christopher Haster 17:7db2f5d503d4 453 if (!s->rx_chain) {
Christopher Haster 17:7db2f5d503d4 454 return NSAPI_ERROR_WOULD_BLOCK;
Christopher Haster 17:7db2f5d503d4 455 }
Christopher Haster 17:7db2f5d503d4 456
Christopher Haster 17:7db2f5d503d4 457 struct pbuf *p = s->rx_chain;
Christopher Haster 17:7db2f5d503d4 458
Christopher Haster 17:7db2f5d503d4 459 if (addr) {
Christopher Haster 17:7db2f5d503d4 460 struct udp_hdr *udphdr;
Christopher Haster 17:7db2f5d503d4 461 struct ip_hdr *iphdr;
Christopher Haster 17:7db2f5d503d4 462
Christopher Haster 17:7db2f5d503d4 463 // roll back the pbuf by udp_hdr to find the source port
Christopher Haster 17:7db2f5d503d4 464 pbuf_header(p, UDP_HLEN);
Christopher Haster 17:7db2f5d503d4 465 udphdr = (struct udp_hdr *)p->payload;
Christopher Haster 17:7db2f5d503d4 466
Christopher Haster 17:7db2f5d503d4 467 // roll back the pbuf by ip_hdr to find the source IP
Christopher Haster 17:7db2f5d503d4 468 pbuf_header(p, IP_HLEN);
Christopher Haster 17:7db2f5d503d4 469 iphdr = (struct ip_hdr *)p->payload;
Christopher Haster 17:7db2f5d503d4 470
Christopher Haster 17:7db2f5d503d4 471 // put the pbuf back where it was
Christopher Haster 17:7db2f5d503d4 472 pbuf_header(p, -UDP_HLEN - IP_HLEN);
Christopher Haster 17:7db2f5d503d4 473
Christopher Haster 17:7db2f5d503d4 474 addr->set_ip_address(inet_ntoa(iphdr->src));
Christopher Haster 17:7db2f5d503d4 475 addr->set_port(ntohs(udphdr->src));
Christopher Haster 17:7db2f5d503d4 476 }
Christopher Haster 17:7db2f5d503d4 477
Christopher Haster 17:7db2f5d503d4 478 // Copy out pbuf
Christopher Haster 17:7db2f5d503d4 479 size = size < p->tot_len ? size : p->tot_len;
Christopher Haster 17:7db2f5d503d4 480 int copied = pbuf_copy_partial(p, buf, size, 0);
Christopher Haster 17:7db2f5d503d4 481 s->rx_chain = pbuf_consume(p, p->tot_len, true);
Christopher Haster 17:7db2f5d503d4 482
Christopher Haster 17:7db2f5d503d4 483 return copied;
Christopher Haster 17:7db2f5d503d4 484 }
Christopher Haster 17:7db2f5d503d4 485
Christopher Haster 17:7db2f5d503d4 486 void LWIPInterface::socket_attach(void *handle, void (*callback)(void *), void *data)
Christopher Haster 17:7db2f5d503d4 487 {
Christopher Haster 17:7db2f5d503d4 488 struct lwip_socket *s = (struct lwip_socket *)handle;
Christopher Haster 17:7db2f5d503d4 489 s->callback = callback;
Christopher Haster 17:7db2f5d503d4 490 s->data = data;
Christopher Haster 17:7db2f5d503d4 491 }