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:
Wed Jul 17 11:55:09 2013 +0000
Revision:
44:ffd9a11d4f95
Parent:
42:13e557b44f68
Child:
50:8c79c30b48e3
Child:
80:d82b69779f35
Added mbed_dbg for debug messages.

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