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$
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 

Generated on Tue Dec 12 08:52:07 2006 for UbixOS V2 by  doxygen 1.4.7