]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/blob - src/api/api_lib.c
patches 1492, 1493 and 1494 from Marc
[pes-rpp/rpp-lwip.git] / src / api / api_lib.c
1 /*
2  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
3  * All rights reserved. 
4  * 
5  * Redistribution and use in source and binary forms, with or without modification, 
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission. 
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
25  * OF SUCH DAMAGE.
26  *
27  * This file is part of the lwIP TCP/IP stack.
28  * 
29  * Author: Adam Dunkels <adam@sics.se>
30  *
31  */
32
33 /* This is the part of the API that is linked with
34    the application */
35
36 #include "lwip/opt.h"
37 #include "lwip/api.h"
38 #include "lwip/api_msg.h"
39 #include "lwip/memp.h"
40
41 /*-----------------------------------------------------------------------------------*/
42 struct
43 netbuf *netbuf_new(void)
44 {
45   struct netbuf *buf;
46
47   buf = memp_mallocp(MEMP_NETBUF);
48   if (buf != NULL) {
49     buf->p = NULL;
50     buf->ptr = NULL;
51     return buf;
52   } else {
53     return NULL;
54   }
55 }
56 /*-----------------------------------------------------------------------------------*/
57 void
58 netbuf_delete(struct netbuf *buf)
59 {
60   if (buf != NULL) {
61     if (buf->p != NULL) {
62       pbuf_free(buf->p);
63       buf->p = buf->ptr = NULL;
64     }
65     memp_freep(MEMP_NETBUF, buf);
66   }
67 }
68 /*-----------------------------------------------------------------------------------*/
69 void *
70 netbuf_alloc(struct netbuf *buf, u16_t size)
71 {
72   /* Deallocate any previously allocated memory. */
73   if (buf->p != NULL) {
74     pbuf_free(buf->p);
75   }
76   buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
77   if (buf->p == NULL) {
78      return NULL;
79   }
80   buf->ptr = buf->p;
81   return buf->p->payload;
82 }
83 /*-----------------------------------------------------------------------------------*/
84 void
85 netbuf_free(struct netbuf *buf)
86 {
87   if (buf->p != NULL) {
88     pbuf_free(buf->p);
89   }
90   buf->p = buf->ptr = NULL;
91 }
92 /*-----------------------------------------------------------------------------------*/
93 void
94 netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
95 {
96   if (buf->p != NULL) {
97     pbuf_free(buf->p);
98   }
99   buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
100   buf->p->payload = dataptr;
101   buf->p->len = buf->p->tot_len = size;
102   buf->ptr = buf->p;
103 }
104 /*-----------------------------------------------------------------------------------*/
105 void
106 netbuf_chain(struct netbuf *head, struct netbuf *tail)
107 {
108   pbuf_chain(head->p, tail->p);
109   head->ptr = head->p;
110   memp_freep(MEMP_NETBUF, tail);
111 }
112 /*-----------------------------------------------------------------------------------*/
113 u16_t
114 netbuf_len(struct netbuf *buf)
115 {
116   return buf->p->tot_len;
117 }
118 /*-----------------------------------------------------------------------------------*/
119 err_t
120 netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
121 {
122   if (buf->ptr == NULL) {
123     return ERR_BUF;
124   }
125   *dataptr = buf->ptr->payload;
126   *len = buf->ptr->len;
127   return ERR_OK;
128 }
129 /*-----------------------------------------------------------------------------------*/
130 s8_t
131 netbuf_next(struct netbuf *buf)
132 {
133   if (buf->ptr->next == NULL) {
134     return -1;
135   }
136   buf->ptr = buf->ptr->next;
137   if (buf->ptr->next == NULL) {
138     return 1;
139   }
140   return 0;
141 }
142 /*-----------------------------------------------------------------------------------*/
143 void
144 netbuf_first(struct netbuf *buf)
145 {
146   buf->ptr = buf->p;
147 }
148 /*-----------------------------------------------------------------------------------*/
149 void
150 netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
151 {
152   struct pbuf *p;
153   u16_t i, left;
154
155   left = 0;
156
157   if (buf == NULL) {
158     return;
159   }
160   
161   /* This implementation is bad. It should use bcopy
162      instead. */
163   for(p = buf->p; left < len && p != NULL; p = p->next) {
164     if (offset != 0 && offset >= p->len) {
165       offset -= p->len;
166     } else {    
167       for(i = offset; i < p->len; ++i) {
168         ((char *)dataptr)[left] = ((char *)p->payload)[i];
169         if (++left >= len) {
170           return;
171         }
172       }
173       offset = 0;
174     }
175   }
176 }
177 /*-----------------------------------------------------------------------------------*/
178 void
179 netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
180 {
181   netbuf_copy_partial(buf, dataptr, len, 0);
182 }
183 /*-----------------------------------------------------------------------------------*/
184 struct ip_addr *
185 netbuf_fromaddr(struct netbuf *buf)
186 {
187   return buf->fromaddr;
188 }
189 /*-----------------------------------------------------------------------------------*/
190 u16_t
191 netbuf_fromport(struct netbuf *buf)
192 {
193   return buf->fromport;
194 }
195 /*-----------------------------------------------------------------------------------*/
196 struct
197 netconn *netconn_new(enum netconn_type t)
198 {
199   struct netconn *conn;
200
201   conn = memp_mallocp(MEMP_NETCONN);
202   if (conn == NULL) {
203     return NULL;
204   }
205   conn->type = t;
206   conn->pcb.tcp = NULL;
207
208   if ((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
209     memp_freep(MEMP_NETCONN, conn);
210     return NULL;
211   }
212   conn->recvmbox = SYS_MBOX_NULL;
213   conn->acceptmbox = SYS_MBOX_NULL;
214   conn->sem = SYS_SEM_NULL;
215   conn->state = NETCONN_NONE;
216   conn->socket = 0;
217   conn->callback = 0;
218   conn->recv_avail = 0;
219   return conn;
220 }
221 /*-----------------------------------------------------------------------------------*/
222 struct
223 netconn *netconn_new_with_callback(enum netconn_type t,
224                                    void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
225 {
226     struct netconn *conn;
227     
228     /* get a netconn and then initialize callback pointer and socket */
229     conn = netconn_new(t);
230     if (conn)
231         conn->callback = callback;
232     return conn;
233 }
234
235 /*-----------------------------------------------------------------------------------*/
236 err_t
237 netconn_delete(struct netconn *conn)
238 {
239   struct api_msg *msg;
240   void *mem;
241   
242   if (conn == NULL) {
243     return ERR_OK;
244   }
245   
246   if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
247     return ERR_MEM;
248   }
249   
250   msg->type = API_MSG_DELCONN;
251   msg->msg.conn = conn;
252   api_msg_post(msg);  
253   sys_mbox_fetch(conn->mbox, NULL);
254   memp_freep(MEMP_API_MSG, msg);
255
256   /* Drain the recvmbox. */
257   if (conn->recvmbox != SYS_MBOX_NULL) {
258     while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
259       if (conn->type == NETCONN_TCP) {
260         pbuf_free((struct pbuf *)mem);
261       } else {
262         netbuf_delete((struct netbuf *)mem);
263       }
264     }
265     sys_mbox_free(conn->recvmbox);
266     conn->recvmbox = SYS_MBOX_NULL;
267   }
268  
269
270   /* Drain the acceptmbox. */
271   if (conn->acceptmbox != SYS_MBOX_NULL) {
272     while (sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
273       netconn_delete((struct netconn *)mem);
274     }
275     
276     sys_mbox_free(conn->acceptmbox);
277     conn->acceptmbox = SYS_MBOX_NULL;
278   }
279
280   sys_mbox_free(conn->mbox);
281   conn->mbox = SYS_MBOX_NULL;
282   if (conn->sem != SYS_SEM_NULL) {
283     sys_sem_free(conn->sem);
284   }
285   /*  conn->sem = SYS_SEM_NULL;*/
286   memp_free(MEMP_NETCONN, conn);
287   return ERR_OK;
288 }
289 /*-----------------------------------------------------------------------------------*/
290 enum netconn_type
291 netconn_type(struct netconn *conn)
292 {
293   return conn->type;
294 }
295 /*-----------------------------------------------------------------------------------*/
296 err_t
297 netconn_peer(struct netconn *conn, struct ip_addr *addr,
298              u16_t *port)
299 {
300   switch (conn->type) {
301   case NETCONN_UDPLITE:
302   case NETCONN_UDPNOCHKSUM:
303   case NETCONN_UDP:
304     if (conn->pcb.udp == NULL ||
305         ((conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0))
306      return ERR_CONN;
307     *addr = (conn->pcb.udp->remote_ip);
308     *port = conn->pcb.udp->remote_port;
309     break;
310   case NETCONN_TCP:
311     if (conn->pcb.tcp == NULL)
312       return ERR_CONN;
313     *addr = (conn->pcb.tcp->remote_ip);
314     *port = conn->pcb.tcp->remote_port;
315     break;
316   }
317   return (conn->err = ERR_OK);
318 }
319 /*-----------------------------------------------------------------------------------*/
320 err_t
321 netconn_addr(struct netconn *conn, struct ip_addr **addr,
322              u16_t *port)
323 {
324   switch (conn->type) {
325   case NETCONN_UDPLITE:
326   case NETCONN_UDPNOCHKSUM:
327   case NETCONN_UDP:
328     *addr = &(conn->pcb.udp->local_ip);
329     *port = conn->pcb.udp->local_port;
330     break;
331   case NETCONN_TCP:
332     *addr = &(conn->pcb.tcp->local_ip);
333     *port = conn->pcb.tcp->local_port;
334     break;
335   }
336   return (conn->err = ERR_OK);
337 }
338 /*-----------------------------------------------------------------------------------*/
339 err_t
340 netconn_bind(struct netconn *conn, struct ip_addr *addr,
341             u16_t port)
342 {
343   struct api_msg *msg;
344
345   if (conn == NULL) {
346     return ERR_VAL;
347   }
348
349   if (conn->type != NETCONN_TCP &&
350      conn->recvmbox == SYS_MBOX_NULL) {
351     if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
352       return ERR_MEM;
353     }
354   }
355   
356   if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
357     return (conn->err = ERR_MEM);
358   }
359   msg->type = API_MSG_BIND;
360   msg->msg.conn = conn;
361   msg->msg.msg.bc.ipaddr = addr;
362   msg->msg.msg.bc.port = port;
363   api_msg_post(msg);
364   sys_mbox_fetch(conn->mbox, NULL);
365   memp_freep(MEMP_API_MSG, msg);
366   return conn->err;
367 }
368
369 /*-----------------------------------------------------------------------------------*/
370 err_t
371 netconn_connect(struct netconn *conn, struct ip_addr *addr,
372                    u16_t port)
373 {
374   struct api_msg *msg;
375   
376   if (conn == NULL) {
377     return ERR_VAL;
378   }
379
380
381   if (conn->recvmbox == SYS_MBOX_NULL) {
382     if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
383       return ERR_MEM;
384     }
385   }
386   
387   if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
388     return ERR_MEM;
389   }
390   msg->type = API_MSG_CONNECT;
391   msg->msg.conn = conn;  
392   msg->msg.msg.bc.ipaddr = addr;
393   msg->msg.msg.bc.port = port;
394   api_msg_post(msg);
395   sys_mbox_fetch(conn->mbox, NULL);
396   memp_freep(MEMP_API_MSG, msg);
397   return conn->err;
398 }
399
400 err_t
401 netconn_disconnect(struct netconn *conn)
402 {
403   struct api_msg *msg;
404   
405   if (conn == NULL) {
406     return ERR_VAL;
407   }
408
409   if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
410     return ERR_MEM;
411   }
412   msg->type = API_MSG_DISCONNECT;
413   msg->msg.conn = conn;  
414   api_msg_post(msg);
415   sys_mbox_fetch(conn->mbox, NULL);
416   memp_freep(MEMP_API_MSG, msg);
417   return conn->err;
418
419 }
420 /*-----------------------------------------------------------------------------------*/
421 err_t
422 netconn_listen(struct netconn *conn)
423 {
424   struct api_msg *msg;
425
426   if (conn == NULL) {
427     return ERR_VAL;
428   }
429
430   if (conn->acceptmbox == SYS_MBOX_NULL) {
431     conn->acceptmbox = sys_mbox_new();
432     if (conn->acceptmbox == SYS_MBOX_NULL) {
433       return ERR_MEM;
434     }
435   }
436   
437   if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
438     return (conn->err = ERR_MEM);
439   }
440   msg->type = API_MSG_LISTEN;
441   msg->msg.conn = conn;
442   api_msg_post(msg);
443   sys_mbox_fetch(conn->mbox, NULL);
444   memp_freep(MEMP_API_MSG, msg);
445   return conn->err;
446 }
447 /*-----------------------------------------------------------------------------------*/
448 struct netconn *
449 netconn_accept(struct netconn *conn)
450 {
451   struct netconn *newconn;
452   
453   if (conn == NULL) {
454     return NULL;
455   }
456   
457   sys_mbox_fetch(conn->acceptmbox, (void **)&newconn);
458   /* Register event with callback */
459   if (conn->callback)
460       (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0);
461   
462   return newconn;
463 }
464 /*-----------------------------------------------------------------------------------*/
465 struct netbuf *
466 netconn_recv(struct netconn *conn)
467 {
468   struct api_msg *msg;
469   struct netbuf *buf;
470   struct pbuf *p;
471   u16_t len;
472     
473   if (conn == NULL) {
474     return NULL;
475   }
476   
477   if (conn->recvmbox == SYS_MBOX_NULL) {
478     conn->err = ERR_CONN;
479     return NULL;
480   }
481
482   if (conn->err != ERR_OK) {
483     return NULL;
484   }
485
486   if (conn->type == NETCONN_TCP) {
487     if (conn->pcb.tcp->state == LISTEN) {
488       conn->err = ERR_CONN;
489       return NULL;
490     }
491
492
493     buf = memp_mallocp(MEMP_NETBUF);
494
495     if (buf == NULL) {
496       conn->err = ERR_MEM;
497       return NULL;
498     }
499     
500     sys_mbox_fetch(conn->recvmbox, (void **)&p);
501
502     if (p != NULL)
503     {
504         len = p->tot_len;
505         conn->recv_avail -= len;
506     }
507     else
508         len = 0;
509     
510     /* Register event with callback */
511       if (conn->callback)
512         (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, len);
513
514     /* If we are closed, we indicate that we no longer wish to receive
515        data by setting conn->recvmbox to SYS_MBOX_NULL. */
516     if (p == NULL) {
517       memp_freep(MEMP_NETBUF, buf);
518       sys_mbox_free(conn->recvmbox);
519       conn->recvmbox = SYS_MBOX_NULL;
520       return NULL;
521     }
522
523     buf->p = p;
524     buf->ptr = p;
525     buf->fromport = 0;
526     buf->fromaddr = NULL;
527
528     /* Let the stack know that we have taken the data. */
529     if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
530       conn->err = ERR_MEM;
531       return buf;
532     }
533     msg->type = API_MSG_RECV;
534     msg->msg.conn = conn;
535     if (buf != NULL) {
536       msg->msg.msg.len = buf->p->tot_len;
537     } else {
538       msg->msg.msg.len = 1;
539     }
540     api_msg_post(msg);
541
542     sys_mbox_fetch(conn->mbox, NULL);
543     memp_freep(MEMP_API_MSG, msg);
544   } else {
545     sys_mbox_fetch(conn->recvmbox, (void **)&buf);
546         conn->recv_avail -= buf->p->tot_len;
547     /* Register event with callback */
548     if (conn->callback)
549         (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
550   }
551
552   
553
554     
555   DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void *)buf, conn->err));
556
557
558   return buf;
559 }
560 /*-----------------------------------------------------------------------------------*/
561 err_t
562 netconn_send(struct netconn *conn, struct netbuf *buf)
563 {
564   struct api_msg *msg;
565
566   if (conn == NULL) {
567     return ERR_VAL;
568   }
569
570   if (conn->err != ERR_OK) {
571     return conn->err;
572   }
573
574   if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
575     return (conn->err = ERR_MEM);
576   }
577
578   DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
579   msg->type = API_MSG_SEND;
580   msg->msg.conn = conn;
581   msg->msg.msg.p = buf->p;
582   api_msg_post(msg);
583
584   sys_mbox_fetch(conn->mbox, NULL);
585   memp_freep(MEMP_API_MSG, msg);
586   return conn->err;
587 }
588 /*-----------------------------------------------------------------------------------*/
589 err_t
590 netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
591 {
592   struct api_msg *msg;
593   u16_t len;
594   
595   if (conn == NULL) {
596     return ERR_VAL;
597   }
598
599   if (conn->err != ERR_OK) {
600     return conn->err;
601   }
602   
603   if (conn->sem == SYS_SEM_NULL) {
604     conn->sem = sys_sem_new(0);
605     if (conn->sem == SYS_SEM_NULL) {
606       return ERR_MEM;
607     }
608   }
609
610   if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
611     return (conn->err = ERR_MEM);
612   }
613   msg->type = API_MSG_WRITE;
614   msg->msg.conn = conn;
615         
616
617   conn->state = NETCONN_WRITE;
618   while (conn->err == ERR_OK && size > 0) {
619     msg->msg.msg.w.dataptr = dataptr;
620     msg->msg.msg.w.copy = copy;
621     
622     if (conn->type == NETCONN_TCP) {
623       if (tcp_sndbuf(conn->pcb.tcp) == 0) {
624         sys_sem_wait(conn->sem);
625         if (conn->err != ERR_OK) {
626           goto ret;
627         }
628       }
629       if (size > tcp_sndbuf(conn->pcb.tcp)) {
630         /* We cannot send more than one send buffer's worth of data at a
631            time. */
632         len = tcp_sndbuf(conn->pcb.tcp);
633       } else {
634         len = size;
635       }
636     } else {
637       len = size;
638     }
639     
640     DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
641     msg->msg.msg.w.len = len;
642     api_msg_post(msg);
643     sys_mbox_fetch(conn->mbox, NULL);    
644     if (conn->err == ERR_OK) {
645       dataptr = (void *)((char *)dataptr + len);
646       size -= len;
647     } else if (conn->err == ERR_MEM) {
648       conn->err = ERR_OK;
649       sys_sem_wait(conn->sem);
650     } else {
651       goto ret;
652     }
653   }
654  ret:
655   memp_freep(MEMP_API_MSG, msg);
656   conn->state = NETCONN_NONE;
657   if (conn->sem != SYS_SEM_NULL) {
658     sys_sem_free(conn->sem);
659     conn->sem = SYS_SEM_NULL;
660   }
661   
662   return conn->err;
663 }
664 /*-----------------------------------------------------------------------------------*/
665 err_t
666 netconn_close(struct netconn *conn)
667 {
668   struct api_msg *msg;
669
670   if (conn == NULL) {
671     return ERR_VAL;
672   }
673   if ((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
674     return (conn->err = ERR_MEM);
675   }
676
677   conn->state = NETCONN_CLOSE;
678  again:
679   msg->type = API_MSG_CLOSE;
680   msg->msg.conn = conn;
681   api_msg_post(msg);
682   sys_mbox_fetch(conn->mbox, NULL);
683   if (conn->err == ERR_MEM &&
684      conn->sem != SYS_SEM_NULL) {
685     sys_sem_wait(conn->sem);
686     goto again;
687   }
688   conn->state = NETCONN_NONE;
689   memp_freep(MEMP_API_MSG, msg);
690   return conn->err;
691 }
692 /*-----------------------------------------------------------------------------------*/
693 err_t
694 netconn_err(struct netconn *conn)
695 {
696   return conn->err;
697 }
698 /*-----------------------------------------------------------------------------------*/