/*
 * mms_sender_sates.def - states for MMS message receiver session state machines
 *
 * Macro calls to generate rows of the state table. See the documentation for
 * guidance how to use and update these.
 *
 * Note that `NULL' state is renamed to `NULL_SESSION' because NULL is
 * reserved by C.
 *
 * Marcel Jansen
 */

STATE_NAME(SEND_NULL_STATE)
STATE_NAME(SEND_BEARER_WAITING)
STATE_NAME(SEND_CONNECTING)
STATE_NAME(SEND_WAITING)
STATE_NAME(SEND_DELIVERY_WAITING)

ROW(SEND_NULL_STATE,
	MMS_Message_Request,
	/* no bearer */ ! checkInterface(interface),
	{
        startbearerservice();
        /* start timer to cope with bearer layer not responding */
        start_timerTO_A_bearer(sm->timer, sm->machine_id, default_bearerinit_delay);

        if (e->http_client != NULL) 
            /* synchronous request: start timer for the client request */
            start_timerTO_Http_Client(sm->timer, sm->machine_id, e->timeout);
	},
	SEND_BEARER_WAITING)

ROW(SEND_NULL_STATE,
	MMS_Message_Request,
	/* bearer */ checkInterface(interface) && /* use WSP */ wapIpAddress != NULL,
	{
        /* need to create an address tuple */
        sm->addrtuple = getRequestTuple(interface);

        /* send connect request */
        sendWSPConnectRequest(sm->addrtuple, sm->machine_id);
	},
	SEND_CONNECTING)

ROW(SEND_NULL_STATE,
	MMS_Message_Request,
	/* bearer */ checkInterface(interface) && /* use HTTP */ wapIpAddress == NULL,
	{
        sendHTTPMSendReq(sm);
	},
	SEND_WAITING)


ROW(SEND_BEARER_WAITING,
	Bearer_Event,
	/* use WSP */ wapIpAddress != NULL,
	{
        /* need to create an address tuple, might rely (for purpose of DNS) on
           bearer capacity */
        sm->addrtuple = getRequestTuple(interface);

        /* send connect request */
        sendWSPConnectRequest(sm->addrtuple, sm->machine_id);
	},
	SEND_CONNECTING)

ROW(SEND_BEARER_WAITING,
	Bearer_Event,
	/* use HTTP */ wapIpAddress == NULL,
	{
        sendHTTPMSendReq(sm);
	},
	SEND_WAITING)

ROW(SEND_BEARER_WAITING,
	TimerTO_A_bearer,
	1,
	{   
        long d;

        /* Make sure that any ongoing bearer service startups are
           cancelled */
        stopbearerservice();

        /* give the bearer service a bit longer to get going */
        d = e->delay;
        d = d * 2 < MAX_BEARER_DELAY ? d * 2 : MAX_BEARER_DELAY;
        
        /* TODO may need a delay here */
        startbearerservice();
        start_timerTO_A_bearer(sm->timer, sm->machine_id, d);
	},
	SEND_BEARER_WAITING)

ROW(SEND_BEARER_WAITING,
	TimerTO_Http_Client,
	1,
	{
        /* ran out of time */
        notifySendClient(sm->mms_send_req->u.MMS_Message_Request.http_client, NULL, NULL, NULL);
	},
	SEND_NULL_STATE)


ROW(SEND_CONNECTING,
	S_Connect_Cnf,
	1,
	{
        sendWSPMSendReq(sm);
	},
	SEND_WAITING)

ROW(SEND_CONNECTING,
	S_Disconnect_Ind,
	/* no bearer */ ! checkInterface(interface),
	{
        startbearerservice();
        start_timerTO_A_bearer(sm->timer, sm->machine_id, default_bearerinit_delay);
	},
	SEND_BEARER_WAITING)

ROW(SEND_CONNECTING,
	S_Disconnect_Ind,
	/* bearer */ checkInterface(interface),
	{
        if (sm->addrtuple == NULL)
            sm->addrtuple = getRequestTuple(interface);

        /* send connect request */
        sendWSPConnectRequest(sm->addrtuple, sm->machine_id);
	},
	SEND_CONNECTING)

ROW(SEND_CONNECTING,
	Bearer_Lost_Event,
	1,
	{
        startbearerservice();
        start_timerTO_A_bearer(sm->timer, sm->machine_id, default_bearerinit_delay);
	},
	SEND_BEARER_WAITING)

ROW(SEND_CONNECTING,
	TimerTO_Http_Client,
	1,
	{
        /* ran out of time */
        notifySendClient(sm->mms_send_req->u.MMS_Message_Request.http_client, NULL, NULL, NULL);
        sendWSPDisconnectRequest(sm->machine_id);
	},
	SEND_NULL_STATE)



ROW(SEND_WAITING,
	S_Disconnect_Ind,
	/* no bearer */ ! checkInterface(interface),
	{
        startbearerservice();
        start_timerTO_A_bearer(sm->timer, sm->machine_id, default_bearerinit_delay);
	},
	SEND_BEARER_WAITING)

ROW(SEND_WAITING,
	S_Disconnect_Ind,
	/* bearer */ checkInterface(interface),
	{
        if (sm->addrtuple == NULL)
            sm->addrtuple = getRequestTuple(interface);

        /* send connect request */
        sendWSPConnectRequest(sm->addrtuple, sm->machine_id);
	},
	SEND_CONNECTING)

ROW(SEND_WAITING,
	S_MethodInvoke_Cnf,
	1,
	{
        /* ignore */
	},
	SEND_WAITING)

ROW(SEND_WAITING,
	S_MethodResult_Ind,
	pdu->type == SendConf && sm->mms_send_req->u.MMS_Message_Request.delivery_report == MMS_TRUE_TOKEN /* delivery report requested */,
	{
        sm->sendconf = pdu;
        notifySendClient(sm->mms_send_req->u.MMS_Message_Request.http_client, sm->mms_send_req->u.MMS_Message_Request.response_url, pdu, sm);
        sendWSPDisconnectRequest(sm->machine_id);
	},
	SEND_DELIVERY_WAITING)

ROW(SEND_WAITING,
	S_MethodResult_Ind,
	pdu->type == SendConf && sm->mms_send_req->u.MMS_Message_Request.delivery_report != MMS_TRUE_TOKEN /* delivery report not requested */,
	{
        sm->sendconf = pdu;
        notifySendClient(sm->mms_send_req->u.MMS_Message_Request.http_client, sm->mms_send_req->u.MMS_Message_Request.response_url, pdu, sm);
        sendWSPDisconnectRequest(sm->machine_id);
	},
	SEND_NULL_STATE)

ROW(SEND_WAITING,
	HTTP_Request_Completed_Event,
	http_status_class(e->status) == HTTP_STATUS_SUCCESSFUL && pdu->type == SendConf && sm->mms_send_req->u.MMS_Message_Request.delivery_report == MMS_TRUE_TOKEN /* delivery report requested */,
	{
        sm->sendconf = pdu;
        notifySendClient(sm->mms_send_req->u.MMS_Message_Request.http_client, sm->mms_send_req->u.MMS_Message_Request.response_url, pdu, sm);
	},
	SEND_DELIVERY_WAITING)

ROW(SEND_WAITING,
	HTTP_Request_Completed_Event,
	http_status_class(e->status) == HTTP_STATUS_SUCCESSFUL && pdu->type == SendConf && sm->mms_send_req->u.MMS_Message_Request.delivery_report != MMS_TRUE_TOKEN /* delivery report not requested */,
	{
        sm->sendconf = pdu;
        notifySendClient(sm->mms_send_req->u.MMS_Message_Request.http_client, sm->mms_send_req->u.MMS_Message_Request.response_url, pdu, sm);
	},
	SEND_NULL_STATE)

ROW(SEND_WAITING,
	S_MethodAbort_Ind,
	1,
	{
        /* method aborted, try again */
        sendWSPMSendReq(sm);
	},
	SEND_WAITING)

ROW(SEND_WAITING,
	HTTP_Request_Completed_Event,
	http_status_class(e->status) != HTTP_STATUS_SUCCESSFUL,
	{
        /* try again */
        sendHTTPMSendReq(sm);
	},
	SEND_WAITING)

ROW(SEND_WAITING,
	Bearer_Lost_Event,
	1,
	{
        startbearerservice();
        start_timerTO_A_bearer(sm->timer, sm->machine_id, default_bearerinit_delay);
	},
	SEND_BEARER_WAITING)

ROW(SEND_WAITING,
	TimerTO_Http_Client,
	1,
	{
        /* ran out of time */
        sendWSPMethodAbort(sm->transaction_id, sm->machine_id);
        notifySendClient(sm->mms_send_req->u.MMS_Message_Request.http_client, NULL, NULL, NULL);
        sendWSPDisconnectRequest(sm->machine_id);
	},
	SEND_NULL_STATE)


ROW(SEND_DELIVERY_WAITING,
	S_Push_Ind,
	pdu->type = DeliveryInd,
	{
        notifySendClientDeliveryReport();
	},
	NULL_STATE)



#undef ROW
#undef STATE_NAME



