# api_msg.c

Go to the documentation of this file.

    00001 /*
    00002  * Copyright (c) 2001, Swedish Institute of Computer Science.
    00003  * All rights reserved.
    00004  *
    00005  * Redistribution and use in source and binary forms, with or without
    00006  * modification, are permitted provided that the following conditions
    00007  * are met:
    00008  * 1. Redistributions of source code must retain the above copyright
    00009  *    notice, this list of conditions and the following disclaimer.
    00010  * 2. Redistributions in binary form must reproduce the above copyright
    00011  *    notice, this list of conditions and the following disclaimer in the
    00012  *    documentation and/or other materials provided with the distribution.
    00013  * 3. Neither the name of the Institute nor the names of its contributors
    00014  *    may be used to endorse or promote products derived from this software
    00015  *    without specific prior written permission.
    00016  *
    00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
    00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
    00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    00027  * SUCH DAMAGE.
    00028  *
    00029  * This file is part of the lwIP TCP/IP stack.
    00030  *
    00031  * Author: Adam Dunkels <adam@sics.se>
    00032  *
    00033  * $Id: api__msg_8c-source.html 88 2016-01-12 00:11:29Z reddawg $
    00034  */
    00035
    00036 #include <ubixos/types.h>
    00037
    00038 #include "net/debug.h"
    00039 #include "net/arch.h"
    00040 #include "net/api_msg.h"
    00041 #include "net/memp.h"
    00042 #include "net/sys.h"
    00043 #include "net/tcpip.h"
    00044
    00045 /*-----------------------------------------------------------------------------------*/
    00046 static err_t
    00047 recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
    00048 {
    00049   struct netconn *conn;
    00050
    00051   conn = arg;
    00052
    00053   if(conn == NULL) {
    00054     pbuf_free(p);
    00055     return ERR_VAL;
    00056   }
    00057
    00058   if(conn->recvmbox != SYS_MBOX_NULL) {
    00059     conn->err = err;
    00060     sys_mbox_post(conn->recvmbox, p);
    00061   }
    00062   return ERR_OK;
    00063 }
    00064 /*-----------------------------------------------------------------------------------*/
    00065 static void
    00066 recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
    00067          struct ip_addr *addr, uInt16 port)
    00068 {
    00069   struct netbuf *buf;
    00070   struct netconn *conn;
    00071
    00072   conn = arg;
    00073
    00074   if(conn == NULL) {
    00075     pbuf_free(p);
    00076     return;
    00077   }
    00078
    00079   if(conn->recvmbox != SYS_MBOX_NULL) {
    00080     buf = memp_mallocp(MEMP_NETBUF);
    00081     if(buf == NULL) {
    00082       pbuf_free(p);
    00083       return;
    00084     } else {
    00085       buf->p = p;
    00086       buf->ptr = p;
    00087       buf->fromaddr = addr;
    00088       buf->fromport = port;
    00089     }
    00090
    00091     sys_mbox_post(conn->recvmbox, buf);
    00092   }
    00093 }
    00094 /*-----------------------------------------------------------------------------------*/
    00095 static err_t
    00096 poll_tcp(void *arg, struct tcp_pcb *pcb)
    00097 {
    00098   struct netconn *conn;
    00099
    00100   conn = arg;
    00101   if(conn != NULL &&
    00102      (conn->state == NETCONN_WRITE || conn->state == NETCONN_CLOSE) &&
    00103      conn->sem != SYS_SEM_NULL) {
    00104     sys_sem_signal(conn->sem);
    00105   }
    00106   return ERR_OK;
    00107 }
    00108 /*-----------------------------------------------------------------------------------*/
    00109 static err_t
    00110 sent_tcp(void *arg, struct tcp_pcb *pcb, uInt16 len)
    00111 {
    00112   struct netconn *conn;
    00113
    00114   conn = arg;
    00115   if(conn != NULL && conn->sem != SYS_SEM_NULL) {
    00116     sys_sem_signal(conn->sem);
    00117   }
    00118   return ERR_OK;
    00119 }
    00120 /*-----------------------------------------------------------------------------------*/
    00121 static void
    00122 err_tcp(void *arg, err_t err)
    00123 {
    00124   struct netconn *conn;
    00125
    00126   conn = arg;
    00127
    00128   conn->pcb.tcp = NULL;
    00129
    00130
    00131   conn->err = err;
    00132   if(conn->recvmbox != SYS_MBOX_NULL) {
    00133     sys_mbox_post(conn->recvmbox, NULL);
    00134   }
    00135   if(conn->mbox != SYS_MBOX_NULL) {
    00136     sys_mbox_post(conn->mbox, NULL);
    00137   }
    00138   if(conn->acceptmbox != SYS_MBOX_NULL) {
    00139     sys_mbox_post(conn->acceptmbox, NULL);
    00140   }
    00141   if(conn->sem != SYS_SEM_NULL) {
    00142     sys_sem_signal(conn->sem);
    00143   }
    00144 }
    00145 /*-----------------------------------------------------------------------------------*/
    00146 static void
    00147 setup_tcp(struct netconn *conn)
    00148 {
    00149   struct tcp_pcb *pcb;
    00150
    00151   pcb = conn->pcb.tcp;
    00152   tcp_arg(pcb, conn);
    00153   tcp_recv(pcb, recv_tcp);
    00154   tcp_sent(pcb, sent_tcp);
    00155   tcp_poll(pcb, poll_tcp, 4);
    00156   tcp_err(pcb, err_tcp);
    00157 }
    00158 /*-----------------------------------------------------------------------------------*/
    00159 static err_t
    00160 accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
    00161 {
    00162   sys_mbox_t *mbox;
    00163   struct netconn *newconn;
    00164
    00165 #if API_MSG_DEBUG
    00166 #if TCP_DEBUG
    00167   tcp_debug_print_state(newpcb->state);
    00168 #endif /* TCP_DEBUG */
    00169 #endif /* API_MSG_DEBUG */
    00170   mbox = (sys_mbox_t *)arg;
    00171   newconn = memp_mallocp(MEMP_NETCONN);
    00172   if(newconn == NULL) {
    00173     return ERR_MEM;
    00174   }
    00175   newconn->type = NETCONN_TCP;
    00176   newconn->pcb.tcp = newpcb;
    00177   setup_tcp(newconn);
    00178   newconn->recvmbox = sys_mbox_new();
    00179   if(newconn->recvmbox == SYS_MBOX_NULL) {
    00180     memp_free(MEMP_NETCONN, newconn);
    00181     return ERR_MEM;
    00182   }
    00183   newconn->mbox = sys_mbox_new();
    00184   if(newconn->mbox == SYS_MBOX_NULL) {
    00185     sys_mbox_free(newconn->recvmbox);
    00186     memp_free(MEMP_NETCONN, newconn);
    00187     return ERR_MEM;
    00188   }
    00189   newconn->sem = sys_sem_new(0);
    00190   if(newconn->sem == SYS_SEM_NULL) {
    00191     sys_mbox_free(newconn->recvmbox);
    00192     sys_mbox_free(newconn->mbox);
    00193     memp_free(MEMP_NETCONN, newconn);
    00194     return ERR_MEM;
    00195   }
    00196   newconn->acceptmbox = SYS_MBOX_NULL;
    00197   newconn->err = err;
    00198   sys_mbox_post(*mbox, newconn);
    00199   return ERR_OK;
    00200 }
    00201 /*-----------------------------------------------------------------------------------*/
    00202 static void
    00203 do_newconn(struct api_msg_msg *msg)
    00204 {
    00205 }
    00206 /*-----------------------------------------------------------------------------------*/
    00207 static void
    00208 do_delconn(struct api_msg_msg *msg)
    00209 {
    00210   if(msg->conn->pcb.tcp != NULL) {
    00211     switch(msg->conn->type) {
    00212     case NETCONN_UDPLITE:
    00213       /* FALLTHROUGH */
    00214     case NETCONN_UDPNOCHKSUM:
    00215       /* FALLTHROUGH */
    00216     case NETCONN_UDP:
    00217       msg->conn->pcb.udp->recv_arg = NULL;
    00218       udp_remove(msg->conn->pcb.udp);
    00219       break;
    00220     case NETCONN_TCP:
    00221       tcp_arg(msg->conn->pcb.tcp, NULL);
    00222       tcp_sent(msg->conn->pcb.tcp, NULL);
    00223       tcp_recv(msg->conn->pcb.tcp, NULL);
    00224       tcp_accept(msg->conn->pcb.tcp, NULL);
    00225       tcp_poll(msg->conn->pcb.tcp, NULL, 0);
    00226       tcp_err(msg->conn->pcb.tcp, NULL);
    00227       if(msg->conn->pcb.tcp->state == LISTEN) {
    00228         tcp_close(msg->conn->pcb.tcp);
    00229       } else {
    00230         if(tcp_close(msg->conn->pcb.tcp) != ERR_OK) {
    00231           tcp_abort(msg->conn->pcb.tcp);
    00232         }
    00233       }
    00234     break;
    00235     }
    00236   }
    00237   if(msg->conn->mbox != SYS_MBOX_NULL) {
    00238     sys_mbox_post(msg->conn->mbox, NULL);
    00239   }
    00240 }
    00241 /*-----------------------------------------------------------------------------------*/
    00242 static void
    00243 do_bind(struct api_msg_msg *msg)
    00244 {
    00245   if(msg->conn->pcb.tcp == NULL) {
    00246     switch(msg->conn->type) {
    00247     case NETCONN_UDPLITE:
    00248       msg->conn->pcb.udp = udp_new();
    00249       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
    00250       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
    00251       break;
    00252     case NETCONN_UDPNOCHKSUM:
    00253       msg->conn->pcb.udp = udp_new();
    00254       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
    00255       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
    00256       break;
    00257     case NETCONN_UDP:
    00258       msg->conn->pcb.udp = udp_new();
    00259       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
    00260       break;
    00261     case NETCONN_TCP:
    00262       msg->conn->pcb.tcp = tcp_new();
    00263       setup_tcp(msg->conn);
    00264       break;
    00265     }
    00266   }
    00267   switch(msg->conn->type) {
    00268   case NETCONN_UDPLITE:
    00269     /* FALLTHROUGH */
    00270   case NETCONN_UDPNOCHKSUM:
    00271     /* FALLTHROUGH */
    00272   case NETCONN_UDP:
    00273     udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
    00274     break;
    00275   case NETCONN_TCP:
    00276     msg->conn->err = tcp_bind(msg->conn->pcb.tcp,
    00277                               msg->msg.bc.ipaddr, msg->msg.bc.port);
    00278     break;
    00279   }
    00280   sys_mbox_post(msg->conn->mbox, NULL);
    00281 }
    00282 /*-----------------------------------------------------------------------------------*/
    00283 static err_t
    00284 do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
    00285 {
    00286   struct netconn *conn;
    00287
    00288   conn = arg;
    00289
    00290   if(conn == NULL) {
    00291     return ERR_VAL;
    00292   }
    00293
    00294   conn->err = err;
    00295
    00296   if(conn->type == NETCONN_TCP && err == ERR_OK) {
    00297     setup_tcp(conn);
    00298   }
    00299
    00300   sys_mbox_post(conn->mbox, NULL);
    00301   return ERR_OK;
    00302 }
    00303 /*-----------------------------------------------------------------------------------*/
    00304 static void
    00305 do_connect(struct api_msg_msg *msg)
    00306 {
    00307   if(msg->conn->pcb.tcp == NULL) {
    00308     switch(msg->conn->type) {
    00309     case NETCONN_UDPLITE:
    00310       msg->conn->pcb.udp = udp_new();
    00311       if(msg->conn->pcb.udp == NULL) {
    00312         msg->conn->err = ERR_MEM;
    00313         sys_mbox_post(msg->conn->mbox, NULL);
    00314         return;
    00315       }
    00316       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
    00317       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
    00318       break;
    00319     case NETCONN_UDPNOCHKSUM:
    00320       msg->conn->pcb.udp = udp_new();
    00321       if(msg->conn->pcb.udp == NULL) {
    00322         msg->conn->err = ERR_MEM;
    00323         sys_mbox_post(msg->conn->mbox, NULL);
    00324         return;
    00325       }
    00326       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
    00327       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
    00328       break;
    00329     case NETCONN_UDP:
    00330       msg->conn->pcb.udp = udp_new();
    00331       if(msg->conn->pcb.udp == NULL) {
    00332         msg->conn->err = ERR_MEM;
    00333         sys_mbox_post(msg->conn->mbox, NULL);
    00334         return;
    00335       }
    00336       udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
    00337       break;
    00338     case NETCONN_TCP:
    00339       msg->conn->pcb.tcp = tcp_new();
    00340       if(msg->conn->pcb.tcp == NULL) {
    00341         msg->conn->err = ERR_MEM;
    00342         sys_mbox_post(msg->conn->mbox, NULL);
    00343         return;
    00344       }
    00345       break;
    00346     }
    00347   }
    00348   switch(msg->conn->type) {
    00349   case NETCONN_UDPLITE:
    00350     /* FALLTHROUGH */
    00351   case NETCONN_UDPNOCHKSUM:
    00352     /* FALLTHROUGH */
    00353   case NETCONN_UDP:
    00354     udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
    00355     sys_mbox_post(msg->conn->mbox, NULL);
    00356     break;
    00357   case NETCONN_TCP:
    00358     /*    tcp_arg(msg->conn->pcb.tcp, msg->conn);*/
    00359     setup_tcp(msg->conn);
    00360     tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,
    00361                 do_connected);
    00362     /*tcp_output(msg->conn->pcb.tcp);*/
    00363     break;
    00364   }
    00365 }
    00366 /*-----------------------------------------------------------------------------------*/
    00367 static void
    00368 do_listen(struct api_msg_msg *msg)
    00369 {
    00370   if(msg->conn->pcb.tcp != NULL) {
    00371     switch(msg->conn->type) {
    00372     case NETCONN_UDPLITE:
    00373       /* FALLTHROUGH */
    00374     case NETCONN_UDPNOCHKSUM:
    00375       /* FALLTHROUGH */
    00376     case NETCONN_UDP:
    00377       DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n"));
    00378       break;
    00379     case NETCONN_TCP:
    00380       msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp);
    00381       if(msg->conn->pcb.tcp == NULL) {
    00382         msg->conn->err = ERR_MEM;
    00383       } else {
    00384         if(msg->conn->acceptmbox == SYS_MBOX_NULL) {
    00385           msg->conn->acceptmbox = sys_mbox_new();
    00386           if(msg->conn->acceptmbox == SYS_MBOX_NULL) {
    00387             msg->conn->err = ERR_MEM;
    00388             break;
    00389           }
    00390         }
    00391         tcp_arg(msg->conn->pcb.tcp, (void *)&(msg->conn->acceptmbox));
    00392         tcp_accept(msg->conn->pcb.tcp, accept_function);
    00393       }
    00394       break;
    00395     }
    00396   }
    00397   sys_mbox_post(msg->conn->mbox, NULL);
    00398 }
    00399 /*-----------------------------------------------------------------------------------*/
    00400 static void
    00401 do_accept(struct api_msg_msg *msg)
    00402 {
    00403   if(msg->conn->pcb.tcp != NULL) {
    00404     switch(msg->conn->type) {
    00405     case NETCONN_UDPLITE:
    00406       /* FALLTHROUGH */
    00407     case NETCONN_UDPNOCHKSUM:
    00408       /* FALLTHROUGH */
    00409     case NETCONN_UDP:
    00410       DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n"));
    00411       break;
    00412     case NETCONN_TCP:
    00413       break;
    00414     }
    00415   }
    00416 }
    00417 /*-----------------------------------------------------------------------------------*/
    00418 static void
    00419 do_send(struct api_msg_msg *msg)
    00420 {
    00421   if(msg->conn->pcb.tcp != NULL) {
    00422     switch(msg->conn->type) {
    00423     case NETCONN_UDPLITE:
    00424       /* FALLTHROUGH */
    00425     case NETCONN_UDPNOCHKSUM:
    00426       /* FALLTHROUGH */
    00427     case NETCONN_UDP:
    00428       udp_send(msg->conn->pcb.udp, msg->msg.p);
    00429       break;
    00430     case NETCONN_TCP:
    00431       break;
    00432     }
    00433   }
    00434   sys_mbox_post(msg->conn->mbox, NULL);
    00435 }
    00436 /*-----------------------------------------------------------------------------------*/
    00437 static void
    00438 do_recv(struct api_msg_msg *msg)
    00439 {
    00440   if(msg->conn->pcb.tcp != NULL) {
    00441     if(msg->conn->type == NETCONN_TCP) {
    00442       tcp_recved(msg->conn->pcb.tcp, msg->msg.len);
    00443     }
    00444   }
    00445   sys_mbox_post(msg->conn->mbox, NULL);
    00446 }
    00447 /*-----------------------------------------------------------------------------------*/
    00448 static void
    00449 do_write(struct api_msg_msg *msg)
    00450 {
    00451   err_t err;
    00452   if(msg->conn->pcb.tcp != NULL) {
    00453     switch(msg->conn->type) {
    00454     case NETCONN_UDPLITE:
    00455       /* FALLTHROUGH */
    00456     case NETCONN_UDPNOCHKSUM:
    00457       /* FALLTHROUGH */
    00458     case NETCONN_UDP:
    00459       msg->conn->err = ERR_VAL;
    00460       break;
    00461     case NETCONN_TCP:
    00462       err = tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr,
    00463                       msg->msg.w.len, msg->msg.w.copy);
    00464       /* This is the Nagle algorithm: inhibit the sending of new TCP
    00465          segments when new outgoing data arrives from the user if any
    00466          previously transmitted data on the connection remains
    00467          unacknowledged. */
    00468       if(err == ERR_OK && msg->conn->pcb.tcp->unacked == NULL) {
    00469         tcp_output(msg->conn->pcb.tcp);
    00470       }
    00471       msg->conn->err = err;
    00472       break;
    00473     }
    00474   }
    00475   sys_mbox_post(msg->conn->mbox, NULL);
    00476 }
    00477 /*-----------------------------------------------------------------------------------*/
    00478 static void
    00479 do_close(struct api_msg_msg *msg)
    00480 {
    00481   err_t err;
    00482   if(msg->conn->pcb.tcp != NULL) {
    00483     switch(msg->conn->type) {
    00484     case NETCONN_UDPLITE:
    00485       /* FALLTHROUGH */
    00486     case NETCONN_UDPNOCHKSUM:
    00487       /* FALLTHROUGH */
    00488     case NETCONN_UDP:
    00489       break;
    00490     case NETCONN_TCP:
    00491       if(msg->conn->pcb.tcp->state == LISTEN) {
    00492         err = tcp_close(msg->conn->pcb.tcp);
    00493       } else {
    00494         err = tcp_close(msg->conn->pcb.tcp);
    00495       }
    00496       msg->conn->err = err;
    00497       break;
    00498     }
    00499   }
    00500   sys_mbox_post(msg->conn->mbox, NULL);
    00501 }
    00502 /*-----------------------------------------------------------------------------------*/
    00503 typedef void (* api_msg_decode)(struct api_msg_msg *msg);
    00504 static api_msg_decode decode[API_MSG_MAX] = {
    00505   do_newconn,
    00506   do_delconn,
    00507   do_bind,
    00508   do_connect,
    00509   do_listen,
    00510   do_accept,
    00511   do_send,
    00512   do_recv,
    00513   do_write,
    00514   do_close
    00515   };
    00516 void
    00517 api_msg_input(struct api_msg *msg)
    00518 {
    00519   decode[msg->type](&(msg->msg));
    00520 }
    00521 /*-----------------------------------------------------------------------------------*/
    00522 void
    00523 api_msg_post(struct api_msg *msg)
    00524 {
    00525   tcpip_apimsg(msg);
    00526 }
    00527 /*-----------------------------------------------------------------------------------*/
    00528
    00529