00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef TORRENT_IP_FILTER_HPP
00034 #define TORRENT_IP_FILTER_HPP
00035
00036 #ifdef _MSC_VER
00037 #pragma warning(push, 1)
00038 #endif
00039
00040 #include <boost/limits.hpp>
00041 #include <boost/utility.hpp>
00042 #include <boost/tuple/tuple.hpp>
00043
00044 #ifdef _MSC_VER
00045 #pragma warning(pop)
00046 #endif
00047
00048
00049 #include "libtorrent/config.hpp"
00050 #include "libtorrent/socket.hpp"
00051 #include <set>
00052 #include <iostream>
00053
00054 namespace libtorrent
00055 {
00056
00057 inline bool operator<=(address const& lhs
00058 , address const& rhs)
00059 {
00060 return lhs < rhs || lhs == rhs;
00061 }
00062
00063 template <class Addr>
00064 struct ip_range
00065 {
00066 Addr first;
00067 Addr last;
00068 int flags;
00069 };
00070
00071 namespace detail
00072 {
00073
00074
00075
00076
00077 template<class Addr>
00078 class filter_impl
00079 {
00080 public:
00081
00082 filter_impl()
00083 {
00084 typename Addr::bytes_type zero;
00085 std::fill(zero.begin(), zero.end(), 0);
00086
00087 m_access_list.insert(range(Addr(zero), 0));
00088 }
00089
00090 void add_rule(Addr first, Addr last, int flags)
00091 {
00092 using boost::next;
00093 using boost::prior;
00094
00095 assert(!m_access_list.empty());
00096 assert(first < last || first == last);
00097
00098 typename range_t::iterator i = m_access_list.upper_bound(first);
00099 typename range_t::iterator j = m_access_list.upper_bound(last);
00100
00101 if (i != m_access_list.begin()) --i;
00102
00103 assert(j != m_access_list.begin());
00104 assert(j != i);
00105
00106 int first_access = i->access;
00107 int last_access = prior(j)->access;
00108
00109 if (i->start != first && first_access != flags)
00110 {
00111 i = m_access_list.insert(i, range(first, flags));
00112 }
00113 else if (i != m_access_list.begin() && prior(i)->access == flags)
00114 {
00115 --i;
00116 first_access = i->access;
00117 }
00118 assert(!m_access_list.empty());
00119 assert(i != m_access_list.end());
00120
00121 if (i != j) m_access_list.erase(next(i), j);
00122 if (i->start == first)
00123 {
00124
00125
00126 const_cast<Addr&>(i->start) = first;
00127 const_cast<int&>(i->access) = flags;
00128 }
00129 else if (first_access != flags)
00130 {
00131 m_access_list.insert(i, range(first, flags));
00132 }
00133
00134 if ((j != m_access_list.end()
00135 && minus_one(j->start) != last)
00136 || (j == m_access_list.end()
00137 && last != max_addr()))
00138 {
00139 assert(j == m_access_list.end() || last < minus_one(j->start));
00140 if (last_access != flags)
00141 j = m_access_list.insert(j, range(plus_one(last), last_access));
00142 }
00143
00144 if (j != m_access_list.end() && j->access == flags) m_access_list.erase(j);
00145 assert(!m_access_list.empty());
00146 }
00147
00148 int access(Addr const& addr) const
00149 {
00150 assert(!m_access_list.empty());
00151 typename range_t::const_iterator i = m_access_list.upper_bound(addr);
00152 if (i != m_access_list.begin()) --i;
00153 assert(i != m_access_list.end());
00154 assert(i->start <= addr && (boost::next(i) == m_access_list.end()
00155 || addr < boost::next(i)->start));
00156 return i->access;
00157 }
00158
00159 std::vector<ip_range<Addr> > export_filter() const
00160 {
00161 std::vector<ip_range<Addr> > ret;
00162 ret.reserve(m_access_list.size());
00163
00164 for (typename range_t::const_iterator i = m_access_list.begin()
00165 , end(m_access_list.end()); i != end;)
00166 {
00167 ip_range<Addr> r;
00168 r.first = i->start;
00169 r.flags = i->access;
00170
00171 ++i;
00172 if (i == end)
00173 r.last = max_addr();
00174 else
00175 r.last = minus_one(i->start);
00176
00177 ret.push_back(r);
00178 }
00179 return ret;
00180 }
00181
00182 private:
00183
00184 Addr plus_one(Addr const& a) const
00185 {
00186 typename Addr::bytes_type tmp(a.to_bytes());
00187 typedef typename Addr::bytes_type::reverse_iterator iter;
00188 for (iter i = tmp.rbegin()
00189 , end(tmp.rend()); i != end; ++i)
00190 {
00191 if (*i < (std::numeric_limits<typename iter::value_type>::max)())
00192 {
00193 *i += 1;
00194 break;
00195 }
00196 *i = 0;
00197 }
00198 return Addr(tmp);
00199 }
00200
00201 Addr minus_one(Addr const& a) const
00202 {
00203 typename Addr::bytes_type tmp(a.to_bytes());
00204 typedef typename Addr::bytes_type::reverse_iterator iter;
00205 for (iter i = tmp.rbegin()
00206 , end(tmp.rend()); i != end; ++i)
00207 {
00208 if (*i > 0)
00209 {
00210 *i -= 1;
00211 break;
00212 }
00213 *i = (std::numeric_limits<typename iter::value_type>::max)();
00214 }
00215 return Addr(tmp);
00216 }
00217
00218 Addr max_addr() const
00219 {
00220 typename Addr::bytes_type tmp;
00221 std::fill(tmp.begin(), tmp.end()
00222 , (std::numeric_limits<typename Addr::bytes_type::value_type>::max)());
00223 return Addr(tmp);
00224 }
00225
00226 struct range
00227 {
00228 range(Addr addr, int access = 0): start(addr), access(access) {}
00229 bool operator<(range const& r) const
00230 { return start < r.start; }
00231 bool operator<(Addr const& a) const
00232 { return start < a; }
00233 Addr start;
00234
00235
00236 int access;
00237 };
00238
00239 typedef std::set<range> range_t;
00240 range_t m_access_list;
00241
00242 };
00243
00244 }
00245
00246 class TORRENT_EXPORT ip_filter
00247 {
00248 public:
00249
00250 enum access_flags
00251 {
00252 blocked = 1
00253 };
00254
00255
00256
00257 void add_rule(address first, address last, int flags);
00258 int access(address const& addr) const;
00259
00260 typedef boost::tuple<std::vector<ip_range<address_v4> >
00261 , std::vector<ip_range<address_v6> > > filter_tuple_t;
00262
00263 filter_tuple_t export_filter() const;
00264
00265
00266
00267 private:
00268
00269 detail::filter_impl<address_v4> m_filter4;
00270 detail::filter_impl<address_v6> m_filter6;
00271 };
00272
00273 }
00274
00275 #endif
00276