Daniele Lacamera / PicoTCP-Experimental_CDC_ECM_Branch

Fork of PicoTCP by Daniele Lacamera

Committer:
tass
Date:
Thu Jun 06 11:40:20 2013 +0000
Revision:
15:129f20ca4d7d
Parent:
14:fe225a6f92c0
updated picotcp_select

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