T message_queue<T, Compare>::dequeue(void) { HC_LOG_TRACE(""); T t; { std::unique_lock<std::mutex> lock(m_global_lock); cond_empty.wait(lock, [&]() { return m_q.size() != 0; }); t = m_q.top(); m_q.pop(); } return t; }
bool message_queue<T, Compare>::enqueue_loseable(const T& t) { HC_LOG_TRACE(""); { std::unique_lock<std::mutex> lock(m_global_lock); if (m_q.size() < m_size) { m_q.push(t); } else { HC_LOG_WARN("message_queue is full, failed to insert message"); return false; } } cond_empty.notify_one(); return true; }
void timing::test_timing(){ HC_LOG_TRACE(""); timing* t = timing::getInstance(); proxy_msg p_msg; p_msg.msg = new struct test_msg(4); t->start(); t->add_time(10000,NULL,p_msg); /*t->add_time(2000,NULL,p_msg); t->add_time(3000,NULL,p_msg); t->add_time(4000,NULL,p_msg); t->add_time(10000,NULL,p_msg);*/ sleep(2); t->stop(); t->join(); }
bool proxy_instance::init_receiver(){ HC_LOG_TRACE(""); if(m_addr_family == AF_INET){ m_receiver = new igmp_receiver(); }else if(m_addr_family == AF_INET6){ m_receiver = new mld_receiver(); }else{ HC_LOG_ERROR("wrong address family"); return false; } if(!m_receiver->init(m_addr_family,m_version, &m_mrt_sock)) return false; m_receiver->start(); return true; }
//interface_filter_fun is very useless, please overwork ??????????????? void querier::suggest_to_forward_traffic(const addr_storage& gaddr, std::list<std::pair<source, std::list<unsigned int>>>& rt_slist, std::function<bool(const addr_storage&)> interface_filter_fun) const { HC_LOG_TRACE(""); if (m_db.is_querier == true) { auto db_info_it = m_db.group_info.find(gaddr); if (db_info_it != std::end(m_db.group_info)) { if (db_info_it->second.is_under_bakcward_compatibility_effects()) { //accept all sources for (auto & e : rt_slist) { if (interface_filter_fun(e.first.saddr)) { e.second.push_back(m_if_index); } } } else { if (db_info_it->second.filter_mode == INCLUDE_MODE) { for (auto & e : rt_slist) { auto irl_it = db_info_it->second.include_requested_list.find(e.first); if (irl_it != std::end(db_info_it->second.include_requested_list) ) { if (interface_filter_fun(e.first.saddr)) { e.second.push_back(m_if_index); } } } } else if (db_info_it->second.filter_mode == EXCLUDE_MODE) { for (auto & e : rt_slist) { auto el_it = db_info_it->second.exclude_list.find(e.first); if (el_it == std::end(db_info_it->second.exclude_list) ) { if (interface_filter_fun(e.first.saddr)) { e.second.push_back(m_if_index); } } } } else { HC_LOG_ERROR("unknown filter mode"); } } } } }
group_mem_protocol parser::parse_group_mem_proto() { HC_LOG_TRACE(""); //protocol = "protocol" potocol_type; //protocol_type = "MLDv1" | "MLDv2" | "IGMPv1" | "IGMPv2" | "IGMPv3"; group_mem_protocol result; if (get_parser_type() == PT_PROTOCOL) { get_next_token(); switch (m_current_token.get_type()) { case TT_MLDV1: result = MLDv1; break; case TT_MLDV2: result = MLDv2; break; case TT_IGMPV1: result = IGMPv1; break; case TT_IGMPV2: result = IGMPv2; break; case TT_IGMPV3: result = IGMPv3; break; default: HC_LOG_ERROR("failed to parse line " << m_current_line << " unknown token " << get_token_type_name(m_current_token.get_type()) << " with value " << m_current_token.get_string() << ", expected \"MLDV1\" or \"MLDv2\" or \"IGMPv1\" or \"IGMPv2\" or \"IGMPv3\""); throw "failed to parse config file"; break; } }else{ HC_LOG_ERROR("failed to parse line " << m_current_line << " unknown token " << get_token_type_name(m_current_token.get_type()) << " with value " << m_current_token.get_string() << ", expected \"protocol\""); throw "failed to parse config file"; } get_next_token(); if (m_current_token.get_type() == TT_NIL) { return result; } else { HC_LOG_ERROR("failed to parse line " << m_current_line << " unknown token " << get_token_type_name(m_current_token.get_type()) << " with value " << m_current_token.get_string()); throw "failed to parse config file"; } }
bool reverse_path_filter::get_rp_filter(const std::string& if_name) const { HC_LOG_TRACE(""); std::stringstream path; bool state; path << REVERSE_PATH_FILTER_PATH << if_name << "/rp_filter"; std::ifstream is(path.str().c_str(), std::ios::binary | std::ios::in); if (!is) { HC_LOG_ERROR("failed to open file:" << path.str()); return false; } else { state = is.get(); } is.close(); return state; }
void if_prop::test_if_prop(){ HC_LOG_TRACE(""); if_prop p; cout << "##-- refresh --##" << endl; if(!p.refresh_network_interfaces()){ cout << "refresh faild" << endl; return; } p.print_if_info(); cout << "##-- refresh --##" << endl; sleep(1); if(!p.refresh_network_interfaces()){ cout << "refresh faild" << endl; return; } p.print_if_info(); }
void proxy_instance::refresh_all_traffic(int if_index, const addr_storage& g_addr){ HC_LOG_TRACE(""); upstream_src_state_map::iterator iter_uss; src_state_map::iterator iter_src; state_table_map::iterator iter_table; g_state_map::iterator iter_state; src_group_state_pair* sgs_pair = 0; if(if_index == m_upstream){ HC_LOG_ERROR("the if_index:" << if_index << " mussnt be the upstream, upstream have no joined groups"); } //process upstream iter_uss = m_upstream_state.find(g_addr); if(iter_uss != m_upstream_state.end()){ //g_addr found for(iter_src = iter_uss->second.begin(); iter_src != iter_uss->second.end(); iter_src++){ if(!split_traffic(m_upstream, g_addr, iter_src->first)){ //have to check old upstream source because the have no default stream so they dont refresh themselve like downstreams iter_src->second.flag = src_state::UNUSED_SRC; del_route(if_index,g_addr,iter_src->first); } } } //process downstream for(iter_table = m_state_table.begin(); iter_table != m_state_table.end(); iter_table++){ if(if_index != iter_table->first){ iter_state = iter_table->second.find(g_addr); if(iter_state != iter_table->second.end()){ sgs_pair = &iter_state->second; for(iter_src = sgs_pair->first.begin(); iter_src != sgs_pair->first.end(); iter_src++){ split_traffic(iter_table->first, g_addr, iter_src->first); } } } } }
void querier::send_Q(const addr_storage& gaddr, gaddr_info& ginfo) { HC_LOG_TRACE(""); //7.6.3.1. Building and Sending Multicast Address Specific Queries //When a table action "Send Q(MA)" is encountered, the Filter Timer //must be lowered to LLQT. The Querier must then immediately send a //Multicast Address Specific query as well as schedule [Last Listener //Query Count - 1] query retransmissions to be sent every [Last //Listener Query Interval], over [Last Listener Query Time]. //When transmitting a Multicast Address Specific Query, if the Filter //Timer is larger than LLQT, the "Suppress Router-Side Processing" bit //is set in the query message. if (ginfo.group_retransmission_timer == nullptr) { ginfo.group_retransmission_count = m_timers_values.get_last_listener_query_count(); auto llqt = m_timers_values.get_last_listener_query_time(); auto ftimer = std::make_shared<filter_timer_msg>(m_if_index, gaddr, llqt); ginfo.shared_filter_timer = ftimer; m_timing->add_time(llqt, m_msg_worker, ftimer); } if (ginfo.group_retransmission_count > 0) { ginfo.group_retransmission_count--; if (ginfo.group_retransmission_count > 0) { auto llqi = m_timers_values.get_last_listener_query_interval(); auto rtimer = std::make_shared<retransmit_group_timer_msg>(m_if_index, gaddr, llqi); ginfo.group_retransmission_timer = rtimer; m_timing->add_time(llqi, m_msg_worker, rtimer); } m_sender->send_mc_addr_specific_query(m_if_index, m_timers_values, gaddr, ginfo.shared_filter_timer->is_remaining_time_greater_than(m_timers_values.get_last_listener_query_time())); } else { //reset itself ginfo.group_retransmission_timer = nullptr; ginfo.group_retransmission_count = -1; } }
void if_prop::print_if_info() const{ HC_LOG_TRACE(""); if (!is_getaddrs_valid()) { HC_LOG_ERROR("data invalid"); return; } const if_prop_map* prop = get_if_props(); if(prop == NULL){ HC_LOG_ERROR("data struct not found"); return; } const struct ifaddrs* if_p; const list<const struct ifaddrs*>* if_p_list; cout << "##-- IPv4 [count:" << prop->size() << "]--##" << endl; for(if_prop_map::const_iterator iter = prop->begin(); iter != prop->end(); iter++){ if_p = get_ip4_if(iter->first); if(if_p == NULL){ HC_LOG_ERROR("interface name not found: " << iter->first); continue; } print_if_addr(if_p); } cout << "##-- IPv6 [count:" << prop->size() << "]--##" << endl; for(if_prop_map::const_iterator iter = prop->begin(); iter != prop->end(); iter++){ if_p_list = get_ip6_if(iter->first); if(if_p_list == NULL){ HC_LOG_ERROR("interface name not found: " << iter->first); continue; } for(list<const struct ifaddrs*>::const_iterator itera = if_p_list->begin(); itera != if_p_list->end(); itera++){ print_if_addr(*itera); } } }
bool querier::send_general_query() { HC_LOG_TRACE(""); if (m_db.general_query_timer.get() == nullptr) { m_db.startup_query_count = m_timers_values.get_startup_query_count() - 1; } std::chrono::seconds t; if (m_db.startup_query_count > 0) { m_db.startup_query_count--; t = m_timers_values.get_startup_query_interval(); } else { t = m_timers_values.get_query_interval(); } auto gqt = std::make_shared<general_query_timer_msg>(m_if_index, t); m_db.general_query_timer = gqt; m_timing->add_time(t, m_msg_worker, gqt); return m_sender->send_general_query(m_if_index, m_timers_values); }
bool reverse_path_filter::set_rp_filter(const std::string& if_name, bool set_to) const { HC_LOG_TRACE(""); std::stringstream path; path << REVERSE_PATH_FILTER_PATH << if_name << "/rp_filter"; std::ofstream os(path.str().c_str(), std::ios::binary | std::ios::out); if (!os) { HC_LOG_ERROR("failed to open file:" << path.str() << " and set rp_filter to " << set_to); return false; } else { if (set_to) { os.put('1'); } else { os.put('0'); } } os.flush(); os.close(); return true; }
querier::querier(worker* msg_worker, group_mem_protocol querier_version_mode, int if_index, const std::shared_ptr<const sender>& sender, const std::shared_ptr<timing>& timing, const timers_values& tv, callback_querier_state_change cb_state_change) : m_msg_worker(msg_worker) , m_if_index(if_index) , m_db(querier_version_mode) , m_timers_values(tv) , m_cb_state_change(cb_state_change) , m_sender(sender) , m_timing(timing) { HC_LOG_TRACE(""); //join all router groups if (!router_groups_function(true)) { HC_LOG_ERROR("failed to subscribe multicast router groups"); throw "failed to subscribe multicast router groups"; } if (!send_general_query()) { HC_LOG_ERROR("failed to initialise query startup"); throw "failed to initialise query startup"; } }
bool mld_sender::add_hbh_opt_header(){ HC_LOG_TRACE(""); unsigned char extbuf[sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh) + sizeof(struct ip6_opt_router)+ sizeof(pad2)]; struct ip6_hbh* hbh_Hdr = (struct ip6_hbh*)extbuf; struct ip6_opt_router* opt_Hdr = (struct ip6_opt_router*)(extbuf + sizeof(struct ip6_hbh)); pad2* pad_Hdr = (pad2*)(extbuf + sizeof(struct ip6_hbh) + sizeof(struct ip6_opt_router)); hbh_Hdr->ip6h_nxt = IPPROTO_ICMPV6; hbh_Hdr->ip6h_len = MC_MASSAGES_IPV6_ROUTER_ALERT_OPT_SIZE; //=> 8 Bytes opt_Hdr->ip6or_type = IP6OPT_ROUTER_ALERT; opt_Hdr->ip6or_len = sizeof(opt_Hdr->ip6or_value); *(u_int16_t*)&opt_Hdr->ip6or_value[0] = IP6_ALERT_MLD; *pad_Hdr = IP6OPT_PADN; if(!m_sock.add_extension_header((unsigned char*)hbh_Hdr,sizeof(struct ip6_hbh) + sizeof(struct ip6_opt_router)+ sizeof(pad2))) return false; return true; }
std::unique_ptr<rule_box> parser::parse_rule(const std::shared_ptr<const global_table_set>& gts, group_mem_protocol gmp) { HC_LOG_TRACE(""); std::string if_name; if (m_current_token.get_type() == TT_STRING || m_current_token.get_type() == TT_LEFT_BRACKET) { if (m_current_token.get_type() == TT_STRING) { if_name = m_current_token.get_string(); get_next_token(); } if (m_current_token.get_type() == TT_LEFT_BRACKET) { get_next_token(); if (m_current_token.get_type() == TT_TABLE) { std::unique_ptr<rule_box> result(new rule_table(parse_table(gts, gmp, true))); return result; } else { std::unique_ptr<addr_match> group; std::unique_ptr<addr_match> source; group = parse_rule_part(gmp); if (m_current_token.get_type() == TT_PIPE) { get_next_token(); source = parse_rule_part(gmp); if (m_current_token.get_type() == TT_RIGHT_BRACKET) { std::unique_ptr<rule_box> result(new rule_addr(if_name, std::move(group), std::move(source))); return result; } } } } } else { return nullptr; } HC_LOG_ERROR("failed to parse line " << m_current_line << " unknown token " << get_token_type_name(m_current_token.get_type()) << " with value " << m_current_token.get_string() << " in this context"); throw "failed to parse config file"; }
bool proxy_instance::init_mrt_socket(){ HC_LOG_TRACE(""); if(m_addr_family == AF_INET){ m_mrt_sock.create_raw_ipv4_socket(); }else if(m_addr_family == AF_INET6){ m_mrt_sock.create_raw_ipv6_socket(); }else{ HC_LOG_ERROR("wrong addr_family: " << m_addr_family); return false; } if(!m_is_single_instance){ if(!m_mrt_sock.set_kernel_table(m_upstream)){ return false; }else{ HC_LOG_DEBUG("proxy instance: " << m_upstream); } } if(!m_mrt_sock.set_mrt_flag(true)) return false; return true; }
reverse_path_filter::~reverse_path_filter() { HC_LOG_TRACE(""); restore_rp_filter(); }
void proxy_instance::handle_config(struct config_msg* c){ HC_LOG_TRACE(""); switch(c->type){ case config_msg::ADD_DOWNSTREAM: { //if interface exist if(m_state_table.find(c->if_index) != m_state_table.end()){ HC_LOG_ERROR("failed to add downstream, interface " << c->if_index << " allready exist"); } m_state_table.insert(state_tabel_pair(c->if_index,g_state_map())); m_vif_map.insert(vif_pair(c->if_index,c->vif)); registrate_if(c->if_index); break; } case config_msg::DEL_DOWNSTREAM: { //if interface exist if(m_state_table.find(c->if_index) == m_state_table.end()){ HC_LOG_ERROR("failed to del downstream, interface " << c->if_index << " not exist"); } unregistrate_if(c->if_index); state_table_map::iterator iter_table; g_state_map::iterator iter_state; src_group_state_pair* sgs_pair = NULL; src_state_map::iterator iter_src; iter_table =m_state_table.find(c->if_index); if(iter_table == m_state_table.end()) { HC_LOG_ERROR("faild to del downstream: cant find if_index: " << c->if_index); return; } vector<addr_storage> tmp_erase_group_vector; for(iter_state= iter_table->second.begin(); iter_state != iter_table->second.end(); iter_state++){ sgs_pair = &iter_state->second; //remove all own sources (routes) for(iter_src = sgs_pair->first.begin(); iter_src != sgs_pair->first.end(); iter_src++){ if(iter_src->second.flag == src_state::CACHED_SRC){ del_route(iter_table->first, iter_state->first, iter_src->first); } } //save all groups for remove tmp_erase_group_vector.push_back(iter_state->first); //refresh upstream if(!is_group_joined(c->if_index,iter_state->first)){ if(!m_sender->send_leave(m_upstream, iter_state->first)){ HC_LOG_ERROR("failed to leave on upstream group: " << iter_state->first); } } } //erase all groups for(unsigned int i=0; i< tmp_erase_group_vector.size(); i++){ if((iter_state = iter_table->second.find(tmp_erase_group_vector[i]))!= iter_table->second.end()){ iter_table->second.erase(iter_state); //calculate the joined group roles refresh_all_traffic(c->if_index, tmp_erase_group_vector[i]); }else{ HC_LOG_ERROR("cant find downstream group: " << tmp_erase_group_vector[i]);} } //clean state table m_state_table.erase(iter_table); //clean vif map vif_map::iterator it_vif_map = m_vif_map.find(c->if_index); if(it_vif_map == m_vif_map.end()) { HC_LOG_ERROR("faild to del downstream: cant find vif to if_index: " << c->if_index); return; } m_vif_map.erase(it_vif_map); //HC_LOG_ERROR("del downstream not implementeted"); break; } case config_msg::SET_UPSTREAM: { //remove current upstream unregistrate_if(c->if_index); vif_map::iterator it_vif_map = m_vif_map.find(c->if_index); if(it_vif_map == m_vif_map.end()) { HC_LOG_ERROR("faild to del downstream: cant find if_index: " << c->if_index); return; } m_vif_map.erase(it_vif_map); //ToDo //refresh routes????????????????????????????????? HC_LOG_ERROR("set upstream not implementeted"); //set new upstream m_upstream = c->if_index; m_vif_map.insert(vif_pair(c->if_index,c->vif)); registrate_if(c->if_index); break; } default: HC_LOG_ERROR("unknown config message format"); } }
std::ostream& operator<<(std::ostream& stream, const reverse_path_filter& r) { HC_LOG_TRACE(""); stream << r.to_string(); return stream; }
reverse_path_filter::reverse_path_filter() : m_used_earlier(false) { HC_LOG_TRACE(""); }
timing::timehandling::timehandling(struct timeval time, proxy_instance* pr_i, proxy_msg pr_msg){ HC_LOG_TRACE(""); m_time = time; m_pr_i = pr_i; m_pr_msg = pr_msg; }
timing* timing::getInstance(){ HC_LOG_TRACE(""); static timing instance; return &instance; }
timing::~timing(){ HC_LOG_TRACE(""); delete m_worker_thread; }
timing::timing(): m_running(false), m_worker_thread(0) { HC_LOG_TRACE(""); }
void proxy_instance::handle_debug_msg(struct debug_msg* db){ HC_LOG_TRACE(""); std::stringstream str; state_table_map::iterator iter_table; g_state_map::iterator iter_state; src_state_map::iterator iter_src_state; vif_map::iterator iter_vif; upstream_src_state_map::iterator iter_up_src_state; char cstr[IF_NAMESIZE]; string if_name(if_indextoname(m_upstream,cstr)); if((iter_vif = m_vif_map.find(m_upstream))== m_vif_map.end()){ HC_LOG_ERROR("failed to find vif to upstream if_index:" << m_upstream); return; } str << "##-- instance upstream " << if_name << " [vif=" << iter_vif->second<< "] --##" << endl; if(db->get_level_of_detail() > debug_msg::LESS){ if(db->get_level_of_detail() > debug_msg::NORMAL){ //upstream output str << "\tgroup addr" << endl; int tmp_g_counter=0; for(iter_up_src_state= m_upstream_state.begin(); iter_up_src_state !=m_upstream_state.end(); iter_up_src_state++){ src_state_map* tmp_src_state_map = &iter_up_src_state->second; str << "\t[" << tmp_g_counter++ << "] " <<iter_up_src_state->first << "\t" << endl; int tmp_s_counter=0; if(db->get_level_of_detail() > debug_msg::MORE){ if(tmp_src_state_map->size()>0 ){ str << "\t\tsrc addr | robustness_counter | flag" << endl; for(iter_src_state = tmp_src_state_map->begin(); iter_src_state != tmp_src_state_map->end(); iter_src_state++){ str << "\t\t[" << tmp_s_counter++ << "] " << iter_src_state->first << "\t" << iter_src_state->second.robustness_counter << "\t" << iter_src_state->second.state_type_to_string() << endl; } } } } str << endl; } //downstream output for(iter_table= m_state_table.begin(); iter_table != m_state_table.end(); iter_table++){ if_name = if_indextoname(iter_table->first,cstr); if((iter_vif = m_vif_map.find(iter_table->first))== m_vif_map.end()){ HC_LOG_ERROR("failed to find vif to downstream if_index:" << iter_table->first); return; } str << "\t-- downstream " << if_name << " [vif=" << iter_vif->second << "] --" << endl; if(db->get_level_of_detail() > debug_msg::NORMAL){ str << "\t\tgroup addr | robustness_counter | flag" << endl; int tmp_g_counter=0; for(iter_state= iter_table->second.begin(); iter_state != iter_table->second.end(); iter_state++){ src_group_state_pair* tmp_gsp = &iter_state->second; str << "\t\t[" << tmp_g_counter++ << "] " <<iter_state->first << "\t" << tmp_gsp->second.robustness_counter << "\t" << tmp_gsp->second.state_type_to_string() << endl; int tmp_s_counter=0; if(db->get_level_of_detail() > debug_msg::MORE){ if(tmp_gsp->first.size()>0 ){ str << "\t\t\tsrc addr | robustness_counter | flag" << endl; for(iter_src_state = tmp_gsp->first.begin(); iter_src_state != tmp_gsp->first.end(); iter_src_state++){ str << "\t\t\t[" << tmp_s_counter++ << "] " << iter_src_state->first << "\t" << iter_src_state->second.robustness_counter << "\t" << iter_src_state->second.state_type_to_string() << endl; } } } } str << endl; } } } db->add_debug_msg(str.str()); }
void timing::stop(){ HC_LOG_TRACE(""); m_running= false; }
mld_sender::mld_sender(){ HC_LOG_TRACE(""); }
bool mld_sender::send_leave(int if_index, const addr_storage& g_addr){ HC_LOG_TRACE(""); return m_sock.leave_group(g_addr.to_string().c_str(),if_index); }
void timing::start(){ HC_LOG_TRACE(""); m_running = true; m_worker_thread = new boost::thread(timing::worker_thread, this); }