示例#1
0
/**
 *
 * Method Name: ResetAllConnections
 *
 *
 * Inputs:      unsigned char *puchReason     - Reason for Reset
 *
 * Outputs:     None
 *
 * Returns:     void

 *
 * Description:  The ResetAllConnections() method shall manage the termination
 *               of all RTCP connections.  This shall include the graceful
 *               release of all associated objects as well as the deallocation
 *               of all resources associated with each contained RTCP
 *               connection.
 *
 *
 * Usage Notes:
 *
 *
 */
void CRTCPSession::ResetAllConnections(unsigned char *puchReason)
{

    unsigned long aulCSRC[MAX_CONNECTIONS];
    unsigned long ulCSRCs = 0;
    CRTCPConnection *poRTCPConnection;

    // Check whether the session is acting as an Audio Mixer.  If so,
    // We should include these sites into our contributing source list.
    if(m_etMixerMode == MIXER_ENABLED)
    {
        // Check each entry of the connection list
        poRTCPConnection = GetFirstEntry();

        // Iterate through the list until all entries have been exhausted
        for(ulCSRCs = 0; poRTCPConnection != NULL; ulCSRCs++)
        {
            // Bump Reference Count of Connection Object
            poRTCPConnection->AddRef();

            // Get the SSRC ID of the connection
            aulCSRC[ulCSRCs] = poRTCPConnection->GetRemoteSSRC();

            // Release Reference to Connection Object
            poRTCPConnection->Release();

            // Get the next connection from the list
            poRTCPConnection = GetNextEntry();
        }
    }

    // Check each entry of the connection list again
    poRTCPConnection = GetFirstEntry();
    while (poRTCPConnection != NULL)
    {

        // Bump Reference Count of Connection Object
        poRTCPConnection->AddRef();

        poRTCPConnection->GenerateRTCPReports(puchReason, aulCSRC, ulCSRCs);

        // Release Reference to Connection Object
        poRTCPConnection->Release();

        // Get Next Entry
        poRTCPConnection = GetNextEntry();
    }
}
示例#2
0
uint32_t ChannelMaskTlv::GetChannelMask(void) const
{
    uint32_t                mask = 0;
    const ChannelMaskEntry *cur  = static_cast<const ChannelMaskEntry *>(GetFirstEntry());
    const ChannelMaskEntry *end  = reinterpret_cast<const ChannelMaskEntry *>(GetValue() + GetLength());

    for (; cur < end; cur = static_cast<const ChannelMaskEntry *>(cur->GetNext()))
    {
        VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end);

#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
        if (cur->GetChannelPage() == OT_RADIO_CHANNEL_PAGE_2)
        {
            mask |= cur->GetMask() & OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK;
        }
#endif

#if OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
        if (cur->GetChannelPage() == OT_RADIO_CHANNEL_PAGE_0)
        {
            mask |= cur->GetMask() & OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK;
        }
#endif
    }

exit:
    return mask;
}
示例#3
0
/**
 *
 * Method Name: CheckRemoteSSRCCollisions
 *
 *
 * Inputs:      IRTCPConnection *piRTCPConnection  - Connection Interface
 *
 * Outputs:     None
 *
 * Returns:     void
 *
 * Description: Check that other remote SSRCs aren't colliding with each other.
 *
 * Usage Notes:
 *
 *
 *
 */
void CRTCPSession::CheckRemoteSSRCCollisions(IRTCPConnection *piRTCPConnection)
{

    // Check for Collision
    CRTCPConnection *poRTCPConnection = GetFirstEntry();
    while(poRTCPConnection)
    {
        // Bump Reference Count of Connection Object
        poRTCPConnection->AddRef();

        bool bInitialSSRCFound = FALSE;
        if(poRTCPConnection->GetRemoteSSRC() ==
                                            piRTCPConnection->GetRemoteSSRC())
        {
            if(!bInitialSSRCFound)
                bInitialSSRCFound = TRUE;
            else
            {
                // A collision has been detected.
                // Let's inform the RTC Manager and its subscribing client's
                //  of this occurence.
                poRTCPConnection->AddRef();
                ((IRTCPSession *)this)->AddRef();
                m_piRTCPNotify->RemoteSSRCCollision(
                   (IRTCPConnection *)poRTCPConnection, (IRTCPSession *)this);
            }
        }

        // Release Reference to Connection Object
        poRTCPConnection->Release();

        // Get the next connection from the list
        poRTCPConnection = GetNextEntry();
    }
}
示例#4
0
int AL_PROTO ALEntryList::FillListBox( HWND hDlg, int list_box /* = -1 */ )
{
    HWND window;

    if ( list_box != -1 )
        window = GetDlgItem( hDlg, (short int) list_box );
    else
        window = hDlg;
    SendMessage( window, LB_RESETCONTENT, 0, 0 );
    ALEntry *job = GetFirstEntry();
    int count = 0;
    while ( job ) {
        if ( job->GetMark() ) {
            count++;
            SendMessage( window,
                         LB_ADDSTRING,
                         0,
                         (LPARAM)( (LPSTR) job->mpStorageObject->mName ) );
        }
        job = job->GetNextEntry();
    }
    if ( count == 0 )
        SendMessage( window,
                     LB_ADDSTRING,
                     0,
                     (LPARAM)( (LPSTR) "<none>" ) );
    return count;
}
示例#5
0
/**
 * @param bCrash - true if crash has occurred.
 * @return true if the log was saved successfully.
 */
BOOL CTextLogFile::SaveEntries(BOOL /*bCrash*/)
{
#ifdef _DEBUG
	DWORD dwStartTime = GetTickCount();
#endif
	PCTSTR pszLogFileName = GetLogFileName();
	HANDLE hFile = CreateFile(pszLogFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
		return FALSE;
	DWORD dwWritten;
	WriteFile(hFile, g_arrUTF8Preamble, sizeof(g_arrUTF8Preamble), &dwWritten, NULL);
	CLogEntry* pLogEntry = GetFirstEntry();
	while (pLogEntry)
	{
		CTextLogEntry* pTextLogEntry = (CTextLogEntry*)pLogEntry;
		WriteFile(hFile, pTextLogEntry->m_pbData, pTextLogEntry->m_dwSize, &dwWritten, NULL);
		pLogEntry = pLogEntry->m_pNextEntry;
	}
#ifdef _DEBUG
	DWORD dwEndTime = GetTickCount();
	TCHAR szMessage[128];
	_stprintf_s(szMessage, countof(szMessage), _T("CTextLogFile::SaveEntries(): %lu entries, %lu bytes, %lu milliseconds\r\n"), GetNumEntries(), GetNumBytes(), dwEndTime - dwStartTime);
	OutputDebugString(szMessage);
#endif
	CloseHandle(hFile);
	return TRUE;
}
示例#6
0
void ChannelMaskTlv::SetChannelMask(uint32_t aChannelMask)
{
    uint8_t           length = 0;
    ChannelMaskEntry *entry;

    entry = static_cast<ChannelMaskEntry *>(GetFirstEntry());

#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
    if (aChannelMask & OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK)
    {
        assert(entry != NULL);
        entry->Init();
        entry->SetChannelPage(OT_RADIO_CHANNEL_PAGE_2);
        entry->SetMask(aChannelMask & OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK);

        length += sizeof(MeshCoP::ChannelMaskEntry);

        entry = static_cast<MeshCoP::ChannelMaskEntry *>(entry->GetNext());
    }
#endif

#if OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT
    if (aChannelMask & OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK)
    {
        assert(entry != NULL);
        entry->Init();
        entry->SetChannelPage(OT_RADIO_CHANNEL_PAGE_0);
        entry->SetMask(aChannelMask & OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK);

        length += sizeof(MeshCoP::ChannelMaskEntry);
    }
#endif

    SetLength(length);
}
示例#7
0
//************************************************************************
// adds an entry to the list
//************************************************************************
CListItem<CEventLogEntry*> *CEventLog::AddItem(CEventLogEntry *pEntry)
{
	CListItem<CEventLogEntry*> *pItem = CLCDList<CEventLogEntry*>::AddItem(pEntry);
	if(GetEntryCount() > CConfig::GetIntSetting(NOTIFY_LOGSIZE))
		RemoveItem(((CListItem<CEventLogEntry*>*)GetFirstEntry())->GetItemData());
	
	if(GetTickCount() - m_dwLastScroll > 10000)
		SetPosition(pItem);
	return pItem;
}
示例#8
0
/**
 *
 * Method Name: ForwardSDESReport
 *
 *
 * Inputs:   IGetSrcDescription *piGetSrcDescription
 *                              - Interface for getting SDES Report Statistics
 *           IRTCPConnection  *piRTCPConnection
 *                              - Interface to RTCP Connection originating SDES
 *
 * Outputs:  None
 *
 * Returns:  None
 *
 * Description: The ForwardSDESReport() method shall enable the RTC Manager to
 *              pass interfaces to SDES Reports received from participating
 *              site while acting in the mode of a conference Mixer.  The
 *              Mixer's role in this situation is to transmit these reports
 *              unchanged to others participating within a conference.  The
 *              handoff of an SDES Report to the CRTCPRender will cause the
 *              report to be transmitted to a participating site using the
 *              associated Network Render object.
 *
 * Usage Notes: The interface for the local site's Source Description Report
 *              generator is passed as an argument at construction time.
 *
 *
 */
void CRTCPSession::ForwardSDESReport(IGetSrcDescription *piGetSrcDescription,
                                     IRTCPConnection    *piRTCPConnection)
{

    // Check the each entry of the connection list and forward this report to
    //  those not matching the originators SSRC
    CRTCPConnection *poRTCPConnection = GetFirstEntry();

    // Iterate through the list until all entries have been exhausted
    while(poRTCPConnection != NULL)
    {
        // Bump Reference Count of Connection Object
        poRTCPConnection->AddRef();

        // Get the SSRC ID of the connection to determine whether it is not
        //  from the originator
        if(poRTCPConnection->GetRemoteSSRC() !=
                                            piRTCPConnection->GetRemoteSSRC())
        {
            // Get Render Interface
            IRTCPRender *piRTCPRender = poRTCPConnection->GetRenderInterface();

#if RTCP_DEBUG /* [ */
            if(bPingtelDebug)
            {
                osPrintf("*** FORWARDING SDES REPORT ****\n");
                osPrintf("\t ON SESSION ==> %d\n", GetSessionID());
                osPrintf("\t FROM SSRC  ==> %u\n",
                                           piRTCPConnection->GetRemoteSSRC());
                osPrintf("\t TO SSRC    ==> %d\n",
                                           poRTCPConnection->GetRemoteSSRC());
            }
#endif /* RTCP_DEBUG ] */

            // Different connection.  Forward the SDES Report for delivery.
            ISDESReport *piSDESReport =
                                      piGetSrcDescription->GetSDESInterface();
            piRTCPRender->ForwardSDESReport(piSDESReport);

            // Release the reference to SDES Report interface
            piSDESReport->Release();

            // Release Render Interface
            piRTCPRender->Release();
        }

        // Release Reference to Connection Object
        poRTCPConnection->Release();

        // Get the next connection from the list
        poRTCPConnection = GetNextEntry();
    }

}
示例#9
0
int AL_PROTO ALEntryList::ToggleMarks()
{
    int count = 0;
    ALEntry *job = GetFirstEntry();
    while ( job ) {
        job->SetMarkState( (short int) !job->GetMark() );
        job = job->GetNextEntry();
        count++;
    }
    return count;
}
示例#10
0
// CountEntries
int32
Directory::CountEntries() const
{
	int32 count = 0;
	Entry* entry = GetFirstEntry();
	while (entry) {
		count++;
		entry = GetNextEntry(entry);
	}
	return count;
}
示例#11
0
AL_PROTO ALEntryList::~ALEntryList()
{
    AL_ASSERT( GoodTag(), "~ALEntryList: attempting to delete invalid object" );
    ALEntry *job = GetFirstEntry();
    while ( job ) {
        ALEntry *next_job = job->GetNextEntry();
        delete job;
        job = next_job;
    }
    if ( mpListHead )
        delete mpListHead;
    AL_ASSERT( GoodTag(), "~ALEntryList: attempting to delete invalid object" );
}
示例#12
0
Zip::Zip(const char *filename, void *mapped, size_t size)
: name(filename ? strdup(filename) : nullptr)
, mapped(mapped)
, size(size)
, nextFile(LocalFile::validate(mapped)) // first Local File entry
, nextDir(nullptr)
, entries(nullptr)
{
  pthread_mutex_init(&mutex, nullptr);
  // If the first local file entry couldn't be found (which can happen
  // with optimized jars), check the first central directory entry.
  if (!nextFile)
    GetFirstEntry();
}
示例#13
0
int AL_PROTO ALEntryList::DeleteUnmarked()
{
    ALEntry *job;
    int count = 0;

    job = GetFirstEntry();
    while ( job ) {
        ALEntry *next_job = job->GetNextEntry();
        if ( job->GetMark() == 0 ) {
            count++;
            delete job;
        }
        job = next_job;
    }
    return count;
}
示例#14
0
/**
 *
 * Method Name:  ReassignSSRC
 *
 *
 * Inputs:   unsigned long  ulSSRC     - Source ID
 *           unsigned char *puchReason - Optional Reason for SSRC Reassignment
 *
 * Outputs:  None
 *
 * Returns:  void
 *
 * Description: Reassigns the Source Identifier associated with an RTP session
 *              due to collision detection and resolution.  Calling of this
 *              method shall result in the resetting of the SSRC IDs of
 *              associated Sender, Receiver, and SDES Reports.
 *
 * Usage Notes:
 *
 *
 *
 */
void CRTCPSession::ReassignSSRC(unsigned long ulSSRC,
                                unsigned char *puchReason)
{
#if RTCP_DEBUG /* [ */
    if(bPingtelDebug)
    {
        osPrintf("*** SSRC REASSIGNED ****\n");
        osPrintf("\t ON SESSION ==> %d\n", GetSessionID());
        osPrintf("\t NEW SSRC    ==> %u\n", ulSSRC);
        osPrintf("\t REASON     ==> %s\n", puchReason);
    }
#endif /* RTCP_DEBUG ] */

    // Reset all connections first
    ResetAllConnections(puchReason);

    // Set new Session SSRC
    m_ulSSRC = ulSSRC;

    // Check the each entry of the connection list
    CRTCPConnection *poRTCPConnection = GetFirstEntry();

    // Iterate through the list until all entries have been exhausted
    while(poRTCPConnection != NULL)
    {
        // Bump Reference Count of Connection Object
        poRTCPConnection->AddRef();

        // Get Render Interface
        IRTCPRender *piRTCPRender = poRTCPConnection->GetRenderInterface();

        // Instruct the Render filter of the new SSRC.
        // It will take care of the reset
        piRTCPRender->ReassignSSRC(ulSSRC);

        // Release Render Interface
        piRTCPRender->Release();

        // Release Reference to Connection Object
        poRTCPConnection->Release();

        // Get the next connection from the list
        poRTCPConnection = GetNextEntry();
    }

}
示例#15
0
void AL_PROTO ALEntryList::UnmarkDuplicates( ALEntryList &list,
                                             const char *error_message /* = 0 */ )
{
    ALEntry *job = GetFirstEntry();
    while ( job ) {
        if ( job->GetMark() ) {
            if ( job->Duplicate( list ) ) {
                job->ClearMark();
                if ( error_message && error_message[ 0 ] != '\0' )
                    job->mpStorageObject->mStatus.SetError(
                            AL_DUPLICATE_ENTRY,
                            error_message );
            }
        }
        job = job->GetNextEntry();
    }
}
示例#16
0
int AL_PROTO ALEntryList::SetMarkState( const char AL_DLL_FAR *name,
                                        short int new_state )
{
    int count = 0;

    ALEntry *job = GetFirstEntry();
    while ( job ) {
        if ( name ) {
            if ( job->mpStorageObject->mName.WildCardMatch( name ) ) {
                job->SetMarkState( new_state );
                count++;
            }
        } else {
            job->SetMarkState( new_state );
            count++;
        }
        job = job->GetNextEntry();
    }
    return count;
}
示例#17
0
/**
 *
 * Method Name: CheckLocalSSRCCollisions
 *
 *
 * Inputs:      None
 *
 * Outputs:     None
 *
 * Returns:     void
 *
 * Description: Check that our local SSRC is not colliding with one fo the
 *              SSRCs of a participating site.
 *
 * Usage Notes:
 *
 *
 *
 */
void CRTCPSession::CheckLocalSSRCCollisions(void)
{

    // Check the each entry of the connection list
    CRTCPConnection *poRTCPConnection = GetFirstEntry();

    // Iterate through the list until all entries have been exhausted
    while(poRTCPConnection != NULL)
    {
        // Bump Reference Count of Connection Object
        poRTCPConnection->AddRef();

        // Get the SSRC ID of the connection to determine whether it is
        //  conflicting with ours
        if(poRTCPConnection->GetRemoteSSRC() == m_ulSSRC)
        {
            // A collision has been detected.
            // Let's reset all the connections.
            ResetAllConnections((unsigned char *)"SSRC Collision");

            // Let's inform the RTC Manager and its subscribing client's of
            //  this occurence.
            poRTCPConnection->AddRef();
            ((IRTCPSession *)this)->AddRef();
            m_piRTCPNotify->LocalSSRCCollision(
                   (IRTCPConnection *)poRTCPConnection, (IRTCPSession *)this);
        }

        // Release Reference to Connection Object
        poRTCPConnection->Release();

        // Get the next connection from the list
        poRTCPConnection = GetNextEntry();
    }

}
示例#18
0
/*|><|************************************************************************
*
* Method Name:  MessageLoop
*
*
* Inputs:       None
*
* Outputs:      None
*
* Returns:      None
*
* Logic Notes:
*
* Caveats:
*
************************************************************************|<>|*/
void CMsgQueue::MessageLoop()
{

    // Establish an array of event on which we are to wait.  Among these
    // events are the message Arrival event and the Thread Termination event.
    HANDLE hEventList[] = {m_hThreadEvent, m_hMessageEvent};
    unsigned long dwEvents = 2;
    BOOL bTerminate = FALSE;

//  Sleep briefly to allow the parent thread to run and pickup the thread
//  initialization signal.
    Sleep(ONE_SECOND);

    while (!bTerminate)
    {

        // Wait for an Event to occur or for the timeout to expire
        unsigned long dwRetValue = WaitForMultipleObjects (
                dwEvents,           // Number of event objects passed in list
                hEventList,         // List of Event objects
                FALSE,              // Do not wait for all to be signalled
                ONE_SECOND);        // Wait timer duration - One Second


        // An Event was Detected.  Let's determine the event type.
        if (dwRetValue  != WAIT_TIMEOUT)
        {
            // Determine which object has signalled us by taking the return
            // value and subtracting the base value of WAIT_OBJECT_0 from it
            unsigned long dwIndex = dwRetValue - WAIT_OBJECT_0;

            // If the object that signalled us is Index 0, it is the terminate
            // thread object.  Let's break out of the while loop and tend to
            // gracefully shutting down the Message processing thread.
            if (dwIndex == 0 || dwIndex > dwEvents)
            {
                // Terminate message processing
                bTerminate = TRUE;
            }
            else
            {
                // Reset Index and Event
                dwIndex = 0;
                ResetEvent(m_hMessageEvent);
            }
        }


        // A message has been received or a timeout has occurred.  We check
        // the queue in the latter case to insure against loosing messages
        // which were pending the completion of a device connection (aka
        // Network connection).  Let's read off all messages which may be
        // on the list and dispatch them for processing.
        CMessage *poMessage = GetFirstEntry();
        while(poMessage)
        {
            // Dispatch the message to the user defined processing method
            if(ProcessMessage(poMessage))
            {
                RemoveEntry(poMessage);
                delete poMessage;
                poMessage = NULL;

            }

            // Remove the next message from the list
            poMessage = GetNextEntry();
        }

    }

    // Terminate the Message Thread
    TerminateMessageThread();

}
示例#19
0
/**
 *
 * Method Name:  RTCPConnectionStopped()
 *
 *
 * Inputs:   IRTCPConnection *piRTCPConnection
 *                                   - Interface to associated RTCP Connection
 *           IRTCPSession    *piRTCPSession
 *                                   - Interface to associated RTCP Session
 *
 * Outputs:  None
 *
 * Returns:  None
 *
 * Description: The RTCPConnectionStopped() event method shall inform the
 *              recipient of the imminent suspension of an RTCP outbound
 *              connection.  This will allow whatever connection related
 *              operations to be suspended until it again resumes.
 *
 * Usage Notes:
 *
 */
void CRTCPSession::RTCPConnectionStopped(IRTCPConnection *piRTCPConnection,
                                         IRTCPSession    *piRTCPSession)
{
    unsigned long aulCSRC[MAX_CONNECTIONS];
    unsigned long ulCSRCs = 0;
    CRTCPConnection *poRTCPConnection;

    // Get the associated RTCP Connection object from the collection list
    if((poRTCPConnection = GetEntry(RTCPConnectionComparitor,
                                   (void *)piRTCPConnection)) != NULL)
    {
#if RTCP_DEBUG /* [ */
        if(bPingtelDebug)
        {
            osPrintf("*** RTCP CONNECTION STOPPED ****\n");
            osPrintf("\t ON SESSION ==> %d\n", GetSessionID());
            osPrintf("\t TO SSRC    ==> %u\n",
                                           piRTCPConnection->GetRemoteSSRC());
        }
#endif /* RTCP_DEBUG ] */

        // Check whether the session is acting as an Audio Mixer.  If so,
        // We should include these sites into our contributing source list.
        if(m_etMixerMode == MIXER_ENABLED)
        {
            // Check each entry of the connection list
            CRTCPConnection *poPeerConnection = GetFirstEntry();

            // Iterate through the list until all entries have been exhausted
            for(ulCSRCs = 0; poPeerConnection != NULL; ulCSRCs++)
            {
                // Bump Reference Count of Connection Object
                poPeerConnection->AddRef();

                // Get the SSRC ID of the connection
                aulCSRC[ulCSRCs] = poPeerConnection->GetRemoteSSRC();

                // Check that we are not adding the Remote SSRC of the
                //  connection being terminated.  If so, we will backup the
                //  CSRC count
                if(poPeerConnection->GetRemoteSSRC() == aulCSRC[ulCSRCs])
                    ulCSRCs--;

                // Release Reference to Connection Object
                poPeerConnection->Release();

                // Get the next connection from the list
                poPeerConnection = GetNextEntry();
            }
        }

        // Bump Reference Count of Connection Object
        poRTCPConnection->AddRef();

        poRTCPConnection->GenerateRTCPReports(
          (unsigned char *)"Normal Connection Termination", aulCSRC, ulCSRCs);

        // Release Reference to Connection Object
        poRTCPConnection->Release();

    }

}
示例#20
0
// destructor
VirtualDir::~VirtualDir()
{
	while (VirtualDirEntry* entry = GetFirstEntry())
		RemoveEntry(entry->GetName());
}
示例#21
0
bool
Zip::GetStream(const char *path, Zip::Stream *out) const
{
  AutoLock lock(&mutex);

  DEBUG_LOG("%s - GetFile %s", name, path);
  /* Fast path: if the Local File header on store matches, we can return the
   * corresponding stream right away.
   * However, the Local File header may not contain enough information, in
   * which case the 3rd bit on the generalFlag is set. Unfortunately, this
   * bit is also set in some archives even when we do have the data (most
   * notably the android packages as built by the Mozilla build system).
   * So instead of testing the generalFlag bit, only use the fast path when
   * we haven't read the central directory entries yet, and when the
   * compressed size as defined in the header is not filled (which is a
   * normal condition for the bit to be set). */
  if (nextFile && nextFile->GetName().Equals(path) &&
      !entries && (nextFile->compressedSize != 0)) {
    DEBUG_LOG("%s - %s was next file: fast path", name, path);
    /* Fill Stream info from Local File header content */
    const char *data = reinterpret_cast<const char *>(nextFile->GetData());
    out->compressedBuf = data;
    out->compressedSize = nextFile->compressedSize;
    out->uncompressedSize = nextFile->uncompressedSize;
    out->CRC32 = nextFile->CRC32;
    out->type = static_cast<Stream::Type>(uint16_t(nextFile->compression));

    /* Find the next Local File header. It is usually simply following the
     * compressed stream, but in cases where the 3rd bit of the generalFlag
     * is set, there is a Data Descriptor header before. */
    data += nextFile->compressedSize;
    if ((nextFile->generalFlag & 0x8) && DataDescriptor::validate(data)) {
      data += sizeof(DataDescriptor);
    }
    nextFile = LocalFile::validate(data);
    return true;
  }

  /* If the directory entry we have in store doesn't match, scan the Central
   * Directory for the entry corresponding to the given path */
  if (!nextDir || !nextDir->GetName().Equals(path)) {
    const DirectoryEntry *entry = GetFirstEntry();
    DEBUG_LOG("%s - Scan directory entries in search for %s", name, path);
    while (entry && !entry->GetName().Equals(path)) {
      entry = entry->GetNext();
    }
    nextDir = entry;
  }
  if (!nextDir) {
    DEBUG_LOG("%s - Couldn't find %s", name, path);
    return false;
  }

  /* Find the Local File header corresponding to the Directory entry that
   * was found. */
  nextFile = LocalFile::validate(static_cast<const char *>(mapped)
                             + nextDir->offset);
  if (!nextFile) {
    ERROR("%s - Couldn't find the Local File header for %s", name, path);
    return false;
  }

  /* Fill Stream info from Directory entry content */
  const char *data = reinterpret_cast<const char *>(nextFile->GetData());
  out->compressedBuf = data;
  out->compressedSize = nextDir->compressedSize;
  out->uncompressedSize = nextDir->uncompressedSize;
  out->CRC32 = nextDir->CRC32;
  out->type = static_cast<Stream::Type>(uint16_t(nextDir->compression));

  /* Store the next directory entry */
  nextDir = nextDir->GetNext();
  nextFile = nullptr;
  return true;
}