/* Process model C form file: mcast_data_gen.pr.c */
/* Portions of this file copyright 1992, 1996 by MIL 3, Inc. */



/* OPNET system definitions */
#include <opnet.h>
#include "/u/class/cjin/pim_dm/mcast_data_gen.pr.h"
FSM_EXT_DECS



/* Header block */
#include "ip3_addr.h"
#include "oms_pr.h"
#include "debug.h"

#define SEND_PKT (op_intrpt_type() == OPC_INTRPT_SELF)
#define RECV_PKT (op_intrpt_type() == OPC_INTRPT_STRM)
 
static Ici *ip_encap_ici_ptr = OPC_NIL;
#if !defined (VOSD_NO_FIN)
#undef	BIN
#undef	BOUT
#define	BIN		_fstack_local_info.last_line_passed = __LINE__ - _block_origin;
#define	BOUT	BIN
#define	BINIT	_fstack_local_info.last_line_passed = 0; _block_origin = __LINE__;
#else
#define	BINIT
#endif /* #if !defined (VOSD_NO_FIN) */



/* State variable definitions */
typedef struct
	{
	FSM_SYS_STATE
	IpT_Address             		sv_mcast_addr;
	IpT_Address             		sv_src_addr;
	Objid                   		sv_own_mod_objid;
	Objid                   		sv_own_node_objid;
	Prohandle               		sv_own_prohandle;
	char                    		sv_proc_model_name[40];
	OmsT_Pr_Handle          		sv_own_process_record_handle;
	char                    		sv_mcast_group_for_sending[40];
	char                    		sv_sending_type[40];
	int	                    		sv_sending_interval;
	} mcast_data_gen_state;

#define pr_state_ptr            		((mcast_data_gen_state*) SimI_Mod_State_Ptr)
#define mcast_addr              		pr_state_ptr->sv_mcast_addr
#define src_addr                		pr_state_ptr->sv_src_addr
#define own_mod_objid           		pr_state_ptr->sv_own_mod_objid
#define own_node_objid          		pr_state_ptr->sv_own_node_objid
#define own_prohandle           		pr_state_ptr->sv_own_prohandle
#define proc_model_name         		pr_state_ptr->sv_proc_model_name
#define own_process_record_handle		pr_state_ptr->sv_own_process_record_handle
#define mcast_group_for_sending 		pr_state_ptr->sv_mcast_group_for_sending
#define sending_type            		pr_state_ptr->sv_sending_type
#define sending_interval        		pr_state_ptr->sv_sending_interval

/* This macro definition will define a local variable called	*/
/* "op_sv_ptr" in each function containing a FIN statement.	*/
/* This variable points to the state variable data structure,	*/
/* and can be used from a C debugger to display their values.	*/
#undef FIN_PREAMBLE
#define FIN_PREAMBLE	mcast_data_gen_state *op_sv_ptr = pr_state_ptr;




/* Process model interrupt handling procedure */



void
mcast_data_gen ()
	{
	Packet* pkptr;
	int _block_origin = 0;


	FSM_ENTER (mcast_data_gen)

	FSM_BLOCK_SWITCH
		{
		/*---------------------------------------------------------*/
		/** state (init) enter executives **/
		FSM_STATE_ENTER_UNFORCED (0, state0_enter_exec, "init", "mcast_data_gen () [init enter execs]")
			{
			/* create an ip_encap ici to be associated with a  */
			/* dummy packet                                    */
			if(ip_encap_ici_ptr == OPC_NIL)
			    ip_encap_ici_ptr = op_ici_create("ip3_encap_req");
			
			/* install the ici */
			op_ici_install(ip_encap_ici_ptr);
			
			/* process registry  */
			/* Obtain the mcast_gen module's objid. */
			own_mod_objid = op_id_self ();
			
			/* Obtain the node's objid. */
			own_node_objid = op_topo_parent (own_mod_objid);
			
			/* Obtain the mcast_gen's process's prohandle. */
			own_prohandle = op_pro_self ();
			
			/* Obtain the name of the process. It is the "process model" attribute of the node. */
			op_ima_obj_attr_get (own_mod_objid, "process model", proc_model_name);
			
			/* Register the process in the model-wide registry. */
			own_process_record_handle = (OmsT_Pr_Handle) oms_pr_process_register (own_node_objid, own_mod_objid, 
										own_prohandle, proc_model_name);
			
			/* Register the protocol attribute in the registry. */
			oms_pr_attr_set (own_process_record_handle, "protocol", OMSC_PR_STRING, "mcast_gen", OPC_NIL);
			
			/* Get attributes set by testing */
			op_ima_obj_attr_get (own_mod_objid, "Mcast Group For Sending", &mcast_group_for_sending);
			op_ima_obj_attr_get (own_mod_objid, "Sending Type", &sending_type);
			op_ima_obj_attr_get (own_mod_objid, "Sending Interval", &sending_interval);
			
			/* Set a dest addr for testing */
			mcast_addr = ip_address_create ( mcast_group_for_sending );
			op_ici_attr_set (ip_encap_ici_ptr, "dest_addr", mcast_addr); 
			
			op_intrpt_schedule_self(op_sim_time(), 0);
			
			
			
			}


		/** blocking after enter executives of unforced state. **/
		FSM_EXIT (1,mcast_data_gen)


		/** state (init) exit executives **/
		FSM_STATE_EXIT_UNFORCED (0, state0_exit_exec, "init", "mcast_data_gen () [init exit execs]")
			{
			}


		/** state (init) transition processing **/
		FSM_TRANSIT_FORCE (2, state2_enter_exec, ;)
		/*---------------------------------------------------------*/



		/** state (send_pkt) enter executives **/
		FSM_STATE_ENTER_FORCED (1, state1_enter_exec, "send_pkt", "mcast_data_gen () [send_pkt enter execs]")
			{
			
			/* send the mcast packet with dummy data field*/
			pkptr = op_pk_create_fmt("mcast_pkt");
			op_pk_send(pkptr, 0);
			
			if(DEBUG)
			  printf("\n\nMCAST_GEN: PKT SENT");
			 
			}


		/** state (send_pkt) exit executives **/
		FSM_STATE_EXIT_FORCED (1, state1_exit_exec, "send_pkt", "mcast_data_gen () [send_pkt exit execs]")
			{
			}


		/** state (send_pkt) transition processing **/
		FSM_TRANSIT_FORCE (2, state2_enter_exec, ;)
		/*---------------------------------------------------------*/



		/** state (idle) enter executives **/
		FSM_STATE_ENTER_UNFORCED (2, state2_enter_exec, "idle", "mcast_data_gen () [idle enter execs]")
			{
			
			/* send packets every 5 seconds */ 
			op_intrpt_schedule_self(op_sim_time()+
				op_dist_outcome(op_dist_load( sending_type, 1, sending_interval)), 0);
			 
			}


		/** blocking after enter executives of unforced state. **/
		FSM_EXIT (5,mcast_data_gen)


		/** state (idle) exit executives **/
		FSM_STATE_EXIT_UNFORCED (2, state2_exit_exec, "idle", "mcast_data_gen () [idle exit execs]")
			{
			}


		/** state (idle) transition processing **/
		FSM_INIT_COND (SEND_PKT)
		FSM_TEST_COND (RECV_PKT)
		FSM_TEST_LOGIC ("idle")

		FSM_TRANSIT_SWITCH
			{
			FSM_CASE_TRANSIT (0, 1, state1_enter_exec, ;)
			FSM_CASE_TRANSIT (1, 3, state3_enter_exec, ;)
			}
		/*---------------------------------------------------------*/



		/** state (recv_pkt) enter executives **/
		FSM_STATE_ENTER_FORCED (3, state3_enter_exec, "recv_pkt", "mcast_data_gen () [recv_pkt enter execs]")
			{
			
			}


		/** state (recv_pkt) exit executives **/
		FSM_STATE_EXIT_FORCED (3, state3_exit_exec, "recv_pkt", "mcast_data_gen () [recv_pkt exit execs]")
			{
			}


		/** state (recv_pkt) transition processing **/
		FSM_TRANSIT_FORCE (2, state2_enter_exec, ;)
		/*---------------------------------------------------------*/



		}


	FSM_EXIT (0,mcast_data_gen)
	}




void
mcast_data_gen_svar (prs_ptr,var_name,var_p_ptr)
	mcast_data_gen_state		*prs_ptr;
	char			*var_name, **var_p_ptr;
	{

	FIN (mcast_data_gen_svar (prs_ptr))

	*var_p_ptr = VOS_NIL;
	if (Vos_String_Equal ("mcast_addr" , var_name))
		*var_p_ptr = (char *) (&prs_ptr->sv_mcast_addr);
	if (Vos_String_Equal ("src_addr" , var_name))
		*var_p_ptr = (char *) (&prs_ptr->sv_src_addr);
	if (Vos_String_Equal ("own_mod_objid" , var_name))
		*var_p_ptr = (char *) (&prs_ptr->sv_own_mod_objid);
	if (Vos_String_Equal ("own_node_objid" , var_name))
		*var_p_ptr = (char *) (&prs_ptr->sv_own_node_objid);
	if (Vos_String_Equal ("own_prohandle" , var_name))
		*var_p_ptr = (char *) (&prs_ptr->sv_own_prohandle);
	if (Vos_String_Equal ("proc_model_name" , var_name))
		*var_p_ptr = (char *) (prs_ptr->sv_proc_model_name);
	if (Vos_String_Equal ("own_process_record_handle" , var_name))
		*var_p_ptr = (char *) (&prs_ptr->sv_own_process_record_handle);
	if (Vos_String_Equal ("mcast_group_for_sending" , var_name))
		*var_p_ptr = (char *) (prs_ptr->sv_mcast_group_for_sending);
	if (Vos_String_Equal ("sending_type" , var_name))
		*var_p_ptr = (char *) (prs_ptr->sv_sending_type);
	if (Vos_String_Equal ("sending_interval" , var_name))
		*var_p_ptr = (char *) (&prs_ptr->sv_sending_interval);

	FOUT;
	}




void
mcast_data_gen_diag ()
	{
	Packet* pkptr;
	int _block_origin;

	FIN (mcast_data_gen_diag ())

	BINIT

	FOUT;
	}




void
mcast_data_gen_terminate ()
	{
	Packet* pkptr;
	int _block_origin;

	FIN (mcast_data_gen_terminate ())

	BINIT

	FOUT;
	}



Compcode
mcast_data_gen_init (pr_state_pptr)
	mcast_data_gen_state			**pr_state_pptr;
	{
	int _block_origin = 0;
	static VosT_Cm_Obtype	obtype = OPC_NIL;

	extern int				Vos_Nop ();

	FIN (mcast_data_gen_init (pr_state_pptr))

	if (obtype == OPC_NIL)
		{
		if (Vos_Catmem_Register ("proc state vars (mcast_data_gen)",
			sizeof (mcast_data_gen_state), Vos_Nop, &obtype) == VOSC_FAILURE)
			FRET (OPC_COMPCODE_FAILURE)
		}

	if ((*pr_state_pptr = (mcast_data_gen_state*) Vos_Catmem_Alloc (obtype, 1)) == OPC_NIL)
		FRET (OPC_COMPCODE_FAILURE)
	else
		{
		(*pr_state_pptr)->current_block = 0;
		FRET (OPC_COMPCODE_SUCCESS)
		}
	}



enum { _block_origin = __LINE__ };
