//*****************************************************************************
/// \brief
///      Function for freeing up and clearing a PDU Buffer Store.
//*****************************************************************************
void asn1_PDU_Buffer_Store_Free
(
   s_PDU_Buffer_Store **p_p_PDU_Buffer_Store   ///< Address of the PDU_Buffer_Store pointer to free.
)
{
   s_PDU_Buffer_Store *p_PDU_Buffer_Store = *p_p_PDU_Buffer_Store;

   if ( p_PDU_Buffer_Store != NULL )
   {
      if( p_PDU_Buffer_Store->PDU_Encoded.p_PDU_Data != NULL )
      {
         GN_Free( p_PDU_Buffer_Store->PDU_Encoded.p_PDU_Data );
      }
      GN_Free( p_PDU_Buffer_Store );
      *p_p_PDU_Buffer_Store = NULL;
   }
}
//*****************************************************************************
/// \brief
///      Frees up an RRLP Agent message.
//*****************************************************************************
void RRLP_Message_Free(s_RRLP_Message *p_Message)
{
   if ( p_Message->Payload.p_GN_AGPS_GAD_Data != NULL )
   {
      GN_Free(p_Message->Payload.p_GN_AGPS_GAD_Data);
   }
   if ( p_Message->Payload.p_GN_GPS_Nav_Data != NULL )
   {
      GN_Free( p_Message->Payload.p_GN_GPS_Nav_Data );
   }
   if ( p_Message->Payload.p_GN_RRLP_QoP != NULL )
   {
      GN_Free( p_Message->Payload.p_GN_RRLP_QoP );
   }
   if ( p_Message->Payload.p_GN_AGPS_Meas != NULL )
   {
      GN_Free( p_Message->Payload.p_GN_AGPS_Meas );
   }
   if ( p_Message->Payload.p_RRLP_PDU != NULL )
   {
      if ( p_Message->Payload.p_RRLP_PDU->p_PDU_Data != NULL )
      {
         GN_Free( p_Message->Payload.p_RRLP_PDU->p_PDU_Data );
      }
      GN_Free( p_Message->Payload.p_RRLP_PDU );
   }
   // free underlying message
   GN_Free( p_Message );
}
//*****************************************************************************
/// \brief
///      RRLP Sequence Start in.
/// \details
///      Delivers the first RRLP PDU in the sequence from an external entity.
///      <p> This function is called in response to data being sent over an
///      RRLP Control Plane connection.
///      <p> For the RRLP Sequence Start the RRLP subsystem provides a
///      Handle which is used in subsequent exchanges to tie up the RRLP
///      sequence.
///      <ul>
///         <li><var>#GN_SUCCESS \copydoc GN_SUCCESS</var>\n
///            p_Status should be set to this value when the return value
///            indicated success.</li>
///         <li><var>#GN_ERR_NO_RESOURCE \copydoc GN_ERR_NO_RESOURCE</var>\n
///            p_Status should be set to this value when there are not
///            enough resources available to the library to perform the
///            requested function.</li>
///      </ul>
/// \attention
///      The calling party is responsible for managing the memory referenced by
///      p_Status and p_PDU.
/// \returns
///      Flag to indicate success or failure of the posting of the request.
/// \retval #TRUE Flag indicating success.
/// \retval #FALSE Flag indicating failure and that the status should be checked.
BL GN_RRLP_Sequence_Start_In(
   void           **p_Handle,    ///< [out] Opaque Handle used to coordinate requests.
   U2             PDU_Size,      ///< [in] Size of data at p_PDU in bytes.
   U1             *p_PDU,        ///< [in] Pointer to data.
   U4             PDU_TimeStamp, ///< [in] Timestamp of reception of PDU.
   s_GN_RRLP_QoP  *p_GN_RRLP_QoP, ///< [in] QoP if available.
   BL              LoggingDisabled ///< [in] This is used to enable/disable logging from the RRLP module
)
{
   s_RRLP_Instance   *p_RRLP_Instance;
   s_PDU_Encoded     *p_POS_Payload    = GN_Calloc( 1, sizeof( s_PDU_Encoded ) );
   s_GN_RRLP_QoP     *p_Temp_Qop;

   GN_RRLP_Log( "+GN_RRLP_Sequence_Start_In:" );
   GN_RRLP_Log( "GN_RRLP_api_call:    RRLP<=SUPL [label=\"GN_RRLP_Sequence_Start_In:\"];" );
   p_RRLP_Instance                  = RRLP_Instance_Request_New();
   *p_Handle                        = p_RRLP_Instance->Handle;
   p_RRLP_Instance->p_RRLP->State   = state_RRLP_Transaction_In_Progress;
   p_RRLP_Instance->p_RRLP->LoggingDisabled = LoggingDisabled;

   // POS_Handle not set, this is the first in the sequence.
   if ( p_GN_RRLP_QoP != NULL )
   {
      p_Temp_Qop = GN_Calloc( 1, sizeof( s_GN_RRLP_QoP ) );
      memcpy( p_Temp_Qop, p_GN_RRLP_QoP, sizeof( s_GN_RRLP_QoP ) );
   }
   else
   {
      p_Temp_Qop = NULL;
   }

   p_POS_Payload->Length      = PDU_Size;
   p_POS_Payload->p_PDU_Data  = GN_Calloc( 1, PDU_Size );

   memcpy( p_POS_Payload->p_PDU_Data, p_PDU, PDU_Size );

   RRLP_Send_PDU_Delivery( p_RRLP_Instance,
                           NULL,
                           p_RRLP_Instance->Handle,
                           p_POS_Payload,
                           PDU_TimeStamp,
                           p_Temp_Qop );
   if ( p_Temp_Qop != NULL )
   {
      GN_Free( p_Temp_Qop );
   }
   GN_RRLP_Log( "GN_RRLP_api_call:    RRLP>>SUPL [label=\"GN_RRLP_Sequence_Start_In: Handle=%p\"];", p_RRLP_Instance->Handle );
   GN_RRLP_Log( "-GN_RRLP_Sequence_Start_In:" );
   return TRUE;
}
//*************************************************************************
/// \brief
///      Removes the Instance entry from the Instance container.
/// \todo
///      Free up data in this instance.
//*************************************************************************
BL SUPL_Instance_Base_Delete
(
    s_SUPL_Instance *p_ThisInstance ///< Pointer to Instance entry to remove.
)
{
   unsigned i;

   for ( i = 0 ; i < SUPL_Instances.MaxInstanceCount ; i++ )
   {
      if ( SUPL_Instances.InstanceList[i] == p_ThisInstance )
      {
         GN_Free( p_ThisInstance );
         SUPL_Instances.InstanceList[i] = NULL;
         // No point checking the rest of the entries. Bail out now.
         return TRUE;
      }
   }
   return FALSE;
}
//*****************************************************************************
/// \brief
///      Deletes an existing instance from the #SUPL_Instance list.
///
/// <b>Global Parameters:</b>
///      <p>#SUPL_Instances [global] Container for current SUPL instances.
//*****************************************************************************
BL SUPL_Instance_Delete
(
   s_SUPL_Instance *p_SUPL_Instance ///< Instance to delete.
)
{
   BL successful = FALSE;
   s_SUPL_Instance *p_TempInstance = SUPL_Instance_Get_Data( p_SUPL_Instance );

   if ( p_TempInstance != NULL )
   {
      if ( p_SUPL_Instance->p_SUPL != NULL )
      {

         /////\Todo This case is no longer valid.
         //if ( p_SUPL_Instance->Peer_RRLP_Instance != NULL )
         //{
         //   BL Status;
         //   e_GN_Status GN_Status;
         //   Status =  GN_RRLP_Sequence_End_In( p_SUPL_Instance->Handle, &GN_Status );
         //}

         if ( p_SUPL_Instance->POS_Handle != NULL )
         {
            BL Status;
            e_GN_Status GN_Status = GN_SUCCESS;
            Status =  GN_RRLP_Sequence_End_In( p_SUPL_Instance->POS_Handle, &GN_Status, NULL );
         }
         if ( p_SUPL_Instance->p_SUPL->p_SlpSessionId != NULL )
         {
            GN_Free( p_SUPL_Instance->p_SUPL->p_SlpSessionId );
            p_SUPL_Instance->p_SUPL->p_SlpSessionId = NULL;
         }
         if ( p_SUPL_Instance->p_SUPL->p_GN_QoP != NULL )
         {
            GN_Free( p_SUPL_Instance->p_SUPL->p_GN_QoP );
            p_SUPL_Instance->p_SUPL->p_GN_QoP = NULL;
         }
         if ( p_SUPL_Instance->p_SUPL->p_VER != NULL )
         {
            GN_Free( p_SUPL_Instance->p_SUPL->p_VER );
            p_SUPL_Instance->p_SUPL->p_VER = NULL;
         }
         if ( p_SUPL_Instance->p_SUPL->SUPL_INIT.p_PDU_Data != NULL )
         {
            GN_Free( p_SUPL_Instance->p_SUPL->SUPL_INIT.p_PDU_Data );
         }
         supl_Free_LocationId_Data( &p_SUPL_Instance->p_SUPL->LocationId );
         if( p_SUPL_Instance->p_SUPL->V2_Data.p_ThirdPartyData != NULL)
         {
            supl_Free_ThirdParty_Data( p_SUPL_Instance->p_SUPL->V2_Data.p_ThirdPartyData );
            p_SUPL_Instance->p_SUPL->V2_Data.p_ThirdPartyData = NULL;
         }
         if( p_SUPL_Instance->p_SUPL->V2_Data.p_ApplicationID != NULL)
         {
             supl_Free_ApplicationID_Data( p_SUPL_Instance->p_SUPL->V2_Data.p_ApplicationID);
             p_SUPL_Instance->p_SUPL->V2_Data.p_ApplicationID = NULL;
         }
         GN_Free( p_SUPL_Instance->p_SUPL );
         p_SUPL_Instance->p_SUPL = NULL;
      }
      
      successful = SUPL_Instance_Base_Delete( p_SUPL_Instance );
   }
   SUPL_Segmented_PDU_Buffer_Init();
   return successful;
}