Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Examples

tcpip.c

00001 /*
00002  * Copyright (c) 2004, 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 Contiki operating system.
00030  *
00031  * Author: Adam Dunkels <adam@sics.se>
00032  *
00033  * $Id: tcpip.c,v 1.1 2006/06/17 22:41:19 adamdunkels Exp $
00034  */
00035 
00036 #include "contiki-conf.h"
00037 #include "contiki-net.h"
00038 
00039 #include "net/packet-service.h"
00040 #include "net/uip-split.h"
00041 
00042 #include <string.h>
00043 
00044 process_event_t tcpip_event;
00045 
00046 /**
00047  * \internal Structure for holding a TCP port and a process ID.
00048  */
00049 struct listenport {
00050   u16_t port;
00051   struct process *p;
00052 };
00053 
00054 /*static struct tcpip_event_args ev_args;*/
00055 
00056 static struct etimer periodic;
00057 
00058 static struct internal_state {
00059   struct listenport listenports[UIP_LISTENPORTS];
00060   struct process *p;
00061 } s;
00062 
00063 enum {
00064   TCP_POLL,
00065   UDP_POLL,
00066   PACKET_INPUT
00067 };
00068 
00069 static unsigned char forwarding = 0;
00070 
00071 PROCESS(tcpip_process, "TCP/IP stack");
00072 
00073 /*---------------------------------------------------------------------------*/
00074 void
00075 tcpip_set_forwarding(unsigned char f)
00076 {
00077   forwarding = f;
00078 }
00079 /*---------------------------------------------------------------------------*/
00080 static void
00081 packet_input(void)
00082 {
00083   if(uip_len > 0) {
00084     if(forwarding) {
00085       if(uip_fw_forward() == 0) {
00086         uip_input();
00087         if(uip_len > 0) {
00088 #if UIP_CONF_TCP_SPLIT
00089           uip_split_output();
00090 #else
00091           tcpip_output();
00092 #endif
00093         }
00094       }
00095     } else {
00096       uip_input();
00097       if(uip_len > 0) {
00098 #if UIP_CONF_TCP_SPLIT
00099         uip_split_output();
00100 #else
00101         tcpip_output();
00102 #endif
00103       }
00104     }
00105   }
00106 }
00107 /*---------------------------------------------------------------------------*/
00108 void
00109 tcpip_output(void)
00110 {
00111   SERVICE_CALL(packet_service, output());
00112 }
00113 /*---------------------------------------------------------------------------*/
00114 struct uip_conn *
00115 tcp_connect(u16_t *ripaddr, u16_t port, void *appstate)
00116 {
00117   struct uip_conn *c;
00118   
00119   c = uip_connect((uip_ipaddr_t *)ripaddr, port);
00120   if(c == NULL) {
00121     return NULL;
00122   }
00123 
00124   c->appstate.p = PROCESS_CURRENT();
00125   c->appstate.state = appstate;
00126   
00127   tcpip_poll_tcp(c);
00128   
00129   return c;
00130 }
00131 /*---------------------------------------------------------------------------*/
00132 void
00133 tcp_unlisten(u16_t port)
00134 {
00135   static unsigned char i;
00136   struct listenport *l;
00137 
00138   l = s.listenports;
00139   for(i = 0; i < UIP_LISTENPORTS; ++i) {
00140     if(l->port == port &&
00141        l->p == PROCESS_CURRENT()) {
00142       l->port = 0;
00143       uip_unlisten(port);
00144       break;
00145     }
00146     ++l;
00147   }
00148 }
00149 /*---------------------------------------------------------------------------*/
00150 void
00151 tcp_listen(u16_t port)
00152 {
00153   static unsigned char i;
00154   struct listenport *l;
00155 
00156   l = s.listenports;
00157   for(i = 0; i < UIP_LISTENPORTS; ++i) {
00158     if(l->port == 0) {
00159       l->port = port;
00160       l->p = PROCESS_CURRENT();
00161       uip_listen(port);
00162       break;
00163     }
00164     ++l;
00165   }
00166 }
00167 /*---------------------------------------------------------------------------*/
00168 void
00169 tcp_attach(struct uip_conn *conn,
00170            void *appstate)
00171 {
00172   register uip_tcp_appstate_t *s;
00173 
00174   s = &conn->appstate;
00175   s->p = PROCESS_CURRENT();
00176   s->state = appstate;
00177 }
00178 /*---------------------------------------------------------------------------*/
00179 void
00180 udp_attach(struct uip_udp_conn *conn,
00181            void *appstate)
00182 {
00183   register uip_udp_appstate_t *s;
00184 
00185   s = &conn->appstate;
00186   s->p = PROCESS_CURRENT();
00187   s->state = appstate;
00188 }
00189 /*---------------------------------------------------------------------------*/
00190 struct uip_udp_conn *
00191 udp_new(u16_t *ripaddr, u16_t port, void *appstate)
00192 {
00193   struct uip_udp_conn *c;
00194   uip_udp_appstate_t *s;
00195   
00196   c = uip_udp_new((uip_ipaddr_t *)ripaddr, port);
00197   if(c == NULL) {
00198     return NULL;
00199   }
00200 
00201   s = &c->appstate;
00202   s->p = PROCESS_CURRENT();
00203   s->state = appstate;
00204 
00205   return c;
00206 }
00207 /*---------------------------------------------------------------------------*/
00208 struct uip_udp_conn *
00209 udp_broadcast_new(u16_t port, void *appstate)
00210 {
00211   uip_ipaddr_t addr;
00212   struct uip_udp_conn *conn;
00213   
00214   uip_ipaddr(addr, 255,255,255,255);
00215   conn = udp_new(addr, port, appstate);
00216   if(conn != NULL) {
00217     udp_bind(conn, port);
00218   }
00219   return conn;
00220 }
00221 /*---------------------------------------------------------------------------*/
00222 static void
00223 eventhandler(process_event_t ev, process_data_t data)
00224 {
00225   static unsigned char i;
00226   register struct listenport *l;
00227   struct process *p;
00228   
00229   switch(ev) {
00230   case PROCESS_EVENT_EXITED:
00231     /* This is the event we get if a process has exited. We go through
00232        the TCP/IP tables to see if this process had any open
00233        connections or listening TCP ports. If so, we'll close those
00234        connections. */
00235     p = (struct process *)data;
00236     l = s.listenports;
00237     for(i = 0; i < UIP_LISTENPORTS; ++i) {
00238       if(l->p == p) {
00239         uip_unlisten(l->port);
00240         l->port = 0;
00241         l->p = PROCESS_NONE;
00242       }
00243       ++l;
00244     }
00245     
00246     {
00247       register struct uip_conn *cptr;
00248      
00249       for(cptr = &uip_conns[0]; cptr < &uip_conns[UIP_CONNS]; ++cptr) {
00250         if(cptr->appstate.p == p) {
00251           cptr->appstate.p = PROCESS_NONE;
00252           cptr->tcpstateflags = UIP_CLOSED;
00253         }
00254       
00255       }
00256       
00257     }
00258 #if UIP_UDP
00259     {
00260       register struct uip_udp_conn *cptr;
00261       for(cptr = &uip_udp_conns[0];
00262           cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) {
00263         if(cptr->appstate.p == p) {
00264           cptr->lport = 0;
00265         }
00266       }
00267       
00268     }
00269 #endif /* UIP_UDP */
00270     break;
00271 
00272   case PROCESS_EVENT_TIMER:
00273     /* We get this event if one of our timers have expired. */
00274     {
00275       static unsigned char i;
00276 
00277       /* Check the clock so see if we should call the periodic uIP
00278          processing. */
00279       if(etimer_expired(&periodic)) {
00280         for(i = 0; i < UIP_CONNS; ++i) {
00281           if(uip_conn_active(i)) {
00282             /* Only restart the timer if there are active
00283                connections. */
00284             etimer_restart(&periodic);
00285             uip_periodic(i);
00286             if(uip_len > 0) {
00287               tcpip_output();
00288             }
00289           }
00290         }
00291         
00292         /*      for(i = 0; i < UIP_UDP_CONNS; i++) {
00293           uip_udp_periodic(i);
00294           if(uip_len > 0) {
00295             tcpip_output();
00296           }
00297           }*/
00298         uip_fw_periodic();
00299       }
00300     }
00301     break;
00302     
00303   case TCP_POLL:
00304     if(data != NULL) {
00305       uip_poll_conn(data);
00306       if(uip_len > 0) {
00307         tcpip_output();
00308       }
00309 
00310       /* Start the periodic polling, if it isn't already active. */
00311       if(etimer_expired(&periodic)) {
00312         etimer_restart(&periodic);
00313       }
00314 
00315     }
00316     break;
00317   case UDP_POLL:
00318     if(data != NULL) {
00319       uip_udp_periodic_conn(data);
00320       if(uip_len > 0) {
00321         tcpip_output();
00322       }
00323     }
00324     break;
00325 
00326   case PACKET_INPUT:
00327     packet_input();
00328     break;
00329   };
00330 }
00331 /*---------------------------------------------------------------------------*/
00332 void
00333 tcpip_input(void)
00334 {
00335   process_post_synch(&tcpip_process, PACKET_INPUT, NULL);
00336   uip_len = 0;
00337 }
00338 /*---------------------------------------------------------------------------*/
00339 void
00340 tcpip_poll_udp(struct uip_udp_conn *conn)
00341 {
00342   process_post(&tcpip_process, UDP_POLL, conn);
00343 }
00344 /*---------------------------------------------------------------------------*/
00345 void
00346 tcpip_poll_tcp(struct uip_conn *conn)
00347 {
00348   process_post(&tcpip_process, TCP_POLL, conn);
00349 }
00350 /*---------------------------------------------------------------------------*/
00351 void
00352 tcpip_uipcall(void)
00353 {
00354   register uip_udp_appstate_t *ts;
00355   static unsigned char i;
00356   register struct listenport *l;
00357 
00358   if(uip_conn != NULL) {
00359     ts = &uip_conn->appstate;
00360   } else {
00361     ts = &uip_udp_conn->appstate;
00362   }
00363 
00364   /* If this is a connection request for a listening port, we must
00365      mark the connection with the right process ID. */
00366   if(uip_connected()) {
00367     l = &s.listenports[0];
00368     for(i = 0; i < UIP_LISTENPORTS; ++i) {
00369       if(l->port == uip_conn->lport &&
00370          l->p != PROCESS_NONE) {
00371         ts->p = l->p;
00372         ts->state = NULL;
00373         break;
00374       }
00375       ++l;
00376     }
00377 
00378     /* Start the periodic polling, if it isn't already active. */
00379     if(etimer_expired(&periodic)) {
00380       etimer_restart(&periodic);
00381     }
00382   }
00383 
00384   if(ts->p != NULL) {
00385     process_post_synch(ts->p, tcpip_event, ts->state);
00386   }
00387 }
00388 /*---------------------------------------------------------------------------*/
00389 PROCESS_THREAD(tcpip_process, ev, data)
00390 {
00391   int i;
00392   
00393   PROCESS_BEGIN();
00394   
00395   for(i = 0; i < UIP_LISTENPORTS; ++i) {
00396     s.listenports[i].port = 0;
00397   }
00398   s.p = PROCESS_CURRENT();
00399   tcpip_event = process_alloc_event();
00400   etimer_set(&periodic, CLOCK_SECOND/2);
00401 
00402   uip_init();
00403   
00404   while(1) {
00405     PROCESS_YIELD();
00406 
00407     eventhandler(ev, data);
00408   }
00409   
00410   PROCESS_END();
00411 }

Generated on Thu Jun 22 17:45:43 2006 for Contiki 2.x by  doxygen 1.4.4