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 21:10:23 2013 +0000
Revision:
24:8bff2b51ea3b
Parent:
23:884f327c3647
Child:
25:d63125298eb3
Reworked socket interface. Fixed several bugs.

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 24:8bff2b51ea3b 192 pico_socket_close(ep->s);
daniele 24:8bff2b51ea3b 193 send_retval(ep, 0);
daniele 24:8bff2b51ea3b 194 stack_Del(ep);
daniele 19:c7debad9a20a 195 }
daniele 19:c7debad9a20a 196
daniele 19:c7debad9a20a 197 static void retry_write(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 198 {
daniele 19:c7debad9a20a 199
daniele 19:c7debad9a20a 200 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 201 return;
daniele 19:c7debad9a20a 202
daniele 19:c7debad9a20a 203 if (!ep->buffer) {
daniele 19:c7debad9a20a 204 send_error(ep);
daniele 19:c7debad9a20a 205 return;
daniele 19:c7debad9a20a 206 }
daniele 19:c7debad9a20a 207
daniele 19:c7debad9a20a 208 if (ep->pending == TOK_SENDTO) {
daniele 19:c7debad9a20a 209 ep->size = pico_socket_sendto(ep->s, ep->buffer, ep->size, &ep->addr, ep->port);
daniele 19:c7debad9a20a 210 } else {
daniele 19:c7debad9a20a 211 ep->size = pico_socket_write(ep->s, ep->buffer, ep->size);
daniele 19:c7debad9a20a 212 }
daniele 19:c7debad9a20a 213 ep->revents &= (~PICO_SOCK_EV_WR);
daniele 19:c7debad9a20a 214 if (ep->size < 0)
daniele 19:c7debad9a20a 215 send_error(ep);
daniele 19:c7debad9a20a 216 else if (ep->size > 0)
daniele 19:c7debad9a20a 217 send_retval(ep, ep->size);
daniele 19:c7debad9a20a 218 else {
daniele 19:c7debad9a20a 219 ep->events |= PICO_SOCK_EV_WR;
daniele 19:c7debad9a20a 220 return;
daniele 19:c7debad9a20a 221 }
daniele 19:c7debad9a20a 222 }
daniele 19:c7debad9a20a 223
daniele 19:c7debad9a20a 224 static void retry_read(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 225 {
daniele 19:c7debad9a20a 226 int len;
daniele 19:c7debad9a20a 227 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 228 return;
daniele 19:c7debad9a20a 229
daniele 19:c7debad9a20a 230 ptsock_dbg("in retry-read, len: %d \n", len);
daniele 19:c7debad9a20a 231
daniele 19:c7debad9a20a 232
daniele 19:c7debad9a20a 233
daniele 19:c7debad9a20a 234 if (!ep->buffer) {
daniele 19:c7debad9a20a 235 send_error(ep);
daniele 19:c7debad9a20a 236 return;
daniele 19:c7debad9a20a 237 } else {
daniele 19:c7debad9a20a 238 if (ep->pending == TOK_RECVFROM)
daniele 19:c7debad9a20a 239 len = pico_socket_recvfrom(ep->s, ep->buffer, ep->size, &ep->addr, &ep->port);
daniele 19:c7debad9a20a 240 else {
daniele 19:c7debad9a20a 241 len = pico_socket_read(ep->s, ep->buffer, ep->size);
daniele 19:c7debad9a20a 242 }
daniele 19:c7debad9a20a 243 }
daniele 19:c7debad9a20a 244
daniele 19:c7debad9a20a 245 if (ep->size > len)
daniele 19:c7debad9a20a 246 ep->revents &= (~PICO_SOCK_EV_RD);
daniele 19:c7debad9a20a 247
daniele 19:c7debad9a20a 248 if (len == 0) {
daniele 19:c7debad9a20a 249 ptsock_dbg("Read returned 0.");
daniele 19:c7debad9a20a 250 ep->events |= PICO_SOCK_EV_RD;
daniele 19:c7debad9a20a 251 return;
daniele 19:c7debad9a20a 252 }
daniele 19:c7debad9a20a 253 send_retval(ep, len);
daniele 19:c7debad9a20a 254 }
daniele 19:c7debad9a20a 255
daniele 19:c7debad9a20a 256 void retry_poll(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 257 {
daniele 19:c7debad9a20a 258 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 259 return;
daniele 19:c7debad9a20a 260
daniele 19:c7debad9a20a 261 set_timer(ep);
daniele 19:c7debad9a20a 262
daniele 19:c7debad9a20a 263 if ((ep->events & ep->revents) != 0) {
daniele 19:c7debad9a20a 264 send_retval(ep, 1);
daniele 19:c7debad9a20a 265 return;
daniele 19:c7debad9a20a 266 }
daniele 19:c7debad9a20a 267
daniele 19:c7debad9a20a 268 check_timer_expired(ep);
daniele 19:c7debad9a20a 269 }
daniele 19:c7debad9a20a 270
daniele 19:c7debad9a20a 271 static void retry_token(struct stack_endpoint *ep)
daniele 19:c7debad9a20a 272 {
daniele 19:c7debad9a20a 273 if (ep->pending == NO_COMMAND)
daniele 19:c7debad9a20a 274 return;
daniele 19:c7debad9a20a 275 ptsock_dbg("in retry-token, cmd: %04x\n", ep->pending);
daniele 19:c7debad9a20a 276 switch(ep->pending) {
daniele 19:c7debad9a20a 277 case TOK_POLL:
daniele 19:c7debad9a20a 278 retry_poll(ep);
daniele 19:c7debad9a20a 279 break;
daniele 19:c7debad9a20a 280 case TOK_CONNECT:
daniele 19:c7debad9a20a 281 retry_connect(ep);
daniele 19:c7debad9a20a 282 break;
daniele 19:c7debad9a20a 283 case TOK_ACCEPT:
daniele 19:c7debad9a20a 284 retry_accept(ep);
daniele 19:c7debad9a20a 285 break;
daniele 19:c7debad9a20a 286
daniele 19:c7debad9a20a 287 case TOK_READ:
daniele 19:c7debad9a20a 288 case TOK_RECV:
daniele 19:c7debad9a20a 289 case TOK_RECVFROM:
daniele 19:c7debad9a20a 290 retry_read(ep);
daniele 19:c7debad9a20a 291 break;
daniele 19:c7debad9a20a 292
daniele 19:c7debad9a20a 293 case TOK_WRITE:
daniele 19:c7debad9a20a 294 case TOK_SEND:
daniele 19:c7debad9a20a 295 case TOK_SENDTO:
daniele 19:c7debad9a20a 296 retry_write(ep);
daniele 19:c7debad9a20a 297 break;
daniele 19:c7debad9a20a 298
daniele 19:c7debad9a20a 299 case TOK_CLOSE:
daniele 19:c7debad9a20a 300 retry_close(ep);
daniele 19:c7debad9a20a 301 break;
daniele 19:c7debad9a20a 302 default:
daniele 19:c7debad9a20a 303 break;
daniele 19:c7debad9a20a 304 }
daniele 19:c7debad9a20a 305 }
daniele 19:c7debad9a20a 306
daniele 19:c7debad9a20a 307 static void wakeup(uint16_t ev, struct pico_socket *s)
daniele 19:c7debad9a20a 308 {
daniele 19:c7debad9a20a 309 int t;
daniele 19:c7debad9a20a 310 struct stack_endpoint *ep = GET_SOCK_BY_PICOSOCK(s);
daniele 19:c7debad9a20a 311
daniele 19:c7debad9a20a 312 if (!ep) {
daniele 19:c7debad9a20a 313 ptsock_dbg("WAKEUP: no socket :(\n");
daniele 19:c7debad9a20a 314 return;
daniele 19:c7debad9a20a 315 }
daniele 19:c7debad9a20a 316 t = ep->pending;
daniele 19:c7debad9a20a 317 ptsock_dbg("Wake up event: %04x\n", ev);
daniele 19:c7debad9a20a 318 ep->revents |= ev;
daniele 19:c7debad9a20a 319
daniele 24:8bff2b51ea3b 320
daniele 24:8bff2b51ea3b 321
daniele 24:8bff2b51ea3b 322 if (ev & PICO_SOCK_EV_CLOSE){
daniele 24:8bff2b51ea3b 323 printf("** CLOSE\n");
daniele 24:8bff2b51ea3b 324 ep->connected = 0;
daniele 24:8bff2b51ea3b 325 send_error(ep);
daniele 24:8bff2b51ea3b 326 }
daniele 24:8bff2b51ea3b 327 if (ev & PICO_SOCK_EV_FIN) {
daniele 24:8bff2b51ea3b 328 printf("** FIN\n");
daniele 24:8bff2b51ea3b 329 }
daniele 24:8bff2b51ea3b 330
daniele 19:c7debad9a20a 331 if (ev & PICO_SOCK_EV_ERR) {
daniele 19:c7debad9a20a 332 ep->revents = PICO_SOCK_EV_ERR;
daniele 19:c7debad9a20a 333 send_error(ep);
daniele 19:c7debad9a20a 334 return;
daniele 19:c7debad9a20a 335 }
daniele 19:c7debad9a20a 336
daniele 19:c7debad9a20a 337 if ((ev & PICO_SOCK_EV_CONN) || (ev & PICO_SOCK_EV_RD)) {
daniele 24:8bff2b51ea3b 338 if ((ev & PICO_SOCK_EV_CONN) && ((ep->pending == TOK_CONNECT) || (ep->pending == TOK_ACCEPT))) {
daniele 24:8bff2b51ea3b 339 printf("** Connected\n");
daniele 19:c7debad9a20a 340 ep->connected = 1;
daniele 19:c7debad9a20a 341 }
daniele 19:c7debad9a20a 342 }
daniele 24:8bff2b51ea3b 343 ep->revents = ev;
daniele 19:c7debad9a20a 344 if ( (ep->pending != 0) && ((ep->events & ep->revents)!=0) )
daniele 19:c7debad9a20a 345 retry_token(ep);
daniele 19:c7debad9a20a 346 }
daniele 19:c7debad9a20a 347
daniele 19:c7debad9a20a 348 static int stack_parse_requests(void)
daniele 19:c7debad9a20a 349 {
daniele 19:c7debad9a20a 350 struct stack_endpoint *ep = NULL;
daniele 19:c7debad9a20a 351 struct picotcp_socketcall *skc;
daniele 19:c7debad9a20a 352 osEvent event; // used to see the status of queue get
daniele 19:c7debad9a20a 353 struct pico_tree_node * index = NULL;
daniele 19:c7debad9a20a 354 uint16_t proto,net;
daniele 19:c7debad9a20a 355 int ret = 0;
daniele 19:c7debad9a20a 356 int yes = 1;
daniele 19:c7debad9a20a 357 // first check if the global queue has something in it
daniele 19:c7debad9a20a 358 // and open a new socket if so
daniele 19:c7debad9a20a 359 do
daniele 19:c7debad9a20a 360 {
daniele 19:c7debad9a20a 361 stack_endpoint *stack_ep = NULL;
daniele 19:c7debad9a20a 362
daniele 19:c7debad9a20a 363 event = picotcp_socketcall_queue.get(0); // non blocking get
daniele 19:c7debad9a20a 364 if(event.status == osEventMessage) {
daniele 19:c7debad9a20a 365 ret = 1;
daniele 19:c7debad9a20a 366 // Get the arguments
daniele 19:c7debad9a20a 367 skc = (struct picotcp_socketcall *)event.value.p;
daniele 19:c7debad9a20a 368
daniele 19:c7debad9a20a 369 // open new socket and send the response
daniele 19:c7debad9a20a 370 stack_ep = (struct stack_endpoint *)pico_zalloc(sizeof(struct stack_endpoint));
daniele 19:c7debad9a20a 371 if(!stack_ep)
daniele 19:c7debad9a20a 372 {
daniele 19:c7debad9a20a 373 ptsock_dbg("Out of memory\n");
daniele 19:c7debad9a20a 374 return -1;
daniele 19:c7debad9a20a 375 }
daniele 19:c7debad9a20a 376 stack_ep->CallActivateQueue = new Queue<struct stack_endpoint,2>();
daniele 19:c7debad9a20a 377 stack_ep->CallResponseQueue = new Queue<struct stack_endpoint,2>();
daniele 19:c7debad9a20a 378
daniele 19:c7debad9a20a 379 net = ((skc->family == AF_INET6)?PICO_PROTO_IPV6:PICO_PROTO_IPV4);
daniele 19:c7debad9a20a 380 proto = ((skc->proto == SOCK_DGRAM)?PICO_PROTO_UDP:PICO_PROTO_TCP);
daniele 19:c7debad9a20a 381 stack_ep->s = pico_socket_open( net, proto, &wakeup );
daniele 19:c7debad9a20a 382
daniele 19:c7debad9a20a 383 if (!stack_ep->s)
daniele 19:c7debad9a20a 384 stack_ep->retval = -1;
daniele 19:c7debad9a20a 385 //pico_socket_setoption(stack_ep->s, PICO_SOCKET_OPT_TCPNODELAY, &yes);
daniele 19:c7debad9a20a 386
daniele 19:c7debad9a20a 387 //stack_ep->pending = NO_COMMAND;
daniele 19:c7debad9a20a 388 stack_Add(stack_ep);
daniele 19:c7debad9a20a 389 // send the response back to the client
daniele 19:c7debad9a20a 390 sendOpenResponse(stack_ep);
daniele 19:c7debad9a20a 391 ptsock_dbg("New socket added: %p\n", stack_ep->s);
daniele 19:c7debad9a20a 392 }
daniele 19:c7debad9a20a 393 }while(event.status == osEventMessage);
daniele 19:c7debad9a20a 394
daniele 19:c7debad9a20a 395 // go through all the sockets and check if there is a request from someone
daniele 19:c7debad9a20a 396 // call to the get function has timeout 0, must be non blocking
daniele 19:c7debad9a20a 397 // if a request has come from someone parse it
daniele 19:c7debad9a20a 398 pico_tree_foreach(index,&stack_ep_tree)
daniele 19:c7debad9a20a 399 {
daniele 19:c7debad9a20a 400 ep = (struct stack_endpoint *)index->keyValue;
daniele 19:c7debad9a20a 401 // check if data has arrived
daniele 19:c7debad9a20a 402 event = ep->CallActivateQueue->get(0); // again non blocking
daniele 19:c7debad9a20a 403 if(event.status == osEventMessage)
daniele 19:c7debad9a20a 404 {
daniele 19:c7debad9a20a 405 ret = 1;
daniele 19:c7debad9a20a 406 //printf("Socket contacted. CMD: %X\n", ep->pending);
daniele 19:c7debad9a20a 407 // check command sent
daniele 19:c7debad9a20a 408 switch(ep->pending)
daniele 19:c7debad9a20a 409 {
daniele 19:c7debad9a20a 410 case TOK_BIND:
daniele 19:c7debad9a20a 411 if(pico_socket_bind(ep->s, &ep->addr, &ep->port) == 0) {
daniele 19:c7debad9a20a 412 ptsock_dbg("stack: bind success (addr: %08x, port %d)!\n", ep->addr.addr, ep->port);
daniele 19:c7debad9a20a 413 send_retval(ep, 0);
daniele 19:c7debad9a20a 414 } else {
daniele 19:c7debad9a20a 415 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 416 send_error(ep);
daniele 19:c7debad9a20a 417 }
daniele 19:c7debad9a20a 418 break;
daniele 19:c7debad9a20a 419 case TOK_LISTEN:
daniele 19:c7debad9a20a 420 if(pico_socket_listen(ep->s, ep->size) == 0)
daniele 19:c7debad9a20a 421 send_retval(ep, 0);
daniele 19:c7debad9a20a 422 else
daniele 19:c7debad9a20a 423 send_error(ep);
daniele 19:c7debad9a20a 424 break;
daniele 19:c7debad9a20a 425 default:
daniele 19:c7debad9a20a 426 retry_token(ep);
daniele 19:c7debad9a20a 427 }
daniele 19:c7debad9a20a 428 break;
daniele 19:c7debad9a20a 429 }
daniele 19:c7debad9a20a 430 }
daniele 19:c7debad9a20a 431 return ret;
daniele 19:c7debad9a20a 432 }
daniele 19:c7debad9a20a 433
daniele 19:c7debad9a20a 434 void pico_wrapper_loop(const void * arg)
daniele 19:c7debad9a20a 435 {
daniele 19:c7debad9a20a 436 (void)arg;
daniele 19:c7debad9a20a 437 int ret = 0;
daniele 19:c7debad9a20a 438 while(1) {
daniele 23:884f327c3647 439 ret = stack_parse_requests();
daniele 19:c7debad9a20a 440 pico_stack_tick();
daniele 24:8bff2b51ea3b 441 Thread::wait(1);
daniele 19:c7debad9a20a 442 }
daniele 19:c7debad9a20a 443 }
daniele 19:c7debad9a20a 444
daniele 19:c7debad9a20a 445 void picotcp_start(void)
daniele 19:c7debad9a20a 446 {
daniele 23:884f327c3647 447 Ticker *picotcpTicker = new Ticker();
daniele 19:c7debad9a20a 448 if (serverThread == NULL) {
daniele 19:c7debad9a20a 449 printf (" *** PicoTCP initialized *** \n");
daniele 19:c7debad9a20a 450 serverThread = new Thread(pico_wrapper_loop);
daniele 19:c7debad9a20a 451 serverThread->set_priority(osPriorityIdle);
daniele 23:884f327c3647 452 //picotcpTicker->attach(&pico_stack_tick, 0.001);
daniele 19:c7debad9a20a 453 }
daniele 19:c7debad9a20a 454 }