// This message is handled by the Link SAP. // // If this MIHF is the destination of the message, forward it to the // default Link SAP. If not then forward it to a peer MIHF. bool command_service::link_actions_request(meta_message_ptr &in, meta_message_ptr &out) { log(1, "(mics) received a Link_Actions.request from", in->source().to_string()); if(utils::this_mihf_is_destination(in)) { // // Kick this message to MIH_Link SAP. // // The solution found to handle this corner case in the // 802.21 standard was to send the message, as is, to the // link sap. // in->destination(mih::id("link")); _lpool.add(in); in->source(mihfid); _transmit(in); return false; } else { utils::forward_request(in, _lpool, _transmit); return false; } return false; }
/** * Link Get Parameters Confirm message handler. * * @param in input message. * @param out output message. * @return true if the response is sent immediately or false otherwise. */ bool command_service::link_get_parameters_confirm(meta_message_ptr &in, meta_message_ptr &out) { ODTONE_LOG(1, "(mics) received Link_Get_Parameters.confirm from ", in->source().to_string()); _link_abook.reset(in->source().to_string()); if(_lpool.set_user_tid(in)) { mih::status st; boost::optional<mih::link_param_list> lpl; boost::optional<mih::link_states_rsp_list> lsrl; boost::optional<mih::link_desc_rsp_list> ldrl; *in >> mih::confirm(mih::confirm::link_get_parameters) & mih::tlv_status(st) & mih::tlv_link_parameters_status_list(lpl) & mih::tlv_link_states_rsp(lsrl) & mih::tlv_link_descriptor_rsp(ldrl); if(st == mih::status_success) { mih::link_status_rsp link_status; link_status.states_rsp_list = lsrl.get(); link_status.param_list = lpl.get(); link_status.desc_rsp_list = ldrl.get(); _lrpool.add(in->source().to_string(), in->tid(), link_status); } return false; }
// This message is handled by the Link SAP. // // If this MIHF is the destination of the message, forward it to the // default Link SAP. If not then forward it to a peer MIHF. bool command_service::link_get_parameters_request(meta_message_ptr &in, meta_message_ptr &out) { log(1, "(mics) received a Link_Get_Parameters.request from", in->source().to_string()); if(utils::this_mihf_is_destination(in)) { // // Kick this message to MIH_Link SAP. // // The solution found to handle this corner case in the // 802.21 standard was to send the message, as is, to the // link sap. // // local_transactions was made to handle request's // from users to peer mihf's but in this case we add an // entry to handle the MIH_Link_Get_Parameters and // Link_Get_Parameters. // in->destination(mih::id("link")); _lpool.add(in); in->source(mihfid); _transmit(in); return false; } else { utils::forward_request(in, _lpool, _transmit); return false; } return false; }
/** * Checks, in the transaction pool, if the incoming message belongs to a pending * transaction. If true it runs the transaction, otherwise it creates a new * transaction. * * @param in The input message. */ void message_in::operator()(meta_message_ptr& in) { // TODO: FIXME: check page 143 when adding support for fragment payload if ((in->ackrsp() && (in->opcode() == mih::operation::request || in->opcode() == mih::operation::indication)) || (!in->ackrsp() && in->opcode() == mih::operation::response) || (in->ackrsp() && in->opcode() == mih::operation::response && in->has_service_specific_tlv())) { // src src_transaction_ptr t; _tpool.find(in->source(), in->tid(), t); if (t) { t->in = in; t->msg_in_avail = true; if (t->start_ack_requestor) t->ack_requestor(); if (t->start_ack_responder) t->ack_responder(); if(t->transaction_status == ONGOING) if(!(in->ackrsp() == true && in->opcode() == mih::operation::request)) t->run(); if (t->transaction_status != ONGOING && t->ack_requestor_status != ONGOING) _tpool.del(t); } else { new_dst_transaction(in); } } else { dst_transaction_ptr t; _tpool.find(in->source(), in->tid(), t); if (t) { t->in = in; t->msg_in_avail = true; if (t->start_ack_requestor) t->ack_requestor(); if(t->transaction_status == ONGOING) t->run(); if (t->start_ack_responder && t->transaction_status == ONGOING) t->ack_responder(); if (t->transaction_status != ONGOING && t->ack_requestor_status != ONGOING) _tpool.del(t); } else { new_dst_transaction(in); } } }
/** * Asks for the capabilities of all local Link SAPs. * * @param in The input message. * @param out The output message. * @return Always false, because it does not send any response directly. */ bool service_management::link_capability_discover_request(meta_message_ptr &in, meta_message_ptr &out) { // Asks for local Link SAPs capabilities ODTONE_LOG(1, "(mism) gathering information about local Link SAPs capabilities"); *out << mih::request(mih::request::capability_discover); out->tid(in->tid()); out->destination(in->source()); // Check if the Link SAP is still active uint16 fails = _link_abook.fail(out->destination().to_string()); if(fails > kConf_MIHF_Link_Delete_Value) { mih::octet_string dst = out->destination().to_string(); _link_abook.inactive(dst); // Update MIHF capabilities utils::update_local_capabilities(_abook, _link_abook, _user_abook); } else { ODTONE_LOG(1, "(mics) forwarding Link_Capability_Discover.request to ", out->destination().to_string()); utils::forward_request(out, _lpool, _transmit); } return false; }
// // Currently Command_Service messages are handled by a default local // user. If this MIHF is the destination of the message, check for a // pending transaction and forward the message. // bool command_service::generic_command_response(const char *recv_msg, const char *send_msg, meta_message_ptr &in, meta_message_ptr &out) { log(1, recv_msg, in->source().to_string()); if(utils::this_mihf_is_destination(in)) { // // Kick this message to default MIH User as an indication // log(1, send_msg); in->opcode(mih::operation::confirm); in->destination(mih::id("user")); // // source identifier is the remote MIHF // _transmit(in); return false; } else { utils::forward_request(in, _lpool, _transmit); return false; } }
/** * Check if there's a handler for this message and call it, else * discard message. * * @param in The input message. * @param out The output message. */ bool sac_process_message(meta_message_ptr& in, meta_message_ptr& out) { // discard messages that this MIHF broadcasted to itself // discard messages that are not destined to this MIHF or if // multicast messages are not supported if(in->source() == mihfid) { ODTONE_LOG(1, "(sac) Discarding message! Reason: ", "message was broadcasted to itself"); return false; } if(!utils::this_mihf_is_destination(in) && !utils::is_multicast(in)) { ODTONE_LOG(1, "(sac) Discarding message! Reason: ", "this is not the message destination"); return false; } /** __no__ authentication at this point */ uint mid = in->mid(); // // no thread safety because insertion should __only__ be made // on MIHF initialization // std::map<uint, handler_t>::iterator it; it = _callbacks.find(mid); if(it != _callbacks.end()) { handler_t process_message = it->second; bool rsp; try { rsp = process_message(in, out); } catch(mih::bad_tlv) { ODTONE_LOG(1, "Discarding malformed message."); return false; } // set ip and port of response message out->ip(in->ip()); out->scope(in->scope()); out->port(in->port()); // response message must have the same tid out->tid(in->tid()); return rsp; } else { ODTONE_LOG(1, "(sac) (warning) message with mid: ", mid, " unknown, discarding."); } return false; }
/** * Piggyback local MIHF Capabilities in request message. * * @param in input message. * @param out output message. */ void service_management::piggyback_capabilities(meta_message_ptr& in, meta_message_ptr& out) { // Get local capabilities address_entry mihf_cap = _abook.get(mihfid_t::instance()->to_string()); *out << mih::request(mih::request::capability_discover) & mih::tlv_net_type_addr_list(mihf_cap.capabilities_list_net_type_addr) & mih::tlv_event_list(mihf_cap.capabilities_event_list) & mih::tlv_command_list(mihf_cap.capabilities_cmd_list) & mih::tlv_query_type_list(mihf_cap.capabilities_query_type) & mih::tlv_transport_option_list(mihf_cap.capabilities_trans_list) & mih::tlv_mbb_ho_supp_list(mihf_cap.capabilities_mbb_ho_supp); out->tid(in->tid()); out->source(in->source()); out->destination(in->destination()); }
// log received message type, and forward it bool event_service::link_down_indication(meta_message_ptr &in, meta_message_ptr&) { // if(in->payload().size() == 0) // return false; log(1, "(mies) received Link_Down.indication from ", in->source().to_string()); link_event_forward(in, mih::link_down); return false; }
// Check if there's a pending transaction and forward the message in // case there is. bool command_service::link_actions_response(meta_message_ptr &in, meta_message_ptr &out) { log(1, "(mics) received Link_Actions.response from ", in->source().to_string()); if(!_lpool.set_user_tid(in)) { log(1, "(mics) no local pending transaction for this message, discarding"); return false; } in->source(mihfid); log(1, "(mics) forwarding Link_Actions.response to ", in->destination().to_string()); _transmit(in); return false; }
// Check if there's a pending transaction and forward the message in // case there is. bool command_service::link_configure_thresholds_response(meta_message_ptr &in, meta_message_ptr &out) { log(1, "(mics) received Link_Configure_Thresholds.response from ", in->source().to_string()); if(!_lpool.set_user_tid(in)) { log(1, "(mics) warning: no local transaction for this msg ", "discarding it"); return false; } in->source(mihfid); log(1, "(mics) forwarding Link_Configure_Thresholds.response to ", in->destination().to_string()); _transmit(in); return false; }
bool event_service::link_pdu_transmit_status_indication(meta_message_ptr &in, meta_message_ptr&) { // if(in->payload().size() == 0) // return false; log(1, "(mies) received Link_PDU_Transmit_Status.indication from ", in->source().to_string()); link_event_forward(in, mih::link_pdu_transmit_status); return false; }
// This MIHF is the destination of the Event_Unsubscribe.request. // Deserialize message, unsubscribe user and send a response bool event_service::local_event_unsubscribe_request(meta_message_ptr &in, meta_message_ptr &out) { mih::status st; mih::link_tuple_id link; mih::event_list events; *in >> mih::request(mih::request::event_unsubscribe) & mih::tlv_link_identifier(link) & mih::tlv_event_list(events); st = unsubscribe(in->source(), link, events); *out << mih::response(mih::response::event_unsubscribe) & mih::tlv_status(st) & mih::tlv_link_identifier(link) & mih::tlv_event_list(events); out->tid(in->tid()); out->destination(in->source()); return true; }
// Check if this MIHF is the destination of the message or if it needs // to forward the message to a peer MIHF. bool event_service::event_subscribe_request(meta_message_ptr &in, meta_message_ptr &out) { log(1, "(mies) received Event_Subscribe.request from ", in->source().to_string()); if (utils::this_mihf_is_destination(in)) { return local_event_subscribe_request(in, out); } else { utils::forward_request(in, _lpool, _transmit); return false; } return false; }
// send message for all users subscribed to event from link identifier void event_service::msg_forward(meta_message_ptr &msg, mih::link_tuple_id &li, mih::event_list_enum event) { std::list<event_registration_t>::iterator it; int i = 0; // for logging purposes msg->source(mihfid); for(it = _event_subscriptions.begin(); it != _event_subscriptions.end(); it++, i++) { if ((it->event == event) &&(it->link == li)) { log(3, i, " (mies) found registration of user: "******" for event type ", event); msg->destination(mih::id(it->user)); _transmit(msg); } } }
/** * Link Get Parameters Response message handler. * * @param in The input message. * @param out The output message. * @return True if the response is sent immediately or false otherwise. */ bool command_service::link_get_parameters_response(meta_message_ptr &in, meta_message_ptr &out) { ODTONE_LOG(1, "(mics) received Link_Get_Parameters.response from ", in->source().to_string()); if(!_lpool.set_user_tid(in)) { ODTONE_LOG(1, "(mics) warning: no local transaction for this msg ", "discarding it"); return false; } ODTONE_LOG(1, "(mics) forwarding Link_Get_Parameters.response to ", in->destination().to_string()); _transmit(in); return false; }
// A peer MIHF sent a Event_Unubscribe.response, check if we have a // pending transaction with a local user. If so, then remove the // subscription of the user to the link and events that came in the // response. bool event_service::event_unsubscribe_response(meta_message_ptr &in, meta_message_ptr &) { log(1, "(mies) received Event_Unsubscribe.response from ", in->source().to_string()); // do we have a request from a user? if (!_lpool.set_user_tid(in)) { log(1, "(mics) warning: no local transaction for this msg ", "discarding it"); return false; } mih::status st; mih::link_tuple_id link; mih::event_list events; mih::message pin; // parse incoming message to (event_registration_t) reg *in >> mih::response() & mih::tlv_status(st) & mih::tlv_link_identifier(link) & mih::tlv_event_list(events); // remove subscription if (st == mih::status_success) st = unsubscribe(mih::id(in->destination().to_string()), link, events); log(1, "(mies) forwarding Event_Unsubscribe.response to ", in->destination().to_string()); // forward to user _transmit(in); return false; }
bool sac_process_message(meta_message_ptr& in, meta_message_ptr& out) { // discard messages that this MIHF broadcasted to itself if (in->source() == mihfid) return false; /** __no__ authentication at this point */ uint mid = in->mid(); // // no thread safety because insertion should __only__ be made // on MIHF initialization // std::map<uint, handler_t>::iterator it; it = _callbacks.find(mid); if(it != _callbacks.end()) { handler_t process_message = it->second; bool rsp = process_message(in, out); // set ip and port of response message out->ip(in->ip()); out->port(in->port()); // response message must have the same tid out->tid(in->tid()); return rsp; } else { log(1, "(sac) (warning) message with mid: ", mid, " unknown, discarding."); } return false; }
// parse link identifiers from list and for each one forward the // message to the subscribed users bool event_service::link_detected_indication(meta_message_ptr &in, meta_message_ptr &out) { // if(in->payload().size() == 0) // return false; log(1, "(mies) received Link_Detected.indication from ", in->source().to_string()); // link detected info from incoming message mih::link_det_info_list list_ids; // link detected info on outgoing message mih::link_det_info_list list_rsp; mih::link_det_info_list::iterator it; *in >> mih::response() & mih::tlv_link_det_info_list(list_ids); for(it = list_ids.begin(); it != list_ids.end(); it++) { // construct new link detected indication message // with just the link detected in the payload list_rsp.push_back(*it); *out << mih::indication(mih::indication::link_detected) & mih::tlv_link_det_info_list(list_rsp); // forward message to subscribed users msg_forward(out, it->id, mih::link_detected); list_rsp.clear(); // FIXME: clear out before continuing } return false; }
/** * Run Acknowledge Responder State Machine transaction. */ void ack_responder() { switch(ack_rsp_state) { case ACK_RSP_INIT: goto _rsp_init_lbl_; case ACK_RSP_RETURN_ACK: goto _rsp_return_ack_lbl_; case ACK_RSP_PIGGYBACKING: goto _rsp_piggybacking_lbl_; case ACK_RSP_RETURN_DUPLICATE: goto _rsp_return_duplicate_lbl_; } _rsp_init_lbl_: { ack->ackreq(false); ack->ackrsp(true); ack->opcode((mih::operation::type)opcode); ack->tid(tid); ack->mid(in->mid()); ack->source(my_mihf_id); ack->destination(peer_mihf_id); ack->ip(in->ip()); ack->port(in->port()); if (msg_out_avail) goto _rsp_piggybacking_lbl_; else { _netsap.send(ack); msg_in_avail = false; goto _rsp_return_ack_lbl_; } return; } _rsp_return_ack_lbl_: { ack_rsp_state = ACK_RSP_RETURN_ACK; if(msg_in_avail) { _netsap.send(ack); msg_in_avail = false; } else if (msg_out_avail) goto _rsp_piggybacking_lbl_; return; } _rsp_piggybacking_lbl_: { ack_rsp_state = ACK_RSP_PIGGYBACKING; out->ackrsp(true); dup = out; if (msg_in_avail) goto _rsp_return_duplicate_lbl_; return; } _rsp_return_duplicate_lbl_: { ack_rsp_state = ACK_RSP_RETURN_DUPLICATE; if (msg_in_avail) { _netsap.send(dup); msg_in_avail = false; } } }