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 Jan 28 15:12:00 2016 +0100
Revision:
155:a70f34550c34
Parent:
153:5e8a725dbd6e
Adding TCP flag for FIN.

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