void Casan::send_discover (Msg &out) { char tmpstr [CASAN_BUF_LEN] ; l2addr *dest ; DBGLN1 (F ("Sending Discover")) ; out.reset () ; out.set_id (curid_++) ; out.set_type (COAP_TYPE_NON) ; out.set_code (COAP_CODE_POST) ; mk_ctl_msg (out) ; snprintf (tmpstr, sizeof tmpstr, CASAN_DISCOVER_SLAVEID, slaveid_) ; option o1 (option::MO_Uri_Query, tmpstr, strlen (tmpstr)) ; out.push_option (o1) ; snprintf (tmpstr, sizeof tmpstr, CASAN_DISCOVER_MTU, (long int) defmtu_) ; option o2 (option::MO_Uri_Query, tmpstr, strlen (tmpstr)) ; out.push_option (o2) ; dest = (master_ != NULL) ? master_ : l2_->bcastaddr () ; out.send (*dest) ; }
void Casan::check_observed_resources (Msg &out) { Resource *res ; reslist *rl ; for (rl = reslist_ ; rl != NULL ; rl = rl->next) { res = rl->res ; if (res->check_trigger ()) { DBG1 (F (B_BLUE "Observed resource '")) ; DBG1 (rl->res->name ()) ; DBG1 (F ("' triggered" C_RESET)) ; DBGLN0 () ; out.reset () ; out.set_type (COAP_TYPE_ACK) ; out.set_token (res->get_token ()) ; out.set_id (curid_++) ; out.set_code (COAP_CODE_OK) ; option obs (option::MO_Observe, res->next_serial ()) ; out.push_option (obs) ; request_resource (NULL, &out, res) ; out.send (*master_) ; } } }
void Casan::send_assoc_answer (Msg &in, Msg &out) { l2addr *dest ; dest = l2_->get_src () ; // send back an acknowledgement message out.set_type (COAP_TYPE_ACK) ; out.set_code (COAP_CODE_OK) ; out.set_id (in.get_id ()) ; // will get the resources and set them in the payload in the right format (void) get_well_known (out) ; // send the packet if (! out.send (*dest)) DBGLN1 (F (RED ("Cannot send the assoc answer message"))) ; delete dest ; }
void Casan::loop () { Msg in (l2_) ; Msg out (l2_) ; l2net::l2_recv_t ret ; uint8_t oldstatus ; long int hlid ; l2addr *srcaddr ; int mtu ; // mtu announced by master in assoc msg oldstatus = status_ ; // keep old value for debug display sync_time (curtime) ; // get current time retrans_.loop (*l2_, curtime) ; // check needed retransmissions srcaddr = NULL ; ret = in.recv () ; // get received message if (ret == l2net::RECV_OK) srcaddr = l2_->get_src () ; // get a new address switch (status_) { case SL_COLDSTART : send_discover (out) ; twait_.init (curtime) ; status_ = SL_WAITING_UNKNOWN ; break ; case SL_WAITING_UNKNOWN : if (ret == l2net::RECV_OK) { retrans_.check_msg_received (in) ; if (is_ctl_msg (in)) { if (is_hello (in, hlid)) { DBGLN1 (F ("Received a CTL HELLO msg")) ; change_master (hlid, -1) ; // don't change mtu twait_.init (curtime) ; status_ = SL_WAITING_KNOWN ; } else if (is_assoc (in, sttl_, mtu)) { DBGLN1 (F ("Received a CTL ASSOC msg")) ; change_master (-1, mtu) ; // "unknown" hlid send_assoc_answer (in, out) ; trenew_.init (curtime, sttl_) ; status_ = SL_RUNNING ; } else DBGLN1 (F (RED ("Unkwnon CTL"))) ; } } if (status_ == SL_WAITING_UNKNOWN && twait_.next (curtime)) send_discover (out) ; break ; case SL_WAITING_KNOWN : if (ret == l2net::RECV_OK) { retrans_.check_msg_received (in) ; if (is_ctl_msg (in)) { if (is_hello (in, hlid)) { DBGLN1 (F ("Received a CTL HELLO msg")) ; change_master (hlid, -1) ; // don't change mtu } else if (is_assoc (in, sttl_, mtu)) { DBGLN1 (F ("Received a CTL ASSOC msg")) ; change_master (-1, mtu) ; // unknown hlid send_assoc_answer (in, out) ; trenew_.init (curtime, sttl_) ; status_ = SL_RUNNING ; } else DBGLN1 (F (RED ("Unkwnon CTL"))) ; } } if (status_ == SL_WAITING_KNOWN) { if (twait_.expired (curtime)) { reset_master () ; // master_ is no longer known send_discover (out) ; twait_.init (curtime) ; // reset timer status_ = SL_WAITING_UNKNOWN ; } else if (twait_.next (curtime)) { send_discover (out) ; } } break ; case SL_RUNNING : case SL_RENEW : if (ret == l2net::RECV_OK) { retrans_.check_msg_received (in) ; if (is_ctl_msg (in)) { if (is_hello (in, hlid)) { DBGLN1 (F ("Received a CTL HELLO msg")) ; if (! same_master (srcaddr) || hlid != hlid_) { int oldhlid = hlid_ ; change_master (hlid, 0) ; // reset mtu if (oldhlid != -1) { twait_.init (curtime) ; status_ = SL_WAITING_KNOWN ; } } } else if (is_assoc (in, sttl_, mtu)) { DBGLN1 (F ("Received a CTL ASSOC msg")) ; if (same_master (srcaddr)) { negociate_mtu (mtu) ; send_assoc_answer (in, out) ; trenew_.init (curtime, sttl_) ; status_ = SL_RUNNING ; } } else DBGLN1 (F (RED ("Unkwnon CTL"))) ; } else // request for a normal resource { // deduplicate () ; process_request (in, out) ; out.send (*master_) ; } } else if (ret == l2net::RECV_TRUNCATED) { DBGLN1 (F (RED ("Request too large"))) ; out.set_type (COAP_TYPE_ACK) ; out.set_id (in.get_id ()) ; out.set_token (in.get_token ()) ; option o (option::MO_Size1, l2_->mtu ()) ; out.push_option (o) ; out.set_code (COAP_CODE_TOO_LARGE) ; out.send (*master_) ; } check_observed_resources (out) ; if (status_ == SL_RUNNING && trenew_.renew (curtime)) { send_discover (out) ; status_ = SL_RENEW ; } if (status_ == SL_RENEW && trenew_.next (curtime)) { send_discover (out) ; } if (status_ == SL_RENEW && trenew_.expired (curtime)) { reset_master () ; // master_ is no longer known send_discover (out) ; twait_.init (curtime) ; // reset timer status_ = SL_WAITING_UNKNOWN ; } break ; default : DBGLN1 (F ("Error : casan status not known")) ; DBGLN1 (status_) ; break ; } if (oldstatus != status_) { DBG1 (F ("Status: " C_GREEN)) ; print_status (oldstatus) ; DBG1 (F (C_RESET " -> " C_GREEN)) ; print_status (status_) ; DBGLN1 (F (C_RESET)) ; } if (srcaddr != NULL) delete srcaddr ; }