Free (GPLv2) TCP/IP stack developed by TASS Belgium

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Committer:
tass picotcp@tass.be
Date:
Wed Apr 09 14:31:41 2014 +0200
Revision:
149:5f4cb161cec3
Parent:
147:c3d157ad90df
Child:
153:5e8a725dbd6e
Update from git masterbranch

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 29:1a47b7151851 1 /*********************************************************************
daniele 29:1a47b7151851 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 29:1a47b7151851 3 See LICENSE and COPYING for usage.
daniele 29:1a47b7151851 4
daniele 29:1a47b7151851 5 Authors: Daniele Lacamera
daniele 29:1a47b7151851 6 *********************************************************************/
daniele 29:1a47b7151851 7
daniele 29:1a47b7151851 8 #include "wrapper.h"
daniele 29:1a47b7151851 9 #include "rtos.h"
daniele 29:1a47b7151851 10 #include "cmsis_os.h"
daniele 29:1a47b7151851 11 #include "mbed.h"
daniele 29:1a47b7151851 12 #include "Socket.h"
daniele 29:1a47b7151851 13 #include "Mutex.h"
daniele 29:1a47b7151851 14
tass 37:bdf736327c71 15 extern "C"
tass 37:bdf736327c71 16 {
tass 90:478be2fd92ac 17 #include "pico_mbed.h"
tass 37:bdf736327c71 18 #include "pico_dns_client.h"
tass picotcp@tass.be 139:1f7a4a8525ef 19 #include "pico_dhcp_server.h"
tass 37:bdf736327c71 20 }
tass 37:bdf736327c71 21
tass 44:ffd9a11d4f95 22 //#define ptsock_dbg mbed_dbg
daniele 29:1a47b7151851 23 #define ptsock_dbg(...)
tass 50:8c79c30b48e3 24 #define SCHEDULER_BASE 4u
tass picotcp@tass.be 142:35da43068894 25 #define SCHEDULER_MAX 10
daniele 29:1a47b7151851 26
tass 50:8c79c30b48e3 27 int scheduler_timeout = 0;
daniele 29:1a47b7151851 28 int in_the_stack = 0;
daniele 29:1a47b7151851 29 Mutex *PicoTcpLock;
tass 37:bdf736327c71 30 Queue<void,32> *PicoTcpEvents;
daniele 29:1a47b7151851 31
daniele 29:1a47b7151851 32 static Thread * serverThread = NULL;
daniele 29:1a47b7151851 33
daniele 29:1a47b7151851 34 /* Testing ng blocking mechanism */
daniele 29:1a47b7151851 35
daniele 29:1a47b7151851 36 /*
daniele 29:1a47b7151851 37 * backend of select function, used in blocking (like picotcp_read()...)
daniele 29:1a47b7151851 38 * calls. Sleeps on the message queue
daniele 29:1a47b7151851 39 *
daniele 29:1a47b7151851 40 *
daniele 29:1a47b7151851 41 * WARNING: PicoTcpLock (big stack lock) must be acquired before entering this.
daniele 29:1a47b7151851 42 */
tass 58:5f6eedbbbd5b 43 void picotcp_async_clean(struct pico_device * dev);
tass 32:865c101e0874 44 static inline int __critical_select(struct stack_endpoint *ep, uint32_t time, uint8_t lock)
daniele 29:1a47b7151851 45 {
daniele 29:1a47b7151851 46 uint32_t in_time = PICO_TIME_MS();
daniele 29:1a47b7151851 47
tass 32:865c101e0874 48 if(lock) PicoTcpLock->unlock();
daniele 29:1a47b7151851 49 while ((ep->events & ep->revents) == 0) {
daniele 29:1a47b7151851 50 ep->queue->get(time);
daniele 29:1a47b7151851 51 if ((time != osWaitForever) && (PICO_TIME_MS() > in_time + time)) {
tass 42:13e557b44f68 52 ptsock_dbg("TIMEOUT in critical select... (ev:%04x rev:%04x \n", ep->events, ep->revents);
tass 32:865c101e0874 53 if(lock) PicoTcpLock->lock();
daniele 29:1a47b7151851 54 return 0;
daniele 29:1a47b7151851 55 }
daniele 29:1a47b7151851 56 }
tass 32:865c101e0874 57 if(lock) PicoTcpLock->lock();
daniele 29:1a47b7151851 58 return 1;
daniele 29:1a47b7151851 59 }
daniele 29:1a47b7151851 60
daniele 29:1a47b7151851 61 static void wakeup(uint16_t ev, struct pico_socket *s)
daniele 29:1a47b7151851 62 {
daniele 29:1a47b7151851 63 struct stack_endpoint *ep = (struct stack_endpoint *)s->priv;
daniele 29:1a47b7151851 64 if (!ep) {
tass 97:e73b01cb3147 65 ptsock_dbg("WAKEUP: socket not found! ev=%04x\n", ev);
tass 97:e73b01cb3147 66 return;
daniele 29:1a47b7151851 67 }
daniele 29:1a47b7151851 68 //if (((ep->revents & PICO_SOCK_EV_RD) == 0) && (ev & PICO_SOCK_EV_RD))
daniele 29:1a47b7151851 69 // printf("Activating RD\n");
tass 97:e73b01cb3147 70 if(!ep->s || !ep->queue)
tass 55:734099a8df4e 71 {
tass 55:734099a8df4e 72 ptsock_dbg("Endpoint null warning : ep=%p, ep->s=%p, ep->queue=%p\n",ep,ep->s,ep->queue);
tass 55:734099a8df4e 73 return;
tass 55:734099a8df4e 74 }
tass 55:734099a8df4e 75
daniele 29:1a47b7151851 76 ep->revents |= ev;
tass 55:734099a8df4e 77
tass 32:865c101e0874 78 if(ev & PICO_SOCK_EV_ERR)
tass 32:865c101e0874 79 {
tass 32:865c101e0874 80 if(pico_err == PICO_ERR_ECONNRESET)
tass 32:865c101e0874 81 {
tass 42:13e557b44f68 82 ptsock_dbg("Connection reset by peer...\n");
tass 32:865c101e0874 83 ep->state = SOCK_RESET_BY_PEER;
tass 32:865c101e0874 84 pico_socket_close(ep->s);
tass 32:865c101e0874 85 ep->s->priv = NULL;
tass 32:865c101e0874 86 }
tass 32:865c101e0874 87 }
daniele 29:1a47b7151851 88 if ((ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN)) {
daniele 29:1a47b7151851 89 ep->connected = 0;
tass 37:bdf736327c71 90 pico_socket_close(ep->s);
tass 77:6764a53bb6e6 91 ep->s->priv = NULL;
tass 35:6078073547bb 92 ep->state = SOCK_CLOSED;
daniele 29:1a47b7151851 93 }
tass 60:a57e18c13f5e 94 if (ev & PICO_SOCK_EV_CONN) {
daniele 29:1a47b7151851 95 ep->connected = 1;
tass 35:6078073547bb 96 ep->state = SOCK_CONNECTED;
daniele 29:1a47b7151851 97 }
daniele 29:1a47b7151851 98 ep->queue->put((void *)0);
daniele 29:1a47b7151851 99 }
daniele 29:1a47b7151851 100
daniele 29:1a47b7151851 101
daniele 29:1a47b7151851 102 struct stack_endpoint *picotcp_socket(uint16_t net, uint16_t proto, uint16_t timeout)
daniele 29:1a47b7151851 103 {
daniele 29:1a47b7151851 104 struct stack_endpoint *ep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint));
daniele 29:1a47b7151851 105 uint16_t p_net = ((net == AF_INET6)?PICO_PROTO_IPV6:PICO_PROTO_IPV4);
daniele 29:1a47b7151851 106 uint16_t p_proto = ((proto == SOCK_DGRAM)?PICO_PROTO_UDP:PICO_PROTO_TCP);
daniele 29:1a47b7151851 107 PicoTcpLock->lock();
daniele 29:1a47b7151851 108 ep->s = pico_socket_open( p_net, p_proto, &wakeup );
daniele 29:1a47b7151851 109 if (ep->s == NULL) {
daniele 29:1a47b7151851 110 delete(ep->queue);
daniele 29:1a47b7151851 111 pico_free(ep);
daniele 29:1a47b7151851 112 ep = NULL;
tass 42:13e557b44f68 113 ptsock_dbg("Error opening socket!\n");
daniele 29:1a47b7151851 114 } else {
daniele 29:1a47b7151851 115 ep->s->priv = ep;
tass 42:13e557b44f68 116 ptsock_dbg("Added socket (open)\n");
tass 35:6078073547bb 117 ep->state = SOCK_OPEN;
daniele 29:1a47b7151851 118 ep->queue = new Queue<void,1>();
daniele 29:1a47b7151851 119 }
daniele 29:1a47b7151851 120 PicoTcpLock->unlock();
daniele 29:1a47b7151851 121 return ep;
daniele 29:1a47b7151851 122 }
daniele 29:1a47b7151851 123
daniele 29:1a47b7151851 124
daniele 29:1a47b7151851 125 int picotcp_state(struct stack_endpoint *ep)
daniele 29:1a47b7151851 126 {
daniele 29:1a47b7151851 127 return ep->state;
daniele 29:1a47b7151851 128 }
daniele 29:1a47b7151851 129
daniele 29:1a47b7151851 130 int picotcp_bind(struct stack_endpoint *ep, struct sockaddr *_local_addr, socklen_t len)
daniele 29:1a47b7151851 131 {
daniele 29:1a47b7151851 132 int ret;
daniele 29:1a47b7151851 133 struct sockaddr_in *local_addr;
daniele 29:1a47b7151851 134 local_addr = (struct sockaddr_in *)_local_addr;
daniele 29:1a47b7151851 135
daniele 29:1a47b7151851 136 PicoTcpLock->lock();
daniele 29:1a47b7151851 137 ret = pico_socket_bind(ep->s, (struct pico_ip4 *)(&local_addr->sin_addr.s_addr), &local_addr->sin_port);
tass 35:6078073547bb 138 if(ret == 0)
tass 35:6078073547bb 139 ep->state = SOCK_BOUND;
daniele 29:1a47b7151851 140 PicoTcpLock->unlock();
daniele 29:1a47b7151851 141 return ret;
daniele 29:1a47b7151851 142 }
daniele 29:1a47b7151851 143
daniele 29:1a47b7151851 144 int picotcp_listen(struct stack_endpoint *ep, int queue)
daniele 29:1a47b7151851 145 {
daniele 29:1a47b7151851 146 int ret;
daniele 29:1a47b7151851 147 PicoTcpLock->lock();
daniele 29:1a47b7151851 148 ret = pico_socket_listen(ep->s, queue);
tass 97:e73b01cb3147 149
tass 35:6078073547bb 150 if(ret == 0)
tass 35:6078073547bb 151 ep->state = SOCK_LISTEN;
daniele 29:1a47b7151851 152 PicoTcpLock->unlock();
daniele 29:1a47b7151851 153 return ret;
daniele 29:1a47b7151851 154 }
daniele 29:1a47b7151851 155
daniele 29:1a47b7151851 156 int picotcp_connect(struct stack_endpoint *ep, struct sockaddr *_srv_addr, socklen_t len)
daniele 29:1a47b7151851 157 {
daniele 29:1a47b7151851 158 int retval;
daniele 29:1a47b7151851 159 struct sockaddr_in *srv_addr;
daniele 29:1a47b7151851 160 srv_addr = (struct sockaddr_in *)_srv_addr;
daniele 29:1a47b7151851 161 PicoTcpLock->lock();
daniele 29:1a47b7151851 162 pico_socket_connect(ep->s, (struct pico_ip4 *)(&srv_addr->sin_addr.s_addr), srv_addr->sin_port);
daniele 29:1a47b7151851 163 ep->events = PICO_SOCK_EV_CONN | PICO_SOCK_EV_ERR;
daniele 33:d8af3f85a484 164 __critical_select(ep, osWaitForever, 1);
daniele 29:1a47b7151851 165 if ((ep->revents & PICO_SOCK_EV_CONN) && ep->connected) {
daniele 29:1a47b7151851 166 ep->revents &= (~PICO_SOCK_EV_CONN);
daniele 29:1a47b7151851 167 ep->revents |= PICO_SOCK_EV_WR;
daniele 29:1a47b7151851 168 ptsock_dbg("Established. sock state: %x\n", ep->s->state);
tass 35:6078073547bb 169 ep->state = SOCK_CONNECTED;
daniele 29:1a47b7151851 170 retval = 0;
daniele 29:1a47b7151851 171 } else {
daniele 29:1a47b7151851 172 retval = -1;
daniele 29:1a47b7151851 173 }
daniele 29:1a47b7151851 174 PicoTcpLock->unlock();
daniele 29:1a47b7151851 175 return retval;
daniele 29:1a47b7151851 176 }
daniele 29:1a47b7151851 177
daniele 29:1a47b7151851 178 struct stack_endpoint *picotcp_accept(struct stack_endpoint *ep, struct sockaddr *_cli_addr, socklen_t *len)
daniele 29:1a47b7151851 179 {
daniele 29:1a47b7151851 180 struct sockaddr_in *cli_addr = (struct sockaddr_in *)_cli_addr;
tass 97:e73b01cb3147 181 struct stack_endpoint *aep = (struct stack_endpoint *) pico_zalloc(sizeof(struct stack_endpoint));
tass 97:e73b01cb3147 182 if (aep)
tass 97:e73b01cb3147 183 aep->queue = new Queue<void,1>();
tass 97:e73b01cb3147 184 else
daniele 29:1a47b7151851 185 return aep;
daniele 29:1a47b7151851 186
daniele 29:1a47b7151851 187 PicoTcpLock->lock();
daniele 29:1a47b7151851 188 ep->events = PICO_SOCK_EV_CONN | PICO_SOCK_EV_ERR;
daniele 33:d8af3f85a484 189 __critical_select(ep, osWaitForever, 1);
daniele 29:1a47b7151851 190 if (ep->revents & PICO_SOCK_EV_CONN) {
tass 42:13e557b44f68 191 ptsock_dbg("Calling Accept\n");
daniele 29:1a47b7151851 192 aep->s = pico_socket_accept(ep->s, (struct pico_ip4 *)(&cli_addr->sin_addr.s_addr), &cli_addr->sin_port);
tass 42:13e557b44f68 193 ptsock_dbg("Accept returned\n");
daniele 29:1a47b7151851 194 aep->s->priv = aep;
daniele 29:1a47b7151851 195 ep->revents &= (~PICO_SOCK_EV_CONN);
tass 32:865c101e0874 196 aep->revents = 0; // set this to 0 to allow seq connections
daniele 29:1a47b7151851 197 aep->revents |= PICO_SOCK_EV_WR;
tass 35:6078073547bb 198 aep->state = SOCK_CONNECTED;
tass 42:13e557b44f68 199 ptsock_dbg("Added socket (accept)\n");
daniele 29:1a47b7151851 200
daniele 29:1a47b7151851 201 *len = sizeof(struct sockaddr_in);
daniele 29:1a47b7151851 202 ptsock_dbg("Established. sock state: %x\n", aep->s->state);
daniele 29:1a47b7151851 203 } else {
daniele 29:1a47b7151851 204 pico_free(aep);
daniele 29:1a47b7151851 205 aep = NULL;
daniele 29:1a47b7151851 206 }
daniele 29:1a47b7151851 207 PicoTcpLock->unlock();
daniele 29:1a47b7151851 208 return aep;
daniele 29:1a47b7151851 209 }
daniele 29:1a47b7151851 210
daniele 29:1a47b7151851 211 int picotcp_select(struct stack_endpoint *ep, struct timeval *timeout, int read, int write)
daniele 29:1a47b7151851 212 {
daniele 29:1a47b7151851 213 int ret;
daniele 29:1a47b7151851 214 ep->timeout |= timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
daniele 29:1a47b7151851 215 ep->events = PICO_SOCK_EV_ERR;
daniele 29:1a47b7151851 216 ep->events |= PICO_SOCK_EV_FIN;
daniele 29:1a47b7151851 217 ep->events |= PICO_SOCK_EV_CLOSE;
daniele 29:1a47b7151851 218 ep->events |= PICO_SOCK_EV_CONN;
daniele 29:1a47b7151851 219 if (read) {
daniele 29:1a47b7151851 220 ep->events |= PICO_SOCK_EV_RD;
daniele 29:1a47b7151851 221 }
daniele 29:1a47b7151851 222 if (write)
daniele 29:1a47b7151851 223 ep->events |= PICO_SOCK_EV_WR;
daniele 33:d8af3f85a484 224 ret = __critical_select(ep, ep->timeout, 0);
daniele 29:1a47b7151851 225 return ret;
daniele 29:1a47b7151851 226 }
daniele 29:1a47b7151851 227
tass 35:6078073547bb 228 int picotcp_send(struct stack_endpoint *ep,void * buf, int len, int flags)
daniele 29:1a47b7151851 229 {
tass 35:6078073547bb 230 int retval = 0;
tass 35:6078073547bb 231 int tot_len = 0;
tass 35:6078073547bb 232 if (!buf || (len <= 0))
tass 35:6078073547bb 233 return 0;
tass 35:6078073547bb 234 PicoTcpLock->lock();
tass 35:6078073547bb 235 while (tot_len < len) {
tass 35:6078073547bb 236 retval = pico_socket_send(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
tass 35:6078073547bb 237 if (retval == 0) {
tass 35:6078073547bb 238 if (tot_len < len)
tass 35:6078073547bb 239 ep->revents &= ~PICO_SOCK_EV_WR;
tass 35:6078073547bb 240 break;
tass 35:6078073547bb 241 }
tass 35:6078073547bb 242 if (retval < 0) {
tass 38:b71e5dd1806a 243 if(tot_len == 0) tot_len = -1;
tass 35:6078073547bb 244 break;
tass 35:6078073547bb 245 }
tass 35:6078073547bb 246 tot_len += retval;
tass 35:6078073547bb 247 }
tass 35:6078073547bb 248 PicoTcpLock->unlock();
tass 35:6078073547bb 249 picotcp_async_interrupt(NULL);
tass 35:6078073547bb 250 return tot_len;
tass 35:6078073547bb 251 }
tass 35:6078073547bb 252
tass 35:6078073547bb 253 int picotcp_recv(struct stack_endpoint *ep,void * buf, int len, int flags)
tass 35:6078073547bb 254 {
tass 35:6078073547bb 255 int retval = 0;
tass 35:6078073547bb 256 int tot_len = 0;
tass 35:6078073547bb 257 if (!buf || (len <= 0))
tass 35:6078073547bb 258 return 0;
tass 35:6078073547bb 259 PicoTcpLock->lock();
tass 35:6078073547bb 260 while (tot_len < len) {
tass 35:6078073547bb 261 retval = pico_socket_recv(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
tass 35:6078073547bb 262 if (retval == 0) {
tass 35:6078073547bb 263 if (tot_len < len)
tass 35:6078073547bb 264 ep->revents &= ~PICO_SOCK_EV_RD;
tass 35:6078073547bb 265 break;
tass 35:6078073547bb 266 }
tass 35:6078073547bb 267 if (retval < 0) {
tass 37:bdf736327c71 268 if(tot_len == 0) tot_len = -1;
tass 35:6078073547bb 269 break;
tass 35:6078073547bb 270 }
tass 35:6078073547bb 271 tot_len += retval;
tass 35:6078073547bb 272 }
tass 35:6078073547bb 273 PicoTcpLock->unlock();
tass 35:6078073547bb 274 picotcp_async_interrupt(NULL);
tass 35:6078073547bb 275 return tot_len;
daniele 29:1a47b7151851 276 }
daniele 29:1a47b7151851 277
tass 35:6078073547bb 278 int picotcp_sendto(struct stack_endpoint * ep,void * buf, int len, struct sockaddr* a,socklen_t size)
daniele 29:1a47b7151851 279 {
tass 35:6078073547bb 280 int retval = 0;
tass 35:6078073547bb 281 int tot_len = 0;
tass 35:6078073547bb 282 struct sockaddr_in * in = (struct sockaddr_in *)a;
tass 35:6078073547bb 283 if (!buf || (len <= 0))
tass 35:6078073547bb 284 return 0;
tass 35:6078073547bb 285 if(!ep->broadcast && pico_ipv4_is_broadcast(in->sin_addr.s_addr))
tass 35:6078073547bb 286 return -1;
tass 35:6078073547bb 287
tass 35:6078073547bb 288 PicoTcpLock->lock();
tass 35:6078073547bb 289 while (tot_len < len) {
tass 35:6078073547bb 290 retval = pico_socket_sendto(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len,(struct pico_ip4 *)&in->sin_addr.s_addr, in->sin_port);
tass 35:6078073547bb 291
tass 35:6078073547bb 292 if (retval == 0)
tass 35:6078073547bb 293 break;
tass 35:6078073547bb 294
tass 35:6078073547bb 295 if (retval < 0) {
tass 38:b71e5dd1806a 296 if(tot_len == 0) tot_len = -1;
tass 35:6078073547bb 297 break;
tass 35:6078073547bb 298 }
tass 35:6078073547bb 299 tot_len += retval;
tass 35:6078073547bb 300 }
tass 35:6078073547bb 301 PicoTcpLock->unlock();
tass 35:6078073547bb 302 picotcp_async_interrupt(NULL);
tass 35:6078073547bb 303 return tot_len;
daniele 29:1a47b7151851 304 }
daniele 29:1a47b7151851 305
tass 35:6078073547bb 306 int picotcp_recvfrom(struct stack_endpoint *ep,void * buf, int len, struct sockaddr *a, socklen_t * size)
daniele 29:1a47b7151851 307 {
tass 35:6078073547bb 308 (void)len;
tass 35:6078073547bb 309 int retval = 0;
tass 35:6078073547bb 310 int tot_len = 0;
tass 35:6078073547bb 311 struct sockaddr_in * in = (struct sockaddr_in *)a;
tass 35:6078073547bb 312 if (!buf || (len <= 0))
tass 35:6078073547bb 313 return 0;
tass 35:6078073547bb 314 PicoTcpLock->lock();
tass 35:6078073547bb 315 while (tot_len < len) {
tass 35:6078073547bb 316 retval = pico_socket_recvfrom(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len,(struct pico_ip4 *)&(in->sin_addr.s_addr),&in->sin_port);
tass 35:6078073547bb 317 if (retval == 0) {
tass 35:6078073547bb 318 if (tot_len < len)
tass 35:6078073547bb 319 ep->revents &= ~PICO_SOCK_EV_RD;
tass 35:6078073547bb 320 break;
tass 35:6078073547bb 321 }
tass 35:6078073547bb 322 if (retval < 0) {
tass 37:bdf736327c71 323 if(tot_len == 0) tot_len = -1;
tass 35:6078073547bb 324 break;
tass 35:6078073547bb 325 }
tass 35:6078073547bb 326 tot_len += retval;
TASS Belgium NV 145:dbc31fdc150d 327 break;
tass 35:6078073547bb 328 }
tass 35:6078073547bb 329 PicoTcpLock->unlock();
tass 35:6078073547bb 330 picotcp_async_interrupt(NULL);
tass 35:6078073547bb 331 return tot_len;
daniele 29:1a47b7151851 332 }
daniele 29:1a47b7151851 333
daniele 29:1a47b7151851 334 int picotcp_read(struct stack_endpoint *ep,void *buf, int len)
daniele 29:1a47b7151851 335 {
daniele 29:1a47b7151851 336 int retval = 0;
daniele 29:1a47b7151851 337 int tot_len = 0;
daniele 29:1a47b7151851 338 if (!buf || (len <= 0))
daniele 29:1a47b7151851 339 return 0;
daniele 29:1a47b7151851 340 PicoTcpLock->lock();
daniele 29:1a47b7151851 341 while (tot_len < len) {
daniele 29:1a47b7151851 342 retval = pico_socket_read(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
daniele 29:1a47b7151851 343 if (retval == 0) {
daniele 29:1a47b7151851 344 if (tot_len < len)
daniele 29:1a47b7151851 345 ep->revents &= ~PICO_SOCK_EV_RD;
daniele 29:1a47b7151851 346 break;
daniele 29:1a47b7151851 347 }
daniele 29:1a47b7151851 348 if (retval < 0) {
tass 37:bdf736327c71 349 if(tot_len == 0) tot_len = -1;
daniele 29:1a47b7151851 350 break;
daniele 29:1a47b7151851 351 }
daniele 29:1a47b7151851 352 tot_len += retval;
daniele 29:1a47b7151851 353 }
daniele 29:1a47b7151851 354 PicoTcpLock->unlock();
daniele 29:1a47b7151851 355 picotcp_async_interrupt(NULL);
daniele 29:1a47b7151851 356 return tot_len;
daniele 29:1a47b7151851 357 }
daniele 29:1a47b7151851 358
daniele 29:1a47b7151851 359 int picotcp_write(struct stack_endpoint *ep,void *buf, int len)
daniele 29:1a47b7151851 360 {
daniele 29:1a47b7151851 361 int retval = 0;
daniele 29:1a47b7151851 362 int tot_len = 0;
daniele 29:1a47b7151851 363 if (!buf || (len <= 0))
daniele 29:1a47b7151851 364 return 0;
daniele 29:1a47b7151851 365 PicoTcpLock->lock();
daniele 29:1a47b7151851 366 while (tot_len < len) {
daniele 29:1a47b7151851 367 retval = pico_socket_write(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
tass 42:13e557b44f68 368
daniele 29:1a47b7151851 369 if (retval == 0) {
daniele 29:1a47b7151851 370 if (tot_len < len)
tass 35:6078073547bb 371 ep->revents &= ~PICO_SOCK_EV_WR;
daniele 29:1a47b7151851 372 break;
daniele 29:1a47b7151851 373 }
daniele 29:1a47b7151851 374 if (retval < 0) {
tass 38:b71e5dd1806a 375 if(tot_len == 0) tot_len = -1;
daniele 29:1a47b7151851 376 break;
daniele 29:1a47b7151851 377 }
daniele 29:1a47b7151851 378 tot_len += retval;
daniele 29:1a47b7151851 379 }
daniele 29:1a47b7151851 380 PicoTcpLock->unlock();
daniele 29:1a47b7151851 381 picotcp_async_interrupt(NULL);
daniele 29:1a47b7151851 382 return tot_len;
daniele 29:1a47b7151851 383 }
daniele 29:1a47b7151851 384
daniele 29:1a47b7151851 385
daniele 29:1a47b7151851 386 int picotcp_setsockopt(struct stack_endpoint *ep, int option, void *value)
daniele 29:1a47b7151851 387 {
tass 35:6078073547bb 388 int ret;
tass 35:6078073547bb 389
tass 35:6078073547bb 390 PicoTcpLock->lock();
tass 35:6078073547bb 391 if(option == SO_BROADCAST)
tass 35:6078073547bb 392 {
tass 35:6078073547bb 393 ep->broadcast = *(int *)value;
tass 35:6078073547bb 394 ret = 0;
tass 35:6078073547bb 395 }
tass 35:6078073547bb 396 else
tass 35:6078073547bb 397 ret = pico_socket_setoption(ep->s,option,value);
tass 35:6078073547bb 398 PicoTcpLock->unlock();
tass 35:6078073547bb 399
tass 35:6078073547bb 400 return ret;
daniele 29:1a47b7151851 401 }
daniele 29:1a47b7151851 402
daniele 29:1a47b7151851 403 int picotcp_getsockopt(struct stack_endpoint *ep, int option, void *value)
daniele 29:1a47b7151851 404 {
tass 35:6078073547bb 405 int ret;
tass 35:6078073547bb 406
tass 35:6078073547bb 407 PicoTcpLock->lock();
tass 35:6078073547bb 408 ret = pico_socket_getoption(ep->s,option,value);
tass 35:6078073547bb 409 PicoTcpLock->unlock();
tass 35:6078073547bb 410
tass 35:6078073547bb 411 return ret;
daniele 29:1a47b7151851 412 }
daniele 29:1a47b7151851 413
daniele 29:1a47b7151851 414 int picotcp_close(struct stack_endpoint *ep)
daniele 29:1a47b7151851 415 {
tass 121:296cd46e5e5b 416 int ret = 0;
daniele 29:1a47b7151851 417 PicoTcpLock->lock();
tass 76:938a140caf12 418 if(ep->state != SOCK_RESET_BY_PEER && ep->state != SOCK_CLOSED)
tass 32:865c101e0874 419 {
tass 32:865c101e0874 420 pico_socket_close(ep->s);
tass 121:296cd46e5e5b 421 // wait for fin, but timeout
tass 121:296cd46e5e5b 422 if( !(ep->revents & PICO_SOCK_EV_FIN) && !(ep->revents & PICO_SOCK_EV_CLOSE))
tass 121:296cd46e5e5b 423 {
tass 121:296cd46e5e5b 424 ep->events = (PICO_SOCK_EV_FIN | PICO_SOCK_EV_CLOSE | PICO_SOCK_EV_ERR);
tass 121:296cd46e5e5b 425 __critical_select(ep,3000u,1);// wait for 3 seconds
tass 121:296cd46e5e5b 426 ret = ((ep->revents & PICO_SOCK_EV_FIN) || (ep->revents & PICO_SOCK_EV_CLOSE) ? 0:-1);
tass 121:296cd46e5e5b 427 }
tass 32:865c101e0874 428 ep->s->priv = NULL;
tass 32:865c101e0874 429 }
tass 42:13e557b44f68 430 ptsock_dbg("Socket closed!\n");
daniele 29:1a47b7151851 431 delete(ep->queue);
daniele 29:1a47b7151851 432 pico_free(ep);
daniele 29:1a47b7151851 433 PicoTcpLock->unlock();
tass 121:296cd46e5e5b 434 return ret;
daniele 29:1a47b7151851 435 }
daniele 29:1a47b7151851 436
daniele 29:1a47b7151851 437 int picotcp_join_multicast(struct stack_endpoint *ep,const char* address,const char* local)
daniele 29:1a47b7151851 438 {
tass 35:6078073547bb 439 int ret;
tass 35:6078073547bb 440 struct pico_ip_mreq mreq={};
tass 35:6078073547bb 441
tass 35:6078073547bb 442 PicoTcpLock->lock();
tass 35:6078073547bb 443 pico_string_to_ipv4(address,&mreq.mcast_group_addr.addr);
tass 35:6078073547bb 444 pico_string_to_ipv4(local,&mreq.mcast_link_addr.addr);
tass 35:6078073547bb 445 ret = pico_socket_setoption(ep->s, PICO_IP_ADD_MEMBERSHIP, &mreq);
tass 35:6078073547bb 446 PicoTcpLock->unlock();
tass 35:6078073547bb 447
tass 35:6078073547bb 448 return ret;
daniele 29:1a47b7151851 449 }
daniele 29:1a47b7151851 450
daniele 29:1a47b7151851 451 void pico_wrapper_loop(const void * arg)
daniele 29:1a47b7151851 452 {
tass 89:49ca05d9a19e 453 #ifdef PICO_MEASURE_STACK
tass 89:49ca05d9a19e 454 stack_fill_pattern((void *)&arg);
tass 89:49ca05d9a19e 455 #else
daniele 29:1a47b7151851 456 (void)arg;
tass 89:49ca05d9a19e 457 #endif
tass 89:49ca05d9a19e 458
daniele 29:1a47b7151851 459 struct pico_device *dev;
daniele 29:1a47b7151851 460 while(1) {
daniele 29:1a47b7151851 461
tass 50:8c79c30b48e3 462 osEvent evt = PicoTcpEvents->get(SCHEDULER_BASE<<scheduler_timeout);
daniele 29:1a47b7151851 463
daniele 29:1a47b7151851 464 if (evt.status == osEventMessage) {
daniele 29:1a47b7151851 465 dev = (struct pico_device *)evt.value.p;
tass 50:8c79c30b48e3 466 scheduler_timeout = 0;
daniele 29:1a47b7151851 467 } else {
daniele 29:1a47b7151851 468 dev = NULL;
tass 50:8c79c30b48e3 469 if(scheduler_timeout < SCHEDULER_MAX)
tass 50:8c79c30b48e3 470 scheduler_timeout++;
daniele 29:1a47b7151851 471 }
daniele 29:1a47b7151851 472 PicoTcpLock->lock();
daniele 29:1a47b7151851 473 if (dev && dev->dsr)
daniele 29:1a47b7151851 474 dev->dsr(dev, 5);
tass 58:5f6eedbbbd5b 475 picotcp_async_clean(dev);
daniele 29:1a47b7151851 476 pico_stack_tick();
daniele 29:1a47b7151851 477 pico_stack_tick();
tass 89:49ca05d9a19e 478 #ifdef PICO_MEASURE_STACK
tass 89:49ca05d9a19e 479 stack_count_free_words((void *)&arg);
tass 89:49ca05d9a19e 480 #endif
daniele 29:1a47b7151851 481 PicoTcpLock->unlock();
daniele 29:1a47b7151851 482 }
daniele 29:1a47b7151851 483 }
daniele 29:1a47b7151851 484
daniele 29:1a47b7151851 485 void picotcp_start(void)
daniele 29:1a47b7151851 486 {
daniele 29:1a47b7151851 487 if (serverThread == NULL) {
daniele 29:1a47b7151851 488 PicoTcpLock = new Mutex();
tass 37:bdf736327c71 489 PicoTcpEvents = new Queue<void,32>();
tass 42:13e557b44f68 490 ptsock_dbg (" *** PicoTCP initialized *** \n");
tass 56:cb6001a770da 491 serverThread = new Thread(pico_wrapper_loop,NULL,osPriorityNormal,4096);
daniele 29:1a47b7151851 492 serverThread->set_priority(osPriorityIdle);
daniele 29:1a47b7151851 493 }
daniele 29:1a47b7151851 494 }
daniele 29:1a47b7151851 495
daniele 29:1a47b7151851 496 void picotcp_init(void)
daniele 29:1a47b7151851 497 {
daniele 29:1a47b7151851 498 picotcp_start();
daniele 29:1a47b7151851 499 }
daniele 29:1a47b7151851 500
tass picotcp@tass.be 139:1f7a4a8525ef 501 int picotcp_dhcp_server_start(struct pico_dhcp_server_setting *setting)
tass picotcp@tass.be 139:1f7a4a8525ef 502 {
tass picotcp@tass.be 139:1f7a4a8525ef 503 int ret;
tass picotcp@tass.be 139:1f7a4a8525ef 504
tass picotcp@tass.be 139:1f7a4a8525ef 505 PicoTcpLock->lock();
tass picotcp@tass.be 139:1f7a4a8525ef 506 ret = pico_dhcp_server_initiate(setting);
tass picotcp@tass.be 139:1f7a4a8525ef 507 PicoTcpLock->unlock();
tass picotcp@tass.be 139:1f7a4a8525ef 508 picotcp_async_interrupt(NULL);
tass picotcp@tass.be 139:1f7a4a8525ef 509
tass picotcp@tass.be 139:1f7a4a8525ef 510 return ret;
tass picotcp@tass.be 139:1f7a4a8525ef 511 }
tass picotcp@tass.be 139:1f7a4a8525ef 512
tass 58:5f6eedbbbd5b 513 /****** Asynchronous event handling ******/
tass 58:5f6eedbbbd5b 514 static int appEvents = 0;
tass 58:5f6eedbbbd5b 515 static Mutex asyncMutex;
tass 58:5f6eedbbbd5b 516 void picotcp_async_interrupt(void *arg)
daniele 29:1a47b7151851 517 {
tass 58:5f6eedbbbd5b 518 asyncMutex.lock();
tass 58:5f6eedbbbd5b 519 if(!arg)
tass 58:5f6eedbbbd5b 520 {
tass 58:5f6eedbbbd5b 521 if(!appEvents) // add NULL to queue
tass 58:5f6eedbbbd5b 522 PicoTcpEvents->put(NULL);
tass 58:5f6eedbbbd5b 523 appEvents++;
tass 58:5f6eedbbbd5b 524 }
tass 58:5f6eedbbbd5b 525 else
tass 58:5f6eedbbbd5b 526 {
tass 58:5f6eedbbbd5b 527 struct pico_device * dev = (struct pico_device *)arg;
tass 58:5f6eedbbbd5b 528 if(!dev->eventCnt) // put arg to queue
tass 58:5f6eedbbbd5b 529 PicoTcpEvents->put(dev);
tass 58:5f6eedbbbd5b 530 dev->eventCnt++;
tass 58:5f6eedbbbd5b 531 }
tass 58:5f6eedbbbd5b 532 asyncMutex.unlock();
daniele 29:1a47b7151851 533 }
tass 37:bdf736327c71 534
tass 58:5f6eedbbbd5b 535 void picotcp_async_clean(struct pico_device * dev)
tass 58:5f6eedbbbd5b 536 {
tass 58:5f6eedbbbd5b 537 asyncMutex.lock();
tass 58:5f6eedbbbd5b 538 if(!dev)
tass 58:5f6eedbbbd5b 539 appEvents = 0;
tass 58:5f6eedbbbd5b 540 else
tass 58:5f6eedbbbd5b 541 dev->eventCnt=0;
tass 58:5f6eedbbbd5b 542 asyncMutex.unlock();
tass 58:5f6eedbbbd5b 543 }
tass 58:5f6eedbbbd5b 544
tass 58:5f6eedbbbd5b 545 /*******************************/
tass 58:5f6eedbbbd5b 546
tass 58:5f6eedbbbd5b 547
tass 37:bdf736327c71 548 // *************** DNS part ***************
tass picotcp@tass.be 142:35da43068894 549
tass picotcp@tass.be 142:35da43068894 550 int picotcp_dns_client_nameserver(const char *ip, int flag)
tass picotcp@tass.be 142:35da43068894 551 {
tass picotcp@tass.be 142:35da43068894 552 int ret;
tass picotcp@tass.be 142:35da43068894 553 struct pico_ip4 addr;
tass picotcp@tass.be 142:35da43068894 554 pico_string_to_ipv4(ip, &addr.addr);
tass picotcp@tass.be 142:35da43068894 555
tass picotcp@tass.be 142:35da43068894 556 PicoTcpLock->lock();
tass picotcp@tass.be 142:35da43068894 557 ret = pico_dns_client_nameserver(&addr, flag);
tass picotcp@tass.be 142:35da43068894 558 PicoTcpLock->unlock();
tass picotcp@tass.be 142:35da43068894 559
tass picotcp@tass.be 142:35da43068894 560 return ret;
tass picotcp@tass.be 142:35da43068894 561 }
tass picotcp@tass.be 142:35da43068894 562
tass 37:bdf736327c71 563 void dns_cb(char *ip,void *arg)
tass 37:bdf736327c71 564 {
tass 37:bdf736327c71 565 if(!arg)
tass 37:bdf736327c71 566 goto fail;
TASS Belgium NV 146:2ab1944e2f16 567 // send the result back
TASS Belgium NV 146:2ab1944e2f16 568 ((Queue<void,1> *)arg)->put((void *)ip);
TASS Belgium NV 146:2ab1944e2f16 569 return;
TASS Belgium NV 146:2ab1944e2f16 570
tass 37:bdf736327c71 571 fail:
TASS Belgium NV 146:2ab1944e2f16 572 if(ip) pico_free(ip);
tass 37:bdf736327c71 573 }
tass 37:bdf736327c71 574
tass 37:bdf736327c71 575 // dns get host
tass 37:bdf736327c71 576 struct hostent *picotcp_gethostbyname(const char *name)
tass 37:bdf736327c71 577 {
tass 37:bdf736327c71 578 Queue<void,1> *dnsResult = new Queue<void,1>();
tass 37:bdf736327c71 579 struct hostent * hostdata = NULL;
tass 37:bdf736327c71 580 char *ip;
tass 37:bdf736327c71 581
tass 37:bdf736327c71 582 if(!dnsResult)
tass 37:bdf736327c71 583 return NULL;
tass 64:0225b609335e 584 PicoTcpLock->lock();
tass 37:bdf736327c71 585 pico_dns_client_getaddr(name,dns_cb,dnsResult);
tass 64:0225b609335e 586 PicoTcpLock->unlock();
tass 64:0225b609335e 587 picotcp_async_interrupt(NULL);
tass 64:0225b609335e 588
tass 37:bdf736327c71 589 osEvent evt = dnsResult->get(7000);// 7 seconds timeout
tass 37:bdf736327c71 590 if (evt.status == osEventMessage){
tass 37:bdf736327c71 591 ip = (char *)evt.value.p;
tass 37:bdf736327c71 592 hostdata = new struct hostent;
tass 37:bdf736327c71 593 hostdata->h_name = new char[strlen(name)+1];
tass 37:bdf736327c71 594 strcpy(hostdata->h_name,name);
tass 37:bdf736327c71 595 hostdata->h_aliases=NULL;
tass 37:bdf736327c71 596 hostdata->h_addrtype = AF_INET;
tass 37:bdf736327c71 597 hostdata->h_length = strlen(ip);
tass 37:bdf736327c71 598 hostdata->h_addr_list = new char*[2];
tass 37:bdf736327c71 599 hostdata->h_addr_list[0] = ip;
tass 37:bdf736327c71 600 hostdata->h_addr_list[1] = NULL;
tass 37:bdf736327c71 601 }
TASS Belgium NV 147:c3d157ad90df 602 free(dnsResult);
tass 37:bdf736327c71 603 return hostdata;
tass picotcp@tass.be 139:1f7a4a8525ef 604 }