/** * 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); } } }
/** * Run Acknowledge Requestor State Machine transaction. */ void ack_requestor() { switch (ack_req_state) { case ACK_REQ_INIT: goto _req_init_lbl_; case ACK_REQ_WAIT_ACK: goto _req_wait_ack_lbl_; case ACK_REQ_RETRANSMIT: goto _req_retransmit_lbl_; case ACK_REQ_SUCCESS: goto _req_success_lbl_; case ACK_REQ_FAILURE: goto _req_failure_lbl_; } _req_init_lbl_: { ack_requestor_status = ONGOING; rtxctr = 0; // unconditional transition to wait_ack } _req_wait_ack_begin_lbl_: { ack_req_state = ACK_REQ_WAIT_ACK; retransmission_when = 5; // FIXME } _req_wait_ack_lbl_: { if (retransmission_when == 0) { if (rtxctr < 2) goto _req_retransmit_lbl_; else goto _req_failure_lbl_; } if ((msg_in_avail && in->ackrsp())) goto _req_success_lbl_; return; } _req_retransmit_lbl_: { ack_req_state = ACK_REQ_RETRANSMIT; _netsap.send(out); rtxctr++; goto _req_wait_ack_begin_lbl_; } _req_failure_lbl_: { ack_req_state = ACK_REQ_FAILURE; ack_requestor_status = FAILURE; return; } _req_success_lbl_: { ack_req_state = ACK_REQ_SUCCESS; ack_requestor_status = SUCCESS; return; } }
/** * 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; } } }