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
Date:
Thu Nov 21 09:35:58 2013 +0000
Revision:
121:296cd46e5e5b
Parent:
98:b0575c2cc01c
Child:
139:1f7a4a8525ef
Closing a socket will wait 3 seconds for a FIN, if FIN hasn't come already.

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