Beispiel #1
0
/**
 * 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);
		}
        }
}
Beispiel #2
0
	/**
	 * 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;
			}
		}
Beispiel #3
0
	/**
	 * 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;
				}
			}
		}