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 Belgium NV
Date:
Mon Feb 24 10:51:06 2014 +0100
Revision:
145:dbc31fdc150d
Parent:
142:35da43068894
Child:
146:2ab1944e2f16
Fixed PicoTCP bug #92

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