/***********************************************************************
 *                                                                     *
 * Filename: openb.c                                                   *
 * Module:   H245 Finite State Machine Subsystem                       *
 *                                                                     *
 ***********************************************************************
 *  INTEL Corporation Proprietary Information                          *
 *                                                                     *
 *  This listing is supplied under the terms of a license agreement    *
 *  with INTEL Corporation and may not be copied nor disclosed except  *
 *  in accordance with the terms of that agreement.                    *
 *                                                                     *
 *      Copyright (c) 1996 Intel Corporation. All rights reserved.     *
 ***********************************************************************
 *                                                                     *
 * $Workfile:   openb.c  $
 * $Revision:   1.5  $
 * $Modtime:   09 Dec 1996 18:05:30  $
 * $Log L:\mphone\h245\h245env\comm\h245_3\h245_fsm\vcs\src\openb.c_v $
 *                                                                     *
 ***********************************************************************/

#include "precomp.h"

#include "h245api.h"
#include "h245com.h"
#include "h245fsm.h"
#include "openb.h"
#include "pdu.x"



// Open Bi-directional Logical Channel Out-going states
#define OpenOutBReleased                 0
#define OpenOutBAwaitingEstablishment    1
#define OpenOutBEstablished              2
#define OpenOutBAwaitingRelease          3

// Open Bi-directional Logical Channel In-coming states
#define OpenInBReleased                  0
#define OpenInBAwaitingEstablishment     1
#define OpenInBAwaitingConfirmation      2
#define OpenInBEstablished               3



extern unsigned int uT103;

/***********************************************************************
 *
 * LOCAL FUNCTIONS
 *
 ***********************************************************************/

/*
 *  NAME
 *      T103OutExpiryF - Callback function called by the timer.
 *      T103InExpiryF  - Callback function called by the timer.
 *
 *
 *  PARAMETERS
 *   INPUT   dwInst     current instance of H245
 *   INPUT   id         timer id
 *   INPUT   obj        pointer to a FSM object
 *
 *
 *  RETURN VALUE
 *       OK
 */

int T103OutExpiryF(struct InstanceStruct *pInstance, DWORD_PTR dwTimerId, void *pObject)
{
    return FsmTimerEvent(pInstance, dwTimerId, pObject, T103OutExpiry);
} // T103OutExpiryF()

int T103InExpiryF(struct InstanceStruct *pInstance, DWORD_PTR dwTimerId, void *pObject)
{
    return FsmTimerEvent(pInstance, dwTimerId, pObject, T103InExpiry);
} // T103InExpiryF()



/***********************************************************************
 *
 * OUT-GOING FINITE STATE MACHINE FUNCTIONS
 *
 ***********************************************************************/

/*
 *  NAME
 *      establishReqBReleased - API request to open bidirectional channel in idle state
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT establishReqBReleased(Object_t *pObject, PDU_t *pPdu)
{
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_OUT);
    ASSERT(pObject->State == OpenOutBReleased);
    H245TRACE(pObject->dwInst, 2,
              "Sending open Bidirectional channel to ASN; Channel=%d",
              pObject->Key);

    /* Send Open Logical Channel to remote peer */
    lError = sendPDU(pObject->pInstance, pPdu);

    /* set timer T103 */
    pObject->State = OpenOutBAwaitingEstablishment;
    FsmStartTimer(pObject, T103OutExpiryF, uT103);

    return lError;
}



/*
 *  NAME
 *      openChannelAckBAwaitingE - received open bidirectional channel Ack in Awaiting Establishment state
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT openChannelAckBAwaitingE(Object_t *pObject, PDU_t *pPdu)
{
    PDU_t *             pOut;
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_OUT);
    ASSERT(pObject->State == OpenOutBAwaitingEstablishment);
    H245TRACE(pObject->dwInst, 2,
              "H245_CONF_NEEDRSP_OPEN with no error to API; Channel=%d",
              pObject->Key);

    /* reset timer T103 */
    FsmStopTimer(pObject);

    /* Send ESTABLISH.confirm to client */
    pObject->State = OpenOutBEstablished;
    H245FsmConfirm(pPdu,H245_CONF_NEEDRSP_OPEN, pObject->pInstance, pObject->dwTransId, FSM_OK);

    /* Send Open Logical Channel Confirm to remote peer */
    pOut = (PDU_t *) MemAlloc(sizeof(PDU_t ));
    if (pOut == NULL)
    {
        H245TRACE(pObject->dwInst, 1,
                  "openChannelAckBAwaitingE: memory allocation failed");
        return H245_ERROR_NOMEM;
    }
    pdu_ind_open_logical_channel_conf(pOut, (WORD)pObject->Key);
    lError = sendPDU(pObject->pInstance, pOut);
    MemFree(pOut);
    return lError;
}



/*
 *  NAME
 *      openChannelRejBAwaitingE - received open bidirectional channel reject in Awaiting Establishment state
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT openChannelRejBAwaitingE(Object_t *pObject, PDU_t *pPdu)
{
    ASSERT(pObject->Entity == BLCSE_OUT);
    ASSERT(pObject->State == OpenOutBAwaitingEstablishment);
    H245TRACE(pObject->dwInst, 2,
              "H245_CONF_NEEDRSP_OPEN with REJECT to API; Channel=%d",
              pObject->Key);

    /* reset  timer T103 */
    FsmStopTimer(pObject);

    /* Send RELEASE.indication to client */
    pObject->State = OpenOutBReleased;
    H245FsmConfirm(pPdu, H245_CONF_NEEDRSP_OPEN, pObject->pInstance, pObject->dwTransId, REJECT);

    return 0;
}



/*
 *  NAME
 *      releaseReqBOutAwaitingE - API request to close bidirectional channel in Awaiting Establishment state
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT releaseReqBOutAwaitingE(Object_t *pObject, PDU_t *pPdu)
{
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_OUT);
    ASSERT(pObject->State == OpenOutBAwaitingEstablishment);
    H245TRACE(pObject->dwInst, 2,
              "Close (Bidirectional) to ASN; Channel=%d",
              pObject->Key);

    /* reset timer T103 */
    FsmStopTimer(pObject);

    /* Send Close Logical Channel to remote peer */
    lError = sendPDU(pObject->pInstance,pPdu);

    /* set timer T103 */
    pObject->State = OpenOutBAwaitingRelease;
    FsmStartTimer(pObject, T103OutExpiryF, uT103);

    return lError;
}



/*
 *  NAME
 *      t103ExpiryBAwaitingE - handle timeout for  outstanding  open bidirectional pdu
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT t103ExpiryBAwaitingE(Object_t *pObject, PDU_t *pPdu)
{
    PDU_t *             pOut;
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_OUT);
    ASSERT(pObject->State == OpenOutBAwaitingEstablishment);
    ASSERT(pPdu == NULL);
    H245TRACE(pObject->dwInst, 2, "H245_CONF_NEEDRSP_OPEN  with a timer expiry to API->Channel=%d", pObject->Key);

    /* Send ERROR.indication(D) to client */
    pObject->State = OpenOutBReleased;
    H245FsmConfirm(NULL, H245_CONF_NEEDRSP_OPEN, pObject->pInstance, pObject->dwTransId, ERROR_D_TIMEOUT);

    /* Send Close Logical Channel (source:=lcse) to remote peer */
    pOut = (PDU_t *) MemAlloc(sizeof(PDU_t ));
    if (pOut == NULL)
    {
        H245TRACE(pObject->dwInst, 1,
                  "t103ExpiryBAwaitingE: memory allocation failed");
        return H245_ERROR_NOMEM;
    }
    pdu_req_close_logical_channel(pOut, (WORD)pObject->Key, 1);
    lError = sendPDU(pObject->pInstance, pOut);
    MemFree(pOut);

#if defined(SDL_COMPLIANT)
    /* Send RELEASE.indication to client */
    H245FsmIndication(pPdu, H245_IND_CLOSE, pObject->pInstance, 0, FSM_OK);
#endif

    return lError;
}

/*
 *  NAME
 *      releaseReqBEstablished - API request to close channel in established state
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT releaseReqBEstablished(Object_t *pObject, PDU_t *pPdu)
{
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_OUT);
    ASSERT(pObject->State == OpenOutBEstablished);
    H245TRACE(pObject->dwInst, 2,
              "Send Close Bidirectional Channel to ASN; Channel=%d",
              pObject->Key);

    /* Send Close Logical Channel to remote peer */
    lError = sendPDU(pObject->pInstance,pPdu);

    /* set timer T103 */
    pObject->State = OpenOutBAwaitingRelease;
    FsmStartTimer(pObject, T103OutExpiryF, uT103);

    return lError;
}



/*
 *  NAME
 *      openChannelRejBEstablished - received open reject in established state
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT openChannelRejBEstablished(Object_t *pObject, PDU_t *pPdu)
{
    ASSERT(pObject->Entity == BLCSE_OUT);
    ASSERT(pObject->State == OpenOutBEstablished);
    H245TRACE(pObject->dwInst, 2, "H245_CONF_NEEDRSP_OPEN with error B then with REJECT to API->Channel=%d", pObject->Key);

    pObject->State = OpenOutBReleased;

#if defined(SDL_COMPLIANT)
    /* Send ERROR.indication(B) to client */
    H245FsmConfirm(pPdu, H245_CONF_NEEDRSP_OPEN, pObject->pInstance, pObject->dwTransId, ERROR_B_INAPPROPRIATE);
#endif

    /* Send RELEASE.indication (SOURCE:=B-LCSE) to client */
    H245FsmConfirm(pPdu, H245_CONF_NEEDRSP_OPEN, pObject->pInstance, pObject->dwTransId, REJECT);

    return 0;
}



/*
 *  NAME
 *      closeChannelAckBEstablished - received close ack in established state
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT closeChannelAckBEstablished(Object_t *pObject, PDU_t *pPdu)
{
    ASSERT(pObject->Entity == BLCSE_OUT);
    ASSERT(pObject->State == OpenOutBEstablished);
    H245TRACE(pObject->dwInst, 2,
              "H245_CONF_NEEDRSP_OPEN with error C then with REJECT to API; Channel=%d",
              pObject->Key);

    pObject->State = OpenOutBReleased;

#if defined(SDL_COMPLIANT)
    /* Send ERROR.indication(C) to client */
    H245FsmConfirm(pPdu, H245_CONF_NEEDRSP_OPEN, pObject->pInstance, pObject->dwTransId, ERROR_C_INAPPROPRIATE);
#endif

    /* Send RELEASE.indication to client */
    H245FsmConfirm(pPdu, H245_CONF_NEEDRSP_OPEN, pObject->pInstance, pObject->dwTransId, REJECT);

    return 0;
}



/*
 *  NAME
 *      closeChannelAckAwaitingR - received close ack in Awaiting Release state
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT closeChannelAckAwaitingR(Object_t *pObject, PDU_t *pPdu)
{
    ASSERT(pObject->Entity == BLCSE_OUT);
    ASSERT(pObject->State == OpenOutBAwaitingRelease);
    H245TRACE(pObject->dwInst, 2,
              "H245_CONF_CLOSE with no error to API; Channel=%d",
              pObject->Key);

    /* reset timer T103 */
    FsmStopTimer(pObject);

    /* Send RELEASE.confirm to client */
    pObject->State = OpenOutBReleased;
    H245FsmConfirm(pPdu, H245_CONF_CLOSE, pObject->pInstance, pObject->dwTransId, FSM_OK);

    return 0;
}



/*
 *  NAME
 *      openChannelRejBAwaitingR - received open reject in awaiting release state
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT openChannelRejBAwaitingR(Object_t *pObject, PDU_t *pPdu)
{
    return closeChannelAckAwaitingR(pObject, pPdu);
}



/*
 *  NAME
 *      t103ExpiryBAwaitingR - handle timer expiry in awaiting release
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT t103ExpiryBAwaitingR(Object_t *pObject, PDU_t *pPdu)
{
    ASSERT(pObject->Entity == BLCSE_OUT);
    ASSERT(pObject->State == OpenOutBAwaitingRelease);
    ASSERT(pPdu == NULL);
    H245TRACE(pObject->dwInst, 2,
              "H245_CONF_CLOSE with timer expiry to API; Channel=%d",
              pObject->Key);

    /* Send ERROR.indication(D) to client */
    pObject->State = OpenOutBReleased;
    H245FsmConfirm(NULL, H245_CONF_CLOSE, pObject->pInstance, pObject->dwTransId, ERROR_D_TIMEOUT);

#if defined(SDL_COMPLIANT)
    /* Send RELEASE.confirm to client */
#endif

    return 0;
}

/*
 *  NAME
 *      establishReqAwaitingR - API open request in awaiting release state
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT establishReqAwaitingR(Object_t *pObject, PDU_t *pPdu)
{
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_OUT);
    ASSERT(pObject->State == OpenOutBAwaitingRelease);
    H245TRACE(pObject->dwInst, 2,
              "Send a (re) Open Bidirectional Channel to ASN; Channel=%d",
              pObject->Key);

    /* reset timer T103 */
    FsmStopTimer(pObject);

    /* Send Open Logical Channel to remote peer */
    lError = sendPDU(pObject->pInstance, pPdu);

    /* set timer T103 */
    pObject->State = OpenOutBAwaitingEstablishment;
    FsmStartTimer(pObject, T103OutExpiryF, uT103);

    return lError;
}



/***********************************************************************
 *
 * IN-COMING FINITE STATE MACHINE FUNCTIONS
 *
 ***********************************************************************/

/*
 *  NAME
 *      openChannelBReleased - open channel received in idle state
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT openChannelBReleased(Object_t *pObject, PDU_t *pPdu)
{
    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBReleased);
    H245TRACE(pObject->dwInst, 2,
              "H245_IND_OPEN with no error to API; Channel=%d",
              pObject->Key);

    /* Send ESTABLISH.indication to client */
    pObject->State = OpenInBAwaitingEstablishment;
    H245FsmIndication(pPdu, H245_IND_OPEN, pObject->pInstance, 0, FSM_OK);
    return 0;
}



/*
 *  NAME
 *      closeChannelBReleased - close channel received in idle state
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT closeChannelBReleased (Object_t *pObject, PDU_t *pPdu)
{
    PDU_t *             pOut;
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBReleased);
    ASSERT(pObject->Key == pPdu->u.MltmdSystmCntrlMssg_rqst.u.closeLogicalChannel.forwardLogicalChannelNumber);
    H245TRACE(pObject->dwInst, 2,
              "Close Channel (Bidirectional) received while in Released state; Channel=%d",
              pObject->Key);
    H245TRACE(pObject->dwInst, 2,
              "Send Close Ack (Bidirectional) to ASN; Channel=%d",
              pObject->Key);

    /* Send Close Logical Channel Ack to remote peer */
    pOut = (PDU_t *) MemAlloc(sizeof(PDU_t));
    if (pOut == NULL)
    {
        H245TRACE(pObject->dwInst, 2,
                  "closeChannelBReleased: memory allocation failed");
        return H245_ERROR_NOMEM;
    }
    pdu_rsp_close_logical_channel_ack(pOut, (WORD)pObject->Key);
    lError = sendPDU(pObject->pInstance, pOut);
    MemFree(pOut);

    return lError;
}

/*
 *  NAME
 *      establishResBAwaitingE - response to an open request    with an ack
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT establishResBAwaitingE (Object_t *pObject, PDU_t *pPdu)
{
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBAwaitingEstablishment);
    H245TRACE(pObject->dwInst, 2,
              "Send OpenAck (Bidirectional) to ASN module; Channel=%d",
              pObject->Key);

    /* Send Open Logical Channel Ack to remote peer */
    lError = sendPDU(pObject->pInstance, pPdu);

    /* set timer T103 */
    pObject->State = OpenInBAwaitingConfirmation;
    FsmStartTimer(pObject, T103InExpiryF, uT103);

    return lError;
}



/*
 *  NAME
 *      releaseReqBInAwaitingE - response to an open request with a reject
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT releaseReqBInAwaitingE (Object_t *pObject, PDU_t *pPdu)
{
    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBAwaitingEstablishment);
    H245TRACE(pObject->dwInst, 2, "Send OpenReject (Bidirectional) to SR module; Channel=%d", pObject->Key);

    /* Send Open Logical Channel Reject to remote peer */
    pObject->State = OpenInBReleased;
    return sendPDU(pObject->pInstance, pPdu);
}



/*
 *  NAME
 *      closeChannelBAwaitingE - received close channel in Awaiting establishment state
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT closeChannelBAwaitingE(Object_t *pObject, PDU_t *pPdu)
{
    PDU_t *             pOut;
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBAwaitingEstablishment);
    H245TRACE(pObject->dwInst, 2,
              "H245_IND_CLOSE with no error to API; Channel=%d",
              pObject->Key);

    /* Send Close Logical Channel Ack to remote peer */
    pOut = (PDU_t *) MemAlloc(sizeof(PDU_t ));
    if (pOut == NULL)
    {
        H245TRACE(pObject->dwInst, 2,
                  "closeChannelBAwaitingE: memory allocation failed");
        return H245_ERROR_NOMEM;
    }
    pdu_rsp_close_logical_channel_ack(pOut, (WORD)pObject->Key);
    lError = sendPDU(pObject->pInstance, pOut);
    MemFree(pOut);

    /* Send RELEASE.indication to client */
    pObject->State = OpenInBReleased;
    H245FsmIndication(pPdu, H245_IND_CLOSE, pObject->pInstance, 0, FSM_OK);

    return lError;
}



/*
 *  NAME
 *      openChannelBAwaitingE - overriding open request
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT openChannelBAwaitingE(Object_t *pObject, PDU_t *pPdu)
{
    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBAwaitingEstablishment);
    H245TRACE(pObject->dwInst, 2, "Overriding H245_IND_OPEN to API; Channel=%d", pObject->Key);

#if defined(SDL_COMPLIANT)
    /* Send RELEASE.indication (SOURCE:=USER) to client */
    H245FsmIndication(pPdu, H245_IND_CLOSE, pObject->pInstance, 0, FSM_OK);
#endif

    /* Send ESTABLISH.indication to client */
    H245FsmIndication(pPdu, H245_IND_OPEN, pObject->pInstance, 0, FSM_OK);

    return 0;
}



/*
 *  NAME
 *      openChannelConfirmBAwaitingE - received open confirm while awaiting establishment
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT openChannelConfirmBAwaitingE (Object_t *pObject, PDU_t *pPdu)
{
    PDU_t *             pOut;
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBAwaitingEstablishment);
    H245TRACE(pObject->dwInst, 2,
              "H245_IND_OPEN_CONF with error F to API; Channel=%d",
              pObject->Key);

    /* Send ERROR.indication(F) to client */
    pObject->State = OpenInBReleased;
    H245FsmIndication(pPdu, H245_IND_OPEN_CONF, pObject->pInstance, 0, ERROR_E_INAPPROPRIATE);

    /* Send Close Logical Channel Ack to remote peer */
    pOut = (PDU_t *) MemAlloc(sizeof(PDU_t ));
    if (pOut == NULL)
    {
        H245TRACE(pObject->dwInst, 2,
                  "openChannelConfirmBAwaitingE: memory allocation failed");
        return H245_ERROR_NOMEM;
    }
    pdu_rsp_close_logical_channel_ack(pOut, (WORD)pObject->Key);
    lError = sendPDU(pObject->pInstance, pOut);
    MemFree(pOut);

#if defined(SDL_COMPLIANT)
    /* Send RELEASE.indication (SOURCE:=B-LCSE) to client */
    H245FsmIndication(pPdu, H245_IND_CLOSE, pObject->pInstance, 0, FSM_OK);
#endif

    return lError;
}



/*
 *  NAME
 *      t103ExpiryBAwaitingC - timer expired waiting for open confirm
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT t103ExpiryBAwaitingC(Object_t *pObject, PDU_t *pPdu)
{
    PDU_t *             pOut;
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBAwaitingConfirmation);
    ASSERT(pPdu == NULL);
    H245TRACE(pObject->dwInst, 2,
              "Timer T103 expired while waiting for OpenConfirm for OpenAck");

    /* Send ERROR.indication(G) to client */
    pObject->State = OpenInBReleased;
    H245FsmIndication(NULL, H245_IND_OPEN_CONF, pObject->pInstance, pObject->dwTransId, ERROR_F_TIMEOUT);

    /* Send Close Logical Channel Ack to remote peer */
    pOut = (PDU_t *) MemAlloc(sizeof(PDU_t ));
    if (pOut == NULL)
    {
        H245TRACE(pObject->dwInst, 2,
                  "t103ExpiryBAwaitingC: memory allocation failed");
        return H245_ERROR_NOMEM;
    }
    pdu_rsp_close_logical_channel_ack(pOut, (WORD)pObject->Key);
    lError = sendPDU(pObject->pInstance, pOut);
    MemFree(pOut);

#if defined(SDL_COMPLIANT)
    /* Send RELEASE.indication to client */
    H245FsmIndication(pPdu, H245_IND_CLOSE, pObject->pInstance, 0, FSM_OK);
#endif

    return lError;
}

/*
 *  NAME
 *      openChannelConfirmBAwaitingC - received open confirm while awaiting confirmation
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT openChannelConfirmBAwaitingC (Object_t *pObject, PDU_t *pPdu)
{
    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBAwaitingConfirmation);
    H245TRACE(pObject->dwInst, 2,
              "H245_IND_OPEN_CONF with no errors; Channel=%d",
              pObject->Key);

    /* reset timer T103 */
    FsmStopTimer(pObject);

    /* Send ESTABLISH.confirm to client */
    pObject->State = OpenInBEstablished;
    H245FsmIndication(pPdu, H245_IND_OPEN_CONF, pObject->pInstance, pObject->dwTransId, FSM_OK);

    return 0;
}



/*
 *  NAME
 *      closeChannelBAwaitingC - received close channel while awaiting confirmation
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT closeChannelBAwaitingC (Object_t *pObject, PDU_t *pPdu)
{
    PDU_t *             pOut;
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBAwaitingConfirmation);
    H245TRACE(pObject->dwInst, 2,
              "H245_IND_CLOSE with no error; Channel=%d",
              pObject->Key);
    H245TRACE(pObject->dwInst, 2,
              "Send Close Ack (Bidirectional) to ASN; Channel=%d",
              pObject->Key);

    /* reset timer T103 */
    FsmStopTimer(pObject);

    /* Send Close Logical Channel Ack to remote peer */
    pOut = (PDU_t *) MemAlloc(sizeof(PDU_t));
    if (pOut == NULL)
    {
        H245TRACE(pObject->dwInst, 2,
                  "closeChannelBAwaitingC: memory allocation failed");
        return H245_ERROR_NOMEM;
    }
    pdu_rsp_close_logical_channel_ack(pOut, (WORD)pObject->Key);
    lError = sendPDU(pObject->pInstance, pOut);
    MemFree(pOut);

    /* Send RELEASE.indication to client */
    pObject->State = OpenInBReleased;
    H245FsmIndication(pPdu, H245_IND_CLOSE, pObject->pInstance, 0, FSM_OK);

    return lError;
}



/*
 *  NAME
 *      openChannelBAwaitingC - received open channel while awaiting confirmation
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT openChannelBAwaitingC (Object_t *pObject, PDU_t *pPdu)
{
    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBAwaitingConfirmation);
    H245TRACE(pObject->dwInst, 2, "Overriding H245_IND_OPEN to API; Channel=%d", pObject->Key);

    /* reset timer T103 */
    FsmStopTimer(pObject);

    pObject->State = OpenInBAwaitingEstablishment;

#if defined(SDL_COMPLIANT)
    /* Send RELEASE.indication (SOURCE:=USER) to client */
    H245FsmIndication(pPdu, H245_IND_CLOSE, pObject->pInstance, 0, FSM_OK);
#endif

    /* Send ESTABLISH.indication to client */
    H245FsmIndication(pPdu, H245_IND_OPEN, pObject->pInstance, 0, FSM_OK);

    return 0;
}



/*
 *  NAME
 *      closeChannelBEstablished - received close channel while in established state
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT closeChannelBEstablished(Object_t *pObject, PDU_t *pPdu)
{
    PDU_t *             pOut;
    HRESULT             lError;

    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBEstablished);
    H245TRACE(pObject->dwInst, 2,
              "H245_IND_CLOSE with no error up to API; Channel=%d",
              pObject->Key);

    /* Send Close Logical Channel Ack to remote peer */
    pOut = (PDU_t *) MemAlloc(sizeof(PDU_t ));
    if (pOut == NULL)
    {
        H245TRACE(pObject->dwInst, 2,
                  "closeChannelBEstablished: memory allocation failed");
        return H245_ERROR_NOMEM;
    }
    pdu_rsp_close_logical_channel_ack(pOut, (WORD)pObject->Key);
    lError = sendPDU(pObject->pInstance, pOut);
    MemFree(pOut);

    /* Send RELEASE.indication to client */
    pObject->State = OpenInBReleased;
    H245FsmIndication(pPdu, H245_IND_CLOSE, pObject->pInstance, 0, FSM_OK);

    return lError;
}



/*
 *  NAME
 *      openChannelBEstablished - received open channel while in established state
 *
 *
 *  PARAMETERS
 *   INPUT   pObject        pointer to a State Entity
 *
 *  RETURN VALUE
 *       error return codes defined in h245com.h
 */

HRESULT openChannelBEstablished(Object_t *pObject, PDU_t *pPdu)
{
    ASSERT(pObject->Entity == BLCSE_IN);
    ASSERT(pObject->State == OpenInBEstablished);
    H245TRACE(pObject->dwInst, 2, "Overriding H245_IND_OPEN to API; Channel=%d", pObject->Key);

    pObject->State = OpenInBAwaitingEstablishment;

#if defined(SDL_COMPLIANT)
    /* Send RELEASE.indication to client */
    H245FsmIndication(pPdu, H245_IND_CLOSE, pObject->pInstance, 0, FSM_OK);
#endif

    /* Send ESTABLISH.indication to client*/
    H245FsmIndication(pPdu, H245_IND_OPEN, pObject->pInstance, 0, FSM_OK);

    return 0;
}