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:
daniele
Date:
Tue Jun 11 23:28:50 2013 +0000
Revision:
25:d63125298eb3
Parent:
24:8bff2b51ea3b
Child:
26:dc3e7f96338f
Child:
31:d3b2dfcc358f
Fixed close

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 19:c7debad9a20a 1 /*********************************************************************
daniele 19:c7debad9a20a 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 19:c7debad9a20a 3 See LICENSE and COPYING for usage.
daniele 19:c7debad9a20a 4
daniele 19:c7debad9a20a 5 Authors: Daniele Lacamera
daniele 19:c7debad9a20a 6 *********************************************************************/
daniele 19:c7debad9a20a 7
daniele 19:c7debad9a20a 8 #include "wrapper.h"
daniele 19:c7debad9a20a 9 #include "rtos.h"
daniele 19:c7debad9a20a 10 #include "cmsis_os.h"
daniele 19:c7debad9a20a 11 #include "mbed.h"
daniele 19:c7debad9a20a 12 #include "Socket.h"
daniele 19:c7debad9a20a 13
daniele 19:c7debad9a20a 14 //#define ptsock_dbg printf
daniele 19:c7debad9a20a 15 #define ptsock_dbg(...)
daniele 19:c7debad9a20a 16
daniele 19:c7debad9a20a 17 int in_the_stack = 0;
daniele 19:c7debad9a20a 18
daniele 19:c7debad9a20a 19
daniele 19:c7debad9a20a 20 static Thread * serverThread = NULL;
daniele 19:c7debad9a20a 21 // global queue for open requests
daniele 19:c7debad9a20a 22 Queue<struct picotcp_socketcall,10> picotcp_socketcall_queue;
daniele 19:c7debad9a20a 23 Queue<struct stack_endpoint,10> picotcp_socketcall_response_queue;
daniele 19:c7debad9a20a 24
daniele 19:c7debad9a20a 25 static inline void sendOpenResponse(struct stack_endpoint * arg)
daniele 19:c7debad9a20a 26 {
daniele 19:c7debad9a20a 27 picotcp_socketcall_response_queue.put(arg);
daniele 19:c7debad9a20a 28 }
daniele 19:c7debad9a20a 29
daniele 19:c7debad9a20a 30 static inline uint16_t readSocketCommand(struct stack_endpoint * endp)
daniele 19:c7debad9a20a 31 {
daniele 19:c7debad9a20a 32 osEvent event = endp->CallActivateQueue->get(0); // Tx for Client, Rx for Me, non blocking
daniele 19:c7debad9a20a 33 if(event.status == osEventMessage)
daniele 19:c7debad9a20a 34 return *((uint16_t *)event.value.p);
daniele 19:c7debad9a20a 35 return NO_COMMAND;
daniele 19:c7debad9a20a 36 }
daniele 19:c7debad9a20a 37
daniele 19:c7debad9a20a 38 static inline void sendSocketResponse(struct stack_endpoint *endp)
daniele 19:c7debad9a20a 39 {
daniele 19:c7debad9a20a 40 endp->CallResponseQueue->put(endp);
daniele 19:c7debad9a20a 41 }
daniele 19:c7debad9a20a 42
daniele 19:c7debad9a20a 43 static int stack_compare(void *ka, void *kb)
daniele 19:c7debad9a20a 44 {
daniele 19:c7debad9a20a 45 struct stack_endpoint *a = (struct stack_endpoint *)ka, *b = (struct stack_endpoint *)kb;
daniele 19:c7debad9a20a 46 if (a->s < b->s)
daniele 19:c7debad9a20a 47 return -1;
daniele 19:c7debad9a20a 48 if (a->s > b->s)
daniele 19:c7debad9a20a 49 return 1;
daniele 19:c7debad9a20a 50 return 0;
daniele 19:c7debad9a20a 51 }
daniele 19:c7debad9a20a 52
daniele 19:c7debad9a20a 53 PICO_TREE_DECLARE(stack_ep_tree, stack_compare);
daniele 19:c7debad9a20a 54
daniele 19:c7debad9a20a 55 static struct stack_endpoint *GET_SOCK_BY_PICOSOCK(struct pico_socket *s)
daniele 19:c7debad9a20a 56 {
daniele 19:c7debad9a20a 57 struct stack_endpoint test;
daniele 19:c7debad9a20a 58 test.s = s;
daniele 19:c7debad9a20a 59 return (struct stack_endpoint *)pico_tree_findKey(&stack_ep_tree, &test);
daniele 19:c7debad9a20a 60 }
daniele 19:c7debad9a20a 61
daniele 19:c7debad9a20a 62 static void stack_Add(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 63 {
daniele 19:c7debad9a20a 64 pico_tree_insert(&stack_ep_tree, ep);
daniele 19:c7debad9a20a 65 }
daniele 19:c7debad9a20a 66
daniele 19:c7debad9a20a 67 static void stack_Del(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 68 {
daniele 19:c7debad9a20a 69 pico_tree_delete(&stack_ep_tree, ep);
daniele 19:c7debad9a20a 70 }
daniele 19:c7debad9a20a 71
daniele 19:c7debad9a20a 72 static void status_pending_off(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 73 {
daniele 19:c7debad9a20a 74 //ep->pending = NO_COMMAND; //no event
daniele 19:c7debad9a20a 75 }
daniele 19:c7debad9a20a 76
daniele 19:c7debad9a20a 77
daniele 24:8bff2b51ea3b 78
daniele 19:c7debad9a20a 79
daniele 19:c7debad9a20a 80 static int send_wakeup(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 81 {
daniele 19:c7debad9a20a 82 int ret = 0;
daniele 19:c7debad9a20a 83 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 84 return -1;
daniele 19:c7debad9a20a 85 ep->retval = 1;
daniele 19:c7debad9a20a 86 // send response
daniele 19:c7debad9a20a 87 sendSocketResponse(ep);
daniele 19:c7debad9a20a 88 return ret;
daniele 19:c7debad9a20a 89 }
daniele 19:c7debad9a20a 90
daniele 19:c7debad9a20a 91
daniele 19:c7debad9a20a 92
daniele 19:c7debad9a20a 93 static int send_retval(struct stack_endpoint *ep, int retval)
daniele 19:c7debad9a20a 94 {
daniele 19:c7debad9a20a 95 int ret = 0;
daniele 19:c7debad9a20a 96 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 97 return -1;
daniele 19:c7debad9a20a 98 ep->retval = retval;
daniele 19:c7debad9a20a 99 // send queue
daniele 19:c7debad9a20a 100 sendSocketResponse(ep);
daniele 19:c7debad9a20a 101 status_pending_off(ep);
daniele 19:c7debad9a20a 102 return ret;
daniele 19:c7debad9a20a 103 }
daniele 19:c7debad9a20a 104
daniele 19:c7debad9a20a 105 static int send_error(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 106 {
daniele 19:c7debad9a20a 107 ep->code = pico_err;
daniele 19:c7debad9a20a 108 return send_retval(ep, -1);
daniele 19:c7debad9a20a 109 }
daniele 19:c7debad9a20a 110 static void set_timer(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 111 {
daniele 19:c7debad9a20a 112 if (ep->timeout == osWaitForever)
daniele 19:c7debad9a20a 113 return;
daniele 19:c7debad9a20a 114
daniele 19:c7debad9a20a 115 if (ep->t_call == 0) {
daniele 19:c7debad9a20a 116 ep->t_call = PICO_TIME_MS();
daniele 19:c7debad9a20a 117 ep->t_expire = ep->t_call + ep->timeout;
daniele 19:c7debad9a20a 118 }
daniele 19:c7debad9a20a 119 }
daniele 19:c7debad9a20a 120
daniele 19:c7debad9a20a 121 static void check_timer_expired(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 122 {
daniele 19:c7debad9a20a 123 if (ep->timeout == osWaitForever)
daniele 19:c7debad9a20a 124 return; /* never */
daniele 19:c7debad9a20a 125
daniele 19:c7debad9a20a 126 if (ep->t_expire < PICO_TIME_MS()) {
daniele 19:c7debad9a20a 127 ep->retval = 0;
daniele 19:c7debad9a20a 128 sendSocketResponse(ep);
daniele 19:c7debad9a20a 129 }
daniele 19:c7debad9a20a 130 }
daniele 19:c7debad9a20a 131
daniele 19:c7debad9a20a 132
daniele 19:c7debad9a20a 133 static void retry_connect(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 134 {
daniele 19:c7debad9a20a 135 if ((ep->revents & PICO_SOCK_EV_CONN) && ep->connected) {
daniele 19:c7debad9a20a 136 ep->revents &= (~PICO_SOCK_EV_CONN);
daniele 19:c7debad9a20a 137 ep->revents |= PICO_SOCK_EV_WR;
daniele 19:c7debad9a20a 138 ptsock_dbg("Established. sock state: %x\n", ep->s->state);
daniele 19:c7debad9a20a 139 send_retval(ep, 0);
daniele 19:c7debad9a20a 140 }else {
daniele 19:c7debad9a20a 141 pico_socket_connect(ep->s, &ep->addr, ep->port);
daniele 19:c7debad9a20a 142 ep->events |= PICO_SOCK_EV_CONN;
daniele 19:c7debad9a20a 143 }
daniele 19:c7debad9a20a 144 }
daniele 19:c7debad9a20a 145
daniele 19:c7debad9a20a 146 static void retry_accept(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 147 {
daniele 19:c7debad9a20a 148 struct pico_ip4 peer ={};
daniele 19:c7debad9a20a 149 uint16_t port = 0;
daniele 19:c7debad9a20a 150
daniele 19:c7debad9a20a 151 struct stack_endpoint *aep;
daniele 19:c7debad9a20a 152 struct pico_socket *sa;
daniele 19:c7debad9a20a 153 set_timer(ep);
daniele 19:c7debad9a20a 154 if (ep->revents & PICO_SOCK_EV_CONN) {
daniele 19:c7debad9a20a 155 ptsock_dbg("Incoming connection...\n");
daniele 19:c7debad9a20a 156 sa = pico_socket_accept(ep->s, &peer.addr, &port);
daniele 19:c7debad9a20a 157 if (sa) {
daniele 19:c7debad9a20a 158 ptsock_dbg("Accepted!\n");
daniele 19:c7debad9a20a 159 aep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint));
daniele 19:c7debad9a20a 160 if (!aep) {
daniele 19:c7debad9a20a 161 send_error(ep);
daniele 19:c7debad9a20a 162 return;
daniele 19:c7debad9a20a 163 }
daniele 19:c7debad9a20a 164
daniele 19:c7debad9a20a 165 aep->sock_fd = (uint16_t)pico_rand();
daniele 19:c7debad9a20a 166 aep->s = sa;
daniele 19:c7debad9a20a 167 aep->connected = 1;
daniele 19:c7debad9a20a 168 aep->peer = peer;
daniele 19:c7debad9a20a 169 aep->peer_port = port;
daniele 19:c7debad9a20a 170 aep->addr = ep->addr;//copy parent's address
daniele 19:c7debad9a20a 171 aep->port = ep->port;
daniele 19:c7debad9a20a 172 aep->pending = NO_COMMAND;
daniele 19:c7debad9a20a 173 aep->revents |= PICO_SOCK_EV_WR;
daniele 19:c7debad9a20a 174 ep->revents &= (~PICO_SOCK_EV_CONN);
daniele 19:c7debad9a20a 175 aep->CallResponseQueue = new Queue<struct stack_endpoint,2>();
daniele 19:c7debad9a20a 176 aep->CallActivateQueue = new Queue<struct stack_endpoint,2>();
daniele 19:c7debad9a20a 177 aep->state = SOCK_CONNECTED;
daniele 19:c7debad9a20a 178 stack_Add(aep);
daniele 19:c7debad9a20a 179 ep->retval = 0;
daniele 19:c7debad9a20a 180 ep->CallResponseQueue->put(aep);
daniele 19:c7debad9a20a 181 } else {
daniele 19:c7debad9a20a 182 send_error(ep);
daniele 19:c7debad9a20a 183 }
daniele 19:c7debad9a20a 184 return;
daniele 19:c7debad9a20a 185 }
daniele 19:c7debad9a20a 186 ep->events |= PICO_SOCK_EV_CONN;
daniele 19:c7debad9a20a 187 check_timer_expired(ep);
daniele 19:c7debad9a20a 188 }
daniele 19:c7debad9a20a 189
daniele 19:c7debad9a20a 190 static void retry_close(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 191 {
daniele 25:d63125298eb3 192 if (ep) {
daniele 25:d63125298eb3 193 pico_socket_close(ep->s);
daniele 25:d63125298eb3 194 send_retval(ep, 0);
daniele 25:d63125298eb3 195 stack_Del(ep);
daniele 25:d63125298eb3 196 }
daniele 19:c7debad9a20a 197 }
daniele 19:c7debad9a20a 198
daniele 19:c7debad9a20a 199 static void retry_write(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 200 {
daniele 19:c7debad9a20a 201
daniele 19:c7debad9a20a 202 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 203 return;
daniele 19:c7debad9a20a 204
daniele 19:c7debad9a20a 205 if (!ep->buffer) {
daniele 19:c7debad9a20a 206 send_error(ep);
daniele 19:c7debad9a20a 207 return;
daniele 19:c7debad9a20a 208 }
daniele 19:c7debad9a20a 209
daniele 19:c7debad9a20a 210 if (ep->pending == TOK_SENDTO) {
daniele 19:c7debad9a20a 211 ep->size = pico_socket_sendto(ep->s, ep->buffer, ep->size, &ep->addr, ep->port);
daniele 19:c7debad9a20a 212 } else {
daniele 19:c7debad9a20a 213 ep->size = pico_socket_write(ep->s, ep->buffer, ep->size);
daniele 19:c7debad9a20a 214 }
daniele 19:c7debad9a20a 215 ep->revents &= (~PICO_SOCK_EV_WR);
daniele 19:c7debad9a20a 216 if (ep->size < 0)
daniele 19:c7debad9a20a 217 send_error(ep);
daniele 19:c7debad9a20a 218 else if (ep->size > 0)
daniele 19:c7debad9a20a 219 send_retval(ep, ep->size);
daniele 19:c7debad9a20a 220 else {
daniele 19:c7debad9a20a 221 ep->events |= PICO_SOCK_EV_WR;
daniele 19:c7debad9a20a 222 return;
daniele 19:c7debad9a20a 223 }
daniele 19:c7debad9a20a 224 }
daniele 19:c7debad9a20a 225
daniele 19:c7debad9a20a 226 static void retry_read(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 227 {
daniele 19:c7debad9a20a 228 int len;
daniele 19:c7debad9a20a 229 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 230 return;
daniele 19:c7debad9a20a 231
daniele 19:c7debad9a20a 232 ptsock_dbg("in retry-read, len: %d \n", len);
daniele 19:c7debad9a20a 233
daniele 19:c7debad9a20a 234
daniele 19:c7debad9a20a 235
daniele 19:c7debad9a20a 236 if (!ep->buffer) {
daniele 19:c7debad9a20a 237 send_error(ep);
daniele 19:c7debad9a20a 238 return;
daniele 19:c7debad9a20a 239 } else {
daniele 19:c7debad9a20a 240 if (ep->pending == TOK_RECVFROM)
daniele 19:c7debad9a20a 241 len = pico_socket_recvfrom(ep->s, ep->buffer, ep->size, &ep->addr, &ep->port);
daniele 19:c7debad9a20a 242 else {
daniele 19:c7debad9a20a 243 len = pico_socket_read(ep->s, ep->buffer, ep->size);
daniele 19:c7debad9a20a 244 }
daniele 19:c7debad9a20a 245 }
daniele 19:c7debad9a20a 246
daniele 19:c7debad9a20a 247 if (ep->size > len)
daniele 19:c7debad9a20a 248 ep->revents &= (~PICO_SOCK_EV_RD);
daniele 19:c7debad9a20a 249
daniele 19:c7debad9a20a 250 if (len == 0) {
daniele 19:c7debad9a20a 251 ptsock_dbg("Read returned 0.");
daniele 19:c7debad9a20a 252 ep->events |= PICO_SOCK_EV_RD;
daniele 19:c7debad9a20a 253 return;
daniele 19:c7debad9a20a 254 }
daniele 19:c7debad9a20a 255 send_retval(ep, len);
daniele 19:c7debad9a20a 256 }
daniele 19:c7debad9a20a 257
daniele 19:c7debad9a20a 258 void retry_poll(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 259 {
daniele 19:c7debad9a20a 260 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 261 return;
daniele 19:c7debad9a20a 262
daniele 19:c7debad9a20a 263 set_timer(ep);
daniele 19:c7debad9a20a 264
daniele 19:c7debad9a20a 265 if ((ep->events & ep->revents) != 0) {
daniele 19:c7debad9a20a 266 send_retval(ep, 1);
daniele 19:c7debad9a20a 267 return;
daniele 19:c7debad9a20a 268 }
daniele 19:c7debad9a20a 269
daniele 19:c7debad9a20a 270 check_timer_expired(ep);
daniele 19:c7debad9a20a 271 }
daniele 19:c7debad9a20a 272
daniele 19:c7debad9a20a 273 static void retry_token(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 274 {
daniele 19:c7debad9a20a 275 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 276 return;
daniele 19:c7debad9a20a 277 ptsock_dbg("in retry-token, cmd: %04x\n", ep->pending);
daniele 19:c7debad9a20a 278 switch(ep->pending) {
daniele 19:c7debad9a20a 279 case TOK_POLL:
daniele 19:c7debad9a20a 280 retry_poll(ep);
daniele 19:c7debad9a20a 281 break;
daniele 19:c7debad9a20a 282 case TOK_CONNECT:
daniele 19:c7debad9a20a 283 retry_connect(ep);
daniele 19:c7debad9a20a 284 break;
daniele 19:c7debad9a20a 285 case TOK_ACCEPT:
daniele 19:c7debad9a20a 286 retry_accept(ep);
daniele 19:c7debad9a20a 287 break;
daniele 19:c7debad9a20a 288
daniele 19:c7debad9a20a 289 case TOK_READ:
daniele 19:c7debad9a20a 290 case TOK_RECV:
daniele 19:c7debad9a20a 291 case TOK_RECVFROM:
daniele 19:c7debad9a20a 292 retry_read(ep);
daniele 19:c7debad9a20a 293 break;
daniele 19:c7debad9a20a 294
daniele 19:c7debad9a20a 295 case TOK_WRITE:
daniele 19:c7debad9a20a 296 case TOK_SEND:
daniele 19:c7debad9a20a 297 case TOK_SENDTO:
daniele 19:c7debad9a20a 298 retry_write(ep);
daniele 19:c7debad9a20a 299 break;
daniele 19:c7debad9a20a 300
daniele 19:c7debad9a20a 301 case TOK_CLOSE:
daniele 19:c7debad9a20a 302 retry_close(ep);
daniele 19:c7debad9a20a 303 break;
daniele 19:c7debad9a20a 304 default:
daniele 19:c7debad9a20a 305 break;
daniele 19:c7debad9a20a 306 }
daniele 19:c7debad9a20a 307 }
daniele 19:c7debad9a20a 308
daniele 19:c7debad9a20a 309 static void wakeup(uint16_t ev, struct pico_socket *s)
daniele 19:c7debad9a20a 310 {
daniele 19:c7debad9a20a 311 int t;
daniele 19:c7debad9a20a 312 struct stack_endpoint *ep = GET_SOCK_BY_PICOSOCK(s);
daniele 19:c7debad9a20a 313
daniele 19:c7debad9a20a 314 if (!ep) {
daniele 19:c7debad9a20a 315 ptsock_dbg("WAKEUP: no socket :(\n");
daniele 19:c7debad9a20a 316 return;
daniele 19:c7debad9a20a 317 }
daniele 19:c7debad9a20a 318 t = ep->pending;
daniele 19:c7debad9a20a 319 ptsock_dbg("Wake up event: %04x\n", ev);
daniele 19:c7debad9a20a 320 ep->revents |= ev;
daniele 19:c7debad9a20a 321
daniele 24:8bff2b51ea3b 322
daniele 24:8bff2b51ea3b 323
daniele 25:d63125298eb3 324 if (ev & (PICO_SOCK_EV_CLOSE | PICO_SOCK_EV_FIN)){
daniele 24:8bff2b51ea3b 325 printf("** CLOSE\n");
daniele 24:8bff2b51ea3b 326 ep->connected = 0;
daniele 24:8bff2b51ea3b 327 }
daniele 24:8bff2b51ea3b 328
daniele 19:c7debad9a20a 329 if (ev & PICO_SOCK_EV_ERR) {
daniele 19:c7debad9a20a 330 ep->revents = PICO_SOCK_EV_ERR;
daniele 19:c7debad9a20a 331 send_error(ep);
daniele 19:c7debad9a20a 332 return;
daniele 19:c7debad9a20a 333 }
daniele 19:c7debad9a20a 334
daniele 19:c7debad9a20a 335 if ((ev & PICO_SOCK_EV_CONN) || (ev & PICO_SOCK_EV_RD)) {
daniele 24:8bff2b51ea3b 336 if ((ev & PICO_SOCK_EV_CONN) && ((ep->pending == TOK_CONNECT) || (ep->pending == TOK_ACCEPT))) {
daniele 24:8bff2b51ea3b 337 printf("** Connected\n");
daniele 19:c7debad9a20a 338 ep->connected = 1;
daniele 19:c7debad9a20a 339 }
daniele 19:c7debad9a20a 340 }
daniele 24:8bff2b51ea3b 341 ep->revents = ev;
daniele 19:c7debad9a20a 342 if ( (ep->pending != 0) && ((ep->events & ep->revents)!=0) )
daniele 19:c7debad9a20a 343 retry_token(ep);
daniele 19:c7debad9a20a 344 }
daniele 19:c7debad9a20a 345
daniele 19:c7debad9a20a 346 static int stack_parse_requests(void)
daniele 19:c7debad9a20a 347 {
daniele 19:c7debad9a20a 348 struct stack_endpoint *ep = NULL;
daniele 19:c7debad9a20a 349 struct picotcp_socketcall *skc;
daniele 19:c7debad9a20a 350 osEvent event; // used to see the status of queue get
daniele 19:c7debad9a20a 351 struct pico_tree_node * index = NULL;
daniele 19:c7debad9a20a 352 uint16_t proto,net;
daniele 19:c7debad9a20a 353 int ret = 0;
daniele 19:c7debad9a20a 354 int yes = 1;
daniele 19:c7debad9a20a 355 // first check if the global queue has something in it
daniele 19:c7debad9a20a 356 // and open a new socket if so
daniele 19:c7debad9a20a 357 do
daniele 19:c7debad9a20a 358 {
daniele 19:c7debad9a20a 359 stack_endpoint *stack_ep = NULL;
daniele 19:c7debad9a20a 360
daniele 19:c7debad9a20a 361 event = picotcp_socketcall_queue.get(0); // non blocking get
daniele 19:c7debad9a20a 362 if(event.status == osEventMessage) {
daniele 19:c7debad9a20a 363 ret = 1;
daniele 19:c7debad9a20a 364 // Get the arguments
daniele 19:c7debad9a20a 365 skc = (struct picotcp_socketcall *)event.value.p;
daniele 19:c7debad9a20a 366
daniele 19:c7debad9a20a 367 // open new socket and send the response
daniele 19:c7debad9a20a 368 stack_ep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint));
daniele 19:c7debad9a20a 369 if(!stack_ep)
daniele 19:c7debad9a20a 370 {
daniele 19:c7debad9a20a 371 ptsock_dbg("Out of memory\n");
daniele 19:c7debad9a20a 372 return -1;
daniele 19:c7debad9a20a 373 }
daniele 19:c7debad9a20a 374 stack_ep->CallActivateQueue = new Queue<struct stack_endpoint,2>();
daniele 19:c7debad9a20a 375 stack_ep->CallResponseQueue = new Queue<struct stack_endpoint,2>();
daniele 19:c7debad9a20a 376
daniele 19:c7debad9a20a 377 net = ((skc->family == AF_INET6)?PICO_PROTO_IPV6:PICO_PROTO_IPV4);
daniele 19:c7debad9a20a 378 proto = ((skc->proto == SOCK_DGRAM)?PICO_PROTO_UDP:PICO_PROTO_TCP);
daniele 19:c7debad9a20a 379 stack_ep->s = pico_socket_open( net, proto, &wakeup );
daniele 19:c7debad9a20a 380
daniele 19:c7debad9a20a 381 if (!stack_ep->s)
daniele 19:c7debad9a20a 382 stack_ep->retval = -1;
daniele 19:c7debad9a20a 383 //pico_socket_setoption(stack_ep->s, PICO_SOCKET_OPT_TCPNODELAY, &yes);
daniele 19:c7debad9a20a 384
daniele 19:c7debad9a20a 385 //stack_ep->pending = NO_COMMAND;
daniele 19:c7debad9a20a 386 stack_Add(stack_ep);
daniele 19:c7debad9a20a 387 // send the response back to the client
daniele 19:c7debad9a20a 388 sendOpenResponse(stack_ep);
daniele 19:c7debad9a20a 389 ptsock_dbg("New socket added: %p\n", stack_ep->s);
daniele 19:c7debad9a20a 390 }
daniele 19:c7debad9a20a 391 }while(event.status == osEventMessage);
daniele 19:c7debad9a20a 392
daniele 19:c7debad9a20a 393 // go through all the sockets and check if there is a request from someone
daniele 19:c7debad9a20a 394 // call to the get function has timeout 0, must be non blocking
daniele 19:c7debad9a20a 395 // if a request has come from someone parse it
daniele 19:c7debad9a20a 396 pico_tree_foreach(index,&stack_ep_tree)
daniele 19:c7debad9a20a 397 {
daniele 19:c7debad9a20a 398 ep = (struct stack_endpoint *)index->keyValue;
daniele 19:c7debad9a20a 399 // check if data has arrived
daniele 19:c7debad9a20a 400 event = ep->CallActivateQueue->get(0); // again non blocking
daniele 19:c7debad9a20a 401 if(event.status == osEventMessage)
daniele 19:c7debad9a20a 402 {
daniele 19:c7debad9a20a 403 ret = 1;
daniele 19:c7debad9a20a 404 //printf("Socket contacted. CMD: %X\n", ep->pending);
daniele 19:c7debad9a20a 405 // check command sent
daniele 19:c7debad9a20a 406 switch(ep->pending)
daniele 19:c7debad9a20a 407 {
daniele 19:c7debad9a20a 408 case TOK_BIND:
daniele 19:c7debad9a20a 409 if(pico_socket_bind(ep->s, &ep->addr, &ep->port) == 0) {
daniele 19:c7debad9a20a 410 ptsock_dbg("stack: bind success (addr: %08x, port %d)!\n", ep->addr.addr, ep->port);
daniele 19:c7debad9a20a 411 send_retval(ep, 0);
daniele 19:c7debad9a20a 412 } else {
daniele 19:c7debad9a20a 413 ptsock_dbg("stack: bind error (pico_s: %p, addr: %08x, port %d err: %d)!\n", ep->s, ep->addr.addr, ep->port, pico_err);
daniele 19:c7debad9a20a 414 send_error(ep);
daniele 19:c7debad9a20a 415 }
daniele 19:c7debad9a20a 416 break;
daniele 19:c7debad9a20a 417 case TOK_LISTEN:
daniele 19:c7debad9a20a 418 if(pico_socket_listen(ep->s, ep->size) == 0)
daniele 19:c7debad9a20a 419 send_retval(ep, 0);
daniele 19:c7debad9a20a 420 else
daniele 19:c7debad9a20a 421 send_error(ep);
daniele 19:c7debad9a20a 422 break;
daniele 19:c7debad9a20a 423 default:
daniele 19:c7debad9a20a 424 retry_token(ep);
daniele 19:c7debad9a20a 425 }
daniele 19:c7debad9a20a 426 break;
daniele 19:c7debad9a20a 427 }
daniele 19:c7debad9a20a 428 }
daniele 19:c7debad9a20a 429 return ret;
daniele 19:c7debad9a20a 430 }
daniele 19:c7debad9a20a 431
daniele 19:c7debad9a20a 432 void pico_wrapper_loop(const void * arg)
daniele 19:c7debad9a20a 433 {
daniele 19:c7debad9a20a 434 (void)arg;
daniele 19:c7debad9a20a 435 int ret = 0;
daniele 19:c7debad9a20a 436 while(1) {
daniele 23:884f327c3647 437 ret = stack_parse_requests();
daniele 19:c7debad9a20a 438 pico_stack_tick();
daniele 25:d63125298eb3 439 //Thread::wait(1);
daniele 24:8bff2b51ea3b 440 Thread::wait(1);
daniele 19:c7debad9a20a 441 }
daniele 19:c7debad9a20a 442 }
daniele 19:c7debad9a20a 443
daniele 19:c7debad9a20a 444 void picotcp_start(void)
daniele 19:c7debad9a20a 445 {
daniele 23:884f327c3647 446 Ticker *picotcpTicker = new Ticker();
daniele 19:c7debad9a20a 447 if (serverThread == NULL) {
daniele 19:c7debad9a20a 448 printf (" *** PicoTCP initialized *** \n");
daniele 19:c7debad9a20a 449 serverThread = new Thread(pico_wrapper_loop);
daniele 19:c7debad9a20a 450 serverThread->set_priority(osPriorityIdle);
daniele 23:884f327c3647 451 //picotcpTicker->attach(&pico_stack_tick, 0.001);
daniele 19:c7debad9a20a 452 }
daniele 19:c7debad9a20a 453 }