Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

api_lib.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
00003  * All rights reserved. 
00004  * 
00005  * Redistribution and use in source and binary forms, with or without modification, 
00006  * are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright notice,
00009  *    this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright notice,
00011  *    this list of conditions and the following disclaimer in the documentation
00012  *    and/or other materials provided with the distribution.
00013  * 3. The name of the author may not be used to endorse or promote products
00014  *    derived from this software without specific prior written permission. 
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
00017  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00018  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
00019  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00020  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
00021  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
00024  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
00025  * OF SUCH DAMAGE.
00026  *
00027  * This file is part of the lwIP TCP/IP stack.
00028  * 
00029  * Author: Adam Dunkels <adam@sics.se>
00030  *
00031  * CHANGELOG: this file has been modified by Sergio Perez Alcañiz <serpeal@disca.upv.es> 
00032  *            Departamento de Informática de Sistemas y Computadores          
00033  *            Universidad Politécnica de Valencia                             
00034  *            Valencia (Spain)    
00035  *            Date: April 2003                                          
00036  *  
00037  */
00038 
00039 #include "lwip/opt.h"
00040 #include "lwip/api.h"
00041 #include "lwip/api_msg.h"
00042 #include "lwip/memp.h"
00043 
00044 /*-----------------------------------------------------------------------------------*/
00045 struct
00046 netbuf *netbuf_new(void)
00047 {
00048   struct netbuf *buf;
00049 
00050   buf = memp_mallocp(MEMP_NETBUF);
00051   if(buf != NULL) {
00052     buf->p = NULL;
00053     buf->ptr = NULL;
00054     return buf;
00055   } else {
00056     return NULL;
00057   }
00058 }
00059 /*-----------------------------------------------------------------------------------*/
00060 void
00061 netbuf_delete(struct netbuf *buf)
00062 {
00063   if(buf != NULL) {
00064     if(buf->p != NULL) {
00065       pbuf_free(buf->p);
00066       buf->p = buf->ptr = NULL;
00067     }
00068     memp_freep(MEMP_NETBUF, buf);
00069   }
00070 }
00071 /*-----------------------------------------------------------------------------------*/
00072 void *
00073 netbuf_alloc(struct netbuf *buf, u16_t size)
00074 {
00075   /* Deallocate any previously allocated memory. */
00076   if(buf->p != NULL) {
00077     pbuf_free(buf->p);
00078   }
00079   buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
00080   if(buf->p == NULL) {
00081      return NULL;
00082   }
00083   buf->ptr = buf->p;
00084   return buf->p->payload;
00085 }
00086 /*-----------------------------------------------------------------------------------*/
00087 void
00088 netbuf_free(struct netbuf *buf)
00089 {
00090   if(buf->p != NULL) {
00091     pbuf_free(buf->p);
00092   }
00093   buf->p = buf->ptr = NULL;
00094 }
00095 /*-----------------------------------------------------------------------------------*/
00096 void
00097 netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
00098 {
00099   if(buf->p != NULL) {
00100     pbuf_free(buf->p);
00101   }
00102   buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
00103   buf->p->payload = dataptr;
00104   buf->p->len = buf->p->tot_len = size;
00105   buf->ptr = buf->p;
00106 }
00107 /*-----------------------------------------------------------------------------------*/
00108 void
00109 netbuf_chain(struct netbuf *head, struct netbuf *tail)
00110 {
00111   pbuf_chain(head->p, tail->p);
00112   head->ptr = head->p;
00113   memp_freep(MEMP_NETBUF, tail);
00114 }
00115 /*-----------------------------------------------------------------------------------*/
00116 u16_t
00117 netbuf_len(struct netbuf *buf)
00118 {
00119   return buf->p->tot_len;
00120 }
00121 /*-----------------------------------------------------------------------------------*/
00122 err_t
00123 netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
00124 {
00125   if(buf->ptr == NULL) {
00126     return ERR_BUF;
00127   }
00128   *dataptr = buf->ptr->payload;
00129   *len = buf->ptr->len;
00130   return ERR_OK;
00131 }
00132 /*-----------------------------------------------------------------------------------*/
00133 s8_t
00134 netbuf_next(struct netbuf *buf)
00135 {
00136   if(buf->ptr->next == NULL) {
00137     return -1;
00138   }
00139   buf->ptr = buf->ptr->next;
00140   if(buf->ptr->next == NULL) {
00141     return 1;
00142   }
00143   return 0;
00144 }
00145 /*-----------------------------------------------------------------------------------*/
00146 void
00147 netbuf_first(struct netbuf *buf)
00148 {
00149   buf->ptr = buf->p;
00150 }
00151 /*-----------------------------------------------------------------------------------*/
00152 void
00153 netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
00154 {
00155   struct pbuf *p;
00156   u16_t i, left;
00157 
00158   left = 0;
00159 
00160   if(buf == NULL) {
00161     return;
00162   }
00163   
00164   /* This implementation is bad. It should use bcopy
00165      instead. */
00166   for(p = buf->p; left < len && p != NULL; p = p->next) {
00167     if(offset != 0 && offset >= p->len) {
00168       offset -= p->len;
00169     } else {    
00170       for(i = offset; i < p->len; ++i) {
00171         ((char *)dataptr)[left] = ((char *)p->payload)[i];
00172         if(++left >= len) {
00173           return;
00174         }
00175       }
00176       offset = 0;
00177     }
00178   }
00179 }
00180 /*-----------------------------------------------------------------------------------*/
00181 void
00182 netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
00183 {
00184   netbuf_copy_partial(buf, dataptr, len, 0);
00185 }
00186 /*-----------------------------------------------------------------------------------*/
00187 struct ip_addr *
00188 netbuf_fromaddr(struct netbuf *buf)
00189 {
00190   return buf->fromaddr;
00191 }
00192 /*-----------------------------------------------------------------------------------*/
00193 u16_t
00194 netbuf_fromport(struct netbuf *buf)
00195 {
00196   return buf->fromport;
00197 }
00198 /*-----------------------------------------------------------------------------------*/
00199 struct
00200 netconn *netconn_new(enum netconn_type t)
00201 {
00202   struct netconn *conn;
00203 
00204   conn = memp_mallocp(MEMP_NETCONN);
00205   if(conn == NULL) {
00206     return NULL;
00207   }
00208   conn->type = t;
00209   conn->pcb.tcp = NULL;
00210 
00211   if((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
00212     memp_freep(MEMP_NETCONN, conn);
00213     return NULL;
00214   }
00215   conn->recvmbox = SYS_MBOX_NULL;
00216   conn->acceptmbox = SYS_MBOX_NULL;
00217   conn->sem = SYS_SEM_NULL;
00218   conn->state = NETCONN_NONE;
00219   conn->socket = 0;
00220   conn->callback = 0;
00221   conn->recv_avail = 0;
00222   return conn;
00223 }
00224 /*-----------------------------------------------------------------------------------*/
00225 struct
00226 netconn *netconn_new_with_callback(enum netconn_type t,
00227                                    void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
00228 {
00229     struct netconn *conn;
00230     
00231     /* get a netconn and then initialize callback pointer and socket */
00232     conn = netconn_new(t);
00233     if (conn)
00234         conn->callback = callback;
00235     return conn;
00236 }
00237 
00238 /*-----------------------------------------------------------------------------------*/
00239 err_t
00240 netconn_delete(struct netconn *conn)
00241 {
00242   struct api_msg *msg;
00243   void *mem;
00244   
00245   if(conn == NULL) {
00246     return ERR_OK;
00247   }
00248   
00249   if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
00250     return ERR_MEM;
00251   }
00252   
00253   msg->type = API_MSG_DELCONN;
00254   msg->msg.conn = conn;
00255   api_msg_post(msg);  
00256   sys_mbox_fetch(conn->mbox, NULL);
00257   memp_freep(MEMP_API_MSG, msg);
00258 
00259   /* Drain the recvmbox. */
00260   if(conn->recvmbox != SYS_MBOX_NULL) {
00261     while(sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != 0) {
00262       if(conn->type == NETCONN_TCP) {
00263         pbuf_free((struct pbuf *)mem);
00264       } else {
00265         netbuf_delete((struct netbuf *)mem);
00266       }
00267     }
00268     sys_mbox_free(conn->recvmbox);
00269     conn->recvmbox = SYS_MBOX_NULL;
00270   }
00271  
00272 
00273   /* Drain the acceptmbox. */
00274   if(conn->acceptmbox != SYS_MBOX_NULL) {
00275     while(sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != 0) {
00276       netconn_delete((struct netconn *)mem);
00277     }
00278     
00279     sys_mbox_free(conn->acceptmbox);
00280     conn->acceptmbox = SYS_MBOX_NULL;
00281   }
00282 
00283   sys_mbox_free(conn->mbox);
00284   conn->mbox = SYS_MBOX_NULL;
00285   if(conn->sem != SYS_SEM_NULL) {
00286     sys_sem_free(conn->sem);
00287   }
00288   /*  conn->sem = SYS_SEM_NULL;*/
00289   memp_free(MEMP_NETCONN, conn);
00290   return ERR_OK;
00291 }
00292 /*-----------------------------------------------------------------------------------*/
00293 enum netconn_type
00294 netconn_type(struct netconn *conn)
00295 {
00296   return conn->type;
00297 }
00298 /*-----------------------------------------------------------------------------------*/
00299 err_t
00300 netconn_peer(struct netconn *conn, struct ip_addr *addr,
00301              u16_t *port)
00302 {
00303   switch(conn->type) {
00304   case NETCONN_UDPLITE:
00305   case NETCONN_UDPNOCHKSUM:
00306   case NETCONN_UDP:
00307     if (conn->pcb.udp == NULL ||
00308         ((conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0))
00309      return ERR_CONN;
00310     *addr = (conn->pcb.udp->remote_ip);
00311     *port = conn->pcb.udp->remote_port;
00312     break;
00313   case NETCONN_TCP:
00314     if(conn->pcb.tcp == NULL)
00315       return ERR_CONN;
00316     *addr = (conn->pcb.tcp->remote_ip);
00317     *port = conn->pcb.tcp->remote_port;
00318     break;
00319   }
00320   return (conn->err = ERR_OK);
00321 }
00322 /*-----------------------------------------------------------------------------------*/
00323 err_t
00324 netconn_addr(struct netconn *conn, struct ip_addr **addr,
00325              u16_t *port)
00326 {
00327   switch(conn->type) {
00328   case NETCONN_UDPLITE:
00329   case NETCONN_UDPNOCHKSUM:
00330   case NETCONN_UDP:
00331     *addr = &(conn->pcb.udp->local_ip);
00332     *port = conn->pcb.udp->local_port;
00333     break;
00334   case NETCONN_TCP:
00335     *addr = &(conn->pcb.tcp->local_ip);
00336     *port = conn->pcb.tcp->local_port;
00337     break;
00338   }
00339   return (conn->err = ERR_OK);
00340 }
00341 /*-----------------------------------------------------------------------------------*/
00342 err_t
00343 netconn_bind(struct netconn *conn, struct ip_addr *addr,
00344             u16_t port)
00345 {
00346   struct api_msg *msg;
00347 
00348   if(conn == NULL) {
00349     return ERR_VAL;
00350   }
00351 
00352   if(conn->type != NETCONN_TCP &&
00353      conn->recvmbox == SYS_MBOX_NULL) {
00354     if((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
00355       return ERR_MEM;
00356     }
00357   }
00358   
00359   if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
00360     return (conn->err = ERR_MEM);
00361   }
00362   msg->type = API_MSG_BIND;
00363   msg->msg.conn = conn;
00364   msg->msg.msg.bc.ipaddr = addr;
00365   msg->msg.msg.bc.port = port;
00366   api_msg_post(msg);
00367   sys_mbox_fetch(conn->mbox, NULL);
00368   memp_freep(MEMP_API_MSG, msg);
00369   return conn->err;
00370 }
00371 
00372 /*-----------------------------------------------------------------------------------*/
00373 err_t
00374 netconn_connect(struct netconn *conn, struct ip_addr *addr,
00375                    u16_t port)
00376 {
00377   struct api_msg *msg;
00378   
00379   if(conn == NULL) {
00380     return ERR_VAL;
00381   }
00382 
00383 
00384   if(conn->recvmbox == SYS_MBOX_NULL) {
00385     if((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
00386       return ERR_MEM;
00387     }
00388   }
00389   
00390   if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
00391     return ERR_MEM;
00392   }
00393   msg->type = API_MSG_CONNECT;
00394   msg->msg.conn = conn;  
00395   msg->msg.msg.bc.ipaddr = addr;
00396   msg->msg.msg.bc.port = port;
00397   api_msg_post(msg);
00398   sys_mbox_fetch(conn->mbox, NULL);
00399   memp_freep(MEMP_API_MSG, msg);
00400   return conn->err;
00401 }
00402 
00403 err_t
00404 netconn_disconnect(struct netconn *conn)
00405 {
00406   struct api_msg *msg;
00407   
00408   if(conn == NULL) {
00409     return ERR_VAL;
00410   }
00411 
00412   if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
00413     return ERR_MEM;
00414   }
00415   msg->type = API_MSG_DISCONNECT;
00416   msg->msg.conn = conn;  
00417   api_msg_post(msg);
00418   sys_mbox_fetch(conn->mbox, NULL);
00419   memp_freep(MEMP_API_MSG, msg);
00420   return conn->err;
00421 
00422 }
00423 /*-----------------------------------------------------------------------------------*/
00424 err_t
00425 netconn_listen(struct netconn *conn)
00426 {
00427   struct api_msg *msg;
00428 
00429   if(conn == NULL) {
00430     return ERR_VAL;
00431   }
00432 
00433   if(conn->acceptmbox == SYS_MBOX_NULL) {
00434     conn->acceptmbox = sys_mbox_new();
00435     if(conn->acceptmbox == SYS_MBOX_NULL) {
00436       return ERR_MEM;
00437     }
00438   }
00439   
00440   if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
00441     return (conn->err = ERR_MEM);
00442   }
00443   msg->type = API_MSG_LISTEN;
00444   msg->msg.conn = conn;
00445   api_msg_post(msg);
00446   sys_mbox_fetch(conn->mbox, NULL);
00447   memp_freep(MEMP_API_MSG, msg);
00448   return conn->err;
00449 }
00450 /*-----------------------------------------------------------------------------------*/
00451 struct netconn *
00452 netconn_accept(struct netconn *conn)
00453 {
00454   struct netconn *newconn;
00455   
00456   if(conn == NULL) {
00457     return NULL;
00458   }
00459   
00460   sys_mbox_fetch(conn->acceptmbox, (void **)&newconn);
00461   /* Register event with callback */
00462   if (conn->callback)
00463       (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0);
00464   
00465   return newconn;
00466 }
00467 /*-----------------------------------------------------------------------------------*/
00468 struct netbuf *
00469 netconn_recv(struct netconn *conn)
00470 {
00471   struct api_msg *msg;
00472   struct netbuf *buf;
00473   struct pbuf *p;
00474   u16_t len;
00475     
00476   if(conn == NULL) {
00477     return NULL;
00478   }
00479   
00480   if(conn->recvmbox == SYS_MBOX_NULL) {
00481     conn->err = ERR_CONN;
00482     return NULL;
00483   }
00484 
00485   if(conn->err != ERR_OK) {
00486     return NULL;
00487   }
00488 
00489   if(conn->type == NETCONN_TCP) {
00490     if(conn->pcb.tcp->state == LISTEN) {
00491       conn->err = ERR_CONN;
00492       return NULL;
00493     }
00494 
00495 
00496     buf = memp_mallocp(MEMP_NETBUF);
00497 
00498     if(buf == NULL) {
00499       conn->err = ERR_MEM;
00500       return NULL;
00501     }
00502     
00503     sys_mbox_fetch(conn->recvmbox, (void **)&p);
00504 
00505     if (p != NULL)
00506     {
00507         len = p->tot_len;
00508         conn->recv_avail -= len;
00509     }
00510     else
00511         len = 0;
00512     
00513     /* Register event with callback */
00514       if (conn->callback)
00515         (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, len);
00516 
00517     /* If we are closed, we indicate that we no longer wish to recieve
00518        data by setting conn->recvmbox to SYS_MBOX_NULL. */
00519     if(p == NULL) {
00520       memp_freep(MEMP_NETBUF, buf);
00521       sys_mbox_free(conn->recvmbox);
00522       conn->recvmbox = SYS_MBOX_NULL;
00523       return NULL;
00524     }
00525 
00526     buf->p = p;
00527     buf->ptr = p;
00528     buf->fromport = 0;
00529     buf->fromaddr = NULL;
00530 
00531     /* Let the stack know that we have taken the data. */
00532     if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
00533       conn->err = ERR_MEM;
00534       return buf;
00535     }
00536     msg->type = API_MSG_RECV;
00537     msg->msg.conn = conn;
00538     if(buf != NULL) {
00539       msg->msg.msg.len = buf->p->tot_len;
00540     } else {
00541       msg->msg.msg.len = 1;
00542     }
00543     api_msg_post(msg);
00544 
00545     sys_mbox_fetch(conn->mbox, NULL);
00546     memp_freep(MEMP_API_MSG, msg);
00547   } else {
00548     sys_mbox_fetch(conn->recvmbox, (void **)&buf);
00549         conn->recv_avail -= buf->p->tot_len;
00550     /* Register event with callback */
00551     if (conn->callback)
00552         (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
00553   }
00554 
00555   
00556 
00557     
00558   DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void *)buf, conn->err));
00559 
00560 
00561   return buf;
00562 }
00563 /*-----------------------------------------------------------------------------------*/
00564 err_t
00565 netconn_send(struct netconn *conn, struct netbuf *buf)
00566 {
00567   struct api_msg *msg;
00568 
00569   if(conn == NULL) {
00570     return ERR_VAL;
00571   }
00572 
00573   if(conn->err != ERR_OK) {
00574     return conn->err;
00575   }
00576 
00577   if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
00578     return (conn->err = ERR_MEM);
00579   }
00580 
00581   DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
00582   msg->type = API_MSG_SEND;
00583   msg->msg.conn = conn;
00584   msg->msg.msg.p = buf->p;
00585   api_msg_post(msg);
00586 
00587   sys_mbox_fetch(conn->mbox, NULL);
00588   memp_freep(MEMP_API_MSG, msg);
00589   return conn->err;
00590 }
00591 /*-----------------------------------------------------------------------------------*/
00592 err_t
00593 netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
00594 {
00595   struct api_msg *msg;
00596   u16_t len;
00597   
00598   if(conn == NULL) {
00599     return ERR_VAL;
00600   }
00601 
00602   if(conn->err != ERR_OK) {
00603     return conn->err;
00604   }
00605   
00606   if(conn->sem == SYS_SEM_NULL) {
00607     conn->sem = sys_sem_new(0);
00608     if(conn->sem == SYS_SEM_NULL) {
00609       return ERR_MEM;
00610     }
00611   }
00612 
00613   if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
00614     return (conn->err = ERR_MEM);
00615   }
00616   msg->type = API_MSG_WRITE;
00617   msg->msg.conn = conn;
00618         
00619 
00620   conn->state = NETCONN_WRITE;
00621   while(conn->err == ERR_OK && size > 0) {
00622     msg->msg.msg.w.dataptr = dataptr;
00623     msg->msg.msg.w.copy = copy;
00624     
00625     if(conn->type == NETCONN_TCP) {
00626       if(tcp_sndbuf(conn->pcb.tcp) == 0) {
00627         sys_sem_wait(conn->sem);
00628         if(conn->err != ERR_OK) {
00629           goto ret;
00630         }
00631       }
00632       if(size > tcp_sndbuf(conn->pcb.tcp)) {
00633         /* We cannot send more than one send buffer's worth of data at a
00634            time. */
00635         len = tcp_sndbuf(conn->pcb.tcp);
00636       } else {
00637         len = size;
00638       }
00639     } else {
00640       len = size;
00641     }
00642     
00643     DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
00644     msg->msg.msg.w.len = len;
00645     api_msg_post(msg);
00646     sys_mbox_fetch(conn->mbox, NULL);    
00647     if(conn->err == ERR_OK) {
00648       dataptr = (void *)((char *)dataptr + len);
00649       size -= len;
00650     } else if(conn->err == ERR_MEM) {
00651       conn->err = ERR_OK;
00652       sys_sem_wait(conn->sem);
00653     } else {
00654       goto ret;
00655     }
00656   }
00657  ret:
00658   memp_freep(MEMP_API_MSG, msg);
00659   conn->state = NETCONN_NONE;
00660   if(conn->sem != SYS_SEM_NULL) {
00661     sys_sem_free(conn->sem);
00662     conn->sem = SYS_SEM_NULL;
00663   }
00664   
00665   return conn->err;
00666 }
00667 /*-----------------------------------------------------------------------------------*/
00668 err_t
00669 netconn_close(struct netconn *conn)
00670 {
00671   struct api_msg *msg;
00672 
00673   if(conn == NULL) {
00674     return ERR_VAL;
00675   }
00676   if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
00677     return (conn->err = ERR_MEM);
00678   }
00679 
00680   conn->state = NETCONN_CLOSE;
00681  again:
00682   msg->type = API_MSG_CLOSE;
00683   msg->msg.conn = conn;
00684   api_msg_post(msg);
00685   sys_mbox_fetch(conn->mbox, NULL);
00686   if(conn->err == ERR_MEM &&
00687      conn->sem != SYS_SEM_NULL) {
00688     sys_sem_wait(conn->sem);
00689     goto again;
00690   }
00691   conn->state = NETCONN_NONE;
00692   memp_freep(MEMP_API_MSG, msg);
00693   return conn->err;
00694 }
00695 /*-----------------------------------------------------------------------------------*/
00696 err_t
00697 netconn_err(struct netconn *conn)
00698 {
00699   return conn->err;
00700 }
00701 /*-----------------------------------------------------------------------------------*/

Generated on Wed Jan 14 12:58:55 2004 for RTL-lwIP-0.4 by doxygen 1.3.4