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:
Mon Jul 22 14:56:25 2013 +0000
Revision:
80:d82b69779f35
Parent:
44:ffd9a11d4f95
ping working in both directions

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