void master_act(master_t *m, const pr_signature_t *packet, int fd, const struct sockaddr_in *remote_addr) { const pr_response_t *response; const pr_vote_t *vote; avl_tree_node_t *updated_slave; uint32_t slave_addr; slave_description_t sd; uint8_t brightness; bool avg_changed = false; LOG(LOG_LEVEL_DEBUG, "Master acting for signature: %#02x, from: %s\n", (int)packet->s, inet_ntoa(remote_addr->sin_addr)); switch (packet->s) { case PR_RESPONSE: /* parse */ response = (const pr_response_t *)(packet + 1); slave_addr = ntohl(remote_addr->sin_addr.s_addr); sd.illumination = response->illumination; sd.temperature = response->temperature; /* update slave, calculate averages, send new info msg if need to */ updated_slave = master_update_slave(m, slave_addr, &sd); avg_changed = master_calculate_averages(m); if (!avg_changed) break; brightness = master_calculate_brightenss(m); send_info_message(m, brightness, fd); break; case PR_VOTE: /* send master reset packet */ vote = (const pr_vote_t *)(vote + 1); reset_master(m); break; default: /* do nothing if the packet is neither response nor vote */ break; } }
void Casan::reset (void) { status_ = SL_COLDSTART ; curid_ = 1 ; // remove resources from the list while (reslist_ != NULL) { reslist *r ; r = reslist_->next ; delete reslist_ ; reslist_ = r ; } retrans_.reset () ; reset_master () ; }
Casan::Casan (l2net *l2, int mtu, long int slaveid) { memset (this, 0, sizeof *this) ; l2_ = l2 ; slaveid_ = slaveid ; curtime = 0 ; // global variable sync_time (curtime) ; defmtu_ = l2->mtu () ; // get default L2 MTU if (mtu > 0 && mtu < defmtu_) defmtu_ = mtu ; // set a different default MTU reset_master () ; // master_ is reset (broadcast addr, mtu) hlid_ = -1 ; curid_ = 1 ; retrans_.master (&master_) ; status_ = SL_COLDSTART ; }
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 ; }