Daniele Lacamera / PicoTCP-Experimental_CDC_ECM_Branch

Fork of PicoTCP by Daniele Lacamera

Committer:
tass
Date:
Thu Jun 06 13:51:27 2013 +0000
Revision:
16:6893f625e337
Parent:
14:fe225a6f92c0
Child:
17:5292cca5c478
added rtosTimer

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 5:445d2fc04784 1
tass 5:445d2fc04784 2 /*********************************************************************
tass 5:445d2fc04784 3 PicoTCP. Copyright (c) 2013 TASS Belgium NV. Some rights reserved.
tass 5:445d2fc04784 4 See LICENSE and COPYING for usage.
tass 5:445d2fc04784 5
tass 5:445d2fc04784 6 Authors: Andrei Carp <andrei.carp@tass.be>, Daniele Lacamera <daniele.lacamera@tass.be>
tass 5:445d2fc04784 7 *********************************************************************/
tass 5:445d2fc04784 8 #include "pico_bsd_layer.h"
tass 5:445d2fc04784 9
tass 5:445d2fc04784 10 #include "mbed.h"
tass 5:445d2fc04784 11 #include "rtos.h"
tass 5:445d2fc04784 12 #include "cmsis_os.h"
tass 5:445d2fc04784 13 #include "Queue.h"
tass 5:445d2fc04784 14 #include "Mutex.h"
tass 5:445d2fc04784 15 #include "PicoCondition.h"
tass 5:445d2fc04784 16 /************************** PICO BSD SOCKET LAYER **************************/
tass 5:445d2fc04784 17
tass 5:445d2fc04784 18 #define DEFAULT_BACKLOG (5u)
tass 5:445d2fc04784 19 #define DEFAULT_TIMEOUT (10000u)
tass 5:445d2fc04784 20
tass 5:445d2fc04784 21 // Handle events received from the callback
tass 5:445d2fc04784 22 #define EVENT_PENDING(x,ev) (x & (ev))
tass 5:445d2fc04784 23 #define CLEAR_EVENTS(x) (x ^= (x))
tass 5:445d2fc04784 24 #define SET_EVENT(x,ev) (x |= (ev))
tass 5:445d2fc04784 25 #define RESET_EVENT(x,ev) (x &= (~ev))
tass 5:445d2fc04784 26 #define CLEAR_ERROR(x) RESET_EVENT(x,PICO_SOCK_EV_ERR)
tass 5:445d2fc04784 27
tass 5:445d2fc04784 28 #define EVENT_EXPECTED(x) (x->event & x->revent)
tass 5:445d2fc04784 29
tass 13:c6662adea07d 30
tass 13:c6662adea07d 31 static PicoCondition globalLock;
tass 13:c6662adea07d 32 static Mutex globalMutex;
tass 13:c6662adea07d 33
tass 5:445d2fc04784 34 /* TODO: Sync blocking from here to blocking from Socket */
tass 5:445d2fc04784 35
tass 5:445d2fc04784 36 static struct socket dummy;
tass 5:445d2fc04784 37 #define MAKE_SOCKET(x) ((struct socket *)x)
tass 5:445d2fc04784 38
tass 5:445d2fc04784 39 static int compareSock(void *ka, void *kb)
tass 5:445d2fc04784 40 {
tass 5:445d2fc04784 41 return MAKE_SOCKET(ka)->socket - MAKE_SOCKET(kb)->socket;
tass 5:445d2fc04784 42 }
tass 5:445d2fc04784 43
tass 5:445d2fc04784 44 PICO_TREE_DECLARE(sockTree,compareSock);
tass 5:445d2fc04784 45
tass 5:445d2fc04784 46 #define VALIDATE_NULL(param) \
tass 5:445d2fc04784 47 if(!param) \
tass 5:445d2fc04784 48 { \
tass 5:445d2fc04784 49 return -1; \
tass 5:445d2fc04784 50 }
tass 5:445d2fc04784 51
tass 5:445d2fc04784 52 #define VALIDATE_ONE(param,value) \
tass 5:445d2fc04784 53 if(param != value) { \
tass 5:445d2fc04784 54 pico_err = PICO_ERR_EINVAL; \
tass 5:445d2fc04784 55 return -1; \
tass 5:445d2fc04784 56 }
tass 5:445d2fc04784 57
tass 5:445d2fc04784 58 #define VALIDATE_TWO(param,value1,value2) \
tass 5:445d2fc04784 59 if(param != value1 && param != value2) { \
tass 5:445d2fc04784 60 pico_err = PICO_ERR_EINVAL; \
tass 5:445d2fc04784 61 return -1; \
tass 5:445d2fc04784 62 }
tass 5:445d2fc04784 63
tass 5:445d2fc04784 64 /* PRIVATE FUNCTIONS */
tass 5:445d2fc04784 65
tass 5:445d2fc04784 66 static inline struct socket * findAfterId(int sock)
tass 5:445d2fc04784 67 {
tass 5:445d2fc04784 68 dummy.socket = sock;
tass 5:445d2fc04784 69 return (struct socket *)pico_tree_findKey(&sockTree,&dummy);
tass 5:445d2fc04784 70 }
tass 5:445d2fc04784 71
tass 5:445d2fc04784 72 static inline struct socket * findAfterSocket(struct pico_socket * sock)
tass 5:445d2fc04784 73 {
tass 5:445d2fc04784 74 struct pico_tree_node * index;
tass 5:445d2fc04784 75
tass 5:445d2fc04784 76 pico_tree_foreach(index,&sockTree)
tass 5:445d2fc04784 77 {
tass 5:445d2fc04784 78 if( MAKE_SOCKET(index->keyValue)->sock == sock )
tass 5:445d2fc04784 79 return (struct socket *)index->keyValue;
tass 5:445d2fc04784 80 }
tass 5:445d2fc04784 81
tass 5:445d2fc04784 82 return NULL;
tass 5:445d2fc04784 83 }
tass 5:445d2fc04784 84
tass 5:445d2fc04784 85 static inline int waitForEvent(struct socket * sock, uint16_t event, uint8_t clear)
tass 5:445d2fc04784 86 {
tass 5:445d2fc04784 87 int retValue = 0;
tass 5:445d2fc04784 88
tass 16:6893f625e337 89 //if(sock->blocking)
tass 5:445d2fc04784 90 {
tass 5:445d2fc04784 91 if(EVENT_PENDING(sock->revent,event))
tass 5:445d2fc04784 92 {
tass 16:6893f625e337 93 RESET_EVENT(sock->event, event);
tass 16:6893f625e337 94
tass 16:6893f625e337 95 if(event & PICO_SOCK_EV_RD)
tass 16:6893f625e337 96 RESET_EVENT(event,PICO_SOCK_EV_RD);
tass 16:6893f625e337 97
tass 5:445d2fc04784 98 RESET_EVENT(sock->revent, event);
tass 5:445d2fc04784 99 }
tass 5:445d2fc04784 100 else
tass 5:445d2fc04784 101 {
tass 5:445d2fc04784 102 SET_EVENT(sock->event, event);
tass 5:445d2fc04784 103 //printf("Locked...\n");
tass 5:445d2fc04784 104 sock->mutex->lock();
tass 5:445d2fc04784 105 RESET_EVENT(sock->event,event);
tass 5:445d2fc04784 106
tass 5:445d2fc04784 107 if(! EVENT_PENDING(sock->revent,event) || EVENT_PENDING(sock->revent, PICO_SOCK_EV_ERR) ||
tass 5:445d2fc04784 108 EVENT_PENDING(sock->revent,PICO_SOCK_EV_CLOSE) || EVENT_PENDING(sock->revent,PICO_SOCK_EV_FIN) )
tass 5:445d2fc04784 109 retValue = -1;
tass 5:445d2fc04784 110 }
tass 5:445d2fc04784 111 if(clear)
tass 5:445d2fc04784 112 RESET_EVENT(sock->revent, event);
tass 5:445d2fc04784 113 }
tass 5:445d2fc04784 114
tass 5:445d2fc04784 115 return retValue;
tass 5:445d2fc04784 116 }
tass 5:445d2fc04784 117
tass 5:445d2fc04784 118
tass 5:445d2fc04784 119 static void dispatch_socket(uint16_t ev, struct pico_socket * sock)
tass 5:445d2fc04784 120 {
tass 5:445d2fc04784 121 struct socket * _sock = findAfterSocket(sock);
tass 5:445d2fc04784 122
tass 5:445d2fc04784 123 if(!_sock)
tass 13:c6662adea07d 124 {
tass 13:c6662adea07d 125 if( (ev & PICO_SOCK_EV_ERR) || (ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN) )
tass 13:c6662adea07d 126 pico_socket_close(sock);
tass 5:445d2fc04784 127 return;
tass 13:c6662adea07d 128 }
tass 5:445d2fc04784 129
tass 5:445d2fc04784 130 //printf("Received : %d\n",ev);
tass 5:445d2fc04784 131
tass 5:445d2fc04784 132 SET_EVENT(_sock->revent,ev);
tass 5:445d2fc04784 133 if(EVENT_EXPECTED(_sock))
tass 5:445d2fc04784 134 {
tass 5:445d2fc04784 135 // if one of the events we're waiting has arrived, unblock this
tass 5:445d2fc04784 136 //printf("Expected event, release the orcs!\n");
tass 5:445d2fc04784 137 _sock->mutex->unlock();
tass 13:c6662adea07d 138 globalLock.lock();
tass 5:445d2fc04784 139 }
tass 5:445d2fc04784 140 else
tass 5:445d2fc04784 141 {
tass 14:fe225a6f92c0 142 printf("Unexpected event\n");
tass 5:445d2fc04784 143 // give semaphore back when -1 occurs or close requested
tass 5:445d2fc04784 144 if( (ev & PICO_SOCK_EV_ERR) || (ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN) )
tass 5:445d2fc04784 145 {
tass 14:fe225a6f92c0 146 printf("Exception\n");
tass 5:445d2fc04784 147
tass 5:445d2fc04784 148 _sock->state = SOCK_CLOSED;
tass 14:fe225a6f92c0 149 if(_sock->state != SOCK_CLOSED)
tass 5:445d2fc04784 150 {
tass 5:445d2fc04784 151 pico_socket_close(_sock->sock);
tass 14:fe225a6f92c0 152 //_sock->sock = NULL;
tass 5:445d2fc04784 153 }
tass 5:445d2fc04784 154 _sock->mutex->unlock();
tass 13:c6662adea07d 155 globalLock.lock();
tass 5:445d2fc04784 156 }
tass 5:445d2fc04784 157 }
tass 5:445d2fc04784 158 }
tass 5:445d2fc04784 159
tass 5:445d2fc04784 160 /* PUBLIC FUNCTIONS */
tass 5:445d2fc04784 161
tass 5:445d2fc04784 162 int picotcp_socket(uint16_t net, uint16_t proto, uint16_t flags)
tass 5:445d2fc04784 163 {
tass 5:445d2fc04784 164 struct socket * sock = NULL;
tass 5:445d2fc04784 165
tass 5:445d2fc04784 166 net = (net == AF_INET ? PICO_PROTO_IPV4 : (net == AF_INET6 ? PICO_PROTO_IPV6 : -1));
tass 5:445d2fc04784 167 proto = (proto == SOCK_DGRAM ? PICO_PROTO_UDP : (proto == SOCK_STREAM ? PICO_PROTO_TCP : -1));
tass 5:445d2fc04784 168
tass 5:445d2fc04784 169 VALIDATE_TWO(net,PICO_PROTO_IPV4,PICO_PROTO_IPV6);
tass 5:445d2fc04784 170 VALIDATE_TWO(proto,PICO_PROTO_TCP,PICO_PROTO_UDP);
tass 5:445d2fc04784 171 //printf("Parameters are correct...\n");
tass 5:445d2fc04784 172 sock = (struct socket*)pico_zalloc(sizeof(struct socket));
tass 5:445d2fc04784 173 VALIDATE_NULL(sock);
tass 5:445d2fc04784 174
tass 5:445d2fc04784 175 sock->proto = proto;
tass 5:445d2fc04784 176 sock->sock = pico_socket_open(net,proto,&dispatch_socket);
tass 5:445d2fc04784 177
tass 5:445d2fc04784 178 if(!sock->sock)
tass 5:445d2fc04784 179 {
tass 5:445d2fc04784 180 pico_free(sock);
tass 5:445d2fc04784 181 return -1;
tass 5:445d2fc04784 182 }
tass 5:445d2fc04784 183
tass 5:445d2fc04784 184 sock->socket = (int)sock;
tass 5:445d2fc04784 185 sock->mutex = new PicoCondition();
tass 13:c6662adea07d 186
tass 13:c6662adea07d 187
tass 13:c6662adea07d 188
tass 5:445d2fc04784 189 if(!sock->mutex)
tass 5:445d2fc04784 190 {
tass 5:445d2fc04784 191 pico_socket_close(sock->sock);
tass 5:445d2fc04784 192 pico_free(sock);
tass 5:445d2fc04784 193 return -1;
tass 5:445d2fc04784 194 }
tass 13:c6662adea07d 195
tass 13:c6662adea07d 196 globalMutex.lock();
tass 5:445d2fc04784 197 pico_tree_insert(&sockTree,sock);
tass 13:c6662adea07d 198 globalMutex.unlock();
tass 13:c6662adea07d 199
tass 5:445d2fc04784 200 sock->state = SOCK_OPEN;
tass 5:445d2fc04784 201
tass 5:445d2fc04784 202 return sock->socket;
tass 5:445d2fc04784 203 }
tass 5:445d2fc04784 204
tass 5:445d2fc04784 205 int picotcp_bind(int sock, struct sockaddr *local_addr, socklen_t len)
tass 5:445d2fc04784 206 {
tass 5:445d2fc04784 207 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 208 int ret;
tass 5:445d2fc04784 209 struct sockaddr_in *s_in = (struct sockaddr_in *) local_addr;
tass 5:445d2fc04784 210
tass 5:445d2fc04784 211 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 212 VALIDATE_NULL(local_addr);
tass 5:445d2fc04784 213 VALIDATE_NULL(len);
tass 5:445d2fc04784 214
tass 5:445d2fc04784 215 ret = pico_socket_bind(_sock->sock,(void *)&s_in->sin_addr,(uint16_t *)&s_in->sin_port);
tass 5:445d2fc04784 216
tass 5:445d2fc04784 217 if(ret == 0)
tass 5:445d2fc04784 218 _sock->state = SOCK_BOUND;
tass 5:445d2fc04784 219
tass 5:445d2fc04784 220 return ret;
tass 5:445d2fc04784 221 }
tass 5:445d2fc04784 222
tass 5:445d2fc04784 223 int picotcp_state(int sock)
tass 5:445d2fc04784 224 {
tass 5:445d2fc04784 225 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 226 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 227
tass 5:445d2fc04784 228 return _sock->state;
tass 5:445d2fc04784 229 }
tass 5:445d2fc04784 230
tass 5:445d2fc04784 231 int picotcp_listen(int sock, int queue)
tass 5:445d2fc04784 232 {
tass 5:445d2fc04784 233 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 234 int ret;
tass 5:445d2fc04784 235
tass 5:445d2fc04784 236 if(queue <= 0)
tass 5:445d2fc04784 237 queue = DEFAULT_BACKLOG;
tass 5:445d2fc04784 238
tass 5:445d2fc04784 239 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 240 VALIDATE_ONE(_sock->state,SOCK_BOUND);
tass 5:445d2fc04784 241
tass 5:445d2fc04784 242 ret = pico_socket_listen(_sock->sock,queue);
tass 5:445d2fc04784 243
tass 5:445d2fc04784 244 if(!ret)
tass 5:445d2fc04784 245 _sock->state = SOCK_LISTEN;
tass 5:445d2fc04784 246
tass 5:445d2fc04784 247 return ret;
tass 5:445d2fc04784 248 }
tass 5:445d2fc04784 249
tass 5:445d2fc04784 250 int picotcp_connect(int sock, struct sockaddr *srv_addr, socklen_t len)
tass 5:445d2fc04784 251 {
tass 5:445d2fc04784 252 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 253 int ret;
tass 5:445d2fc04784 254 struct sockaddr_in *s_in = (struct sockaddr_in *) srv_addr;
tass 5:445d2fc04784 255
tass 5:445d2fc04784 256 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 257 VALIDATE_NULL(len);
tass 5:445d2fc04784 258
tass 5:445d2fc04784 259 ret = pico_socket_connect(_sock->sock,(void*)&s_in->sin_addr,s_in->sin_port);
tass 5:445d2fc04784 260
tass 5:445d2fc04784 261 if(ret < 0)
tass 5:445d2fc04784 262 {
tass 5:445d2fc04784 263 printf("connect error\n");
tass 5:445d2fc04784 264 return -1;
tass 5:445d2fc04784 265 }
tass 5:445d2fc04784 266
tass 5:445d2fc04784 267 if(_sock->proto == PICO_PROTO_TCP)
tass 5:445d2fc04784 268 {
tass 5:445d2fc04784 269 if(waitForEvent(_sock,PICO_SOCK_EV_CONN,1) < 0)
tass 5:445d2fc04784 270 return -1;
tass 5:445d2fc04784 271 }
tass 5:445d2fc04784 272
tass 5:445d2fc04784 273 _sock->state = SOCK_CONNECTED;
tass 5:445d2fc04784 274
tass 5:445d2fc04784 275 return ret;
tass 5:445d2fc04784 276 }
tass 5:445d2fc04784 277
tass 5:445d2fc04784 278 int picotcp_accept(int sock, struct sockaddr *orig, socklen_t *len)
tass 5:445d2fc04784 279 {
tass 5:445d2fc04784 280 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 281 struct socket * client = NULL;
tass 5:445d2fc04784 282 struct pico_socket * sck = NULL;
tass 5:445d2fc04784 283 struct sockaddr_in *s_in = (struct sockaddr_in *) orig;
tass 5:445d2fc04784 284
tass 5:445d2fc04784 285
tass 5:445d2fc04784 286 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 287 VALIDATE_ONE(_sock->proto, PICO_PROTO_TCP);
tass 5:445d2fc04784 288 VALIDATE_ONE(_sock->state, SOCK_LISTEN);
tass 5:445d2fc04784 289 VALIDATE_NULL(len);
tass 5:445d2fc04784 290
tass 5:445d2fc04784 291 if(waitForEvent(_sock,PICO_SOCK_EV_CONN,1))
tass 5:445d2fc04784 292 {
tass 5:445d2fc04784 293 printf("Wait for event failed\n");
tass 5:445d2fc04784 294 return -1;
tass 5:445d2fc04784 295 }
tass 5:445d2fc04784 296
tass 5:445d2fc04784 297 // create new socket and set it directly to connected
tass 5:445d2fc04784 298 sck = pico_socket_accept(_sock->sock,(void *)&s_in->sin_addr,(uint16_t *)&s_in->sin_port);
tass 5:445d2fc04784 299 *len = sizeof(struct sockaddr_in);
tass 5:445d2fc04784 300
tass 5:445d2fc04784 301 if(!sck)
tass 13:c6662adea07d 302 {
tass 13:c6662adea07d 303 globalLock.unlock();
tass 5:445d2fc04784 304 return -1;
tass 13:c6662adea07d 305 }
tass 5:445d2fc04784 306
tass 5:445d2fc04784 307 client = (struct socket *)pico_zalloc(sizeof(struct socket));
tass 5:445d2fc04784 308
tass 5:445d2fc04784 309 if(!client)
tass 13:c6662adea07d 310 {
tass 13:c6662adea07d 311 globalLock.unlock();
tass 5:445d2fc04784 312 return -1;
tass 13:c6662adea07d 313 }
tass 5:445d2fc04784 314
tass 5:445d2fc04784 315 client->sock = sck;
tass 5:445d2fc04784 316 client->proto = _sock->proto;
tass 5:445d2fc04784 317 client->state = SOCK_CONNECTED;
tass 5:445d2fc04784 318 client->socket = (int)sck;
tass 5:445d2fc04784 319 client->mutex = new PicoCondition();
tass 5:445d2fc04784 320
tass 13:c6662adea07d 321 globalMutex.lock();
tass 5:445d2fc04784 322 pico_tree_insert(&sockTree,client);
tass 13:c6662adea07d 323 globalMutex.unlock();
tass 13:c6662adea07d 324
tass 13:c6662adea07d 325 globalLock.unlock();
tass 5:445d2fc04784 326 return client->socket;
tass 5:445d2fc04784 327 }
tass 5:445d2fc04784 328
tass 5:445d2fc04784 329 int picotcp_close(int sock)
tass 5:445d2fc04784 330 {
tass 5:445d2fc04784 331 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 332 int ret = 0;
tass 5:445d2fc04784 333
tass 5:445d2fc04784 334 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 335 pico_socket_close(_sock->sock);
tass 5:445d2fc04784 336 if(_sock->state == SOCK_CONNECTED && _sock->proto == PICO_PROTO_TCP)
tass 5:445d2fc04784 337 {
tass 5:445d2fc04784 338 ret = waitForEvent(_sock,PICO_SOCK_EV_CLOSE | PICO_SOCK_EV_FIN,1);
tass 5:445d2fc04784 339 }
tass 5:445d2fc04784 340
tass 5:445d2fc04784 341
tass 5:445d2fc04784 342 if(_sock->mutex)
tass 5:445d2fc04784 343 {
tass 5:445d2fc04784 344 delete(_sock->mutex);
tass 5:445d2fc04784 345 }
tass 13:c6662adea07d 346 globalMutex.lock();
tass 5:445d2fc04784 347 pico_tree_delete(&sockTree,_sock);
tass 13:c6662adea07d 348 globalMutex.unlock();
tass 5:445d2fc04784 349 pico_free(_sock);
tass 13:c6662adea07d 350
tass 13:c6662adea07d 351
tass 13:c6662adea07d 352 globalLock.unlock();
tass 5:445d2fc04784 353 return ret;
tass 5:445d2fc04784 354 }
tass 5:445d2fc04784 355
tass 5:445d2fc04784 356 int picotcp_send(int sock,void * buff, int len, int flags)
tass 5:445d2fc04784 357 {
tass 5:445d2fc04784 358 struct socket * _sock = findAfterId(sock);
tass 13:c6662adea07d 359 int ret;
tass 5:445d2fc04784 360
tass 5:445d2fc04784 361 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 362
tass 5:445d2fc04784 363 if(_sock->state != SOCK_BOUND && _sock->state != SOCK_CONNECTED)
tass 5:445d2fc04784 364 {
tass 5:445d2fc04784 365 printf("Bad state\n");
tass 5:445d2fc04784 366 return -1;
tass 5:445d2fc04784 367 }
tass 5:445d2fc04784 368 if(_sock->proto == PICO_PROTO_TCP)
tass 5:445d2fc04784 369 {
tass 5:445d2fc04784 370 if(waitForEvent(_sock,PICO_SOCK_EV_WR,1))
tass 5:445d2fc04784 371 return -1;
tass 5:445d2fc04784 372 }
tass 13:c6662adea07d 373
tass 13:c6662adea07d 374 ret = pico_socket_send(_sock->sock,buff,len);
tass 13:c6662adea07d 375 globalLock.unlock();
tass 13:c6662adea07d 376 return ret;
tass 5:445d2fc04784 377 }
tass 5:445d2fc04784 378
tass 5:445d2fc04784 379 int picotcp_recv(int sock,void * buff, int len, int flags)
tass 5:445d2fc04784 380 {
tass 5:445d2fc04784 381 struct socket * _sock = findAfterId(sock);
tass 13:c6662adea07d 382 int ret;
tass 13:c6662adea07d 383
tass 5:445d2fc04784 384 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 385
tass 5:445d2fc04784 386 if(_sock->state != SOCK_BOUND && _sock->state != SOCK_CONNECTED)
tass 5:445d2fc04784 387 return -1;
tass 5:445d2fc04784 388
tass 5:445d2fc04784 389 if(waitForEvent(_sock,PICO_SOCK_EV_RD,1))
tass 5:445d2fc04784 390 return -1;
tass 5:445d2fc04784 391
tass 13:c6662adea07d 392 ret = pico_socket_recv(_sock->sock,buff,len);
tass 13:c6662adea07d 393
tass 13:c6662adea07d 394 globalLock.unlock();
tass 13:c6662adea07d 395 return ret;
tass 5:445d2fc04784 396 }
tass 5:445d2fc04784 397
tass 5:445d2fc04784 398 int picotcp_sendto(int sock,void * buff, int len, struct sockaddr *orig, socklen_t socklen)
tass 5:445d2fc04784 399 {
tass 5:445d2fc04784 400 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 401 struct sockaddr_in *s_in = (struct sockaddr_in *) orig;
tass 5:445d2fc04784 402
tass 5:445d2fc04784 403 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 404 VALIDATE_ONE(_sock->proto,PICO_PROTO_UDP);
tass 5:445d2fc04784 405 VALIDATE_NULL(len);
tass 5:445d2fc04784 406 VALIDATE_NULL(socklen);
tass 5:445d2fc04784 407 printf("Sendto : parameters correct !\n");
tass 5:445d2fc04784 408
tass 5:445d2fc04784 409 return pico_socket_sendto(_sock->sock,buff,len,(void *)&s_in->sin_addr,s_in->sin_port);
tass 5:445d2fc04784 410 }
tass 5:445d2fc04784 411
tass 5:445d2fc04784 412 int picotcp_recvfrom(int sock,void * buff, int len, struct sockaddr *orig, socklen_t *socklen)
tass 5:445d2fc04784 413 {
tass 5:445d2fc04784 414 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 415 struct sockaddr_in *s_in = (struct sockaddr_in *) orig;
tass 13:c6662adea07d 416 int ret;
tass 13:c6662adea07d 417
tass 5:445d2fc04784 418 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 419 VALIDATE_ONE(_sock->proto,PICO_PROTO_UDP);
tass 5:445d2fc04784 420 VALIDATE_NULL(socklen);
tass 5:445d2fc04784 421
tass 5:445d2fc04784 422 if(waitForEvent(_sock,PICO_SOCK_EV_RD,1))
tass 5:445d2fc04784 423 return -1;
tass 13:c6662adea07d 424 ret = pico_socket_recvfrom(_sock->sock,buff,len,(void *)&s_in->sin_addr,(uint16_t *)&s_in->sin_port);
tass 13:c6662adea07d 425 globalLock.unlock();
tass 13:c6662adea07d 426 return ret;
tass 5:445d2fc04784 427 }
tass 5:445d2fc04784 428
tass 5:445d2fc04784 429 int picotcp_read(int sock,void *buf, int len)
tass 5:445d2fc04784 430 {
tass 5:445d2fc04784 431 struct socket * _sock = findAfterId(sock);
daniele 11:58acd53df75c 432 int r, tot_len = 0;
tass 5:445d2fc04784 433 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 434 VALIDATE_ONE(_sock->proto,PICO_PROTO_TCP);
tass 5:445d2fc04784 435 VALIDATE_ONE(_sock->state, SOCK_CONNECTED);
tass 5:445d2fc04784 436
tass 5:445d2fc04784 437 if(waitForEvent(_sock,PICO_SOCK_EV_RD,1))
tass 5:445d2fc04784 438 return -1;
daniele 11:58acd53df75c 439 while(tot_len < len) {
daniele 11:58acd53df75c 440 r = pico_socket_read(_sock->sock, (unsigned char *)buf + tot_len, len - tot_len);
daniele 11:58acd53df75c 441 if (r > 0)
daniele 11:58acd53df75c 442 tot_len += r;
tass 16:6893f625e337 443 else
tass 16:6893f625e337 444 {
tass 16:6893f625e337 445 RESET_EVENT(_sock->revent,PICO_SOCK_EV_RD);
tass 16:6893f625e337 446 break;
tass 16:6893f625e337 447 }
daniele 11:58acd53df75c 448 }
tass 13:c6662adea07d 449 globalLock.unlock();
daniele 11:58acd53df75c 450 return tot_len;
tass 5:445d2fc04784 451 }
tass 5:445d2fc04784 452
tass 5:445d2fc04784 453 int picotcp_write(int sock,void *buf, int len)
tass 5:445d2fc04784 454 {
tass 5:445d2fc04784 455 struct socket * _sock = findAfterId(sock);
daniele 11:58acd53df75c 456 int r, tot_len = 0;
tass 5:445d2fc04784 457
tass 5:445d2fc04784 458 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 459 VALIDATE_ONE(_sock->proto,PICO_PROTO_TCP);
tass 5:445d2fc04784 460 VALIDATE_ONE(_sock->state, SOCK_CONNECTED);
tass 5:445d2fc04784 461 if(waitForEvent(_sock,PICO_SOCK_EV_WR,1))
tass 5:445d2fc04784 462 return -1;
daniele 11:58acd53df75c 463
daniele 11:58acd53df75c 464 if(waitForEvent(_sock,PICO_SOCK_EV_WR,1))
daniele 11:58acd53df75c 465 return -1;
daniele 11:58acd53df75c 466 while(tot_len < len) {
daniele 11:58acd53df75c 467 r = pico_socket_write(_sock->sock, (unsigned char *)buf + tot_len, len - tot_len);
daniele 11:58acd53df75c 468 if (r > 0)
daniele 11:58acd53df75c 469 tot_len += r;
daniele 11:58acd53df75c 470 else break;
daniele 11:58acd53df75c 471 }
tass 13:c6662adea07d 472
tass 13:c6662adea07d 473 globalLock.unlock();
daniele 11:58acd53df75c 474 return tot_len;
tass 5:445d2fc04784 475 }
tass 5:445d2fc04784 476
tass 5:445d2fc04784 477 int picotcp_setsockopt(int sock, int option, void *value)
tass 5:445d2fc04784 478 {
tass 5:445d2fc04784 479 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 480
tass 5:445d2fc04784 481 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 482
tass 5:445d2fc04784 483 return pico_socket_setoption(_sock->sock,option,value);
tass 5:445d2fc04784 484 }
tass 5:445d2fc04784 485
tass 5:445d2fc04784 486 int picotcp_getsockopt(int sock, int option, void *value)
tass 5:445d2fc04784 487 {
tass 5:445d2fc04784 488 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 489
tass 5:445d2fc04784 490 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 491
tass 5:445d2fc04784 492 return pico_socket_getoption(_sock->sock,option,value);
tass 5:445d2fc04784 493 }
tass 5:445d2fc04784 494
tass 16:6893f625e337 495 void timeoutCb(void const *s)
tass 16:6893f625e337 496 {
tass 16:6893f625e337 497 struct socket * _sock = (struct socket *)s;
tass 16:6893f625e337 498 _sock->mutex->unlock();
tass 16:6893f625e337 499 }
tass 16:6893f625e337 500
tass 16:6893f625e337 501
tass 5:445d2fc04784 502 int picotcp_select(int sock, struct timeval *timeout, int read, int write)
tass 5:445d2fc04784 503 {
tass 5:445d2fc04784 504 uint32_t ms = 1000 * timeout->tv_sec + timeout->tv_usec / 1000;
tass 5:445d2fc04784 505 uint32_t now = PICO_TIME_MS();
tass 16:6893f625e337 506 uint16_t event = 0;
tass 5:445d2fc04784 507 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 508
tass 16:6893f625e337 509 if(!_sock)
tass 16:6893f625e337 510 return -1;
tass 13:c6662adea07d 511
tass 5:445d2fc04784 512
tass 16:6893f625e337 513 while(PICO_TIME_MS() < ms + now)
tass 16:6893f625e337 514 {
tass 16:6893f625e337 515 int events = 0;
tass 16:6893f625e337 516 RtosTimer tioTmr(timeoutCb, osTimerPeriodic, (void*)_sock);
tass 16:6893f625e337 517
tass 16:6893f625e337 518 if(read)
tass 16:6893f625e337 519 event |= PICO_SOCK_EV_RD;
tass 16:6893f625e337 520 if(write)
tass 16:6893f625e337 521 event |= PICO_SOCK_EV_WR;
tass 16:6893f625e337 522
tass 16:6893f625e337 523 waitForEvent(_sock,event,0);
tass 16:6893f625e337 524
tass 16:6893f625e337 525 if(read && EVENT_PENDING(_sock->revent,PICO_SOCK_EV_RD))
tass 16:6893f625e337 526 {
tass 16:6893f625e337 527 events++;
tass 16:6893f625e337 528 }
tass 16:6893f625e337 529
tass 16:6893f625e337 530 if(write && EVENT_PENDING(_sock->revent,PICO_SOCK_EV_WR))
tass 16:6893f625e337 531 {
tass 16:6893f625e337 532 events++;
tass 16:6893f625e337 533 RESET_EVENT(_sock->revent,PICO_SOCK_EV_WR);
tass 16:6893f625e337 534 }
tass 16:6893f625e337 535
tass 16:6893f625e337 536 if(events>0)
tass 16:6893f625e337 537 return events;
tass 16:6893f625e337 538
tass 16:6893f625e337 539 }
tass 16:6893f625e337 540 return 0;
tass 5:445d2fc04784 541 }
tass 5:445d2fc04784 542
tass 5:445d2fc04784 543 int picotcp_setblocking(int sock, int blocking)
tass 5:445d2fc04784 544 {
tass 5:445d2fc04784 545 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 546 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 547
tass 5:445d2fc04784 548 _sock->blocking = blocking;
tass 5:445d2fc04784 549
tass 5:445d2fc04784 550 return 0;
tass 5:445d2fc04784 551 }
tass 5:445d2fc04784 552
tass 5:445d2fc04784 553
tass 5:445d2fc04784 554 int picotcp_join_multicast(int sock,const char* address,const char* local)
tass 5:445d2fc04784 555 {
tass 5:445d2fc04784 556 struct socket * _sock = findAfterId(sock);
tass 5:445d2fc04784 557 struct pico_ip4 inaddr_dst, inaddr_link;
tass 5:445d2fc04784 558 struct pico_ip_mreq mreq = {{0},{0}};
tass 5:445d2fc04784 559 VALIDATE_NULL(_sock);
tass 5:445d2fc04784 560 pico_string_to_ipv4(address, &inaddr_dst.addr);
tass 5:445d2fc04784 561 pico_string_to_ipv4(local, &inaddr_link.addr); // local ip address ?
tass 5:445d2fc04784 562 mreq.mcast_group_addr = inaddr_dst;
tass 5:445d2fc04784 563 mreq.mcast_link_addr = inaddr_link;
tass 5:445d2fc04784 564 return pico_socket_setoption(_sock->sock, PICO_IP_ADD_MEMBERSHIP, &mreq);
tass 5:445d2fc04784 565 }
tass 5:445d2fc04784 566
tass 5:445d2fc04784 567 /************************** PICO BSD DNS LAYER **************************/
tass 5:445d2fc04784 568
tass 5:445d2fc04784 569 struct dnsQuery
tass 5:445d2fc04784 570 {
tass 5:445d2fc04784 571 PicoCondition * mutex;
tass 5:445d2fc04784 572 char * result;
tass 5:445d2fc04784 573 };
tass 5:445d2fc04784 574
tass 5:445d2fc04784 575 static void dispatch_dns(char *ip, void *arg)
tass 5:445d2fc04784 576 {
tass 5:445d2fc04784 577 ((struct dnsQuery *)arg)->result = ip;
tass 5:445d2fc04784 578 printf("Disp : %x\n",((struct dnsQuery *)arg)->mutex);
tass 5:445d2fc04784 579 ((struct dnsQuery *)arg)->mutex->unlock();
tass 5:445d2fc04784 580 printf("Result : %s\n",ip);
tass 5:445d2fc04784 581 }
tass 5:445d2fc04784 582
tass 5:445d2fc04784 583 struct hostent * picotcp_gethostbyname(const char *url)
tass 5:445d2fc04784 584 {
tass 5:445d2fc04784 585 struct dnsQuery * dns;
tass 5:445d2fc04784 586 struct hostent * hresult = NULL;
tass 5:445d2fc04784 587
tass 5:445d2fc04784 588 dns = (struct dnsQuery *)pico_zalloc(sizeof(struct dnsQuery));
tass 5:445d2fc04784 589
tass 5:445d2fc04784 590 if(!dns)
tass 5:445d2fc04784 591 return NULL;
tass 5:445d2fc04784 592
tass 5:445d2fc04784 593 dns->mutex = new PicoCondition();
tass 5:445d2fc04784 594
tass 5:445d2fc04784 595 pico_dns_client_getaddr(url,dispatch_dns,(void *)dns);
tass 5:445d2fc04784 596 dns->mutex->lock();
tass 5:445d2fc04784 597
tass 5:445d2fc04784 598 if(dns->result)
tass 5:445d2fc04784 599 {
tass 5:445d2fc04784 600 hresult = (struct hostent *)pico_zalloc(sizeof(struct hostent));
tass 5:445d2fc04784 601 hresult->h_addrtype = AF_INET; // ipv4
tass 5:445d2fc04784 602 // make a copy of the name
tass 5:445d2fc04784 603 hresult->h_name = new char[strlen(url)+1];
tass 5:445d2fc04784 604 memcpy(hresult->h_name,url,strlen(url)+1);
tass 5:445d2fc04784 605 hresult->h_aliases = NULL;
tass 5:445d2fc04784 606 // address list
tass 5:445d2fc04784 607 hresult->h_addr_list = new char* [2];
tass 5:445d2fc04784 608 hresult->h_addr_list[0] = dns->result;
tass 5:445d2fc04784 609 hresult->h_addr_list[1] = NULL;
tass 5:445d2fc04784 610 }
tass 5:445d2fc04784 611
tass 5:445d2fc04784 612 delete(dns->mutex);
tass 5:445d2fc04784 613 pico_free(dns);
tass 5:445d2fc04784 614 //
tass 5:445d2fc04784 615 return hresult;
tass 5:445d2fc04784 616 }
tass 5:445d2fc04784 617
tass 5:445d2fc04784 618 char * picotcp_gethostbyaddr(const char *ip)
tass 5:445d2fc04784 619 {
tass 5:445d2fc04784 620 struct dnsQuery * dns;
tass 5:445d2fc04784 621 char * result;
tass 5:445d2fc04784 622 dns = (struct dnsQuery *)pico_zalloc(sizeof(struct dnsQuery));
tass 5:445d2fc04784 623 int tries = 5u;
tass 5:445d2fc04784 624
tass 5:445d2fc04784 625 if(!dns)
tass 5:445d2fc04784 626 return NULL;
tass 5:445d2fc04784 627
tass 5:445d2fc04784 628 dns->mutex = new PicoCondition();
tass 5:445d2fc04784 629
tass 5:445d2fc04784 630 pico_dns_client_getname(ip,dispatch_dns,(void *)dns);
tass 5:445d2fc04784 631
tass 5:445d2fc04784 632 while(tries>0)
tass 5:445d2fc04784 633 {
tass 5:445d2fc04784 634 if(dns->mutex->lock() == false)
tass 5:445d2fc04784 635 tries--;
tass 5:445d2fc04784 636 else
tass 5:445d2fc04784 637 break;
tass 5:445d2fc04784 638 }
tass 5:445d2fc04784 639
tass 5:445d2fc04784 640 result = dns->result;
tass 5:445d2fc04784 641 delete(dns->mutex);
tass 5:445d2fc04784 642 pico_free(dns);
tass 5:445d2fc04784 643
tass 5:445d2fc04784 644 return result;
tass 5:445d2fc04784 645 }
tass 5:445d2fc04784 646
tass 5:445d2fc04784 647
tass 5:445d2fc04784 648 static void picotcp_loop(void const *args)
tass 5:445d2fc04784 649 {
tass 5:445d2fc04784 650 while(1) {
tass 5:445d2fc04784 651 pico_stack_tick();
tass 5:445d2fc04784 652 Thread::wait(1);
tass 5:445d2fc04784 653 }
tass 5:445d2fc04784 654 }
tass 5:445d2fc04784 655
tass 5:445d2fc04784 656 static Thread * pico_thread;
tass 5:445d2fc04784 657
tass 5:445d2fc04784 658 void picotcp_init(void)
tass 5:445d2fc04784 659 {
tass 5:445d2fc04784 660 //Thread pico_thread(picotcp_loop);
tass 5:445d2fc04784 661 pico_thread= new Thread(picotcp_loop);
tass 5:445d2fc04784 662 // doesn;t this call the ~Thread
tass 5:445d2fc04784 663 }
tass 5:445d2fc04784 664