<commit_before>/*************************************************************************
 *
 *  $RCSfile: virdev.cxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: rt $ $Date: 2004-07-13 09:29:45 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SV_SVSYS_HXX
#include <svsys.h>
#endif

#ifndef _SV_SALINST_HXX
#include <salinst.hxx>
#endif
#ifndef _SV_SALGDI_HXX
#include <salgdi.hxx>
#endif
#ifndef _SV_SALFRAME_HXX
#include <salframe.hxx>
#endif
#ifndef _SV_SALVD_HXX
#include <salvd.hxx>
#endif

#ifndef _DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _SV_SVDATA_HXX
#include <svdata.hxx>
#endif
#ifndef _SV_SETTINGS_HXX
#include <settings.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <svapp.hxx>
#endif
#ifndef _SV_WRKWIN_HXX
#include <wrkwin.hxx>
#endif
#ifndef _SV_OUTDEV_H
#include <outdev.h>
#endif
#ifndef _SV_VIRDEV_HXX
#include <virdev.hxx>
#endif

using namespace ::com::sun::star::uno;

// =======================================================================

void VirtualDevice::ImplInitVirDev( const OutputDevice* pOutDev,
                                    long nDX, long nDY, USHORT nBitCount )
{
    DBG_ASSERT( nBitCount <= 1,
                "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" );

    if ( nDX < 1 )
        nDX = 1;

    if ( nDY < 1 )
        nDY = 1;

    ImplSVData* pSVData = ImplGetSVData();

    if ( !pOutDev )
        pOutDev = ImplGetDefaultWindow();

    SalGraphics* pGraphics;
    if ( !pOutDev->mpGraphics )
        ((OutputDevice*)pOutDev)->ImplGetGraphics();
    pGraphics = pOutDev->mpGraphics;
    if ( pGraphics )
        mpVirDev = pSVData->mpDefInst->CreateVirtualDevice( pGraphics, nDX, nDY, nBitCount );
    else
        mpVirDev = NULL;
    if ( !mpVirDev )
        GetpApp()->Exception( EXC_SYSOBJNOTCREATED );

    mnBitCount      = ( nBitCount ? nBitCount : pOutDev->GetBitCount() );
    mnOutWidth      = nDX;
    mnOutHeight     = nDY;
    mbScreenComp    = TRUE;
    mbScreenComp    = FALSE;
    mnAlphaDepth    = -1;

    if( mnBitCount < 8 )
        SetAntialiasing( ANTIALIASING_DISABLE_TEXT );

    if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
        mbScreenComp = FALSE;
    else if ( pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
        mbScreenComp = ((VirtualDevice*)pOutDev)->mbScreenComp;

    meOutDevType    = OUTDEV_VIRDEV;
    mbDevOutput     = TRUE;
    mpFontList      = pSVData->maGDIData.mpScreenFontList;
    mpFontCache     = pSVData->maGDIData.mpScreenFontCache;
    mnDPIX          = pOutDev->mnDPIX;
    mnDPIY          = pOutDev->mnDPIY;
    maFont          = pOutDev->maFont;

    // Virtuelle Devices haben defaultmaessig einen weissen Hintergrund
    SetBackground( Wallpaper( Color( COL_WHITE ) ) );
    Erase();

    // VirDev in Liste eintragen
    mpNext = pSVData->maGDIData.mpFirstVirDev;
    mpPrev = NULL;
    if ( mpNext )
        mpNext->mpPrev = this;
    else
        pSVData->maGDIData.mpLastVirDev = this;
    pSVData->maGDIData.mpFirstVirDev = this;
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( USHORT nBitCount )
:   mpVirDev( NULL ),
    meRefDevMode( REFDEV_NONE )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount );
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, USHORT nBitCount )
    : mpVirDev( NULL ),
    meRefDevMode( REFDEV_NONE )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( &rCompDev, 1, 1, nBitCount );
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, USHORT nBitCount, USHORT nAlphaBitCount )
    : mpVirDev( NULL )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( &rCompDev, 1, 1, nBitCount );

    // #110958# Enable alpha channel
    mnAlphaDepth = nAlphaBitCount;
}

// -----------------------------------------------------------------------

VirtualDevice::~VirtualDevice()
{
    DBG_TRACE( "VirtualDevice::~VirtualDevice()" );

    ImplSVData* pSVData = ImplGetSVData();

    ImplReleaseGraphics();

    if ( mpVirDev )
        pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );

    // remove this VirtualDevice from the double-linked global list
    if( mpPrev )
        mpPrev->mpNext = mpNext;
    else
        pSVData->maGDIData.mpFirstVirDev = mpNext;

    if( mpNext )
        mpNext->mpPrev = mpPrev;
    else
        pSVData->maGDIData.mpLastVirDev = mpPrev;
}

// -----------------------------------------------------------------------

BOOL VirtualDevice::ImplSetOutputSizePixel( const Size& rNewSize, BOOL bErase )
{
    DBG_TRACE3( "VirtualDevice::ImplSetOutputSizePixel( %ld, %ld, %d )", rNewSize.Width(), rNewSize.Height(), (int)bErase );

    if ( !mpVirDev )
        return FALSE;
    else if ( rNewSize == GetOutputSizePixel() )
    {
        if ( bErase )
            Erase();
        return TRUE;
    }

    BOOL bRet;
    long nNewWidth = rNewSize.Width(), nNewHeight = rNewSize.Height();

    if ( nNewWidth < 1 )
        nNewWidth = 1;

    if ( nNewHeight < 1 )
        nNewHeight = 1;

    if ( bErase )
    {
        bRet = mpVirDev->SetSize( nNewWidth, nNewHeight );

        if ( bRet )
        {
            mnOutWidth  = rNewSize.Width();
            mnOutHeight = rNewSize.Height();
            Erase();
        }
    }
    else
    {
        SalVirtualDevice*   pNewVirDev;
        ImplSVData*         pSVData = ImplGetSVData();

        // we need a graphics
        if ( !mpGraphics )
        {
            if ( !ImplGetGraphics() )
                return FALSE;
        }

        pNewVirDev = pSVData->mpDefInst->CreateVirtualDevice( mpGraphics, nNewWidth, nNewHeight, mnBitCount );
        if ( pNewVirDev )
        {
            SalGraphics* pGraphics = pNewVirDev->GetGraphics();
            if ( pGraphics )
            {
                SalTwoRect aPosAry;
                long nWidth;
                long nHeight;
                if ( mnOutWidth < nNewWidth )
                    nWidth = mnOutWidth;
                else
                    nWidth = nNewWidth;
                if ( mnOutHeight < nNewHeight )
                    nHeight = mnOutHeight;
                else
                    nHeight = nNewHeight;
                aPosAry.mnSrcX       = 0;
                aPosAry.mnSrcY       = 0;
                aPosAry.mnSrcWidth   = nWidth;
                aPosAry.mnSrcHeight  = nHeight;
                aPosAry.mnDestX      = 0;
                aPosAry.mnDestY      = 0;
                aPosAry.mnDestWidth  = nWidth;
                aPosAry.mnDestHeight = nHeight;

                pGraphics->CopyBits( &aPosAry, mpGraphics, this, this );
                pNewVirDev->ReleaseGraphics( pGraphics );
                ImplReleaseGraphics();
                pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );
                mpVirDev = pNewVirDev;
                mnOutWidth  = rNewSize.Width();
                mnOutHeight = rNewSize.Height();
                bRet = TRUE;
            }
            else
            {
                bRet = FALSE;
                pSVData->mpDefInst->DestroyVirtualDevice( pNewVirDev );
            }
        }
        else
            bRet = FALSE;
    }

    return bRet;
}

// -----------------------------------------------------------------------

BOOL VirtualDevice::SetOutputSizePixel( const Size& rNewSize, BOOL bErase )
{
    if( ImplSetOutputSizePixel(rNewSize, bErase) )
    {
        if( mnAlphaDepth != -1 )
        {
            // #110958# Setup alpha bitmap
            if(mpAlphaVDev && mpAlphaVDev->GetOutputSizePixel() != rNewSize)
            {
                delete mpAlphaVDev;
                mpAlphaVDev = 0L;
            }

            if( !mpAlphaVDev )
            {
                mpAlphaVDev = new VirtualDevice( *this, mnAlphaDepth );
                mpAlphaVDev->ImplSetOutputSizePixel(rNewSize, bErase);
            }

            // TODO: copy full outdev state to new one, here. Also needed in outdev2.cxx:DrawOutDev
            if( GetLineColor() != Color( COL_TRANSPARENT ) )
                mpAlphaVDev->SetLineColor( COL_BLACK );

            if( GetFillColor() != Color( COL_TRANSPARENT ) )
                mpAlphaVDev->SetFillColor( COL_BLACK );

            mpAlphaVDev->SetMapMode( GetMapMode() );
        }

        return TRUE;
    }

    return FALSE;
}

// -----------------------------------------------------------------------

void VirtualDevice::SetReferenceDevice( RefDevMode eRefDevMode )
{
    switch( eRefDevMode )
    {
    case REFDEV_NONE:
    default:
        DBG_ASSERT( FALSE, "VDev::SetRefDev illegal argument!" );
        // fall through
    case REFDEV_MODE06:
        mnDPIX = mnDPIY = 600;
        break;
    case REFDEV_MODE48:
        mnDPIX = mnDPIY = 4800;
        break;
    case REFDEV_MODE96:
        mnDPIX = mnDPIY = 1440; // as agreed with FME and AMA
        break;
    }

    EnableOutput( FALSE );  // prevent output on reference device
    mbScreenComp = FALSE;

    // invalidate currently selected fonts
    mbInitFont = TRUE;
    mbNewFont = TRUE;

    // avoid adjusting font lists when already in refdev mode
    BYTE nOldRefDevMode = meRefDevMode;
    meRefDevMode = (BYTE)eRefDevMode;
    if( nOldRefDevMode != REFDEV_NONE )
        return;

    // the reference device should have only scalable fonts
    // => clean up the original font lists before getting new ones
    if ( mpFontEntry )
    {
        mpFontCache->Release( mpFontEntry );
        mpFontEntry = NULL;
    }
    if ( mpGetDevFontList )
    {
        delete mpGetDevFontList;
        mpGetDevFontList = NULL;
    }
    if ( mpGetDevSizeList )
    {
        delete mpGetDevSizeList;
        mpGetDevSizeList = NULL;
    }

    // preserve global font lists
    ImplSVData* pSVData = ImplGetSVData();
    if( mpFontList && (mpFontList != pSVData->maGDIData.mpScreenFontList) )
        delete mpFontList;
    if( mpFontCache && (mpFontCache != pSVData->maGDIData.mpScreenFontCache) )
        delete mpFontCache;

    // get font list with scalable fonts only
    ImplGetGraphics();
    mpFontList = pSVData->maGDIData.mpScreenFontList->Clone( true, false );

    // prepare to use new font lists
    mpFontCache = new ImplFontCache( false );
}

// -----------------------------------------------------------------------
<commit_msg>INTEGRATION: CWS c02v1 (1.15.34); FILE MERGED 2004/08/18 15:52:05 thb 1.15.34.1: #i32109#: Fill opaque areas reliably, apply bitmasks only where mask is opaque<commit_after>/*************************************************************************
 *
 *  $RCSfile: virdev.cxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: kz $ $Date: 2004-08-31 14:59:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SV_SVSYS_HXX
#include <svsys.h>
#endif

#ifndef _SV_SALINST_HXX
#include <salinst.hxx>
#endif
#ifndef _SV_SALGDI_HXX
#include <salgdi.hxx>
#endif
#ifndef _SV_SALFRAME_HXX
#include <salframe.hxx>
#endif
#ifndef _SV_SALVD_HXX
#include <salvd.hxx>
#endif

#ifndef _DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _SV_SVDATA_HXX
#include <svdata.hxx>
#endif
#ifndef _SV_SETTINGS_HXX
#include <settings.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <svapp.hxx>
#endif
#ifndef _SV_WRKWIN_HXX
#include <wrkwin.hxx>
#endif
#ifndef _SV_OUTDEV_H
#include <outdev.h>
#endif
#ifndef _SV_VIRDEV_HXX
#include <virdev.hxx>
#endif

using namespace ::com::sun::star::uno;

// =======================================================================

void VirtualDevice::ImplInitVirDev( const OutputDevice* pOutDev,
                                    long nDX, long nDY, USHORT nBitCount )
{
    DBG_ASSERT( nBitCount <= 1,
                "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" );

    if ( nDX < 1 )
        nDX = 1;

    if ( nDY < 1 )
        nDY = 1;

    ImplSVData* pSVData = ImplGetSVData();

    if ( !pOutDev )
        pOutDev = ImplGetDefaultWindow();

    SalGraphics* pGraphics;
    if ( !pOutDev->mpGraphics )
        ((OutputDevice*)pOutDev)->ImplGetGraphics();
    pGraphics = pOutDev->mpGraphics;
    if ( pGraphics )
        mpVirDev = pSVData->mpDefInst->CreateVirtualDevice( pGraphics, nDX, nDY, nBitCount );
    else
        mpVirDev = NULL;
    if ( !mpVirDev )
        GetpApp()->Exception( EXC_SYSOBJNOTCREATED );

    mnBitCount      = ( nBitCount ? nBitCount : pOutDev->GetBitCount() );
    mnOutWidth      = nDX;
    mnOutHeight     = nDY;
    mbScreenComp    = TRUE;
    mbScreenComp    = FALSE;
    mnAlphaDepth    = -1;

    if( mnBitCount < 8 )
        SetAntialiasing( ANTIALIASING_DISABLE_TEXT );

    if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
        mbScreenComp = FALSE;
    else if ( pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
        mbScreenComp = ((VirtualDevice*)pOutDev)->mbScreenComp;

    meOutDevType    = OUTDEV_VIRDEV;
    mbDevOutput     = TRUE;
    mpFontList      = pSVData->maGDIData.mpScreenFontList;
    mpFontCache     = pSVData->maGDIData.mpScreenFontCache;
    mnDPIX          = pOutDev->mnDPIX;
    mnDPIY          = pOutDev->mnDPIY;
    maFont          = pOutDev->maFont;

    // Virtuelle Devices haben defaultmaessig einen weissen Hintergrund
    SetBackground( Wallpaper( Color( COL_WHITE ) ) );
    Erase();

    // VirDev in Liste eintragen
    mpNext = pSVData->maGDIData.mpFirstVirDev;
    mpPrev = NULL;
    if ( mpNext )
        mpNext->mpPrev = this;
    else
        pSVData->maGDIData.mpLastVirDev = this;
    pSVData->maGDIData.mpFirstVirDev = this;
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( USHORT nBitCount )
:   mpVirDev( NULL ),
    meRefDevMode( REFDEV_NONE )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount );
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, USHORT nBitCount )
    : mpVirDev( NULL ),
    meRefDevMode( REFDEV_NONE )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( &rCompDev, 1, 1, nBitCount );
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, USHORT nBitCount, USHORT nAlphaBitCount )
    : mpVirDev( NULL )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( &rCompDev, 1, 1, nBitCount );

    // #110958# Enable alpha channel
    mnAlphaDepth = nAlphaBitCount;
}

// -----------------------------------------------------------------------

VirtualDevice::~VirtualDevice()
{
    DBG_TRACE( "VirtualDevice::~VirtualDevice()" );

    ImplSVData* pSVData = ImplGetSVData();

    ImplReleaseGraphics();

    if ( mpVirDev )
        pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );

    // remove this VirtualDevice from the double-linked global list
    if( mpPrev )
        mpPrev->mpNext = mpNext;
    else
        pSVData->maGDIData.mpFirstVirDev = mpNext;

    if( mpNext )
        mpNext->mpPrev = mpPrev;
    else
        pSVData->maGDIData.mpLastVirDev = mpPrev;
}

// -----------------------------------------------------------------------

BOOL VirtualDevice::ImplSetOutputSizePixel( const Size& rNewSize, BOOL bErase )
{
    DBG_TRACE3( "VirtualDevice::ImplSetOutputSizePixel( %ld, %ld, %d )", rNewSize.Width(), rNewSize.Height(), (int)bErase );

    if ( !mpVirDev )
        return FALSE;
    else if ( rNewSize == GetOutputSizePixel() )
    {
        if ( bErase )
            Erase();
        return TRUE;
    }

    BOOL bRet;
    long nNewWidth = rNewSize.Width(), nNewHeight = rNewSize.Height();

    if ( nNewWidth < 1 )
        nNewWidth = 1;

    if ( nNewHeight < 1 )
        nNewHeight = 1;

    if ( bErase )
    {
        bRet = mpVirDev->SetSize( nNewWidth, nNewHeight );

        if ( bRet )
        {
            mnOutWidth  = rNewSize.Width();
            mnOutHeight = rNewSize.Height();
            Erase();
        }
    }
    else
    {
        SalVirtualDevice*   pNewVirDev;
        ImplSVData*         pSVData = ImplGetSVData();

        // we need a graphics
        if ( !mpGraphics )
        {
            if ( !ImplGetGraphics() )
                return FALSE;
        }

        pNewVirDev = pSVData->mpDefInst->CreateVirtualDevice( mpGraphics, nNewWidth, nNewHeight, mnBitCount );
        if ( pNewVirDev )
        {
            SalGraphics* pGraphics = pNewVirDev->GetGraphics();
            if ( pGraphics )
            {
                SalTwoRect aPosAry;
                long nWidth;
                long nHeight;
                if ( mnOutWidth < nNewWidth )
                    nWidth = mnOutWidth;
                else
                    nWidth = nNewWidth;
                if ( mnOutHeight < nNewHeight )
                    nHeight = mnOutHeight;
                else
                    nHeight = nNewHeight;
                aPosAry.mnSrcX       = 0;
                aPosAry.mnSrcY       = 0;
                aPosAry.mnSrcWidth   = nWidth;
                aPosAry.mnSrcHeight  = nHeight;
                aPosAry.mnDestX      = 0;
                aPosAry.mnDestY      = 0;
                aPosAry.mnDestWidth  = nWidth;
                aPosAry.mnDestHeight = nHeight;

                pGraphics->CopyBits( &aPosAry, mpGraphics, this, this );
                pNewVirDev->ReleaseGraphics( pGraphics );
                ImplReleaseGraphics();
                pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );
                mpVirDev = pNewVirDev;
                mnOutWidth  = rNewSize.Width();
                mnOutHeight = rNewSize.Height();
                bRet = TRUE;
            }
            else
            {
                bRet = FALSE;
                pSVData->mpDefInst->DestroyVirtualDevice( pNewVirDev );
            }
        }
        else
            bRet = FALSE;
    }

    return bRet;
}

// -----------------------------------------------------------------------

// #i32109#: Fill opaque areas correctly (without relying on
// fill/linecolor state)
void VirtualDevice::ImplFillOpaqueRectangle( const Rectangle& rRect )
{
    // Set line and fill color to black (->opaque),
    // fill rect with that (linecolor, too, because of
    // those pesky missing pixel problems)
    Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
    SetLineColor( COL_BLACK );
    SetFillColor( COL_BLACK );
    DrawRect( rRect );
    Pop();
}

// -----------------------------------------------------------------------

BOOL VirtualDevice::SetOutputSizePixel( const Size& rNewSize, BOOL bErase )
{
    if( ImplSetOutputSizePixel(rNewSize, bErase) )
    {
        if( mnAlphaDepth != -1 )
        {
            // #110958# Setup alpha bitmap
            if(mpAlphaVDev && mpAlphaVDev->GetOutputSizePixel() != rNewSize)
            {
                delete mpAlphaVDev;
                mpAlphaVDev = 0L;
            }

            if( !mpAlphaVDev )
            {
                mpAlphaVDev = new VirtualDevice( *this, mnAlphaDepth );
                mpAlphaVDev->ImplSetOutputSizePixel(rNewSize, bErase);
            }

            // TODO: copy full outdev state to new one, here. Also needed in outdev2.cxx:DrawOutDev
            if( GetLineColor() != Color( COL_TRANSPARENT ) )
                mpAlphaVDev->SetLineColor( COL_BLACK );

            if( GetFillColor() != Color( COL_TRANSPARENT ) )
                mpAlphaVDev->SetFillColor( COL_BLACK );

            mpAlphaVDev->SetMapMode( GetMapMode() );
        }

        return TRUE;
    }

    return FALSE;
}

// -----------------------------------------------------------------------

void VirtualDevice::SetReferenceDevice( RefDevMode eRefDevMode )
{
    switch( eRefDevMode )
    {
    case REFDEV_NONE:
    default:
        DBG_ASSERT( FALSE, "VDev::SetRefDev illegal argument!" );
        // fall through
    case REFDEV_MODE06:
        mnDPIX = mnDPIY = 600;
        break;
    case REFDEV_MODE48:
        mnDPIX = mnDPIY = 4800;
        break;
    case REFDEV_MODE96:
        mnDPIX = mnDPIY = 1440; // as agreed with FME and AMA
        break;
    }

    EnableOutput( FALSE );  // prevent output on reference device
    mbScreenComp = FALSE;

    // invalidate currently selected fonts
    mbInitFont = TRUE;
    mbNewFont = TRUE;

    // avoid adjusting font lists when already in refdev mode
    BYTE nOldRefDevMode = meRefDevMode;
    meRefDevMode = (BYTE)eRefDevMode;
    if( nOldRefDevMode != REFDEV_NONE )
        return;

    // the reference device should have only scalable fonts
    // => clean up the original font lists before getting new ones
    if ( mpFontEntry )
    {
        mpFontCache->Release( mpFontEntry );
        mpFontEntry = NULL;
    }
    if ( mpGetDevFontList )
    {
        delete mpGetDevFontList;
        mpGetDevFontList = NULL;
    }
    if ( mpGetDevSizeList )
    {
        delete mpGetDevSizeList;
        mpGetDevSizeList = NULL;
    }

    // preserve global font lists
    ImplSVData* pSVData = ImplGetSVData();
    if( mpFontList && (mpFontList != pSVData->maGDIData.mpScreenFontList) )
        delete mpFontList;
    if( mpFontCache && (mpFontCache != pSVData->maGDIData.mpScreenFontCache) )
        delete mpFontCache;

    // get font list with scalable fonts only
    ImplGetGraphics();
    mpFontList = pSVData->maGDIData.mpScreenFontList->Clone( true, false );

    // prepare to use new font lists
    mpFontCache = new ImplFontCache( false );
}

// -----------------------------------------------------------------------
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/sys_info.h"

#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/string_tokenizer.h"
#include "base/string_util.h"

namespace base {

#if defined(OFFICIAL_BUILD)
static const char kLinuxStandardBaseVersionKey[] = "GOOGLE_RELEASE";
#else
static const char kLinuxStandardBaseVersionKey[] = "DISTRIB_RELEASE";
#endif

const char kLinuxStandardBaseReleaseFile[] = "/etc/lsb-release";

// static
void SysInfo::OperatingSystemVersionNumbers(int32 *major_version,
                                            int32 *minor_version,
                                            int32 *bugfix_version) {
  // TODO(cmasone): If this gets called a lot, it may kill performance.
  // consider using static variables to cache these values?
  FilePath path(kLinuxStandardBaseReleaseFile);
  std::string contents;
  if (file_util::ReadFileToString(path, &contents)) {
    ParseLsbRelease(contents, major_version, minor_version, bugfix_version);
  }
}

// static
std::string SysInfo::GetLinuxStandardBaseVersionKey() {
  return std::string(kLinuxStandardBaseVersionKey);
}

// static
void SysInfo::ParseLsbRelease(const std::string& lsb_release,
                              int32 *major_version,
                              int32 *minor_version,
                              int32 *bugfix_version) {
  size_t version_key_index =
      lsb_release.find(kLinuxStandardBaseVersionKey,
                       arraysize(kLinuxStandardBaseVersionKey) - 1);
  if (std::string::npos == version_key_index) {
    return;
  }
  size_t start_index = lsb_release.find_first_of('=', version_key_index);
  start_index++;  // Move past '='.
  size_t length = lsb_release.find_first_of('\n', start_index) - start_index;
  std::string version = lsb_release.substr(start_index, length);
  StringTokenizer tokenizer(version, ".");
  for (int i = 0; i < 3 && tokenizer.GetNext(); i++) {
    if (0 == i) {
      *major_version = StringToInt(tokenizer.token());
      *minor_version = *bugfix_version = 0;
    } else if (1 == i) {
      *minor_version = StringToInt(tokenizer.token());
    } else {  // 2 == i
      *bugfix_version = StringToInt(tokenizer.token());
    }
  }
}

}  // namespace base
<commit_msg>We want GOOGLE_CHROME_BUILDs on Chrome OS to get the appropriate OS version info. Review URL: http://codereview.chromium.org/294003<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/sys_info.h"

#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/string_tokenizer.h"
#include "base/string_util.h"

namespace base {

#if defined(GOOGLE_CHROME_BUILD)
static const char kLinuxStandardBaseVersionKey[] = "GOOGLE_RELEASE";
#else
static const char kLinuxStandardBaseVersionKey[] = "DISTRIB_RELEASE";
#endif

const char kLinuxStandardBaseReleaseFile[] = "/etc/lsb-release";

// static
void SysInfo::OperatingSystemVersionNumbers(int32 *major_version,
                                            int32 *minor_version,
                                            int32 *bugfix_version) {
  // TODO(cmasone): If this gets called a lot, it may kill performance.
  // consider using static variables to cache these values?
  FilePath path(kLinuxStandardBaseReleaseFile);
  std::string contents;
  if (file_util::ReadFileToString(path, &contents)) {
    ParseLsbRelease(contents, major_version, minor_version, bugfix_version);
  }
}

// static
std::string SysInfo::GetLinuxStandardBaseVersionKey() {
  return std::string(kLinuxStandardBaseVersionKey);
}

// static
void SysInfo::ParseLsbRelease(const std::string& lsb_release,
                              int32 *major_version,
                              int32 *minor_version,
                              int32 *bugfix_version) {
  size_t version_key_index =
      lsb_release.find(kLinuxStandardBaseVersionKey,
                       arraysize(kLinuxStandardBaseVersionKey) - 1);
  if (std::string::npos == version_key_index) {
    return;
  }
  size_t start_index = lsb_release.find_first_of('=', version_key_index);
  start_index++;  // Move past '='.
  size_t length = lsb_release.find_first_of('\n', start_index) - start_index;
  std::string version = lsb_release.substr(start_index, length);
  StringTokenizer tokenizer(version, ".");
  for (int i = 0; i < 3 && tokenizer.GetNext(); i++) {
    if (0 == i) {
      *major_version = StringToInt(tokenizer.token());
      *minor_version = *bugfix_version = 0;
    } else if (1 == i) {
      *minor_version = StringToInt(tokenizer.token());
    } else {  // 2 == i
      *bugfix_version = StringToInt(tokenizer.token());
    }
  }
}

}  // namespace base
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Tests for Watchdog class.

#include "base/watchdog.h"

#include "base/logging.h"
#include "base/platform_thread.h"
#include "base/spin_wait.h"
#include "base/time.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::TimeDelta;
using base::TimeTicks;

namespace {

//------------------------------------------------------------------------------
// Provide a derived class to facilitate testing.

class WatchdogCounter : public Watchdog {
 public:
  WatchdogCounter(const TimeDelta& duration,
                  const std::string& thread_watched_name,
                  bool enabled)
      : Watchdog(duration, thread_watched_name, enabled), alarm_counter_(0) {
  }

  virtual ~WatchdogCounter() {}

  virtual void Alarm() {
    alarm_counter_++;
    Watchdog::Alarm();
  }

  int alarm_counter() { return alarm_counter_; }

 private:
  int alarm_counter_;

  DISALLOW_COPY_AND_ASSIGN(WatchdogCounter);
};

class WatchdogTest : public testing::Test {
 public:
  void SetUp() {
    Watchdog::ResetStaticData();
  }
};

//------------------------------------------------------------------------------
// Actual tests

// Minimal constructor/destructor test.
TEST_F(WatchdogTest, StartupShutdownTest) {
  Watchdog watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false);
  Watchdog watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true);
}

// Test ability to call Arm and Disarm repeatedly.
TEST_F(WatchdogTest, ArmDisarmTest) {
  Watchdog watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false);
  watchdog1.Arm();
  watchdog1.Disarm();
  watchdog1.Arm();
  watchdog1.Disarm();

  Watchdog watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true);
  watchdog2.Arm();
  watchdog2.Disarm();
  watchdog2.Arm();
  watchdog2.Disarm();
}

// Make sure a basic alarm fires when the time has expired.
TEST_F(WatchdogTest, AlarmTest) {
  WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), "Enabled", true);
  watchdog.Arm();
  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
                                   watchdog.alarm_counter() > 0);
  EXPECT_EQ(1, watchdog.alarm_counter());
}

// Make sure a basic alarm fires when the time has expired.
TEST_F(WatchdogTest, AlarmPriorTimeTest) {
  WatchdogCounter watchdog(TimeDelta::TimeDelta(), "Enabled2", true);
  // Set a time in the past.
  watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(2));
  // It should instantly go off, but certainly in less than 5 minutes.
  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
                                   watchdog.alarm_counter() > 0);

  EXPECT_EQ(1, watchdog.alarm_counter());
}

// Make sure a disable alarm does nothing, even if we arm it.
TEST_F(WatchdogTest, ConstructorDisabledTest) {
  WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), "Disabled", false);
  watchdog.Arm();
  // Alarm should not fire, as it was disabled.
  PlatformThread::Sleep(500);
  EXPECT_EQ(0, watchdog.alarm_counter());
}

// Make sure Disarming will prevent firing, even after Arming.
TEST_F(WatchdogTest, DisarmTest) {
  WatchdogCounter watchdog(TimeDelta::FromSeconds(1), "Enabled3", true);

  TimeTicks start = TimeTicks::Now();
  watchdog.Arm();
  PlatformThread::Sleep(100);  // Sleep a bit, but not past the alarm point.
  watchdog.Disarm();
  TimeTicks end = TimeTicks::Now();

  if (end - start > TimeDelta::FromMilliseconds(500)) {
    LOG(WARNING) << "100ms sleep took over 500ms, making the results of this "
                 << "timing-sensitive test suspicious.  Aborting now.";
    return;
  }

  // Alarm should not have fired before it was disarmed.
  EXPECT_EQ(0, watchdog.alarm_counter());

  // Sleep past the point where it would have fired if it wasn't disarmed,
  // and verify that it didn't fire.
  PlatformThread::Sleep(1000);
  EXPECT_EQ(0, watchdog.alarm_counter());

  // ...but even after disarming, we can still use the alarm...
  // Set a time greater than the timeout into the past.
  watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(10));
  // It should almost instantly go off, but certainly in less than 5 minutes.
  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
                                   watchdog.alarm_counter() > 0);

  EXPECT_EQ(1, watchdog.alarm_counter());
}

}  // namespace
<commit_msg>[Linux] Fix base_unittests for GCC 4.5.1<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Tests for Watchdog class.

#include "base/watchdog.h"

#include "base/logging.h"
#include "base/platform_thread.h"
#include "base/spin_wait.h"
#include "base/time.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::TimeDelta;
using base::TimeTicks;

namespace {

//------------------------------------------------------------------------------
// Provide a derived class to facilitate testing.

class WatchdogCounter : public Watchdog {
 public:
  WatchdogCounter(const TimeDelta& duration,
                  const std::string& thread_watched_name,
                  bool enabled)
      : Watchdog(duration, thread_watched_name, enabled), alarm_counter_(0) {
  }

  virtual ~WatchdogCounter() {}

  virtual void Alarm() {
    alarm_counter_++;
    Watchdog::Alarm();
  }

  int alarm_counter() { return alarm_counter_; }

 private:
  int alarm_counter_;

  DISALLOW_COPY_AND_ASSIGN(WatchdogCounter);
};

class WatchdogTest : public testing::Test {
 public:
  void SetUp() {
    Watchdog::ResetStaticData();
  }
};

//------------------------------------------------------------------------------
// Actual tests

// Minimal constructor/destructor test.
TEST_F(WatchdogTest, StartupShutdownTest) {
  Watchdog watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false);
  Watchdog watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true);
}

// Test ability to call Arm and Disarm repeatedly.
TEST_F(WatchdogTest, ArmDisarmTest) {
  Watchdog watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false);
  watchdog1.Arm();
  watchdog1.Disarm();
  watchdog1.Arm();
  watchdog1.Disarm();

  Watchdog watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true);
  watchdog2.Arm();
  watchdog2.Disarm();
  watchdog2.Arm();
  watchdog2.Disarm();
}

// Make sure a basic alarm fires when the time has expired.
TEST_F(WatchdogTest, AlarmTest) {
  WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), "Enabled", true);
  watchdog.Arm();
  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
                                   watchdog.alarm_counter() > 0);
  EXPECT_EQ(1, watchdog.alarm_counter());
}

// Make sure a basic alarm fires when the time has expired.
TEST_F(WatchdogTest, AlarmPriorTimeTest) {
  WatchdogCounter watchdog(TimeDelta(), "Enabled2", true);
  // Set a time in the past.
  watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(2));
  // It should instantly go off, but certainly in less than 5 minutes.
  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
                                   watchdog.alarm_counter() > 0);

  EXPECT_EQ(1, watchdog.alarm_counter());
}

// Make sure a disable alarm does nothing, even if we arm it.
TEST_F(WatchdogTest, ConstructorDisabledTest) {
  WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), "Disabled", false);
  watchdog.Arm();
  // Alarm should not fire, as it was disabled.
  PlatformThread::Sleep(500);
  EXPECT_EQ(0, watchdog.alarm_counter());
}

// Make sure Disarming will prevent firing, even after Arming.
TEST_F(WatchdogTest, DisarmTest) {
  WatchdogCounter watchdog(TimeDelta::FromSeconds(1), "Enabled3", true);

  TimeTicks start = TimeTicks::Now();
  watchdog.Arm();
  PlatformThread::Sleep(100);  // Sleep a bit, but not past the alarm point.
  watchdog.Disarm();
  TimeTicks end = TimeTicks::Now();

  if (end - start > TimeDelta::FromMilliseconds(500)) {
    LOG(WARNING) << "100ms sleep took over 500ms, making the results of this "
                 << "timing-sensitive test suspicious.  Aborting now.";
    return;
  }

  // Alarm should not have fired before it was disarmed.
  EXPECT_EQ(0, watchdog.alarm_counter());

  // Sleep past the point where it would have fired if it wasn't disarmed,
  // and verify that it didn't fire.
  PlatformThread::Sleep(1000);
  EXPECT_EQ(0, watchdog.alarm_counter());

  // ...but even after disarming, we can still use the alarm...
  // Set a time greater than the timeout into the past.
  watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(10));
  // It should almost instantly go off, but certainly in less than 5 minutes.
  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
                                   watchdog.alarm_counter() > 0);

  EXPECT_EQ(1, watchdog.alarm_counter());
}

}  // namespace
<|endoftext|>


<commit_before>/*
 * SocketFunctions.c
 *
 *  Created on: Jan 31, 2014
 *      Author: d
 */

#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>

#include "BasicPacket.h"
#include "Server_Error.h"
#include "timing.h"

//function definitions

int sendall(size_t msgsize, void * buffer, int file_descriptor);
int receiveall(size_t msgsize, void * buffer, int file_descriptor);

bh_server_error SendPacket(bh_packet * packet, int filedesc) {
    if (packet == NULL || filedesc < 0) {
        return BH_SRVR_SENDERR;
    }

    // send the packet header, after the header is sent we send the data
    int res = sendall(sizeof(packet_header), &packet->header, filedesc);
    if( res == BH_SRVR_SUCCESS)
    {
       return sendall(packet->header.packetSize, packet->data, filedesc);
    }
    return res;
}

bh_server_error ReceivePacket(int filedesc, bh_packet * packet, long * dataBufferSize, buffer_type flag) {

    if (filedesc < 0 || packet == NULL || (flag != CREATE_BUFFER && dataBufferSize == NULL)) {
        return BH_SRVR_RECVERR;
    }

    int res = receiveall(sizeof(packet_header), &packet->header, filedesc);
    if(res != BH_SRVR_SUCCESS)
    {
        if(res != BH_SRVR_SOCKET_CLOSED)
            printf("Socket closed\n");
        return res;
    }
    // check incoming data size
    if(packet->header.packetSize > 0 )
    {
        // if we have allocated memory and the packet size does not surpass the maximum
        if (flag == STATIC_BUFFER )
        {
            if( packet->data != NULL && *dataBufferSize > 0 && packet->header.packetSize <= *dataBufferSize )
            {
                res = receiveall(packet->header.packetSize, packet->data, filedesc);
                if(res != BH_SRVR_SUCCESS)
                {
                    printf("Error during packet data receive\n");
                    return res;
                }
            }
            else if (packet->header.packetSize > *dataBufferSize)
                        return BH_SRVR_BUFFERSIZE_ERR;
            else
                return BH_SRVR_RECVERR;
        }
        // if we have allocated memory an want to allow reallocation of any size to happen
        else if (flag == DYNAMIC_BUFFER )
        {
            if(!(*dataBufferSize >= 0))
            {
                return BH_SRVR_BUFFERSIZE_ERR;
            }
            else if (packet->data == NULL)
            {
                return BH_SRVR_RECVERR;
            }
            // if the packet we will receive is larger than the buffer
            if(packet->header.packetSize > *dataBufferSize)
            {
                packet->data = realloc(packet->data, packet->header.packetSize);
                if (packet->data == NULL) {
                    printf("Realloc failed during packet receive\n");
                    *dataBufferSize = 0;
                    return BH_SRVR_OUT_OF_MEMORY;
                }
                *dataBufferSize = packet->header.packetSize;
            }

            res = receiveall(packet->header.packetSize, packet->data, filedesc);
            if(res != BH_SRVR_SUCCESS)
            {
                printf("Error during packet data receive\n");
                return res;
            }
        }
        // if we wish to allow the function to perform the memory allocation
        else if (flag == CREATE_BUFFER )
        {
            if(packet->data != NULL)
            {
                printf("Non NULL data pointer passed in ReceivePacket with CREATE_BUFFER flag\n");
            }

            packet->data = malloc(packet->header.packetSize);
            if (packet->data == NULL) {
                printf("Malloc failed during packet receive: %s\n", strerror(errno));
                return BH_SRVR_OUT_OF_MEMORY;
            }
            if(dataBufferSize!=NULL)
                *dataBufferSize = packet->header.packetSize;
            res = receiveall(packet->header.packetSize, packet->data, filedesc);
            if(res != BH_SRVR_SUCCESS)
            {
                free(packet->data);
                printf("Error during packet data receive\n");
                return res;
            }
        }
        else
        {
            printf("Unknown flag in ReceivePacket\n");
            return BH_SRVR_RECVERR;
        }

    }
    else if(packet->header.packetSize < 0)
    {
        printf("Negative packet size in ReceivePacket\n");
        return BH_SRVR_RECVERR;
    }

    return BH_SRVR_SUCCESS;
}

// this version is used to populate a buffer with updated data. Thus it is more strict in data
// alignment and checks.
bh_server_error ReceiveArrayPacket(int filedesc, bh_packet * packet, long dataBufferSize, packet_protocol messageType, long keyVal) {

    if (filedesc < 0 || packet == NULL || packet->data == NULL) {
        return BH_SRVR_RECVERR;
    }

    int res = receiveall(sizeof(packet_header), &packet->header, filedesc);
    if(res != BH_SRVR_SUCCESS)
    {
        if(res != BH_SRVR_SOCKET_CLOSED)
            printf("Socket closed\n");
        return res;
    }
    // check incoming data size
    if( packet->data != NULL &&
        packet->header.packetSize == dataBufferSize &&
        messageType == packet->header.packetID &&
        packet->header.key == keyVal )
    {
        res = receiveall(packet->header.packetSize, packet->data, filedesc);
        if(res != BH_SRVR_SUCCESS)
        {
            printf("Error during packet data receive\n");
            return res;
        }
    }
    else if (messageType != packet->header.packetID)
        return BH_SRVR_PROTOCOLMISMATCH;
    else if (packet->header.key != keyVal)
        return BH_SRVR_ARRAYKEYMISMATCH;
    else if (packet->header.packetSize != dataBufferSize)
        return BH_SRVR_BUFFERSIZE_ERR;
    else
        return BH_SRVR_RECVERR;
    return BH_SRVR_SUCCESS;
}

// basic send and receive functions

bh_server_error sendall(size_t msgsize, void * buffer, int file_descriptor) {
    //
    if(msgsize == 0 || buffer == NULL)
        return BH_SRVR_SUCCESS;

    timing_sleep();

    size_t sendSize = msgsize;
    int sendlen;
    // pointer to the data buffer
    void * ptr = buffer;

    do {
        sendlen = send(file_descriptor, ptr, sendSize, 0);
        if (sendlen == 0) {
            //file descriptor has closed
            printf("Connection lost during send\n");
            return BH_SRVR_SOCKET_CLOSED;
        } else if (sendlen < 0) {
            // send error
            printf("Send error: %s\n", strerror(errno));
            return BH_SRVR_SENDERR;
        }

        //move pointer to point where data has not been sent
        ptr = (char*) ptr + sendlen;
        //reduce sent size
        sendSize -= sendlen;

    } while (sendSize > 0);

    if (sendSize != 0) {
        if (sendSize > 0) {
            printf("Not all data has been sent during sendall\n");
        } else {
            printf("Error during sendall\n");
        }
    }
    //after the header is sent we should handle any preprocessing and then send the data
    return BH_SRVR_SUCCESS;
}

bh_server_error receiveall(size_t msgsize, void * buffer, int file_descriptor) {
    size_t recvSize = msgsize;
    int recvlen;
    // pointer to the data buffer
    void * ptr = buffer;

    timing_sleep();

    do {
        recvlen = recv(file_descriptor, ptr, recvSize, 0);
        if (recvlen == 0) {
            //file descriptor has closed
            if(recvSize == msgsize)
                printf("Connection closed\n");
            else
                printf("Connection closed during receiveall\n");
            return BH_SRVR_SOCKET_CLOSED;
        } else if (recvlen < 0) {
            // recv error
            printf("Recv error: %s\n", strerror(errno));
            return BH_SRVR_RECVERR;
        }

        //move pointer to point where data has not been sent
        ptr = (char*)ptr + recvlen;
        //reduce sent size
        recvSize -= recvlen;

    } while (recvSize > 0);

    if (recvSize != 0) {
        if (recvSize > 0) {
            printf("Data has not been received completely\n");
        } else {
            printf("Receive error in receiveall\n");
        }
    }
    //after the header is sent we should handle any preprocessing and then send the data
    return BH_SRVR_SUCCESS;
}

bh_packet * AllocatePacket(long datasize)
{
    bh_packet * packet = (bh_packet*) malloc(sizeof(bh_packet));
    memset(packet, '0', sizeof(bh_packet));
    packet->header.packetSize = datasize;
    packet->header.packetID = BH_PTC_UNKNOWN;
    packet->header.key = 0;
    if(datasize > 0)
    {
        packet->data = malloc(packet->header.packetSize);
        memset(packet->data, '0', sizeof(packet->header.packetSize));
    }
    else
        packet->data = NULL;
    return packet;
}

void FreePacket(bh_packet * packet)
{
    free(packet->data);
    free(packet);
}

<commit_msg>moved timing_sleep to after recv<commit_after>/*
 * SocketFunctions.c
 *
 *  Created on: Jan 31, 2014
 *      Author: d
 */

#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>

#include "BasicPacket.h"
#include "Server_Error.h"
#include "timing.h"

//function definitions

int sendall(size_t msgsize, void * buffer, int file_descriptor);
int receiveall(size_t msgsize, void * buffer, int file_descriptor);

bh_server_error SendPacket(bh_packet * packet, int filedesc) {
    if (packet == NULL || filedesc < 0) {
        return BH_SRVR_SENDERR;
    }

    // send the packet header, after the header is sent we send the data
    int res = sendall(sizeof(packet_header), &packet->header, filedesc);
    if( res == BH_SRVR_SUCCESS)
    {
       return sendall(packet->header.packetSize, packet->data, filedesc);
    }
    return res;
}

bh_server_error ReceivePacket(int filedesc, bh_packet * packet, long * dataBufferSize, buffer_type flag) {

    if (filedesc < 0 || packet == NULL || (flag != CREATE_BUFFER && dataBufferSize == NULL)) {
        return BH_SRVR_RECVERR;
    }

    int res = receiveall(sizeof(packet_header), &packet->header, filedesc);
    if(res != BH_SRVR_SUCCESS)
    {
        if(res != BH_SRVR_SOCKET_CLOSED)
            printf("Socket closed\n");
        return res;
    }
    // check incoming data size
    if(packet->header.packetSize > 0 )
    {
        // if we have allocated memory and the packet size does not surpass the maximum
        if (flag == STATIC_BUFFER )
        {
            if( packet->data != NULL && *dataBufferSize > 0 && packet->header.packetSize <= *dataBufferSize )
            {
                res = receiveall(packet->header.packetSize, packet->data, filedesc);
                if(res != BH_SRVR_SUCCESS)
                {
                    printf("Error during packet data receive\n");
                    return res;
                }
            }
            else if (packet->header.packetSize > *dataBufferSize)
                        return BH_SRVR_BUFFERSIZE_ERR;
            else
                return BH_SRVR_RECVERR;
        }
        // if we have allocated memory an want to allow reallocation of any size to happen
        else if (flag == DYNAMIC_BUFFER )
        {
            if(!(*dataBufferSize >= 0))
            {
                return BH_SRVR_BUFFERSIZE_ERR;
            }
            else if (packet->data == NULL)
            {
                return BH_SRVR_RECVERR;
            }
            // if the packet we will receive is larger than the buffer
            if(packet->header.packetSize > *dataBufferSize)
            {
                packet->data = realloc(packet->data, packet->header.packetSize);
                if (packet->data == NULL) {
                    printf("Realloc failed during packet receive\n");
                    *dataBufferSize = 0;
                    return BH_SRVR_OUT_OF_MEMORY;
                }
                *dataBufferSize = packet->header.packetSize;
            }

            res = receiveall(packet->header.packetSize, packet->data, filedesc);
            if(res != BH_SRVR_SUCCESS)
            {
                printf("Error during packet data receive\n");
                return res;
            }
        }
        // if we wish to allow the function to perform the memory allocation
        else if (flag == CREATE_BUFFER )
        {
            if(packet->data != NULL)
            {
                printf("Non NULL data pointer passed in ReceivePacket with CREATE_BUFFER flag\n");
            }

            packet->data = malloc(packet->header.packetSize);
            if (packet->data == NULL) {
                printf("Malloc failed during packet receive: %s\n", strerror(errno));
                return BH_SRVR_OUT_OF_MEMORY;
            }
            if(dataBufferSize!=NULL)
                *dataBufferSize = packet->header.packetSize;
            res = receiveall(packet->header.packetSize, packet->data, filedesc);
            if(res != BH_SRVR_SUCCESS)
            {
                free(packet->data);
                printf("Error during packet data receive\n");
                return res;
            }
        }
        else
        {
            printf("Unknown flag in ReceivePacket\n");
            return BH_SRVR_RECVERR;
        }

    }
    else if(packet->header.packetSize < 0)
    {
        printf("Negative packet size in ReceivePacket\n");
        return BH_SRVR_RECVERR;
    }

    return BH_SRVR_SUCCESS;
}

// this version is used to populate a buffer with updated data. Thus it is more strict in data
// alignment and checks.
bh_server_error ReceiveArrayPacket(int filedesc, bh_packet * packet, long dataBufferSize, packet_protocol messageType, long keyVal) {

    if (filedesc < 0 || packet == NULL || packet->data == NULL) {
        return BH_SRVR_RECVERR;
    }

    int res = receiveall(sizeof(packet_header), &packet->header, filedesc);
    if(res != BH_SRVR_SUCCESS)
    {
        if(res != BH_SRVR_SOCKET_CLOSED)
            printf("Socket closed\n");
        return res;
    }
    // check incoming data size
    if( packet->data != NULL &&
        packet->header.packetSize == dataBufferSize &&
        messageType == packet->header.packetID &&
        packet->header.key == keyVal )
    {
        res = receiveall(packet->header.packetSize, packet->data, filedesc);
        if(res != BH_SRVR_SUCCESS)
        {
            printf("Error during packet data receive\n");
            return res;
        }
    }
    else if (messageType != packet->header.packetID)
        return BH_SRVR_PROTOCOLMISMATCH;
    else if (packet->header.key != keyVal)
        return BH_SRVR_ARRAYKEYMISMATCH;
    else if (packet->header.packetSize != dataBufferSize)
        return BH_SRVR_BUFFERSIZE_ERR;
    else
        return BH_SRVR_RECVERR;
    return BH_SRVR_SUCCESS;
}

// basic send and receive functions

bh_server_error sendall(size_t msgsize, void * buffer, int file_descriptor) {
    //
    if(msgsize == 0 || buffer == NULL)
        return BH_SRVR_SUCCESS;

    timing_sleep();

    size_t sendSize = msgsize;
    int sendlen;
    // pointer to the data buffer
    void * ptr = buffer;

    do {
        sendlen = send(file_descriptor, ptr, sendSize, 0);
        if (sendlen == 0) {
            //file descriptor has closed
            printf("Connection lost during send\n");
            return BH_SRVR_SOCKET_CLOSED;
        } else if (sendlen < 0) {
            // send error
            printf("Send error: %s\n", strerror(errno));
            return BH_SRVR_SENDERR;
        }

        //move pointer to point where data has not been sent
        ptr = (char*) ptr + sendlen;
        //reduce sent size
        sendSize -= sendlen;

    } while (sendSize > 0);

    if (sendSize != 0) {
        if (sendSize > 0) {
            printf("Not all data has been sent during sendall\n");
        } else {
            printf("Error during sendall\n");
        }
    }
    //after the header is sent we should handle any preprocessing and then send the data
    return BH_SRVR_SUCCESS;
}

bh_server_error receiveall(size_t msgsize, void * buffer, int file_descriptor) {
    size_t recvSize = msgsize;
    int recvlen;
    // pointer to the data buffer
    void * ptr = buffer;

    do {
        recvlen = recv(file_descriptor, ptr, recvSize, 0);
        if (recvlen == 0) {
            //file descriptor has closed
            if(recvSize == msgsize)
                printf("Connection closed\n");
            else
                printf("Connection closed during receiveall\n");
            return BH_SRVR_SOCKET_CLOSED;
        } else if (recvlen < 0) {
            // recv error
            printf("Recv error: %s\n", strerror(errno));
            return BH_SRVR_RECVERR;
        }

        //move pointer to point where data has not been sent
        ptr = (char*)ptr + recvlen;
        //reduce sent size
        recvSize -= recvlen;

    } while (recvSize > 0);

    if (recvSize != 0) {
        if (recvSize > 0) {
            printf("Data has not been received completely\n");
        } else {
            printf("Receive error in receiveall\n");
        }
    }

    timing_sleep();

    //after the header is sent we should handle any preprocessing and then send the data
    return BH_SRVR_SUCCESS;
}

bh_packet * AllocatePacket(long datasize)
{
    bh_packet * packet = (bh_packet*) malloc(sizeof(bh_packet));
    memset(packet, '0', sizeof(bh_packet));
    packet->header.packetSize = datasize;
    packet->header.packetID = BH_PTC_UNKNOWN;
    packet->header.key = 0;
    if(datasize > 0)
    {
        packet->data = malloc(packet->header.packetSize);
        memset(packet->data, '0', sizeof(packet->header.packetSize));
    }
    else
        packet->data = NULL;
    return packet;
}

void FreePacket(bh_packet * packet)
{
    free(packet->data);
    free(packet);
}

<|endoftext|>


<commit_before>#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>

#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

extern "C" {
#include <lirc/lirc_client.h>
}

static const std::size_t UNIX_PATH_MAX = 108;

void ir_received(char* raw_code){
    std::string full_code(raw_code);

    auto code_end = full_code.find(' ');
    std::string code(full_code.begin(), full_code.begin() + code_end);

    auto repeat_end = full_code.find(' ', code_end + 1);
    std::string repeat(full_code.begin() + code_end + 1, full_code.begin() + repeat_end);

    auto key_end = full_code.find(' ', repeat_end + 1);
    std::string key(full_code.begin() + repeat_end + 1, full_code.begin() + key_end);

    std::cout << "Code: " << code << std::endl;
    std::cout << "Repeat: " << repeat << std::endl;
    std::cout << "Key: " << key << std::endl;
}

int main(){
    //Initiate LIRC. Exit on failure
    char lirc_name[] = "lirc";
    if(lirc_init(lirc_name, 1) == -1){
        std::cout << "asgard:ir: Failed to init LIRC" << std::endl;
        return 1;
    }

    //Open the socket
    auto socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
    if(socket_fd < 0){
        std::cout << "asgard:ir: socket() failed" << std::endl;
        return 1;
    }

    //Init the address
    struct sockaddr_un address;
    memset(&address, 0, sizeof(struct sockaddr_un));
    address.sun_family = AF_UNIX;
    snprintf(address.sun_path, UNIX_PATH_MAX, "/tmp/asgard_socket");

    //Connect to the server
    if(connect(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0){
        std::cout << "asgard:ir: connect() failed" << std::endl;
        return 1;
    }

    char buffer[4096];

    auto nbytes = snprintf(buffer, 4096, "hello from a client");
    write(socket_fd, buffer, nbytes);

    nbytes = read(socket_fd, buffer, 4096);
    buffer[nbytes] = 0;

    printf("MESSAGE FROM SERVER: %s\n", buffer);

    //Read the default LIRC config
    struct lirc_config* config;
    if(lirc_readconfig(NULL,&config,NULL)==0){
        char* code;

        //Do stuff while LIRC socket is open  0=open  -1=closed.
        while(lirc_nextcode(&code)==0){
            //If code = NULL, nothing was returned from LIRC socket
            if(code){
                //Send code further
                ir_received(code);

                //Need to free up code before the next loop
                free(code);
            }
        }

        //Frees the data structures associated with config.
        lirc_freeconfig(config);
    } else {
        std::cout << "asgard:ir: Failed to read LIRC config" << std::endl;
    }

    //Closes LIRC
    lirc_deinit();

    //Close the socket
    close(socket_fd);

    return 0;
}
<commit_msg>Send events to the server<commit_after>#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>

#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

extern "C" {
#include <lirc/lirc_client.h>
}

namespace {

const std::size_t UNIX_PATH_MAX = 108;

//Buffer
char buffer[4096];

void ir_received(int socket_fd, char* raw_code){
    std::string full_code(raw_code);

    auto code_end = full_code.find(' ');
    std::string code(full_code.begin(), full_code.begin() + code_end);

    auto repeat_end = full_code.find(' ', code_end + 1);
    std::string repeat(full_code.begin() + code_end + 1, full_code.begin() + repeat_end);

    auto key_end = full_code.find(' ', repeat_end + 1);
    std::string key(full_code.begin() + repeat_end + 1, full_code.begin() + key_end);

    std::cout << "asgard:ir: Received: " << code << ":" << repeat << ":" << key << std::endl;

    //Send the event to the server
    auto nbytes = snprintf(buffer, 4096, "EVENT IR %s", key.c_str());
    write(socket_fd, buffer, nbytes);
}

} //End of anonymous namespace

int main(){
    //Initiate LIRC. Exit on failure
    char lirc_name[] = "lirc";
    if(lirc_init(lirc_name, 1) == -1){
        std::cout << "asgard:ir: Failed to init LIRC" << std::endl;
        return 1;
    }

    //Open the socket
    auto socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
    if(socket_fd < 0){
        std::cout << "asgard:ir: socket() failed" << std::endl;
        return 1;
    }

    //Init the address
    struct sockaddr_un address;
    memset(&address, 0, sizeof(struct sockaddr_un));
    address.sun_family = AF_UNIX;
    snprintf(address.sun_path, UNIX_PATH_MAX, "/tmp/asgard_socket");

    //Connect to the server
    if(connect(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0){
        std::cout << "asgard:ir: connect() failed" << std::endl;
        return 1;
    }

    //Read the default LIRC config
    struct lirc_config* config;
    if(lirc_readconfig(NULL,&config,NULL)==0){
        char* code;

        //Do stuff while LIRC socket is open  0=open  -1=closed.
        while(lirc_nextcode(&code)==0){
            //If code = NULL, nothing was returned from LIRC socket
            if(code){
                //Send code further
                ir_received(socket_fd, code);

                //Need to free up code before the next loop
                free(code);
            }
        }

        //Frees the data structures associated with config.
        lirc_freeconfig(config);
    } else {
        std::cout << "asgard:ir: Failed to read LIRC config" << std::endl;
    }

    //Closes LIRC
    lirc_deinit();

    //Close the socket
    close(socket_fd);

    return 0;
}
<|endoftext|>


<commit_before><commit_msg>Fix checkfailure caused by stupidity.<commit_after><|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <random>

#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <signal.h>

namespace {

const std::size_t UNIX_PATH_MAX = 108;
const std::size_t buffer_size = 4096;

// Configuration (this should be in a configuration file)
const char* server_socket_path = "/tmp/asgard_socket";
const char* client_socket_path = "/tmp/asgard_random_socket";
const std::size_t delay_ms = 5000;

//Buffer
char write_buffer[buffer_size];
char receive_buffer[buffer_size];

// The socket file descriptor
int socket_fd;

// The socket addresses
struct sockaddr_un client_address;
struct sockaddr_un server_address;

// The remote IDs
int source_id = -1;
int sensor_id = -1;

void stop(){
    std::cout << "asgard:random: stop the driver" << std::endl;

    // Unregister the sensor, if necessary
    if(sensor_id >= 0){
        auto nbytes = snprintf(write_buffer, buffer_size, "UNREG_SENSOR %d %d", source_id, sensor_id);
        sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));
    }

    // Unregister the source, if necessary
    if(source_id >= 0){
        auto nbytes = snprintf(write_buffer, buffer_size, "UNREG_SOURCE %d", source_id);
        sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));
    }

    // Unlink the client socket
    unlink(client_socket_path);

    // Close the socket
    close(socket_fd);
}

void terminate(int){
    stop();

    std::exit(0);
}

} //End of anonymous namespace

int main(){
    // Open the socket
    socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if(socket_fd < 0){
        std::cerr << "asgard:random: socket() failed" << std::endl;
        return 1;
    }

    // Init the client address
    memset(&client_address, 0, sizeof(struct sockaddr_un));
    client_address.sun_family = AF_UNIX;
    snprintf(client_address.sun_path, UNIX_PATH_MAX, client_socket_path);

    // Unlink the client socket
    unlink(client_socket_path);

    // Bind to client socket
    if(bind(socket_fd, (const struct sockaddr *) &client_address, sizeof(struct sockaddr_un)) < 0){
        std::cerr << "asgard:random: bind() failed" << std::endl;
        return 1;
    }

    //Register signals for "proper" shutdown
    signal(SIGTERM, terminate);
    signal(SIGINT, terminate);

    // Init the server address
    memset(&server_address, 0, sizeof(struct sockaddr_un));
    server_address.sun_family = AF_UNIX;
    snprintf(server_address.sun_path, UNIX_PATH_MAX, server_socket_path);

    socklen_t address_length = sizeof(struct sockaddr_un);

    // Register the source
    auto nbytes = snprintf(write_buffer, buffer_size, "REG_SOURCE random");
    sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));

    auto bytes_received = recvfrom(socket_fd, receive_buffer, buffer_size, 0, (struct sockaddr *) &(server_address), &address_length);
    receive_buffer[bytes_received] = '\0';

    source_id = atoi(receive_buffer);

    std::cout << "asgard:random: remote source: " << source_id << std::endl;

    // Register the sensor
    nbytes = snprintf(write_buffer, buffer_size, "REG_SENSOR %d %s %s", source_id, "RANDOM", "rand_100");
    sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));

    bytes_received = recvfrom(socket_fd, receive_buffer, buffer_size, 0, (struct sockaddr *) &(server_address), &address_length);
    receive_buffer[bytes_received] = '\0';

    sensor_id = atoi(receive_buffer);

    std::cout << "asgard:random: remote sensor: " << sensor_id << std::endl;

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> distribution(1, 100);

    while(true){
        int value = distribution(gen);

        // Send the data
        nbytes = snprintf(write_buffer, buffer_size, "DATA %d %d %d", source_id, sensor_id, value);
        sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));

        // Wait some time before messages
        usleep(delay_ms * 1000);
    }

    stop();

    return 0;
}
<commit_msg>Update copyright<commit_after>//=======================================================================
// Copyright (c) 2015-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <random>

#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <signal.h>

namespace {

const std::size_t UNIX_PATH_MAX = 108;
const std::size_t buffer_size = 4096;

// Configuration (this should be in a configuration file)
const char* server_socket_path = "/tmp/asgard_socket";
const char* client_socket_path = "/tmp/asgard_random_socket";
const std::size_t delay_ms = 5000;

//Buffer
char write_buffer[buffer_size];
char receive_buffer[buffer_size];

// The socket file descriptor
int socket_fd;

// The socket addresses
struct sockaddr_un client_address;
struct sockaddr_un server_address;

// The remote IDs
int source_id = -1;
int sensor_id = -1;

void stop(){
    std::cout << "asgard:random: stop the driver" << std::endl;

    // Unregister the sensor, if necessary
    if(sensor_id >= 0){
        auto nbytes = snprintf(write_buffer, buffer_size, "UNREG_SENSOR %d %d", source_id, sensor_id);
        sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));
    }

    // Unregister the source, if necessary
    if(source_id >= 0){
        auto nbytes = snprintf(write_buffer, buffer_size, "UNREG_SOURCE %d", source_id);
        sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));
    }

    // Unlink the client socket
    unlink(client_socket_path);

    // Close the socket
    close(socket_fd);
}

void terminate(int){
    stop();

    std::exit(0);
}

} //End of anonymous namespace

int main(){
    // Open the socket
    socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if(socket_fd < 0){
        std::cerr << "asgard:random: socket() failed" << std::endl;
        return 1;
    }

    // Init the client address
    memset(&client_address, 0, sizeof(struct sockaddr_un));
    client_address.sun_family = AF_UNIX;
    snprintf(client_address.sun_path, UNIX_PATH_MAX, client_socket_path);

    // Unlink the client socket
    unlink(client_socket_path);

    // Bind to client socket
    if(bind(socket_fd, (const struct sockaddr *) &client_address, sizeof(struct sockaddr_un)) < 0){
        std::cerr << "asgard:random: bind() failed" << std::endl;
        return 1;
    }

    //Register signals for "proper" shutdown
    signal(SIGTERM, terminate);
    signal(SIGINT, terminate);

    // Init the server address
    memset(&server_address, 0, sizeof(struct sockaddr_un));
    server_address.sun_family = AF_UNIX;
    snprintf(server_address.sun_path, UNIX_PATH_MAX, server_socket_path);

    socklen_t address_length = sizeof(struct sockaddr_un);

    // Register the source
    auto nbytes = snprintf(write_buffer, buffer_size, "REG_SOURCE random");
    sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));

    auto bytes_received = recvfrom(socket_fd, receive_buffer, buffer_size, 0, (struct sockaddr *) &(server_address), &address_length);
    receive_buffer[bytes_received] = '\0';

    source_id = atoi(receive_buffer);

    std::cout << "asgard:random: remote source: " << source_id << std::endl;

    // Register the sensor
    nbytes = snprintf(write_buffer, buffer_size, "REG_SENSOR %d %s %s", source_id, "RANDOM", "rand_100");
    sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));

    bytes_received = recvfrom(socket_fd, receive_buffer, buffer_size, 0, (struct sockaddr *) &(server_address), &address_length);
    receive_buffer[bytes_received] = '\0';

    sensor_id = atoi(receive_buffer);

    std::cout << "asgard:random: remote sensor: " << sensor_id << std::endl;

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> distribution(1, 100);

    while(true){
        int value = distribution(gen);

        // Send the data
        nbytes = snprintf(write_buffer, buffer_size, "DATA %d %d %d", source_id, sensor_id, value);
        sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));

        // Wait some time before messages
        usleep(delay_ms * 1000);
    }

    stop();

    return 0;
}
<|endoftext|>