dispatcher.c

Go to the documentation of this file.
00001 /*##############################################################################
00002 
00003 nIP - nano IP stack
00004 
00005 File        : dispatcher.c
00006 
00007 Description : Functions to serve ethernet interfaces
00008 
00009 Copyright notice:
00010 
00011 Copyright (C) 2005 -
00012 Andreas Dittrich, dittrich@informatik.hu-berlin.de
00013 Jon Kowal, kowal@informatik.hu-berlin.de
00014 
00015 This program is free software; you can redistribute it and/or
00016 modify it under the terms of the GNU General Public License
00017 as published by the Free Software Foundation; either version 2
00018 of the License, or (at your option) any later version.
00019 
00020 This program is distributed in the hope that it will be useful,
00021 but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00023 GNU General Public License for more details.
00024 
00025 You should have received a copy of the GNU General Public License
00026 along with this program; if not, write to the Free Software
00027 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00028 
00029 ##############################################################################*/
00030 
00031 #include "dispatcher.h"
00032 #include "net/net_if.h"
00033 #include "net/arp.h"
00034 #include "app/dhcp.h"
00035 #include "net/autoip.h"
00036 #include "app/mdns.h"
00037 
00038 #if (NIP_DISP_ENABLE==1)
00039 
00040 extern nip_net_if_t nip_net_if_list[];
00041 nip_disp_state_t nip_disp;
00042 
00043 /** Notify dispatcher about one or more events */
00044 // void nip_disp_notify( uint8_t events )
00045 // {
00046 //      nip_disp.flags |= events;
00047 // }
00048 
00049 /** Notify dispatcher to handle incoming ethernet data on given interface */
00050 void nip_disp_notify_if( nip_net_if_id_t net_if_id, uint8_t event )
00051 {
00052         nip_disp.if_flags[ net_if_id ] |= event;
00053 //      nip_disp.flags |= NIP_DISP_CHECK_IF;
00054         nip_disp_notify( NIP_DISP_CHECK_IF );
00055 }
00056 
00057 /** Checks if dispatcher is running.
00058  *
00059  * @return NIP_E_OK if dispatcher is not running, or NIP_E_DISP_RUNNING else
00060  */
00061 nip_error_t nip_disp_check()
00062 {
00063         if ( (nip_disp.flags & NIP_DISP_RUNNING) != 0 )
00064                 return NIP_E_DISP_RUNNING;
00065         else
00066                 return NIP_E_OK;
00067 }
00068 
00069 /** Call nIP stack dispatcher. The dispatcher will check for accumulated events
00070  * and act accordingly. That is, it will initiate packet reception, transmission
00071  * and retransmission. Events are used to put the dispatcher on track.
00072  *
00073  * Only one instance of the dispatcher can be running at a time. It will return
00074  * NIP_E_DISP_RUNNING if there is another instance active. That instance will
00075  * take care of all events so no event will be lost.
00076  *
00077  * For blocking operations that need to wait for the dispatcher to finish in
00078  * order to complete what they're doing, the nip_disp_check() function may be
00079  * used to check the dispatcher status.
00080  *
00081  * @note Interrupting the dispatcher may lead to deadlock in non-multitasking
00082  * environments, if you attempt to wait for the dispatcher to to finish within
00083  * the interrupt. E.g. Do NOT wait for the already running dispatcher to handle
00084  * your event/request/packet if you're not in a multicasting environment.
00085  */
00086 nip_error_t nip_dispatcher()
00087 {
00088         void (*tmp_cmd)(void);
00089 
00090         // only allow one instance of dispatcher to be active
00091         if (nip_disp_check() == NIP_E_DISP_RUNNING) return NIP_E_DISP_RUNNING;
00092 
00093         // set dispatcher status
00094         nip_disp.flags |= NIP_DISP_RUNNING;
00095 
00096         // Repeat processing until all pending events have been handled. This has to
00097         // be a loop since new events may be added as the dispatcher is running.
00098         while ( nip_disp.flags > NIP_DISP_RUNNING )
00099         {
00100                 NIP_CURR_CMD = NULL;
00101 
00102                 // Handle Network Interface Events
00103                 if ( nip_disp.flags & NIP_DISP_CHECK_IF )
00104                 {
00105                         // reset check_if flag
00106                         nip_disp.flags &= ~NIP_DISP_CHECK_IF;
00107 
00108                         // check all interfaces for events
00109                         SET_CURR_IF( 0 );
00110                         #if NIP_NET_IF_COUNT>1
00111                         do
00112                         {
00113                         #endif
00114                                 // check for newly received (ethernet) packets
00115                                 if ( nip_disp.if_flags[ NIP_CURR_IF ] & NIP_DISP_IF_ETH_R )
00116                                 {
00117 //                                      NIP_CURR_CMD = NIP_DC_HARD_RECV;
00118                                         nip_disp.if_flags[ NIP_CURR_IF ] &= ~NIP_DISP_IF_ETH_R;
00119                                         NIP_CURR_CMD = nip_net_if_list[ NIP_CURR_IF ].phy_conf.hard_disp_recv;
00120 
00121                                         // set check_if flag to make sure we didn't miss any event
00122                                         nip_disp_notify( NIP_DISP_CHECK_IF );
00123                                         goto eval_cmd;
00124                                 }
00125 
00126                                 if ( nip_disp.if_flags[ NIP_CURR_IF ] & NIP_DISP_IF_TIMER )
00127                                 {
00128                                         nip_disp.if_flags[ NIP_CURR_IF ] &= ~NIP_DISP_IF_TIMER;
00129                                         nip_disp.if_flags[ NIP_CURR_IF ] = nip_disp.if_flags[NIP_CURR_IF]
00130                                           #if NIP_DHCP_ENABLE == 1
00131                                                  | NIP_DISP_IF_DHCP
00132                                           #endif
00133                                           #if NIP_AUTOIP_ENABLE == 1
00134                                                  | NIP_DISP_IF_AUTOIP
00135                                           #endif
00136                                           #if NIP_IGMP_ENABLE == 1
00137                                                  | NIP_DISP_IF_GROUP
00138                                           #endif
00139                                                         ;
00140                                 }
00141 
00142                                 #if ( NIP_DHCP_ENABLE == 1 )
00143                                 if ( nip_disp.if_flags[ NIP_CURR_IF ] & NIP_DISP_IF_DHCP )
00144                                 {
00145                                         nip_disp.if_flags[ NIP_CURR_IF ] &= ~NIP_DISP_IF_DHCP;
00146                                         NIP_CURR_CMD = &nip_dhcp_disp_check;
00147                                         // set check_if flag to make sure we didn't miss any event
00148                                         nip_disp_notify( NIP_DISP_CHECK_IF );
00149                                         goto eval_cmd;
00150                                 }
00151                                 #endif // ( NIP_DHCP_ENABLE == 1 )
00152 
00153                                 #if ( NIP_AUTOIP_ENABLE == 1 )
00154                                 if ( nip_disp.if_flags[ NIP_CURR_IF ] & NIP_DISP_IF_AUTOIP )
00155                                 {
00156                                         nip_disp.if_flags[ NIP_CURR_IF ] &= ~NIP_DISP_IF_AUTOIP;
00157                                         NIP_CURR_CMD = &nip_autoip_disp_check;
00158                                         // set check_if flag to make sure we didn't miss any event
00159                                         nip_disp_notify( NIP_DISP_CHECK_IF );
00160                                         goto eval_cmd;
00161                                 }
00162                                 #endif
00163 
00164                                 #if ( NIP_IGMP_ENABLE == 1 )
00165                                 if ( nip_disp.if_flags[ NIP_CURR_IF ] & NIP_DISP_IF_GROUP )
00166                                 {
00167                                         nip_disp.if_flags[ NIP_CURR_IF ] &= ~NIP_DISP_IF_GROUP;
00168                                         NIP_CURR_CMD = &nip_ip_disp_check_group;
00169                                         // set check_if flag to make sure we didn't miss any event
00170                                         nip_disp_notify( NIP_DISP_CHECK_IF );
00171                                         goto eval_cmd;
00172                                 }
00173                                 #endif
00174 
00175                         #if NIP_NET_IF_COUNT>1
00176                         } while ( ++NIP_CURR_IF < NIP_NET_IF_COUNT );
00177                         #endif
00178                 }
00179 
00180                 if ( nip_disp.flags & NIP_DISP_TIMER )
00181                 {
00182                         nip_disp.flags &= ~NIP_DISP_TIMER;
00183                         nip_disp.flags |=
00184                                         NIP_DISP_CHECK_TRANS
00185                                         #if NIP_TCP_ENABLE == 1
00186                                                 | NIP_DISP_CHECK_TCP
00187                                         #endif
00188                                         #if NIP_MDNS_ENABLE == 1
00189                                                 | NIP_DISP_CHECK_MDNS
00190                                         #endif
00191                                         ;
00192                 }
00193 
00194                 // Transmission events
00195                 // check for IP address resolution flag
00196                 if ( nip_disp.flags & NIP_DISP_CHECK_TRANS )
00197                 {
00198 
00199                         nip_disp.flags &= ~NIP_DISP_CHECK_TRANS;
00200                         // find transmissions with status NIP_NET_IF_RESOLV_ADDR
00201 #if NIP_ARP_ENABLE == 1
00202                         NIP_CURR_CMD = &nip_arp_disp_resolve_any;
00203 #endif
00204                         goto eval_cmd;
00205                 }
00206 
00207                 // mDNS events
00208 #if NIP_MDNS_ENABLE == 1
00209                 if ( nip_disp.flags & NIP_DISP_CHECK_MDNS )
00210                 {
00211 
00212                         nip_disp.flags &= ~NIP_DISP_CHECK_MDNS;
00213                         // find transmissions with status NIP_NET_IF_RESOLV_ADDR
00214                         NIP_CURR_CMD = &nip_mdns_disp_check;
00215                         goto eval_cmd;
00216                 }
00217 #endif
00218 
00219 #if NIP_TCP_ENABLE == 1
00220                 // TCP events
00221                 // check for IP address resolution flag
00222                 if ( nip_disp.flags & NIP_DISP_CHECK_TCP )
00223                 {
00224 
00225                         nip_disp.flags &= ~NIP_DISP_CHECK_TCP;
00226                         // find transmissions with status NIP_NET_IF_RESOLV_ADDR
00227                         NIP_CURR_CMD = &nip_tcp_disp_check;
00228                         goto eval_cmd;
00229                 }
00230 #endif /* NIP_TCP_ENABLE */
00231 
00232                 // Handle UDP Events if UDP has been enabled
00233                 /// @todo Check if using an UDP state machine makes more sense than the
00234                 /// current, direct approach of nip_udp_transmit(). Check nip_udp_disp_send()
00235                 /// for further details.
00236 //              #if ( NIP_UDP_ENABLE == 1 )
00237 //              if ( nip_disp.flags & NIP_DISP_CHECK_UDP )
00238 //              {
00239 //                      nip_disp.flags &= ~NIP_DISP_CHECK_UDP;
00240 //                      NIP_CURR_CMD = &nip_udp_disp_send;
00241 //                      goto eval_cmd;
00242 //              }
00243 //              #endif
00244 
00245                 // Execute Dispatcher Command Chain. A command is a pointer to a function
00246                 // which may relocate that pointer during it's runtime. The dispatcher
00247                 // will execute the new function after the previous function returned which
00248                 // will possibly lead to chain of functions to be executed. In a non-
00249                 // multitasking environment it is necessary that any chain of functions
00250                 // implements defined exit points which will allow continuation of the
00251                 // chain at a later, event-driven (e.g. timer) point of time. Any function
00252                 // chain must ensure that no deadlock situation can arise from its
00253                 // execution.
00254                 eval_cmd:
00255                 while ( NIP_CURR_CMD != NULL )
00256                 {
00257                         tmp_cmd = NIP_CURR_CMD;
00258                         NIP_CURR_CMD = NULL;
00259                         tmp_cmd();
00260 
00261                 }
00262 
00263 
00264         };
00265 
00266         ///\todo Take result value from nip_disp - Structure
00267         nip_disp.flags &= ~NIP_DISP_RUNNING;
00268         return NIP_E_OK;
00269 }
00270 #endif /*(NIP_DISP_ENABLE==1)*/

Generated on Thu Jul 10 01:09:29 2008 for NIP by  doxygen 1.5.5