ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

api_lib.c
Go to the documentation of this file.
00001 
00007 /*
00008  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
00009  * All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without modification, 
00012  * are permitted provided that the following conditions are met:
00013  *
00014  * 1. Redistributions of source code must retain the above copyright notice,
00015  *    this list of conditions and the following disclaimer.
00016  * 2. Redistributions in binary form must reproduce the above copyright notice,
00017  *    this list of conditions and the following disclaimer in the documentation
00018  *    and/or other materials provided with the distribution.
00019  * 3. The name of the author may not be used to endorse or promote products
00020  *    derived from this software without specific prior written permission. 
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
00023  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00024  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
00025  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00026  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
00027  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
00030  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
00031  * OF SUCH DAMAGE.
00032  *
00033  * This file is part of the lwIP TCP/IP stack.
00034  * 
00035  * Author: Adam Dunkels <adam@sics.se>
00036  *
00037  */
00038 
00039 /* This is the part of the API that is linked with
00040    the application */
00041 
00042 #include "lwip/opt.h"
00043 
00044 #if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
00045 
00046 #include "lwip/api.h"
00047 #include "lwip/tcpip.h"
00048 #include "lwip/memp.h"
00049 
00050 #include "lwip/ip.h"
00051 #include "lwip/raw.h"
00052 #include "lwip/udp.h"
00053 #include "lwip/tcp.h"
00054 
00055 #include <string.h>
00056 
00067 struct netconn*
00068 netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
00069 {
00070   struct netconn *conn;
00071   struct api_msg msg;
00072 
00073   conn = netconn_alloc(t, callback);
00074   if (conn != NULL) {
00075     msg.function = do_newconn;
00076     msg.msg.msg.n.proto = proto;
00077     msg.msg.conn = conn;
00078     if (TCPIP_APIMSG(&msg) != ERR_OK) {
00079       LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
00080       LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
00081       LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
00082 #if LWIP_TCP
00083       LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
00084 #endif /* LWIP_TCP */
00085       sys_sem_free(&conn->op_completed);
00086       sys_mbox_free(&conn->recvmbox);
00087       memp_free(MEMP_NETCONN, conn);
00088       return NULL;
00089     }
00090   }
00091   return conn;
00092 }
00093 
00102 err_t
00103 netconn_delete(struct netconn *conn)
00104 {
00105   struct api_msg msg;
00106 
00107   /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
00108   if (conn == NULL) {
00109     return ERR_OK;
00110   }
00111 
00112   msg.function = do_delconn;
00113   msg.msg.conn = conn;
00114   tcpip_apimsg(&msg);
00115 
00116   netconn_free(conn);
00117 
00118   /* don't care for return value of do_delconn since it only calls void functions */
00119 
00120   return ERR_OK;
00121 }
00122 
00134 err_t
00135 netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
00136 {
00137   struct api_msg msg;
00138   err_t err;
00139 
00140   LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
00141   LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
00142   LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;);
00143 
00144   msg.function = do_getaddr;
00145   msg.msg.conn = conn;
00146   msg.msg.msg.ad.ipaddr = addr;
00147   msg.msg.msg.ad.port = port;
00148   msg.msg.msg.ad.local = local;
00149   err = TCPIP_APIMSG(&msg);
00150 
00151   NETCONN_SET_SAFE_ERR(conn, err);
00152   return err;
00153 }
00154 
00165 err_t
00166 netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port)
00167 {
00168   struct api_msg msg;
00169   err_t err;
00170 
00171   LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
00172 
00173   msg.function = do_bind;
00174   msg.msg.conn = conn;
00175   msg.msg.msg.bc.ipaddr = addr;
00176   msg.msg.msg.bc.port = port;
00177   err = TCPIP_APIMSG(&msg);
00178 
00179   NETCONN_SET_SAFE_ERR(conn, err);
00180   return err;
00181 }
00182 
00191 err_t
00192 netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port)
00193 {
00194   struct api_msg msg;
00195   err_t err;
00196 
00197   LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
00198 
00199   msg.function = do_connect;
00200   msg.msg.conn = conn;
00201   msg.msg.msg.bc.ipaddr = addr;
00202   msg.msg.msg.bc.port = port;
00203   /* This is the only function which need to not block tcpip_thread */
00204   err = tcpip_apimsg(&msg);
00205 
00206   NETCONN_SET_SAFE_ERR(conn, err);
00207   return err;
00208 }
00209 
00216 err_t
00217 netconn_disconnect(struct netconn *conn)
00218 {
00219   struct api_msg msg;
00220   err_t err;
00221 
00222   LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
00223 
00224   msg.function = do_disconnect;
00225   msg.msg.conn = conn;
00226   err = TCPIP_APIMSG(&msg);
00227 
00228   NETCONN_SET_SAFE_ERR(conn, err);
00229   return err;
00230 }
00231 
00240 err_t
00241 netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
00242 {
00243 #if LWIP_TCP
00244   struct api_msg msg;
00245   err_t err;
00246 
00247   /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
00248   LWIP_UNUSED_ARG(backlog);
00249 
00250   LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;);
00251 
00252   msg.function = do_listen;
00253   msg.msg.conn = conn;
00254 #if TCP_LISTEN_BACKLOG
00255   msg.msg.msg.lb.backlog = backlog;
00256 #endif /* TCP_LISTEN_BACKLOG */
00257   err = TCPIP_APIMSG(&msg);
00258 
00259   NETCONN_SET_SAFE_ERR(conn, err);
00260   return err;
00261 #else /* LWIP_TCP */
00262   LWIP_UNUSED_ARG(conn);
00263   LWIP_UNUSED_ARG(backlog);
00264   return ERR_ARG;
00265 #endif /* LWIP_TCP */
00266 }
00267 
00276 err_t
00277 netconn_accept(struct netconn *conn, struct netconn **new_conn)
00278 {
00279 #if LWIP_TCP
00280   struct netconn *newconn;
00281   err_t err;
00282 #if TCP_LISTEN_BACKLOG
00283   struct api_msg msg;
00284 #endif /* TCP_LISTEN_BACKLOG */
00285 
00286   LWIP_ERROR("netconn_accept: invalid pointer",    (new_conn != NULL),                  return ERR_ARG;);
00287   *new_conn = NULL;
00288   LWIP_ERROR("netconn_accept: invalid conn",       (conn != NULL),                      return ERR_ARG;);
00289   LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox),   return ERR_ARG;);
00290 
00291   err = conn->last_err;
00292   if (ERR_IS_FATAL(err)) {
00293     /* don't recv on fatal errors: this might block the application task
00294        waiting on acceptmbox forever! */
00295     return err;
00296   }
00297 
00298 #if LWIP_SO_RCVTIMEO
00299   if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
00300     NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
00301     return ERR_TIMEOUT;
00302   }
00303 #else
00304   sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0);
00305 #endif /* LWIP_SO_RCVTIMEO*/
00306   /* Register event with callback */
00307   API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
00308 
00309   if (newconn == NULL) {
00310     /* connection has been aborted */
00311     NETCONN_SET_SAFE_ERR(conn, ERR_ABRT);
00312     return ERR_ABRT;
00313   }
00314 #if TCP_LISTEN_BACKLOG
00315   /* Let the stack know that we have accepted the connection. */
00316   msg.function = do_recv;
00317   msg.msg.conn = conn;
00318   /* don't care for the return value of do_recv */
00319   TCPIP_APIMSG(&msg);
00320 #endif /* TCP_LISTEN_BACKLOG */
00321 
00322   *new_conn = newconn;
00323   /* don't set conn->last_err: it's only ERR_OK, anyway */
00324   return ERR_OK;
00325 #else /* LWIP_TCP */
00326   LWIP_UNUSED_ARG(conn);
00327   LWIP_UNUSED_ARG(new_conn);
00328   return ERR_ARG;
00329 #endif /* LWIP_TCP */
00330 }
00331 
00341 static err_t
00342 netconn_recv_data(struct netconn *conn, void **new_buf)
00343 {
00344   void *buf = NULL;
00345   u16_t len;
00346   err_t err;
00347 #if LWIP_TCP
00348   struct api_msg msg;
00349 #endif /* LWIP_TCP */
00350 
00351   LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
00352   *new_buf = NULL;
00353   LWIP_ERROR("netconn_recv: invalid conn",    (conn != NULL),    return ERR_ARG;);
00354   LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
00355 
00356   err = conn->last_err;
00357   if (ERR_IS_FATAL(err)) {
00358     /* don't recv on fatal errors: this might block the application task
00359        waiting on recvmbox forever! */
00360     /* @todo: this does not allow us to fetch data that has been put into recvmbox
00361        before the fatal error occurred - is that a problem? */
00362     return err;
00363   }
00364 
00365 #if LWIP_SO_RCVTIMEO
00366   if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
00367     NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
00368     return ERR_TIMEOUT;
00369   }
00370 #else
00371   sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);
00372 #endif /* LWIP_SO_RCVTIMEO*/
00373 
00374 #if LWIP_TCP
00375   if (conn->type == NETCONN_TCP) {
00376     if (!netconn_get_noautorecved(conn) || (buf == NULL)) {
00377       /* Let the stack know that we have taken the data. */
00378       /* TODO: Speedup: Don't block and wait for the answer here
00379          (to prevent multiple thread-switches). */
00380       msg.function = do_recv;
00381       msg.msg.conn = conn;
00382       if (buf != NULL) {
00383         msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len;
00384       } else {
00385         msg.msg.msg.r.len = 1;
00386       }
00387       /* don't care for the return value of do_recv */
00388       TCPIP_APIMSG(&msg);
00389     }
00390 
00391     /* If we are closed, we indicate that we no longer wish to use the socket */
00392     if (buf == NULL) {
00393       API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
00394       /* Avoid to lose any previous error code */
00395       NETCONN_SET_SAFE_ERR(conn, ERR_CLSD);
00396       return ERR_CLSD;
00397     }
00398     len = ((struct pbuf *)buf)->tot_len;
00399   }
00400 #endif /* LWIP_TCP */
00401 #if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
00402   else
00403 #endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
00404 #if (LWIP_UDP || LWIP_RAW)
00405   {
00406     LWIP_ASSERT("buf != NULL", buf != NULL);
00407     len = netbuf_len((struct netbuf *)buf);
00408   }
00409 #endif /* (LWIP_UDP || LWIP_RAW) */
00410 
00411 #if LWIP_SO_RCVBUF
00412   SYS_ARCH_DEC(conn->recv_avail, len);
00413 #endif /* LWIP_SO_RCVBUF */
00414   /* Register event with callback */
00415   API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
00416 
00417   LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len));
00418 
00419   *new_buf = buf;
00420   /* don't set conn->last_err: it's only ERR_OK, anyway */
00421   return ERR_OK;
00422 }
00423 
00433 err_t
00434 netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
00435 {
00436   LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
00437              netconn_type(conn) == NETCONN_TCP, return ERR_ARG;);
00438 
00439   return netconn_recv_data(conn, (void **)new_buf);
00440 }
00441 
00450 err_t
00451 netconn_recv(struct netconn *conn, struct netbuf **new_buf)
00452 {
00453 #if LWIP_TCP
00454   struct netbuf *buf = NULL;
00455   err_t err;
00456 #endif /* LWIP_TCP */
00457 
00458   LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
00459   *new_buf = NULL;
00460   LWIP_ERROR("netconn_recv: invalid conn",    (conn != NULL),    return ERR_ARG;);
00461   LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
00462 
00463 #if LWIP_TCP
00464   if (conn->type == NETCONN_TCP) {
00465     struct pbuf *p = NULL;
00466     /* This is not a listening netconn, since recvmbox is set */
00467 
00468     buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
00469     if (buf == NULL) {
00470       NETCONN_SET_SAFE_ERR(conn, ERR_MEM);
00471       return ERR_MEM;
00472     }
00473 
00474     err = netconn_recv_data(conn, (void **)&p);
00475     if (err != ERR_OK) {
00476       memp_free(MEMP_NETBUF, buf);
00477       return err;
00478     }
00479     LWIP_ASSERT("p != NULL", p != NULL);
00480 
00481     buf->p = p;
00482     buf->ptr = p;
00483     buf->port = 0;
00484     ip_addr_set_any(&buf->addr);
00485     *new_buf = buf;
00486     /* don't set conn->last_err: it's only ERR_OK, anyway */
00487     return ERR_OK;
00488   } else
00489 #endif /* LWIP_TCP */
00490   {
00491 #if (LWIP_UDP || LWIP_RAW)
00492     return netconn_recv_data(conn, (void **)new_buf);
00493 #endif /* (LWIP_UDP || LWIP_RAW) */
00494   }
00495 }
00496 
00507 void
00508 netconn_recved(struct netconn *conn, u32_t length)
00509 {
00510 #if LWIP_TCP
00511   if ((conn != NULL) && (conn->type == NETCONN_TCP) &&
00512       (netconn_get_noautorecved(conn))) {
00513     struct api_msg msg;
00514     /* Let the stack know that we have taken the data. */
00515     /* TODO: Speedup: Don't block and wait for the answer here
00516        (to prevent multiple thread-switches). */
00517     msg.function = do_recv;
00518     msg.msg.conn = conn;
00519     msg.msg.msg.r.len = length;
00520     /* don't care for the return value of do_recv */
00521     TCPIP_APIMSG(&msg);
00522   }
00523 #else /* LWIP_TCP */
00524   LWIP_UNUSED_ARG(conn);
00525   LWIP_UNUSED_ARG(length);
00526 #endif /* LWIP_TCP */
00527 }
00528 
00539 err_t
00540 netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port)
00541 {
00542   if (buf != NULL) {
00543     ip_addr_set(&buf->addr, addr);
00544     buf->port = port;
00545     return netconn_send(conn, buf);
00546   }
00547   return ERR_VAL;
00548 }
00549 
00557 err_t
00558 netconn_send(struct netconn *conn, struct netbuf *buf)
00559 {
00560   struct api_msg msg;
00561   err_t err;
00562 
00563   LWIP_ERROR("netconn_send: invalid conn",  (conn != NULL), return ERR_ARG;);
00564 
00565   LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
00566   msg.function = do_send;
00567   msg.msg.conn = conn;
00568   msg.msg.msg.b = buf;
00569   err = TCPIP_APIMSG(&msg);
00570 
00571   NETCONN_SET_SAFE_ERR(conn, err);
00572   return err;
00573 }
00574 
00587 err_t
00588 netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apiflags)
00589 {
00590   struct api_msg msg;
00591   err_t err;
00592 
00593   LWIP_ERROR("netconn_write: invalid conn",  (conn != NULL), return ERR_ARG;);
00594   LWIP_ERROR("netconn_write: invalid conn->type",  (conn->type == NETCONN_TCP), return ERR_VAL;);
00595   if (size == 0) {
00596     return ERR_OK;
00597   }
00598 
00599   /* @todo: for non-blocking write, check if 'size' would ever fit into
00600             snd_queue or snd_buf */
00601   msg.function = do_write;
00602   msg.msg.conn = conn;
00603   msg.msg.msg.w.dataptr = dataptr;
00604   msg.msg.msg.w.apiflags = apiflags;
00605   msg.msg.msg.w.len = size;
00606   /* For locking the core: this _can_ be delayed on low memory/low send buffer,
00607      but if it is, this is done inside api_msg.c:do_write(), so we can use the
00608      non-blocking version here. */
00609   err = TCPIP_APIMSG(&msg);
00610 
00611   NETCONN_SET_SAFE_ERR(conn, err);
00612   return err;
00613 }
00614 
00622 static err_t
00623 netconn_close_shutdown(struct netconn *conn, u8_t how)
00624 {
00625   struct api_msg msg;
00626   err_t err;
00627 
00628   LWIP_ERROR("netconn_close: invalid conn",  (conn != NULL), return ERR_ARG;);
00629 
00630   msg.function = do_close;
00631   msg.msg.conn = conn;
00632   /* shutting down both ends is the same as closing */
00633   msg.msg.msg.sd.shut = how;
00634   /* because of the LWIP_TCPIP_CORE_LOCKING implementation of do_close,
00635      don't use TCPIP_APIMSG here */
00636   err = tcpip_apimsg(&msg);
00637 
00638   NETCONN_SET_SAFE_ERR(conn, err);
00639   return err;
00640 }
00641 
00648 err_t
00649 netconn_close(struct netconn *conn)
00650 {
00651   /* shutting down both ends is the same as closing */
00652   return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR);
00653 }
00654 
00661 err_t
00662 netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
00663 {
00664   return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
00665 }
00666 
00667 #if LWIP_IGMP
00668 
00678 err_t
00679 netconn_join_leave_group(struct netconn *conn,
00680                          ip_addr_t *multiaddr,
00681                          ip_addr_t *netif_addr,
00682                          enum netconn_igmp join_or_leave)
00683 {
00684   struct api_msg msg;
00685   err_t err;
00686 
00687   LWIP_ERROR("netconn_join_leave_group: invalid conn",  (conn != NULL), return ERR_ARG;);
00688 
00689   msg.function = do_join_leave_group;
00690   msg.msg.conn = conn;
00691   msg.msg.msg.jl.multiaddr = multiaddr;
00692   msg.msg.msg.jl.netif_addr = netif_addr;
00693   msg.msg.msg.jl.join_or_leave = join_or_leave;
00694   err = TCPIP_APIMSG(&msg);
00695 
00696   NETCONN_SET_SAFE_ERR(conn, err);
00697   return err;
00698 }
00699 #endif /* LWIP_IGMP */
00700 
00701 #if LWIP_DNS
00702 
00712 err_t
00713 netconn_gethostbyname(const char *name, ip_addr_t *addr)
00714 {
00715   struct dns_api_msg msg;
00716   err_t err;
00717   sys_sem_t sem;
00718 
00719   LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
00720   LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
00721 
00722   err = sys_sem_new(&sem, 0);
00723   if (err != ERR_OK) {
00724     return err;
00725   }
00726 
00727   msg.name = name;
00728   msg.addr = addr;
00729   msg.err = &err;
00730   msg.sem = &sem;
00731 
00732   tcpip_callback(do_gethostbyname, &msg);
00733   sys_sem_wait(&sem);
00734   sys_sem_free(&sem);
00735 
00736   return err;
00737 }
00738 #endif /* LWIP_DNS*/
00739 
00740 #endif /* LWIP_NETCONN */

Generated on Sun May 27 2012 04:36:00 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.