00001 // Copyright (C) 2003, 2004, 2005, 2006 Laboratoire de Recherche en Informatique 00002 00003 // This file is part of Qolyester. 00004 00005 // Qolyester is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU General Public License 00007 // as published by the Free Software Foundation; either version 2 00008 // of the License, or (at your option) any later version. 00009 00010 // Qolyester is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 00019 #ifndef QOLYESTER_DAEMON_SET_INTERFACES_HXX 00020 # define QOLYESTER_DAEMON_SET_INTERFACES_HXX 1 00021 00022 # include <map> 00023 # include <cassert> 00024 00025 # include "config.hh" 00026 00027 # include "pkt/packet.hh" 00028 # include "sch/events.hh" 00029 # include "sch/scheduler.hh" 00030 # include "set/gate.hh" 00031 # include "utl/comparator.hh" 00032 00033 # include "interfaces.hh" 00034 00035 namespace olsr { 00036 00037 extern address_t main_addr; 00038 extern gateset_t gate_set; 00039 extern cproxy_t cproxy; 00040 extern sched_t scheduler; 00041 extern ifaceset_t iface_set; 00042 00043 namespace set { 00044 00045 InterfaceSet::InterfaceSet() 00046 : _iset(), 00047 _mid_iset(_iset), 00048 _min_mtu(0) 00049 {} 00050 00051 InterfaceSet::iterator 00052 InterfaceSet::begin() const { 00053 return _iset.begin(); 00054 } 00055 00056 InterfaceSet::iterator 00057 InterfaceSet::end() const { 00058 return _iset.end(); 00059 } 00060 00061 bool 00062 InterfaceSet::empty() const { 00063 return _iset.empty(); 00064 } 00065 00066 size_t 00067 InterfaceSet::size() const { 00068 return _iset.size(); 00069 } 00070 00071 const iface_t& 00072 InterfaceSet::operator[](const address_t& iaddr) const { 00073 const_iterator i = find(iaddr); 00074 assert(i != end()); 00075 return *i; 00076 } 00077 00078 std::pair<InterfaceSet::iterator, bool> 00079 InterfaceSet::insert(const iset_t::value_type& x) { 00080 if (main_addr == address_t()) 00081 main_addr = x.addr(); 00082 if (_iset.find(x) == _iset.end()) 00083 _mid_iset.add_key(x.addr()); 00084 std::pair<iset_t::iterator, bool> p = _iset.insert(x); 00085 if (p.second) { 00086 _mid_iset.insert(p.first); 00087 if (_min_mtu == 0 || x.mtu() < _min_mtu) 00088 _min_mtu = x.mtu(); 00089 cproxy.add_interface(x.addr()); 00090 gate_set.hna_gset().add_key(x.addr()); 00091 scheduler.insert(new sch::PacketReceiver(const_cast<iface_t*>(&*p.first))); 00092 } 00093 // const_cast<iset_t::value_type&>(x).configure(); 00094 return p; 00095 } 00096 00097 void 00098 InterfaceSet::erase(iterator pos) { 00099 assert(pos != end()); 00100 // const_cast<iset_t::value_type&>(*pos).unconfigure(); 00101 const_cast<iface_t&>(*pos).destroy_all_events(); 00102 gate_set.hna_gset().remove_key(pos->addr()); 00103 cproxy.remove_interface(pos->addr()); 00104 if (pos->addr() == main_addr) 00105 main_addr = address_t(); 00106 _mid_iset.remove_key(pos->addr()); 00107 _mid_iset.erase(pos); 00108 _iset.erase(pos); 00109 _min_mtu = 0; 00110 for (iset_t::iterator i = _iset.begin(); i != _iset.end(); ++i) 00111 if (_min_mtu == 0 || i->mtu() < _min_mtu) 00112 _min_mtu = i->mtu(); 00113 if (main_addr == address_t() && !_iset.empty()) 00114 main_addr = _iset.begin()->addr(); 00115 } 00116 00117 InterfaceSet::iterator 00118 InterfaceSet::find(const address_t& iaddr) const { 00119 return _iset.find(iface_t::make_key(iaddr)); 00120 } 00121 00122 void 00123 InterfaceSet::send_messages() { 00124 00125 assert(iface_set.empty() || min_mtu() > 0); 00126 00127 // FIXME: this should not be that way, we should remove pending 00128 // messages if there are no current interfaces. 00129 if (iface_set.empty()) { 00130 pending_messages.clear(); 00131 return; 00132 } 00133 00134 while (!pending_messages.empty()) { 00135 00136 typedef std::map<iface_t*, 00137 pkt::Packet, 00138 utl::pless<iface_t> > packets_t; 00139 00140 packets_t packets; 00141 00142 // Create a packet for each interface. 00143 for (iset_t::iterator i = _iset.begin(); i != _iset.end(); ++i) 00144 packets.insert(packets_t::value_type(const_cast<iface_t*>(&*i), 00145 pkt::Packet(_min_mtu, 00146 i->addr()))); 00147 00148 // Add each message in all the packets. 00149 for (pending_t::iterator m = pending_messages.begin(); 00150 m != pending_messages.end(); /* ++m elsewhere */) { 00151 // Add the message to the first packet. 00152 bool resend = packets.begin()->second.add_message(**m); 00153 00154 // Add the message to the remaining packets and check that 00155 // it fits the same way. 00156 00157 // FIXME: this should be avoided, since the packets should 00158 // be identical on every interface for we always broadcast 00159 // messages on all interfaces. 00160 for (packets_t::iterator i = ++packets.begin(); 00161 i != packets.end(); ++i) { 00162 # ifndef NDEBUG 00163 bool resend_this = i->second.add_message(**m); 00164 assert(resend_this == resend); 00165 # else // !NDEBUG 00166 i->second.add_message(**m); 00167 # endif 00168 } 00169 00170 // Increment the message sequence number. 00171 const_cast<msg::Message*>(*m)->inc_seqnum(); 00172 00173 // Destroy the message if it is not to be resent. 00174 if (!resend) { 00175 pending_t::iterator tmp = m++; 00176 const msg::Message* mptr = *tmp; 00177 pending_messages.erase(tmp); 00178 delete mptr; 00179 } 00180 } 00181 00182 // Now send the packets. 00183 for (packets_t::iterator i = packets.begin(); 00184 i != packets.end(); ++i) { 00185 i->second.close(i->first->addr()); 00186 if (i->second.size() > pkt::Packet::min_length) 00187 i->first->shipout(i->second); 00188 } 00189 } 00190 } 00191 00192 // for (iset_t::iterator i = iface_set._iset.begin(); 00193 // i != iface_set._iset.end(); ++i) { 00194 // pending_t local_pm = pending_messages; 00195 00196 // while (!local_pm.empty()) { 00197 // pkt::Packet p(min_mtu(), i->addr()); 00198 00199 // p.fill(local_pm); 00200 00201 // if (p.size() > pkt::Packet::min_length) { 00202 // i->send(p); 00203 // } 00204 // } 00205 // } 00206 // for (pending_t::iterator i = pending_messages.begin(); 00207 // i != pending_messages.end(); ++i) 00208 // delete *i; 00209 // pending_messages.clear(); 00210 // } 00211 00212 } // namespace set 00213 00214 } // namespace olsr 00215 00216 #endif // ! QOLYESTER_DAEMON_SET_INTERFACES_HXX