Daniele Lacamera / PicoTCP-Experimental_CDC_ECM_Branch

Fork of PicoTCP by Daniele Lacamera

Committer:
daniele
Date:
Thu Jun 06 07:08:58 2013 +0000
Revision:
11:58acd53df75c
Parent:
5:445d2fc04784
Child:
13:c6662adea07d
Update from masterbranch;

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