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:
Tue Oct 01 10:16:32 2013 +0000
Revision:
77:6764a53bb6e6
Parent:
76:938a140caf12
Child:
89:49ca05d9a19e
Making private field NULL.

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 37:bdf736327c71 17 #include "pico_dns_client.h"
tass 37:bdf736327c71 18 }
tass 37:bdf736327c71 19
tass 44:ffd9a11d4f95 20 //#define ptsock_dbg mbed_dbg
daniele 29:1a47b7151851 21 #define ptsock_dbg(...)
tass 50:8c79c30b48e3 22 #define SCHEDULER_BASE 4u
tass 50:8c79c30b48e3 23 #define SCHEDULER_MAX 10u
daniele 29:1a47b7151851 24
tass 50:8c79c30b48e3 25 int scheduler_timeout = 0;
daniele 29:1a47b7151851 26 int in_the_stack = 0;
daniele 29:1a47b7151851 27 Mutex *PicoTcpLock;
tass 37:bdf736327c71 28 Queue<void,32> *PicoTcpEvents;
daniele 29:1a47b7151851 29
daniele 29:1a47b7151851 30 static struct stack_endpoint *ep_accepting;
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 int retval = 0;
daniele 29:1a47b7151851 46 uint16_t ev = ep->revents;
daniele 29:1a47b7151851 47 uint32_t in_time = PICO_TIME_MS();
daniele 29:1a47b7151851 48
tass 32:865c101e0874 49 if(lock) PicoTcpLock->unlock();
daniele 29:1a47b7151851 50 while ((ep->events & ep->revents) == 0) {
daniele 29:1a47b7151851 51 ep->queue->get(time);
daniele 29:1a47b7151851 52 if ((time != osWaitForever) && (PICO_TIME_MS() > in_time + time)) {
tass 42:13e557b44f68 53 ptsock_dbg("TIMEOUT in critical select... (ev:%04x rev:%04x \n", ep->events, ep->revents);
tass 32:865c101e0874 54 if(lock) PicoTcpLock->lock();
daniele 29:1a47b7151851 55 return 0;
daniele 29:1a47b7151851 56 }
daniele 29:1a47b7151851 57 }
tass 32:865c101e0874 58 if(lock) PicoTcpLock->lock();
daniele 29:1a47b7151851 59 return 1;
daniele 29:1a47b7151851 60 }
daniele 29:1a47b7151851 61
daniele 29:1a47b7151851 62 static void wakeup(uint16_t ev, struct pico_socket *s)
daniele 29:1a47b7151851 63 {
daniele 29:1a47b7151851 64 struct stack_endpoint *ep = (struct stack_endpoint *)s->priv;
daniele 29:1a47b7151851 65 if (!ep) {
daniele 29:1a47b7151851 66 if (ep_accepting != NULL) {
tass 42:13e557b44f68 67 ptsock_dbg("Delivering %02x to accepting socket...\n", ev);
daniele 29:1a47b7151851 68 ep = ep_accepting;
daniele 29:1a47b7151851 69 } else {
tass 42:13e557b44f68 70 ptsock_dbg("WAKEUP: socket not found! ev=%04x\n", ev);
daniele 29:1a47b7151851 71 return;
daniele 29:1a47b7151851 72 }
daniele 29:1a47b7151851 73 }
daniele 29:1a47b7151851 74 //if (((ep->revents & PICO_SOCK_EV_RD) == 0) && (ev & PICO_SOCK_EV_RD))
daniele 29:1a47b7151851 75 // printf("Activating RD\n");
tass 55:734099a8df4e 76 if(!ep || !ep->s || !ep->queue)
tass 55:734099a8df4e 77 {
tass 55:734099a8df4e 78 ptsock_dbg("Endpoint null warning : ep=%p, ep->s=%p, ep->queue=%p\n",ep,ep->s,ep->queue);
tass 55:734099a8df4e 79 return;
tass 55:734099a8df4e 80 }
tass 55:734099a8df4e 81
daniele 29:1a47b7151851 82 ep->revents |= ev;
tass 55:734099a8df4e 83
tass 32:865c101e0874 84 if(ev & PICO_SOCK_EV_ERR)
tass 32:865c101e0874 85 {
tass 32:865c101e0874 86 if(pico_err == PICO_ERR_ECONNRESET)
tass 32:865c101e0874 87 {
tass 42:13e557b44f68 88 ptsock_dbg("Connection reset by peer...\n");
tass 32:865c101e0874 89 ep->state = SOCK_RESET_BY_PEER;
tass 32:865c101e0874 90 pico_socket_close(ep->s);
tass 32:865c101e0874 91 ep->s->priv = NULL;
tass 32:865c101e0874 92 }
tass 32:865c101e0874 93 }
daniele 29:1a47b7151851 94 if ((ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN)) {
daniele 29:1a47b7151851 95 ep->connected = 0;
tass 37:bdf736327c71 96 pico_socket_close(ep->s);
tass 77:6764a53bb6e6 97 ep->s->priv = NULL;
tass 35:6078073547bb 98 ep->state = SOCK_CLOSED;
daniele 29:1a47b7151851 99 }
tass 60:a57e18c13f5e 100 if (ev & PICO_SOCK_EV_CONN) {
daniele 29:1a47b7151851 101 ep->connected = 1;
tass 35:6078073547bb 102 ep->state = SOCK_CONNECTED;
daniele 29:1a47b7151851 103 }
daniele 29:1a47b7151851 104 ep->queue->put((void *)0);
daniele 29:1a47b7151851 105 }
daniele 29:1a47b7151851 106
daniele 29:1a47b7151851 107
daniele 29:1a47b7151851 108 struct stack_endpoint *picotcp_socket(uint16_t net, uint16_t proto, uint16_t timeout)
daniele 29:1a47b7151851 109 {
daniele 29:1a47b7151851 110 struct stack_endpoint *ep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint));
daniele 29:1a47b7151851 111 uint16_t p_net = ((net == AF_INET6)?PICO_PROTO_IPV6:PICO_PROTO_IPV4);
daniele 29:1a47b7151851 112 uint16_t p_proto = ((proto == SOCK_DGRAM)?PICO_PROTO_UDP:PICO_PROTO_TCP);
daniele 29:1a47b7151851 113 PicoTcpLock->lock();
daniele 29:1a47b7151851 114 ep->s = pico_socket_open( p_net, p_proto, &wakeup );
daniele 29:1a47b7151851 115 if (ep->s == NULL) {
daniele 29:1a47b7151851 116 delete(ep->queue);
daniele 29:1a47b7151851 117 pico_free(ep);
daniele 29:1a47b7151851 118 ep = NULL;
tass 42:13e557b44f68 119 ptsock_dbg("Error opening socket!\n");
daniele 29:1a47b7151851 120 } else {
daniele 29:1a47b7151851 121 ep->s->priv = ep;
tass 42:13e557b44f68 122 ptsock_dbg("Added socket (open)\n");
tass 35:6078073547bb 123 ep->state = SOCK_OPEN;
daniele 29:1a47b7151851 124 ep->queue = new Queue<void,1>();
daniele 29:1a47b7151851 125 }
daniele 29:1a47b7151851 126 PicoTcpLock->unlock();
daniele 29:1a47b7151851 127 return ep;
daniele 29:1a47b7151851 128 }
daniele 29:1a47b7151851 129
daniele 29:1a47b7151851 130
daniele 29:1a47b7151851 131 int picotcp_state(struct stack_endpoint *ep)
daniele 29:1a47b7151851 132 {
daniele 29:1a47b7151851 133 return ep->state;
daniele 29:1a47b7151851 134 }
daniele 29:1a47b7151851 135
daniele 29:1a47b7151851 136 int picotcp_bind(struct stack_endpoint *ep, struct sockaddr *_local_addr, socklen_t len)
daniele 29:1a47b7151851 137 {
daniele 29:1a47b7151851 138 int ret;
daniele 29:1a47b7151851 139 struct sockaddr_in *local_addr;
daniele 29:1a47b7151851 140 local_addr = (struct sockaddr_in *)_local_addr;
daniele 29:1a47b7151851 141
daniele 29:1a47b7151851 142 PicoTcpLock->lock();
daniele 29:1a47b7151851 143 ret = pico_socket_bind(ep->s, (struct pico_ip4 *)(&local_addr->sin_addr.s_addr), &local_addr->sin_port);
tass 35:6078073547bb 144 if(ret == 0)
tass 35:6078073547bb 145 ep->state = SOCK_BOUND;
daniele 29:1a47b7151851 146 PicoTcpLock->unlock();
daniele 29:1a47b7151851 147 return ret;
daniele 29:1a47b7151851 148 }
daniele 29:1a47b7151851 149
daniele 29:1a47b7151851 150 int picotcp_listen(struct stack_endpoint *ep, int queue)
daniele 29:1a47b7151851 151 {
daniele 29:1a47b7151851 152 int ret;
daniele 29:1a47b7151851 153 PicoTcpLock->lock();
daniele 29:1a47b7151851 154 ret = pico_socket_listen(ep->s, queue);
daniele 29:1a47b7151851 155 ep_accepting = (struct stack_endpoint *) pico_zalloc(sizeof(struct stack_endpoint));
daniele 29:1a47b7151851 156 ep_accepting->queue = new Queue<void,1>();
daniele 29:1a47b7151851 157 if (!ep_accepting)
daniele 29:1a47b7151851 158 ret = -1;
tass 35:6078073547bb 159 if(ret == 0)
tass 35:6078073547bb 160 ep->state = SOCK_LISTEN;
daniele 29:1a47b7151851 161 PicoTcpLock->unlock();
daniele 29:1a47b7151851 162 return ret;
daniele 29:1a47b7151851 163 }
daniele 29:1a47b7151851 164
daniele 29:1a47b7151851 165 int picotcp_connect(struct stack_endpoint *ep, struct sockaddr *_srv_addr, socklen_t len)
daniele 29:1a47b7151851 166 {
daniele 29:1a47b7151851 167 int retval;
daniele 29:1a47b7151851 168 struct sockaddr_in *srv_addr;
daniele 29:1a47b7151851 169 srv_addr = (struct sockaddr_in *)_srv_addr;
daniele 29:1a47b7151851 170 PicoTcpLock->lock();
daniele 29:1a47b7151851 171 pico_socket_connect(ep->s, (struct pico_ip4 *)(&srv_addr->sin_addr.s_addr), srv_addr->sin_port);
daniele 29:1a47b7151851 172 ep->events = PICO_SOCK_EV_CONN | PICO_SOCK_EV_ERR;
daniele 33:d8af3f85a484 173 __critical_select(ep, osWaitForever, 1);
daniele 29:1a47b7151851 174 if ((ep->revents & PICO_SOCK_EV_CONN) && ep->connected) {
daniele 29:1a47b7151851 175 ep->revents &= (~PICO_SOCK_EV_CONN);
daniele 29:1a47b7151851 176 ep->revents |= PICO_SOCK_EV_WR;
daniele 29:1a47b7151851 177 ptsock_dbg("Established. sock state: %x\n", ep->s->state);
tass 35:6078073547bb 178 ep->state = SOCK_CONNECTED;
daniele 29:1a47b7151851 179 retval = 0;
daniele 29:1a47b7151851 180 } else {
daniele 29:1a47b7151851 181 retval = -1;
daniele 29:1a47b7151851 182 }
daniele 29:1a47b7151851 183 PicoTcpLock->unlock();
daniele 29:1a47b7151851 184 return retval;
daniele 29:1a47b7151851 185 }
daniele 29:1a47b7151851 186
daniele 29:1a47b7151851 187 struct stack_endpoint *picotcp_accept(struct stack_endpoint *ep, struct sockaddr *_cli_addr, socklen_t *len)
daniele 29:1a47b7151851 188 {
daniele 29:1a47b7151851 189 int retval;
daniele 29:1a47b7151851 190 struct stack_endpoint *aep = ep_accepting;
daniele 29:1a47b7151851 191 struct sockaddr_in *cli_addr = (struct sockaddr_in *)_cli_addr;
daniele 29:1a47b7151851 192 ep_accepting = (struct stack_endpoint *) pico_zalloc(sizeof(struct stack_endpoint));
daniele 29:1a47b7151851 193 if (ep_accepting)
daniele 29:1a47b7151851 194 ep_accepting->queue = new Queue<void,1>();
daniele 29:1a47b7151851 195
daniele 29:1a47b7151851 196
daniele 29:1a47b7151851 197 if (!aep)
daniele 29:1a47b7151851 198 return aep;
daniele 29:1a47b7151851 199
daniele 29:1a47b7151851 200 PicoTcpLock->lock();
daniele 29:1a47b7151851 201 ep->events = PICO_SOCK_EV_CONN | PICO_SOCK_EV_ERR;
daniele 33:d8af3f85a484 202 __critical_select(ep, osWaitForever, 1);
daniele 29:1a47b7151851 203 if (ep->revents & PICO_SOCK_EV_CONN) {
tass 42:13e557b44f68 204 ptsock_dbg("Calling Accept\n");
daniele 29:1a47b7151851 205 aep->s = pico_socket_accept(ep->s, (struct pico_ip4 *)(&cli_addr->sin_addr.s_addr), &cli_addr->sin_port);
tass 42:13e557b44f68 206 ptsock_dbg("Accept returned\n");
daniele 29:1a47b7151851 207 aep->s->priv = aep;
daniele 29:1a47b7151851 208 ep->revents &= (~PICO_SOCK_EV_CONN);
tass 32:865c101e0874 209 aep->revents = 0; // set this to 0 to allow seq connections
daniele 29:1a47b7151851 210 aep->revents |= PICO_SOCK_EV_WR;
tass 35:6078073547bb 211 aep->state = SOCK_CONNECTED;
tass 42:13e557b44f68 212 ptsock_dbg("Added socket (accept)\n");
daniele 29:1a47b7151851 213
daniele 29:1a47b7151851 214 *len = sizeof(struct sockaddr_in);
daniele 29:1a47b7151851 215 ptsock_dbg("Established. sock state: %x\n", aep->s->state);
daniele 29:1a47b7151851 216 } else {
daniele 29:1a47b7151851 217 pico_free(aep);
daniele 29:1a47b7151851 218 aep = NULL;
daniele 29:1a47b7151851 219 }
daniele 29:1a47b7151851 220 PicoTcpLock->unlock();
daniele 29:1a47b7151851 221 return aep;
daniele 29:1a47b7151851 222 }
daniele 29:1a47b7151851 223
daniele 29:1a47b7151851 224 int picotcp_select(struct stack_endpoint *ep, struct timeval *timeout, int read, int write)
daniele 29:1a47b7151851 225 {
daniele 29:1a47b7151851 226 int ret;
daniele 29:1a47b7151851 227 ep->timeout |= timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
daniele 29:1a47b7151851 228 ep->events = PICO_SOCK_EV_ERR;
daniele 29:1a47b7151851 229 ep->events |= PICO_SOCK_EV_FIN;
daniele 29:1a47b7151851 230 ep->events |= PICO_SOCK_EV_CLOSE;
daniele 29:1a47b7151851 231 ep->events |= PICO_SOCK_EV_CONN;
daniele 29:1a47b7151851 232 if (read) {
daniele 29:1a47b7151851 233 ep->events |= PICO_SOCK_EV_RD;
daniele 29:1a47b7151851 234 }
daniele 29:1a47b7151851 235 if (write)
daniele 29:1a47b7151851 236 ep->events |= PICO_SOCK_EV_WR;
daniele 33:d8af3f85a484 237 ret = __critical_select(ep, ep->timeout, 0);
daniele 29:1a47b7151851 238 return ret;
daniele 29:1a47b7151851 239 }
daniele 29:1a47b7151851 240
tass 35:6078073547bb 241 int picotcp_send(struct stack_endpoint *ep,void * buf, int len, int flags)
daniele 29:1a47b7151851 242 {
tass 35:6078073547bb 243 int retval = 0;
tass 35:6078073547bb 244 int tot_len = 0;
tass 35:6078073547bb 245 if (!buf || (len <= 0))
tass 35:6078073547bb 246 return 0;
tass 35:6078073547bb 247 PicoTcpLock->lock();
tass 35:6078073547bb 248 while (tot_len < len) {
tass 35:6078073547bb 249 retval = pico_socket_send(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
tass 35:6078073547bb 250 if (retval == 0) {
tass 35:6078073547bb 251 if (tot_len < len)
tass 35:6078073547bb 252 ep->revents &= ~PICO_SOCK_EV_WR;
tass 35:6078073547bb 253 break;
tass 35:6078073547bb 254 }
tass 35:6078073547bb 255 if (retval < 0) {
tass 38:b71e5dd1806a 256 if(tot_len == 0) tot_len = -1;
tass 35:6078073547bb 257 break;
tass 35:6078073547bb 258 }
tass 35:6078073547bb 259 tot_len += retval;
tass 35:6078073547bb 260 }
tass 35:6078073547bb 261 PicoTcpLock->unlock();
tass 35:6078073547bb 262 picotcp_async_interrupt(NULL);
tass 35:6078073547bb 263 return tot_len;
tass 35:6078073547bb 264 }
tass 35:6078073547bb 265
tass 35:6078073547bb 266 int picotcp_recv(struct stack_endpoint *ep,void * buf, int len, int flags)
tass 35:6078073547bb 267 {
tass 35:6078073547bb 268 int retval = 0;
tass 35:6078073547bb 269 int tot_len = 0;
tass 35:6078073547bb 270 if (!buf || (len <= 0))
tass 35:6078073547bb 271 return 0;
tass 35:6078073547bb 272 PicoTcpLock->lock();
tass 35:6078073547bb 273 while (tot_len < len) {
tass 35:6078073547bb 274 retval = pico_socket_recv(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
tass 35:6078073547bb 275 if (retval == 0) {
tass 35:6078073547bb 276 if (tot_len < len)
tass 35:6078073547bb 277 ep->revents &= ~PICO_SOCK_EV_RD;
tass 35:6078073547bb 278 break;
tass 35:6078073547bb 279 }
tass 35:6078073547bb 280 if (retval < 0) {
tass 37:bdf736327c71 281 if(tot_len == 0) tot_len = -1;
tass 35:6078073547bb 282 break;
tass 35:6078073547bb 283 }
tass 35:6078073547bb 284 tot_len += retval;
tass 35:6078073547bb 285 }
tass 35:6078073547bb 286 PicoTcpLock->unlock();
tass 35:6078073547bb 287 picotcp_async_interrupt(NULL);
tass 35:6078073547bb 288 return tot_len;
daniele 29:1a47b7151851 289 }
daniele 29:1a47b7151851 290
tass 35:6078073547bb 291 int picotcp_sendto(struct stack_endpoint * ep,void * buf, int len, struct sockaddr* a,socklen_t size)
daniele 29:1a47b7151851 292 {
tass 35:6078073547bb 293 int retval = 0;
tass 35:6078073547bb 294 int tot_len = 0;
tass 35:6078073547bb 295 struct sockaddr_in * in = (struct sockaddr_in *)a;
tass 35:6078073547bb 296 if (!buf || (len <= 0))
tass 35:6078073547bb 297 return 0;
tass 35:6078073547bb 298 if(!ep->broadcast && pico_ipv4_is_broadcast(in->sin_addr.s_addr))
tass 35:6078073547bb 299 return -1;
tass 35:6078073547bb 300
tass 35:6078073547bb 301 PicoTcpLock->lock();
tass 35:6078073547bb 302 while (tot_len < len) {
tass 35:6078073547bb 303 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 304
tass 35:6078073547bb 305 if (retval == 0)
tass 35:6078073547bb 306 break;
tass 35:6078073547bb 307
tass 35:6078073547bb 308 if (retval < 0) {
tass 38:b71e5dd1806a 309 if(tot_len == 0) tot_len = -1;
tass 35:6078073547bb 310 break;
tass 35:6078073547bb 311 }
tass 35:6078073547bb 312 tot_len += retval;
tass 35:6078073547bb 313 }
tass 35:6078073547bb 314 PicoTcpLock->unlock();
tass 35:6078073547bb 315 picotcp_async_interrupt(NULL);
tass 35:6078073547bb 316 return tot_len;
daniele 29:1a47b7151851 317 }
daniele 29:1a47b7151851 318
tass 35:6078073547bb 319 int picotcp_recvfrom(struct stack_endpoint *ep,void * buf, int len, struct sockaddr *a, socklen_t * size)
daniele 29:1a47b7151851 320 {
tass 35:6078073547bb 321 (void)len;
tass 35:6078073547bb 322 int retval = 0;
tass 35:6078073547bb 323 int tot_len = 0;
tass 35:6078073547bb 324 struct sockaddr_in * in = (struct sockaddr_in *)a;
tass 35:6078073547bb 325 if (!buf || (len <= 0))
tass 35:6078073547bb 326 return 0;
tass 35:6078073547bb 327 PicoTcpLock->lock();
tass 35:6078073547bb 328 while (tot_len < len) {
tass 35:6078073547bb 329 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 330 if (retval == 0) {
tass 35:6078073547bb 331 if (tot_len < len)
tass 35:6078073547bb 332 ep->revents &= ~PICO_SOCK_EV_RD;
tass 35:6078073547bb 333 break;
tass 35:6078073547bb 334 }
tass 35:6078073547bb 335 if (retval < 0) {
tass 37:bdf736327c71 336 if(tot_len == 0) tot_len = -1;
tass 35:6078073547bb 337 break;
tass 35:6078073547bb 338 }
tass 35:6078073547bb 339 tot_len += retval;
tass 35:6078073547bb 340 }
tass 35:6078073547bb 341 PicoTcpLock->unlock();
tass 35:6078073547bb 342 picotcp_async_interrupt(NULL);
tass 35:6078073547bb 343 return tot_len;
daniele 29:1a47b7151851 344 }
daniele 29:1a47b7151851 345
daniele 29:1a47b7151851 346 int picotcp_read(struct stack_endpoint *ep,void *buf, int len)
daniele 29:1a47b7151851 347 {
daniele 29:1a47b7151851 348 int retval = 0;
daniele 29:1a47b7151851 349 int tot_len = 0;
daniele 29:1a47b7151851 350 if (!buf || (len <= 0))
daniele 29:1a47b7151851 351 return 0;
daniele 29:1a47b7151851 352 PicoTcpLock->lock();
daniele 29:1a47b7151851 353 while (tot_len < len) {
daniele 29:1a47b7151851 354 retval = pico_socket_read(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
daniele 29:1a47b7151851 355 if (retval == 0) {
daniele 29:1a47b7151851 356 if (tot_len < len)
daniele 29:1a47b7151851 357 ep->revents &= ~PICO_SOCK_EV_RD;
daniele 29:1a47b7151851 358 break;
daniele 29:1a47b7151851 359 }
daniele 29:1a47b7151851 360 if (retval < 0) {
tass 37:bdf736327c71 361 if(tot_len == 0) tot_len = -1;
daniele 29:1a47b7151851 362 break;
daniele 29:1a47b7151851 363 }
daniele 29:1a47b7151851 364 tot_len += retval;
daniele 29:1a47b7151851 365 }
daniele 29:1a47b7151851 366 PicoTcpLock->unlock();
daniele 29:1a47b7151851 367 picotcp_async_interrupt(NULL);
daniele 29:1a47b7151851 368 return tot_len;
daniele 29:1a47b7151851 369 }
daniele 29:1a47b7151851 370
daniele 29:1a47b7151851 371 int picotcp_write(struct stack_endpoint *ep,void *buf, int len)
daniele 29:1a47b7151851 372 {
daniele 29:1a47b7151851 373 int retval = 0;
daniele 29:1a47b7151851 374 int tot_len = 0;
daniele 29:1a47b7151851 375 if (!buf || (len <= 0))
daniele 29:1a47b7151851 376 return 0;
daniele 29:1a47b7151851 377 PicoTcpLock->lock();
daniele 29:1a47b7151851 378 while (tot_len < len) {
daniele 29:1a47b7151851 379 retval = pico_socket_write(ep->s, ((uint8_t *)buf) + tot_len , len - tot_len);
tass 42:13e557b44f68 380
daniele 29:1a47b7151851 381 if (retval == 0) {
daniele 29:1a47b7151851 382 if (tot_len < len)
tass 35:6078073547bb 383 ep->revents &= ~PICO_SOCK_EV_WR;
daniele 29:1a47b7151851 384 break;
daniele 29:1a47b7151851 385 }
daniele 29:1a47b7151851 386 if (retval < 0) {
tass 38:b71e5dd1806a 387 if(tot_len == 0) tot_len = -1;
daniele 29:1a47b7151851 388 break;
daniele 29:1a47b7151851 389 }
daniele 29:1a47b7151851 390 tot_len += retval;
daniele 29:1a47b7151851 391 }
daniele 29:1a47b7151851 392 PicoTcpLock->unlock();
daniele 29:1a47b7151851 393 picotcp_async_interrupt(NULL);
daniele 29:1a47b7151851 394 return tot_len;
daniele 29:1a47b7151851 395 }
daniele 29:1a47b7151851 396
daniele 29:1a47b7151851 397
daniele 29:1a47b7151851 398 int picotcp_setsockopt(struct stack_endpoint *ep, int option, void *value)
daniele 29:1a47b7151851 399 {
tass 35:6078073547bb 400 int ret;
tass 35:6078073547bb 401
tass 35:6078073547bb 402 PicoTcpLock->lock();
tass 35:6078073547bb 403 if(option == SO_BROADCAST)
tass 35:6078073547bb 404 {
tass 35:6078073547bb 405 ep->broadcast = *(int *)value;
tass 35:6078073547bb 406 ret = 0;
tass 35:6078073547bb 407 }
tass 35:6078073547bb 408 else
tass 35:6078073547bb 409 ret = pico_socket_setoption(ep->s,option,value);
tass 35:6078073547bb 410 PicoTcpLock->unlock();
tass 35:6078073547bb 411
tass 35:6078073547bb 412 return ret;
daniele 29:1a47b7151851 413 }
daniele 29:1a47b7151851 414
daniele 29:1a47b7151851 415 int picotcp_getsockopt(struct stack_endpoint *ep, int option, void *value)
daniele 29:1a47b7151851 416 {
tass 35:6078073547bb 417 int ret;
tass 35:6078073547bb 418
tass 35:6078073547bb 419 PicoTcpLock->lock();
tass 35:6078073547bb 420 ret = pico_socket_getoption(ep->s,option,value);
tass 35:6078073547bb 421 PicoTcpLock->unlock();
tass 35:6078073547bb 422
tass 35:6078073547bb 423 return ret;
daniele 29:1a47b7151851 424 }
daniele 29:1a47b7151851 425
daniele 29:1a47b7151851 426 int picotcp_close(struct stack_endpoint *ep)
daniele 29:1a47b7151851 427 {
daniele 29:1a47b7151851 428 PicoTcpLock->lock();
tass 76:938a140caf12 429 if(ep->state != SOCK_RESET_BY_PEER && ep->state != SOCK_CLOSED)
tass 32:865c101e0874 430 {
tass 32:865c101e0874 431 pico_socket_close(ep->s);
tass 32:865c101e0874 432 ep->s->priv = NULL;
tass 32:865c101e0874 433 }
tass 42:13e557b44f68 434 ptsock_dbg("Socket closed!\n");
daniele 29:1a47b7151851 435 delete(ep->queue);
daniele 29:1a47b7151851 436 pico_free(ep);
daniele 29:1a47b7151851 437 PicoTcpLock->unlock();
daniele 29:1a47b7151851 438 }
daniele 29:1a47b7151851 439
daniele 29:1a47b7151851 440 int picotcp_join_multicast(struct stack_endpoint *ep,const char* address,const char* local)
daniele 29:1a47b7151851 441 {
tass 35:6078073547bb 442 int ret;
tass 35:6078073547bb 443 struct pico_ip_mreq mreq={};
tass 35:6078073547bb 444
tass 35:6078073547bb 445 PicoTcpLock->lock();
tass 35:6078073547bb 446 pico_string_to_ipv4(address,&mreq.mcast_group_addr.addr);
tass 35:6078073547bb 447 pico_string_to_ipv4(local,&mreq.mcast_link_addr.addr);
tass 35:6078073547bb 448 ret = pico_socket_setoption(ep->s, PICO_IP_ADD_MEMBERSHIP, &mreq);
tass 35:6078073547bb 449 PicoTcpLock->unlock();
tass 35:6078073547bb 450
tass 35:6078073547bb 451 return ret;
daniele 29:1a47b7151851 452 }
daniele 29:1a47b7151851 453
daniele 29:1a47b7151851 454
daniele 29:1a47b7151851 455
daniele 29:1a47b7151851 456 void pico_wrapper_loop(const void * arg)
daniele 29:1a47b7151851 457 {
daniele 29:1a47b7151851 458 (void)arg;
daniele 29:1a47b7151851 459 int ret = 0;
daniele 29:1a47b7151851 460 struct pico_device *dev;
daniele 29:1a47b7151851 461 while(1) {
daniele 29:1a47b7151851 462
tass 50:8c79c30b48e3 463 osEvent evt = PicoTcpEvents->get(SCHEDULER_BASE<<scheduler_timeout);
daniele 29:1a47b7151851 464
daniele 29:1a47b7151851 465 if (evt.status == osEventMessage) {
daniele 29:1a47b7151851 466 dev = (struct pico_device *)evt.value.p;
tass 50:8c79c30b48e3 467 scheduler_timeout = 0;
daniele 29:1a47b7151851 468 } else {
daniele 29:1a47b7151851 469 dev = NULL;
tass 50:8c79c30b48e3 470 if(scheduler_timeout < SCHEDULER_MAX)
tass 50:8c79c30b48e3 471 scheduler_timeout++;
daniele 29:1a47b7151851 472 }
daniele 29:1a47b7151851 473 PicoTcpLock->lock();
daniele 29:1a47b7151851 474 if (dev && dev->dsr)
daniele 29:1a47b7151851 475 dev->dsr(dev, 5);
tass 58:5f6eedbbbd5b 476 picotcp_async_clean(dev);
daniele 29:1a47b7151851 477 pico_stack_tick();
daniele 29:1a47b7151851 478 pico_stack_tick();
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 }