<commit_before>/*---------------------------------------------------------------
 * Copyright (c) 1999,2000,2001,2002,2003
 * The Board of Trustees of the University of Illinois
 * All Rights Reserved.
 *---------------------------------------------------------------
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software (Iperf) and associated
 * documentation files (the "Software"), to deal in the Software
 * without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit
 * persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 *
 * Redistributions of source code must retain the above
 * copyright notice, this list of conditions and
 * the following disclaimers.
 *
 *
 * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following
 * disclaimers in the documentation and/or other materials
 * provided with the distribution.
 *
 *
 * Neither the names of the University of Illinois, NCSA,
 * nor the names of its contributors may be used to endorse
 * or promote products derived from this Software without
 * specific prior written permission.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * ________________________________________________________________
 * National Laboratory for Applied Network Research
 * National Center for Supercomputing Applications
 * University of Illinois at Urbana-Champaign
 * http://www.ncsa.uiuc.edu
 * ________________________________________________________________
 * main.cpp
 * by Mark Gates <mgates@nlanr.net>
 * &  Ajay Tirumala <tirumala@ncsa.uiuc.edu>
 * -------------------------------------------------------------------
 * main does initialization and creates the various objects that will
 * actually run the iperf program, then waits in the Joinall().
 * -------------------------------------------------------------------
 * headers
 * uses
 *   <stdlib.h>
 *   <string.h>
 *
 *   <signal.h>
 * ------------------------------------------------------------------- */

#define HEADERS()

#include "headers.h"

#include "Client.hpp"
#include "Settings.hpp"
#include "Listener.hpp"
#include "Speaker.hpp"
#include "Locale.hpp"
#include "Condition.hpp"
#include "List.h"
#include "util.h"
//#include "ocomm/o_log.h"
//#include "oml_orbit_winlab_iperf.h"
extern "C" {
#include <oml2/omlc.h>
#include <oml2/o_log.h>
OmlMP* tcp_measure;
OmlMP* udp_measure;
OmlMP* peer_information;
static OmlMPDef tcp_receiverport[] = {
  {"ID", OML_LONG_VALUE},
  {"Begin_interval", OML_DOUBLE_VALUE},
  {"End_interval", OML_DOUBLE_VALUE},
  {"Transfer", OML_STRING_VALUE},
  {"Bandwidth", OML_STRING_VALUE},
  {NULL, (OmlValueT)0}
};
static OmlMPDef udp_receiverport[] = {
  {"ID", OML_LONG_VALUE},
  {"Begin_interval", OML_DOUBLE_VALUE},
  {"End_interval", OML_DOUBLE_VALUE},
  {"Transfer", OML_STRING_VALUE},
  {"Bandwidth", OML_STRING_VALUE},
  {"Jitter", OML_DOUBLE_VALUE},
  {"Packet_Lost", OML_LONG_VALUE},
  {"Total_Packet", OML_LONG_VALUE},
  {"PLR", OML_DOUBLE_VALUE},
  {NULL, (OmlValueT)0}
};
static OmlMPDef peer_info[] = {
  {"ID", OML_LONG_VALUE},
  {"local_address", OML_STRING_VALUE},
  {"local_port", OML_LONG_VALUE},
  {"foreign_address", OML_STRING_VALUE},
  {"foreign_port", OML_LONG_VALUE},
  {NULL, (OmlValueT)0}
};
}

#ifdef WIN32
    #include "service.h"
#endif

/* -------------------------------------------------------------------
 * prototypes
 * ------------------------------------------------------------------- */

void waitUntilQuit( void );

void sig_quit( int inSigno );

void cleanup( void );

/* -------------------------------------------------------------------
 * global variables
 * ------------------------------------------------------------------- */
#define GLOBAL()

Condition gQuit_cond;

/* -------------------------------------------------------------------
 * sets up signal handlers
 * parses settings from environment and command line
 * starts up server or client thread
 * waits for all threads to complete
 * ------------------------------------------------------------------- */

int main( int argc,  char *argv[] ) {

#ifdef WIN32
    SERVICE_TABLE_ENTRY dispatchTable[] =
    {
        { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main},
        { NULL, NULL}
    };
#endif

    omlc_init("iperf", &argc,  (const char**) argv, NULL);

    printf("ADD MP \n");
    tcp_measure = omlc_add_mp("TCP_received", tcp_receiverport);
    udp_measure = omlc_add_mp("UDP_received", udp_receiverport);
    peer_information = omlc_add_mp("Peer_Info", peer_info);

    Listener *theListener = NULL;
    Speaker  *theSpeaker  = NULL;

    // signal handlers quietly exit on ^C and kill
    // these are usually remapped later by the client or server
    my_signal( SIGTERM, sig_exit );
    my_signal( SIGINT,  sig_exit );

#ifndef WIN32
    signal(SIGPIPE,SIG_IGN);
#else
    WSADATA wsaData;
    int rc = WSAStartup( 0x202, &wsaData );
    FAIL_errno( rc == SOCKET_ERROR, "WSAStartup" );

    SetConsoleCtrlHandler( sig_dispatcher, true );
#endif

    // perform any cleanup when quitting Iperf
    atexit( cleanup );

    ext_Settings* ext_gSettings = new ext_Settings;
    Settings* gSettings = NULL;

    // read settings from environment variables and command-line interface
    gSettings = new Settings( ext_gSettings );
    gSettings->ParseEnvironment();
    gSettings->ParseCommandLine( argc, argv );

    // start up client or server (listener)
    if ( gSettings->GetServerMode() == kMode_Server ) {
        // start up a listener
        printf("OML_START 1\n");
        theListener = new Listener( ext_gSettings );
        printf("OML_START 2\n");
        theListener->DeleteSelfAfterRun();

        // Start the server as a daemon
        if ( gSettings->GetDaemonMode() == true ) {
#ifdef WIN32
            CmdInstallService(argc, argv);
            DELETE_PTR( theListener );
            DELETE_PTR( gSettings );

            return 0;
#else
            theListener->runAsDaemon(argv[0],LOG_DAEMON);
#endif
        }
#ifdef WIN32
          else {
            if ( gSettings->GetRemoveService() == true ) {
                // remove the service and continue to run as a normal process
                if ( CmdRemoveService() ) {
                    printf("IPerf Service is removed.\n");

                    DELETE_PTR( theListener );
                    DELETE_PTR( gSettings );

                    return 0;
                }
            } else {
                // try to start the service
                if ( CmdStartService(argc, argv) ) {
                    printf("IPerf Service already exists.\n");

                    DELETE_PTR( theListener );
                    DELETE_PTR( gSettings );

                    return 0;
                }
            }
        }
#endif
        omlc_start();
        theListener->Start();

        if ( ext_gSettings->mThreads == 0 ) {
            theListener->SetDaemon();

            // the listener keeps going; we terminate on user input only
            waitUntilQuit();
#ifdef HAVE_THREAD
            if ( Thread::NumUserThreads() > 0 ) {
                printf( wait_server_threads );
                fflush( 0 );
            }
#endif
        }
    } else if ( gSettings->GetServerMode() == kMode_Client ) {
#ifdef HAVE_THREAD
        theSpeaker = new Speaker(ext_gSettings);
        theSpeaker->OwnSettings();
        theSpeaker->DeleteSelfAfterRun();
        omlc_start();
        theSpeaker->Start();
#else
        // If we need to start up a listener do it now
        ext_Settings *temp = NULL;
        Settings::GenerateListenerSettings( ext_gSettings, &temp );
        if ( temp != NULL ) {
            theListener = new Listener( temp );
            theListener->DeleteSelfAfterRun();
        }
        Client* theClient = new Client( ext_gSettings );
        omlc_start();
        theClient->InitiateServer();
        theClient->Start();
        if ( theListener != NULL ) {
            theListener->Start();
        }
#endif
    } else {
        // neither server nor client mode was specified
        // print usage and exit

#ifdef WIN32

        // starting the service by SCM, there is no arguments will be passed in.
        // the arguments will pass into Service_Main entry.

        if ( !StartServiceCtrlDispatcher(dispatchTable) )
            printf(usage_short, argv[0], argv[0]);
#else
        printf( usage_short, argv[0], argv[0] );
#endif
    }

    // wait for other (client, server) threads to complete
    Thread::Joinall();
    DELETE_PTR( gSettings );  // modified by qfeng
    // all done!
    return 0;
} // end main

/* -------------------------------------------------------------------
 * Blocks the thread until a quit thread signal is sent
 * ------------------------------------------------------------------- */

void waitUntilQuit( void ) {
#ifdef HAVE_THREAD

    // signal handlers send quit signal on ^C and kill
    gQuit_cond.Lock();
    my_signal( SIGTERM, sig_quit );
    my_signal( SIGINT,  sig_quit );

#ifdef HAVE_USLEEP

    // this sleep is a hack to get around an apparent bug? in IRIX
    // where pthread_cancel doesn't work unless the thread
    // starts up before the gQuit_cand.Wait() call below.
    // A better solution is to just use sigwait here, but
    // then I have to emulate that for Windows...
    usleep( 10 );
#endif

    // wait for quit signal
    gQuit_cond.Wait();
    gQuit_cond.Unlock();
#endif
} // end waitUntilQuit

/* -------------------------------------------------------------------
 * Sends a quit thread signal to let the main thread quit nicely.
 * ------------------------------------------------------------------- */

void sig_quit( int inSigno ) {
#ifdef HAVE_THREAD

    // if we get a second signal after 1/10 second, exit
    // some implementations send the signal to all threads, so the 1/10 sec
    // allows us to ignore multiple receipts of the same signal
    static Timestamp* first = NULL;
    if ( first != NULL ) {
        Timestamp now;
        if ( now.subSec( *first ) > 0.1 ) {
            sig_exit( inSigno );
        }
    } else {
        first = new Timestamp();
    }

    // with threads, send a quit signal
    gQuit_cond.Signal();

#else

    // without threads, just exit quietly, same as sig_exit()
    sig_exit( inSigno );

#endif
} // end sig_quit

/* -------------------------------------------------------------------
 * Any necesary cleanup before Iperf quits. Called at program exit,
 * either by exit() or terminating main().
 * ------------------------------------------------------------------- */

void cleanup( void ) {
#ifdef WIN32
    WSACleanup();
#endif
    extern Iperf_ListEntry *clients;
    Iperf_destroy ( &clients );

} // end cleanup

#ifdef WIN32
/*--------------------------------------------------------------------
 * ServiceStart
 *
 * each time starting the service, this is the entry point of the service.
 * Start the service, certainly it is on server-mode
 *
 *
 *-------------------------------------------------------------------- */
VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv) {
    Listener *theListener = NULL;

    // report the status to the service control manager.
    //
    if ( !ReportStatusToSCMgr(
                             SERVICE_START_PENDING, // service state
                             NO_ERROR,              // exit code
                             3000) )                 // wait hint
        goto clean;

    ext_Settings* ext_gSettings = new ext_Settings;
    Settings *gSettings;

    // read settings from passing by StartService
    gSettings = new Settings( ext_gSettings );
    gSettings->ParseEnvironment();
    gSettings->ParseCommandLine( dwArgc, lpszArgv );

    // report the status to the service control manager.
    //
    if ( !ReportStatusToSCMgr(
                             SERVICE_START_PENDING, // service state
                             NO_ERROR,              // exit code
                             3000) )                 // wait hint
        goto clean;

    // if needed, redirect the output into a specified file
    if ( gSettings->GetFileOutput() ) {
        redirect(gSettings->GetOutputFileName());
    }

    // report the status to the service control manager.
    //
    if ( !ReportStatusToSCMgr(
                             SERVICE_START_PENDING, // service state
                             NO_ERROR,              // exit code
                             3000) )                 // wait hint
        goto clean;

    theListener = new Listener( ext_gSettings );

    theListener->Start();
    theListener->SetDaemon();

    // report the status to the service control manager.
    //
    if ( !ReportStatusToSCMgr(
                             SERVICE_RUNNING,       // service state
                             NO_ERROR,              // exit code
                             0) )                    // wait hint
        goto clean;

    // the listener keeps going; we terminate on user input only
    waitUntilQuit();
#ifdef HAVE_THREAD
    if ( Thread::NumUserThreads() > 0 ) {
        printf( wait_server_threads );
        fflush( 0 );
    }
#endif

    clean:
    // wait for other (client, server) threads to complete
    Thread::Joinall();
    DELETE_PTR( theListener );
    DELETE_PTR( gSettings );  // modified by qfeng
    DELETE_PTR( ext_gSettings );  // modified by qfeng
}

//
//  FUNCTION: ServiceStop
//
//  PURPOSE: Stops the service
//
//  PARAMETERS:
//    none
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:
//    If a ServiceStop procedure is going to
//    take longer than 3 seconds to execute,
//    it should spawn a thread to execute the
//    stop code, and return.  Otherwise, the
//    ServiceControlManager will believe that
//    the service has stopped responding.
//
VOID ServiceStop() {
#ifdef HAVE_THREAD
    gQuit_cond.Signal();
#else
    sig_exit(1);
#endif
}

#endif

<commit_msg>Remove some comments in iperf<commit_after>/*---------------------------------------------------------------
 * Copyright (c) 1999,2000,2001,2002,2003
 * The Board of Trustees of the University of Illinois
 * All Rights Reserved.
 *---------------------------------------------------------------
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software (Iperf) and associated
 * documentation files (the "Software"), to deal in the Software
 * without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit
 * persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 *
 * Redistributions of source code must retain the above
 * copyright notice, this list of conditions and
 * the following disclaimers.
 *
 *
 * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following
 * disclaimers in the documentation and/or other materials
 * provided with the distribution.
 *
 *
 * Neither the names of the University of Illinois, NCSA,
 * nor the names of its contributors may be used to endorse
 * or promote products derived from this Software without
 * specific prior written permission.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * ________________________________________________________________
 * National Laboratory for Applied Network Research
 * National Center for Supercomputing Applications
 * University of Illinois at Urbana-Champaign
 * http://www.ncsa.uiuc.edu
 * ________________________________________________________________
 * main.cpp
 * by Mark Gates <mgates@nlanr.net>
 * &  Ajay Tirumala <tirumala@ncsa.uiuc.edu>
 * -------------------------------------------------------------------
 * main does initialization and creates the various objects that will
 * actually run the iperf program, then waits in the Joinall().
 * -------------------------------------------------------------------
 * headers
 * uses
 *   <stdlib.h>
 *   <string.h>
 *
 *   <signal.h>
 * ------------------------------------------------------------------- */

#define HEADERS()

#include "headers.h"

#include "Client.hpp"
#include "Settings.hpp"
#include "Listener.hpp"
#include "Speaker.hpp"
#include "Locale.hpp"
#include "Condition.hpp"
#include "List.h"
#include "util.h"
//#include "ocomm/o_log.h"
//#include "oml_orbit_winlab_iperf.h"
extern "C" {
#include <oml2/omlc.h>
#include <oml2/o_log.h>
OmlMP* tcp_measure;
OmlMP* udp_measure;
OmlMP* peer_information;
static OmlMPDef tcp_receiverport[] = {
  {"ID", OML_LONG_VALUE},
  {"Begin_interval", OML_DOUBLE_VALUE},
  {"End_interval", OML_DOUBLE_VALUE},
  {"Transfer", OML_STRING_VALUE},
  {"Bandwidth", OML_STRING_VALUE},
  {NULL, (OmlValueT)0}
};
static OmlMPDef udp_receiverport[] = {
  {"ID", OML_LONG_VALUE},
  {"Begin_interval", OML_DOUBLE_VALUE},
  {"End_interval", OML_DOUBLE_VALUE},
  {"Transfer", OML_STRING_VALUE},
  {"Bandwidth", OML_STRING_VALUE},
  {"Jitter", OML_DOUBLE_VALUE},
  {"Packet_Lost", OML_LONG_VALUE},
  {"Total_Packet", OML_LONG_VALUE},
  {"PLR", OML_DOUBLE_VALUE},
  {NULL, (OmlValueT)0}
};
static OmlMPDef peer_info[] = {
  {"ID", OML_LONG_VALUE},
  {"local_address", OML_STRING_VALUE},
  {"local_port", OML_LONG_VALUE},
  {"foreign_address", OML_STRING_VALUE},
  {"foreign_port", OML_LONG_VALUE},
  {NULL, (OmlValueT)0}
};
}

#ifdef WIN32
    #include "service.h"
#endif

/* -------------------------------------------------------------------
 * prototypes
 * ------------------------------------------------------------------- */

void waitUntilQuit( void );

void sig_quit( int inSigno );

void cleanup( void );

/* -------------------------------------------------------------------
 * global variables
 * ------------------------------------------------------------------- */
#define GLOBAL()

Condition gQuit_cond;

/* -------------------------------------------------------------------
 * sets up signal handlers
 * parses settings from environment and command line
 * starts up server or client thread
 * waits for all threads to complete
 * ------------------------------------------------------------------- */

int main( int argc,  char *argv[] ) {

#ifdef WIN32
    SERVICE_TABLE_ENTRY dispatchTable[] =
    {
        { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main},
        { NULL, NULL}
    };
#endif

    omlc_init("iperf", &argc,  (const char**) argv, NULL);

    printf("ADD MP \n");
    tcp_measure = omlc_add_mp("TCP_received", tcp_receiverport);
    udp_measure = omlc_add_mp("UDP_received", udp_receiverport);
    peer_information = omlc_add_mp("Peer_Info", peer_info);

    Listener *theListener = NULL;
    Speaker  *theSpeaker  = NULL;

    // signal handlers quietly exit on ^C and kill
    // these are usually remapped later by the client or server
    my_signal( SIGTERM, sig_exit );
    my_signal( SIGINT,  sig_exit );

#ifndef WIN32
    signal(SIGPIPE,SIG_IGN);
#else
    WSADATA wsaData;
    int rc = WSAStartup( 0x202, &wsaData );
    FAIL_errno( rc == SOCKET_ERROR, "WSAStartup" );

    SetConsoleCtrlHandler( sig_dispatcher, true );
#endif

    // perform any cleanup when quitting Iperf
    atexit( cleanup );

    ext_Settings* ext_gSettings = new ext_Settings;
    Settings* gSettings = NULL;

    // read settings from environment variables and command-line interface
    gSettings = new Settings( ext_gSettings );
    gSettings->ParseEnvironment();
    gSettings->ParseCommandLine( argc, argv );

    // start up client or server (listener)
    if ( gSettings->GetServerMode() == kMode_Server ) {
        // start up a listener
        theListener = new Listener( ext_gSettings );
        theListener->DeleteSelfAfterRun();

        // Start the server as a daemon
        if ( gSettings->GetDaemonMode() == true ) {
#ifdef WIN32
            CmdInstallService(argc, argv);
            DELETE_PTR( theListener );
            DELETE_PTR( gSettings );

            return 0;
#else
            theListener->runAsDaemon(argv[0],LOG_DAEMON);
#endif
        }
#ifdef WIN32
          else {
            if ( gSettings->GetRemoveService() == true ) {
                // remove the service and continue to run as a normal process
                if ( CmdRemoveService() ) {
                    printf("IPerf Service is removed.\n");

                    DELETE_PTR( theListener );
                    DELETE_PTR( gSettings );

                    return 0;
                }
            } else {
                // try to start the service
                if ( CmdStartService(argc, argv) ) {
                    printf("IPerf Service already exists.\n");

                    DELETE_PTR( theListener );
                    DELETE_PTR( gSettings );

                    return 0;
                }
            }
        }
#endif
        omlc_start();
        theListener->Start();

        if ( ext_gSettings->mThreads == 0 ) {
            theListener->SetDaemon();

            // the listener keeps going; we terminate on user input only
            waitUntilQuit();
#ifdef HAVE_THREAD
            if ( Thread::NumUserThreads() > 0 ) {
                printf( wait_server_threads );
                fflush( 0 );
            }
#endif
        }
    } else if ( gSettings->GetServerMode() == kMode_Client ) {
#ifdef HAVE_THREAD
        theSpeaker = new Speaker(ext_gSettings);
        theSpeaker->OwnSettings();
        theSpeaker->DeleteSelfAfterRun();
        omlc_start();
        theSpeaker->Start();
#else
        // If we need to start up a listener do it now
        ext_Settings *temp = NULL;
        Settings::GenerateListenerSettings( ext_gSettings, &temp );
        if ( temp != NULL ) {
            theListener = new Listener( temp );
            theListener->DeleteSelfAfterRun();
        }
        Client* theClient = new Client( ext_gSettings );
        omlc_start();
        theClient->InitiateServer();
        theClient->Start();
        if ( theListener != NULL ) {
            theListener->Start();
        }
#endif
    } else {
        // neither server nor client mode was specified
        // print usage and exit

#ifdef WIN32

        // starting the service by SCM, there is no arguments will be passed in.
        // the arguments will pass into Service_Main entry.

        if ( !StartServiceCtrlDispatcher(dispatchTable) )
            printf(usage_short, argv[0], argv[0]);
#else
        printf( usage_short, argv[0], argv[0] );
#endif
    }

    // wait for other (client, server) threads to complete
    Thread::Joinall();
    DELETE_PTR( gSettings );  // modified by qfeng
    // all done!
    return 0;
} // end main

/* -------------------------------------------------------------------
 * Blocks the thread until a quit thread signal is sent
 * ------------------------------------------------------------------- */

void waitUntilQuit( void ) {
#ifdef HAVE_THREAD

    // signal handlers send quit signal on ^C and kill
    gQuit_cond.Lock();
    my_signal( SIGTERM, sig_quit );
    my_signal( SIGINT,  sig_quit );

#ifdef HAVE_USLEEP

    // this sleep is a hack to get around an apparent bug? in IRIX
    // where pthread_cancel doesn't work unless the thread
    // starts up before the gQuit_cand.Wait() call below.
    // A better solution is to just use sigwait here, but
    // then I have to emulate that for Windows...
    usleep( 10 );
#endif

    // wait for quit signal
    gQuit_cond.Wait();
    gQuit_cond.Unlock();
#endif
} // end waitUntilQuit

/* -------------------------------------------------------------------
 * Sends a quit thread signal to let the main thread quit nicely.
 * ------------------------------------------------------------------- */

void sig_quit( int inSigno ) {
#ifdef HAVE_THREAD

    // if we get a second signal after 1/10 second, exit
    // some implementations send the signal to all threads, so the 1/10 sec
    // allows us to ignore multiple receipts of the same signal
    static Timestamp* first = NULL;
    if ( first != NULL ) {
        Timestamp now;
        if ( now.subSec( *first ) > 0.1 ) {
            sig_exit( inSigno );
        }
    } else {
        first = new Timestamp();
    }

    // with threads, send a quit signal
    gQuit_cond.Signal();

#else

    // without threads, just exit quietly, same as sig_exit()
    sig_exit( inSigno );

#endif
} // end sig_quit

/* -------------------------------------------------------------------
 * Any necesary cleanup before Iperf quits. Called at program exit,
 * either by exit() or terminating main().
 * ------------------------------------------------------------------- */

void cleanup( void ) {
#ifdef WIN32
    WSACleanup();
#endif
    extern Iperf_ListEntry *clients;
    Iperf_destroy ( &clients );

} // end cleanup

#ifdef WIN32
/*--------------------------------------------------------------------
 * ServiceStart
 *
 * each time starting the service, this is the entry point of the service.
 * Start the service, certainly it is on server-mode
 *
 *
 *-------------------------------------------------------------------- */
VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv) {
    Listener *theListener = NULL;

    // report the status to the service control manager.
    //
    if ( !ReportStatusToSCMgr(
                             SERVICE_START_PENDING, // service state
                             NO_ERROR,              // exit code
                             3000) )                 // wait hint
        goto clean;

    ext_Settings* ext_gSettings = new ext_Settings;
    Settings *gSettings;

    // read settings from passing by StartService
    gSettings = new Settings( ext_gSettings );
    gSettings->ParseEnvironment();
    gSettings->ParseCommandLine( dwArgc, lpszArgv );

    // report the status to the service control manager.
    //
    if ( !ReportStatusToSCMgr(
                             SERVICE_START_PENDING, // service state
                             NO_ERROR,              // exit code
                             3000) )                 // wait hint
        goto clean;

    // if needed, redirect the output into a specified file
    if ( gSettings->GetFileOutput() ) {
        redirect(gSettings->GetOutputFileName());
    }

    // report the status to the service control manager.
    //
    if ( !ReportStatusToSCMgr(
                             SERVICE_START_PENDING, // service state
                             NO_ERROR,              // exit code
                             3000) )                 // wait hint
        goto clean;

    theListener = new Listener( ext_gSettings );

    theListener->Start();
    theListener->SetDaemon();

    // report the status to the service control manager.
    //
    if ( !ReportStatusToSCMgr(
                             SERVICE_RUNNING,       // service state
                             NO_ERROR,              // exit code
                             0) )                    // wait hint
        goto clean;

    // the listener keeps going; we terminate on user input only
    waitUntilQuit();
#ifdef HAVE_THREAD
    if ( Thread::NumUserThreads() > 0 ) {
        printf( wait_server_threads );
        fflush( 0 );
    }
#endif

    clean:
    // wait for other (client, server) threads to complete
    Thread::Joinall();
    DELETE_PTR( theListener );
    DELETE_PTR( gSettings );  // modified by qfeng
    DELETE_PTR( ext_gSettings );  // modified by qfeng
}

//
//  FUNCTION: ServiceStop
//
//  PURPOSE: Stops the service
//
//  PARAMETERS:
//    none
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:
//    If a ServiceStop procedure is going to
//    take longer than 3 seconds to execute,
//    it should spawn a thread to execute the
//    stop code, and return.  Otherwise, the
//    ServiceControlManager will believe that
//    the service has stopped responding.
//
VOID ServiceStop() {
#ifdef HAVE_THREAD
    gQuit_cond.Signal();
#else
    sig_exit(1);
#endif
}

#endif

<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/initfiles/p9_cxa_scom.H $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef _INIT_P9_CXA_SCOM_PROCEDURE_H_
#define _INIT_P9_CXA_SCOM_PROCEDURE_H_

#include <stddef.h>
#include <stdint.h>
#include <fapi2.H>

typedef fapi2::ReturnCode (*p9_cxa_scom_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_CAPP>&,
        const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>&);

extern "C"
{

    fapi2::ReturnCode p9_cxa_scom(const fapi2::Target<fapi2::TARGET_TYPE_CAPP>& TGT0,
                                  const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>& TGT1);

}

#endif
<commit_msg>Updates to initcompiler to support DD2 and cumulus<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/initfiles/p9_cxa_scom.H $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef _INIT_P9_CXA_SCOM_PROCEDURE_H_
#define _INIT_P9_CXA_SCOM_PROCEDURE_H_

#include <stddef.h>
#include <stdint.h>
#include <fapi2.H>

typedef fapi2::ReturnCode (*p9_cxa_scom_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_CAPP>&,
        const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>&, const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&);

extern "C"
{

    fapi2::ReturnCode p9_cxa_scom(const fapi2::Target<fapi2::TARGET_TYPE_CAPP>& TGT0,
                                  const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>& TGT1, const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& TGT2);

}

#endif
<|endoftext|>


<commit_before>#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    ofBackground(37, 203, 206);
    gui.setup();
    gui.setPosition(5, 40);
    gui.add(degree.setup("degree", 137.5, 130.00, 140.00));
    gui.add(spread.setup("spread", 11, 2, 40));
    gui.add(extrude.setup("extrude", 0.3, 0.01, 0.90));
    light.setup();
    light.setPosition(-100, 200,0);
    masterColor = ofFloatColor::red;
    secondColor = ofFloatColor::yellow;
    ofEnableDepthTest();
    for(int i = 0;  i < nCubes;i++){
        children.push_back(ofBoxPrimitive(5,5,5));
    }
}

//--------------------------------------------------------------
void ofApp::update(){
    float rad = ofDegToRad(degree);
    for (int i = 0;  i < nCubes;i++) {
        ofVec3f pos;
        if (selectedType == "simple") {
            pos = ofxPhyllotaxis::simple(i, rad, spread);
        }

        if (selectedType == "conical") {
            pos = ofxPhyllotaxis::conical(i, rad, spread, extrude);
        }

        if (selectedType == "apple") {
            pos = ofxPhyllotaxis::apple(i, rad, spread, nCubes);
        }
        children[i].setPosition(pos);
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    maybeDrawGui();
    camera.begin();

    secondMaterial.setEmissiveColor(masterColor);
    for (int i = 0;  i < nCubes;i++) {
        float lerp = ofMap(i, 0, nCubes, 0.0, 1.0);
        auto interpolatedColor = masterColor.getLerped(secondColor, lerp);
        secondMaterial.setEmissiveColor(interpolatedColor);
        secondMaterial.begin();
        children[i].draw();
        secondMaterial.end();
    }
    camera.end();
}

void ofApp::maybeDrawGui(){
    if(!hideGui){
        ofDisableDepthTest();
        gui.draw();
        ofPushStyle();
        string displayGui = "press 'g' to toggle the gui, up and down to change presets";
        ofDrawBitmapString(displayGui, 5, 10);
        string types = "press 1, 2, 3 to try different implementation";
        ofDrawBitmapString(types, 5, 20);
        string currentType = "current: "+ selectedType;
        ofDrawBitmapString(currentType, 5, 30);
        ofPopStyle();
        ofEnableDepthTest();
    }
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

    switch(key){
        case 'g':
            hideGui = !hideGui;
            break;
        case 49:
            selectedType = "conical";
            break;
        case 50:
            selectedType = "apple";
            break;
        case 51:
            selectedType = "simple";
            break;
        default:
            break;
    }
}

<commit_msg>Update ofApp.cpp<commit_after>#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    ofBackground(37, 203, 206);
    gui.setup();
    gui.setPosition(5, 40);
    gui.add(degree.setup("degree", 137.5, 130.00, 140.00));
    gui.add(spread.setup("spread", 11, 2, 40));
    gui.add(extrude.setup("extrude", 0.3, 0.01, 0.90));
    light.setup();
    light.setPosition(-100, 200,0);
    masterColor = ofFloatColor::red;
    secondColor = ofFloatColor::yellow;
    ofEnableDepthTest();
    for(int i = 0;  i < nCubes;i++){
        children.push_back(ofBoxPrimitive(5,5,5));
    }
}

//--------------------------------------------------------------
void ofApp::update(){
    float rad = ofDegToRad(degree);
    for (int i = 0;  i < nCubes;i++) {
        glm::vec3 pos;
        if (selectedType == "simple") {
            pos = ofxPhyllotaxis::simple(i, rad, spread);
        }

        if (selectedType == "conical") {
            pos = ofxPhyllotaxis::conical(i, rad, spread, extrude);
        }

        if (selectedType == "apple") {
            pos = ofxPhyllotaxis::apple(i, rad, spread, nCubes);
        }
        children[i].setPosition(pos);
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    maybeDrawGui();
    camera.begin();

    secondMaterial.setEmissiveColor(masterColor);
    for (int i = 0;  i < nCubes;i++) {
        float lerp = ofMap(i, 0, nCubes, 0.0, 1.0);
        auto interpolatedColor = masterColor.getLerped(secondColor, lerp);
        secondMaterial.setEmissiveColor(interpolatedColor);
        secondMaterial.begin();
        children[i].draw();
        secondMaterial.end();
    }
    camera.end();
}

void ofApp::maybeDrawGui(){
    if(!hideGui){
        ofDisableDepthTest();
        gui.draw();
        ofPushStyle();
        string displayGui = "press 'g' to toggle the gui, up and down to change presets";
        ofDrawBitmapString(displayGui, 5, 10);
        string types = "press 1, 2, 3 to try different implementation";
        ofDrawBitmapString(types, 5, 20);
        string currentType = "current: "+ selectedType;
        ofDrawBitmapString(currentType, 5, 30);
        ofPopStyle();
        ofEnableDepthTest();
    }
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

    switch(key){
        case 'g':
            hideGui = !hideGui;
            break;
        case 49:
            selectedType = "conical";
            break;
        case 50:
            selectedType = "apple";
            break;
        case 51:
            selectedType = "simple";
            break;
        default:
            break;
    }
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libetonyek project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <libetonyek/libetonyek.h>

#include <cassert>

#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/logic/tribool.hpp>

#include <libxml/xmlreader.h>

#include "libetonyek_utils.h"
#include "libetonyek_xml.h"
#include "IWORKPresentationRedirector.h"
#include "IWORKSpreadsheetRedirector.h"
#include "IWORKTextRedirector.h"
#include "IWORKTokenizer.h"
#include "IWORKZlibStream.h"
#include "KEY1Parser.h"
#include "KEY2Parser.h"
#include "KEY2Token.h"
#include "KEYCollector.h"
#include "KEYDictionary.h"
#include "NUMCollector.h"
#include "NUMDictionary.h"
#include "NUM1Parser.h"
#include "NUM1Token.h"
#include "PAGCollector.h"
#include "PAG1Parser.h"
#include "PAG1Token.h"
#include "PAGDictionary.h"

using boost::logic::indeterminate;
using boost::logic::tribool;
using boost::scoped_ptr;
using boost::shared_ptr;
using std::string;

using librevenge::RVNG_SEEK_SET;

namespace libetonyek
{

namespace
{

enum CheckType
{
  CHECK_TYPE_NONE = 0,
  CHECK_TYPE_KEYNOTE = 1 << 1,
  CHECK_TYPE_NUMBERS = 1 << 2,
  CHECK_TYPE_PAGES = 1 << 3,
  CHECK_TYPE_ANY = CHECK_TYPE_KEYNOTE | CHECK_TYPE_NUMBERS | CHECK_TYPE_PAGES
};

struct DetectionInfo
{
  DetectionInfo();

  RVNGInputStreamPtr_t m_input;
  RVNGInputStreamPtr_t m_package;
  EtonyekDocument::Confidence m_confidence;
  EtonyekDocument::Type m_type;
  unsigned m_version;
};

DetectionInfo::DetectionInfo()
  : m_input()
  , m_package()
  , m_confidence(EtonyekDocument::CONFIDENCE_NONE)
  , m_type(EtonyekDocument::TYPE_UNKNOWN)
  , m_version(0)
{
}

typedef bool (*ProbeXMLFun_t)(const RVNGInputStreamPtr_t &, unsigned &, xmlTextReaderPtr);

std::string queryAttribute(xmlTextReaderPtr reader, const int name, const int ns, const IWORKTokenizer &tokenizer)
{
  if (xmlTextReaderHasAttributes(reader))
  {
    int ret = xmlTextReaderMoveToFirstAttribute(reader);
    while (1 == ret)
    {
      const int id = tokenizer.getQualifiedId(char_cast(xmlTextReaderConstLocalName(reader)), char_cast(xmlTextReaderConstNamespaceUri(reader)));
      if ((ns | name) == id)
        return char_cast(xmlTextReaderConstValue(reader));

      ret = xmlTextReaderMoveToNextAttribute(reader);
    }
  }

  return "";
}

bool probeKeynote1XML(const RVNGInputStreamPtr_t &input, unsigned &version, xmlTextReaderPtr reader)
{
  // TODO: implement me
  (void) input;
  (void) version;
  (void) reader;
  return false;
}

bool probeKeynote2XML(const RVNGInputStreamPtr_t &input, unsigned &version, xmlTextReaderPtr reader)
{
  if (input->isEnd())
    return false;

  const IWORKTokenizer &tokenizer(KEY2Token::getTokenizer());
  assert(reader);

  const int id = tokenizer.getQualifiedId(char_cast(xmlTextReaderConstLocalName(reader)), char_cast(xmlTextReaderConstNamespaceUri(reader)));

  if ((KEY2Token::NS_URI_KEY | KEY2Token::presentation) == id)
  {
    const std::string v = queryAttribute(reader, KEY2Token::version, KEY2Token::NS_URI_KEY, tokenizer);

    switch (tokenizer.getId(v.c_str()))
    {
    case KEY2Token::VERSION_STR_2 :
      version = 2;
      return true;
    case KEY2Token::VERSION_STR_3 :
      version = 3;
      return true;
    case KEY2Token::VERSION_STR_4 :
      version = 4;
      return true;
    case KEY2Token::VERSION_STR_5 :
      version = 5;
      return true;
    }
  }

  return false;
}

bool probeKeynoteXML(const RVNGInputStreamPtr_t &input, unsigned &version, xmlTextReaderPtr reader)
{
  if (probeKeynote2XML(input, version, reader))
    return true;

  input->seek(0, RVNG_SEEK_SET);

  return probeKeynote1XML(input, version, reader);
}

bool probeNumbersXML(const RVNGInputStreamPtr_t &input, unsigned &version, xmlTextReaderPtr reader)
{
  if (input->isEnd())
    return false;

  const IWORKTokenizer &tokenizer(NUM1Token::getTokenizer());
  assert(reader);

  const int id = tokenizer.getQualifiedId(char_cast(xmlTextReaderConstLocalName(reader)), char_cast(xmlTextReaderConstNamespaceUri(reader)));

  if ((NUM1Token::NS_URI_LS | NUM1Token::document) == id)
  {
    const std::string v = queryAttribute(reader, NUM1Token::version, NUM1Token::NS_URI_LS, tokenizer);

    switch (tokenizer.getId(v.c_str()))
    {
    case NUM1Token::VERSION_STR_2 :
      version = 2;
      break;
    }
    return true;
  }

  return false;
}

bool probePagesXML(const RVNGInputStreamPtr_t &input, unsigned &version, xmlTextReaderPtr reader)
{
  if (input->isEnd())
    return false;

  const IWORKTokenizer &tokenizer(PAG1Token::getTokenizer());
  assert(reader);

  const int id = tokenizer.getQualifiedId(char_cast(xmlTextReaderConstLocalName(reader)), char_cast(xmlTextReaderConstNamespaceUri(reader)));

  if ((PAG1Token::NS_URI_SL | PAG1Token::document) == id)
  {
    const std::string v = queryAttribute(reader, PAG1Token::version, PAG1Token::NS_URI_SL, tokenizer);

    switch (tokenizer.getId(v.c_str()))
    {
    case PAG1Token::VERSION_STR_4 :
      version = 4;
      break;
    }
    return true;
  }

  return false;
}

bool probeXMLImpl(const RVNGInputStreamPtr_t &input, const ProbeXMLFun_t probe, const EtonyekDocument::Type type, DetectionInfo &info)
{
  const shared_ptr<xmlTextReader> reader(xmlReaderForIO(readFromStream, closeStream, input.get(), "", 0, 0), xmlFreeTextReader);
  if (!reader)
    return false;

  int ret = 0;
  do
  {
    ret = xmlTextReaderRead(reader.get());
  }
  while ((1 == ret) && (XML_READER_TYPE_ELEMENT != xmlTextReaderNodeType(reader.get())));

  if (1 != ret)
    return false;

  if (probe(input, info.m_version, reader.get()))
  {
    info.m_type = type;
    return true;
  }

  return false;
}

bool probeXML(const ProbeXMLFun_t probe, const EtonyekDocument::Type type, tribool &isGzipped, DetectionInfo &info)
{
  if (isGzipped || indeterminate(isGzipped))
  {
    try
    {
      const RVNGInputStreamPtr_t uncompressed(new IWORKZlibStream(info.m_input));
      isGzipped = true;

      if (probeXMLImpl(uncompressed, probe, type, info))
      {
        info.m_input = uncompressed;
        return true;
      }
      else
      {
        return false; // compressed, but invalid format
      }
    }
    catch (...)
    {
      if (isGzipped) // decompression failed? most probably a broken file...
        return false;

      isGzipped = false;
    }

    info.m_input->seek(0, RVNG_SEEK_SET);
  }

  assert(isGzipped == false);

  return probeXMLImpl(info.m_input, probe, type, info);
}

bool detect(const RVNGInputStreamPtr_t &input, unsigned checkTypes, DetectionInfo &info)
{
  info.m_confidence = EtonyekDocument::CONFIDENCE_SUPPORTED_PART;
  bool isXML = true;
  tribool isGzipped = indeterminate;
  tribool isKeynote1 = indeterminate;

  if (input->isStructured())
  {
    info.m_package = input;

    // check which format it might be
    if (CHECK_TYPE_KEYNOTE & checkTypes)
    {
      if (input->existsSubStream("index.apxl"))
      {
        checkTypes = CHECK_TYPE_KEYNOTE;
        isGzipped = false;
        isKeynote1 = false;
        info.m_input.reset(input->getSubStreamByName("index.apxl"));
      }
      else if (input->existsSubStream("index.apxl.gz"))
      {
        checkTypes = CHECK_TYPE_KEYNOTE;
        isGzipped = true;
        isKeynote1 = false;
        info.m_input.reset(input->getSubStreamByName("index.apxl.gz"));
      }
      else if (input->existsSubStream("presentation.apxl"))
      {
        checkTypes = CHECK_TYPE_KEYNOTE;
        isGzipped = false;
        isKeynote1 = true;
        info.m_input.reset(input->getSubStreamByName("presentation.apxl"));
      }
      else if (input->existsSubStream("presentation.apxl.gz"))
      {
        checkTypes = CHECK_TYPE_KEYNOTE;
        isGzipped = true;
        isKeynote1 = true;
        info.m_input.reset(input->getSubStreamByName("presentation.apxl.gz"));
      }
    }

    if ((CHECK_TYPE_NUMBERS | CHECK_TYPE_PAGES) & checkTypes)
    {
      if (input->existsSubStream("index.xml"))
      {
        checkTypes &= (CHECK_TYPE_NUMBERS | CHECK_TYPE_PAGES);
        isGzipped = false;
        info.m_input.reset(input->getSubStreamByName("index.xml"));
      }
      else if (input->existsSubStream("index.xml.gz"))
      {
        checkTypes &= (CHECK_TYPE_NUMBERS | CHECK_TYPE_PAGES);
        isGzipped = false;
        info.m_input.reset(input->getSubStreamByName("index.xml.gz"));
      }
    }

    if (!info.m_input && (CHECK_TYPE_ANY & checkTypes))
    {
      if (input->existsSubStream("Index.zip"))
      {
        isXML = false;
        info.m_input.reset(input->getSubStreamByName("Index.zip"));
      }
    }

    if (!info.m_input)
    {
      // nothing detected
      // TODO: this might also be Index.zip...
      return EtonyekDocument::CONFIDENCE_NONE;
    }

    info.m_confidence = EtonyekDocument::CONFIDENCE_EXCELLENT; // this is either a valid package of a false positive
  }
  else
  {
    info.m_input = input;
  }

  assert(bool(info.m_input));

  if (isXML)
  {
    assert(CHECK_TYPE_ANY & checkTypes);
    assert(!info.m_input->isStructured());

    info.m_input->seek(0, RVNG_SEEK_SET);

    if (CHECK_TYPE_KEYNOTE & checkTypes)
    {
      const ProbeXMLFun_t probe = (isKeynote1 ? probeKeynote1XML : ((!isKeynote1) ? probeKeynote2XML : probeKeynoteXML));
      if (probeXML(probe, EtonyekDocument::TYPE_KEYNOTE, isGzipped, info))
        return true;

      info.m_input->seek(0, RVNG_SEEK_SET);
    }

    if (CHECK_TYPE_NUMBERS & checkTypes)
    {
      if (probeXML(probeNumbersXML, EtonyekDocument::TYPE_NUMBERS, isGzipped, info))
        return true;

      info.m_input->seek(0, RVNG_SEEK_SET);
    }

    if (CHECK_TYPE_PAGES & checkTypes)
    {
      if (probeXML(probePagesXML, EtonyekDocument::TYPE_PAGES, isGzipped, info))
        return true;
    }
  }
  else
  {
    // TODO: detect type in binary format
  }

  return EtonyekDocument::CONFIDENCE_NONE;
}

}

namespace
{

shared_ptr<IWORKParser> makeKeynoteParser(const unsigned version, const RVNGInputStreamPtr_t &input, const RVNGInputStreamPtr_t &package, KEYCollector &collector, KEYDictionary &dict)
{
  shared_ptr<IWORKParser> parser;

  if (1 == version)
    parser.reset(new KEY1Parser(input, package, collector));
  else if ((2 <= version) && (5 >= version))
    parser.reset(new KEY2Parser(input, package, collector, dict));
  else
    assert(0);

  return parser;
}

}

ETONYEKAPI EtonyekDocument::Confidence EtonyekDocument::isSupported(librevenge::RVNGInputStream *const input, EtonyekDocument::Type *type) try
{
  if (!input)
    return CONFIDENCE_NONE;

  if (type)
    *type = TYPE_UNKNOWN;

  DetectionInfo info;

  if (detect(RVNGInputStreamPtr_t(input, EtonyekDummyDeleter()), CHECK_TYPE_ANY, info))
  {
    assert(TYPE_UNKNOWN != info.m_type);
    assert(CONFIDENCE_NONE != info.m_confidence);
    assert(bool(info.m_input));

    if (type)
      *type = info.m_type;
    return info.m_confidence;
  }

  return CONFIDENCE_NONE;
}
catch (...)
{
  return CONFIDENCE_NONE;
}

ETONYEKAPI bool EtonyekDocument::parse(librevenge::RVNGInputStream *const input, librevenge::RVNGPresentationInterface *const generator) try
{
  if (!input || !generator)
    return false;

  DetectionInfo info;

  if (!detect(RVNGInputStreamPtr_t(input, EtonyekDummyDeleter()), CHECK_TYPE_KEYNOTE, info))
    return false;

  assert(TYPE_UNKNOWN != info.m_type);
  assert(CONFIDENCE_NONE != info.m_confidence);
  assert(bool(info.m_input));
  assert(0 != info.m_version);

  info.m_input->seek(0, librevenge::RVNG_SEEK_SET);

  KEYDictionary dict;
  IWORKPresentationRedirector redirector(generator);
  KEYCollector collector(&redirector);
  const shared_ptr<IWORKParser> parser = makeKeynoteParser(info.m_version, info.m_input, info.m_package, collector, dict);
  return parser->parse();
}
catch (...)
{
  return false;
}

ETONYEKAPI bool EtonyekDocument::parse(librevenge::RVNGInputStream *const input, librevenge::RVNGSpreadsheetInterface *const document) try
{
  if (!input || !document)
    return false;

  DetectionInfo info;

  if (!detect(RVNGInputStreamPtr_t(input, EtonyekDummyDeleter()), CHECK_TYPE_NUMBERS, info))
    return false;

  assert(TYPE_UNKNOWN != info.m_type);
  assert(CONFIDENCE_NONE != info.m_confidence);
  assert(bool(info.m_input));
  assert(0 != info.m_version);

  info.m_input->seek(0, librevenge::RVNG_SEEK_SET);

  IWORKSpreadsheetRedirector redirector(document);
  NUMCollector collector(&redirector);
  NUMDictionary dict;
  NUM1Parser parser(info.m_input, info.m_package, collector, &dict);
  return parser.parse();
}
catch (...)
{
  return false;
}

ETONYEKAPI bool EtonyekDocument::parse(librevenge::RVNGInputStream *const input, librevenge::RVNGTextInterface *const document) try
{
  if (!input || !document)
    return false;

  DetectionInfo info;

  if (!detect(RVNGInputStreamPtr_t(input, EtonyekDummyDeleter()), CHECK_TYPE_PAGES, info))
    return false;

  assert(TYPE_UNKNOWN != info.m_type);
  assert(CONFIDENCE_NONE != info.m_confidence);
  assert(bool(info.m_input));
  assert(0 != info.m_version);

  info.m_input->seek(0, librevenge::RVNG_SEEK_SET);

  IWORKTextRedirector redirector(document);
  PAGCollector collector(&redirector);
  PAGDictionary dict;
  PAG1Parser parser(info.m_input, info.m_package, collector, &dict);
  return parser.parse();
}
catch (...)
{
  return false;
}

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<commit_msg>only detect the format kind<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libetonyek project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <libetonyek/libetonyek.h>

#include <cassert>

#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/logic/tribool.hpp>

#include <libxml/xmlreader.h>

#include "libetonyek_utils.h"
#include "libetonyek_xml.h"
#include "IWORKPresentationRedirector.h"
#include "IWORKSpreadsheetRedirector.h"
#include "IWORKTextRedirector.h"
#include "IWORKTokenizer.h"
#include "IWORKZlibStream.h"
#include "KEY1Parser.h"
#include "KEY2Parser.h"
#include "KEY2Token.h"
#include "KEYCollector.h"
#include "KEYDictionary.h"
#include "NUMCollector.h"
#include "NUMDictionary.h"
#include "NUM1Parser.h"
#include "NUM1Token.h"
#include "PAGCollector.h"
#include "PAG1Parser.h"
#include "PAG1Token.h"
#include "PAGDictionary.h"

using boost::logic::indeterminate;
using boost::logic::tribool;
using boost::scoped_ptr;
using boost::shared_ptr;
using std::string;

using librevenge::RVNG_SEEK_SET;

namespace libetonyek
{

namespace
{

enum CheckType
{
  CHECK_TYPE_NONE = 0,
  CHECK_TYPE_KEYNOTE = 1 << 1,
  CHECK_TYPE_NUMBERS = 1 << 2,
  CHECK_TYPE_PAGES = 1 << 3,
  CHECK_TYPE_ANY = CHECK_TYPE_KEYNOTE | CHECK_TYPE_NUMBERS | CHECK_TYPE_PAGES
};

enum Format
{
  FORMAT_UNKNOWN,
  FORMAT_XML1,
  FORMAT_XML2,
  FORMAT_BINARY
};

struct DetectionInfo
{
  DetectionInfo();

  RVNGInputStreamPtr_t m_input;
  RVNGInputStreamPtr_t m_package;
  EtonyekDocument::Confidence m_confidence;
  EtonyekDocument::Type m_type;
  Format m_format;
};

DetectionInfo::DetectionInfo()
  : m_input()
  , m_package()
  , m_confidence(EtonyekDocument::CONFIDENCE_NONE)
  , m_type(EtonyekDocument::TYPE_UNKNOWN)
  , m_format(FORMAT_UNKNOWN)
{
}

typedef bool (*ProbeXMLFun_t)(const RVNGInputStreamPtr_t &, Format &, xmlTextReaderPtr);

bool probeKeynote1XML(const RVNGInputStreamPtr_t &input, Format &format, xmlTextReaderPtr reader)
{
  // TODO: implement me
  (void) input;
  (void) format;
  (void) reader;
  return false;
}

bool probeKeynote2XML(const RVNGInputStreamPtr_t &input, Format &format, xmlTextReaderPtr reader)
{
  if (input->isEnd())
    return false;

  const IWORKTokenizer &tokenizer(KEY2Token::getTokenizer());
  assert(reader);

  const int id = tokenizer.getQualifiedId(char_cast(xmlTextReaderConstLocalName(reader)), char_cast(xmlTextReaderConstNamespaceUri(reader)));
  if ((KEY2Token::NS_URI_KEY | KEY2Token::presentation) == id)
  {
    format = FORMAT_XML2;
    return true;
  }

  return false;
}

bool probeKeynoteXML(const RVNGInputStreamPtr_t &input, Format &format, xmlTextReaderPtr reader)
{
  if (probeKeynote2XML(input, format, reader))
    return true;

  input->seek(0, RVNG_SEEK_SET);

  if (probeKeynote1XML(input, format, reader))
    return true;

  return false;
}

bool probeNumbersXML(const RVNGInputStreamPtr_t &input, Format &format, xmlTextReaderPtr reader)
{
  if (input->isEnd())
    return false;

  const IWORKTokenizer &tokenizer(NUM1Token::getTokenizer());
  assert(reader);

  const int id = tokenizer.getQualifiedId(char_cast(xmlTextReaderConstLocalName(reader)), char_cast(xmlTextReaderConstNamespaceUri(reader)));
  if ((NUM1Token::NS_URI_LS | NUM1Token::document) == id)
  {
    format = FORMAT_XML2;
    return true;
  }

  return false;
}

bool probePagesXML(const RVNGInputStreamPtr_t &input, Format &format, xmlTextReaderPtr reader)
{
  if (input->isEnd())
    return false;

  const IWORKTokenizer &tokenizer(PAG1Token::getTokenizer());
  assert(reader);

  const int id = tokenizer.getQualifiedId(char_cast(xmlTextReaderConstLocalName(reader)), char_cast(xmlTextReaderConstNamespaceUri(reader)));
  if ((PAG1Token::NS_URI_SL | PAG1Token::document) == id)
  {
    format = FORMAT_XML2;
    return true;
  }

  return false;
}

bool probeXMLImpl(const RVNGInputStreamPtr_t &input, const ProbeXMLFun_t probe, const EtonyekDocument::Type type, DetectionInfo &info)
{
  const shared_ptr<xmlTextReader> reader(xmlReaderForIO(readFromStream, closeStream, input.get(), "", 0, 0), xmlFreeTextReader);
  if (!reader)
    return false;

  int ret = 0;
  do
  {
    ret = xmlTextReaderRead(reader.get());
  }
  while ((1 == ret) && (XML_READER_TYPE_ELEMENT != xmlTextReaderNodeType(reader.get())));

  if (1 != ret)
    return false;

  if (probe(input, info.m_format, reader.get()))
  {
    info.m_type = type;
    return true;
  }

  return false;
}

bool probeXML(const ProbeXMLFun_t probe, const EtonyekDocument::Type type, tribool &isGzipped, DetectionInfo &info)
{
  if (isGzipped || indeterminate(isGzipped))
  {
    try
    {
      const RVNGInputStreamPtr_t uncompressed(new IWORKZlibStream(info.m_input));
      isGzipped = true;

      if (probeXMLImpl(uncompressed, probe, type, info))
      {
        info.m_input = uncompressed;
        return true;
      }
      else
      {
        return false; // compressed, but invalid format
      }
    }
    catch (...)
    {
      if (isGzipped) // decompression failed? most probably a broken file...
        return false;

      isGzipped = false;
    }

    info.m_input->seek(0, RVNG_SEEK_SET);
  }

  assert(isGzipped == false);

  return probeXMLImpl(info.m_input, probe, type, info);
}

bool detect(const RVNGInputStreamPtr_t &input, unsigned checkTypes, DetectionInfo &info)
{
  info.m_confidence = EtonyekDocument::CONFIDENCE_SUPPORTED_PART;
  bool isXML = true;
  tribool isGzipped = indeterminate;
  tribool isKeynote1 = indeterminate;

  if (input->isStructured())
  {
    info.m_package = input;

    // check which format it might be
    if (CHECK_TYPE_KEYNOTE & checkTypes)
    {
      if (input->existsSubStream("index.apxl"))
      {
        checkTypes = CHECK_TYPE_KEYNOTE;
        isGzipped = false;
        isKeynote1 = false;
        info.m_input.reset(input->getSubStreamByName("index.apxl"));
      }
      else if (input->existsSubStream("index.apxl.gz"))
      {
        checkTypes = CHECK_TYPE_KEYNOTE;
        isGzipped = true;
        isKeynote1 = false;
        info.m_input.reset(input->getSubStreamByName("index.apxl.gz"));
      }
      else if (input->existsSubStream("presentation.apxl"))
      {
        checkTypes = CHECK_TYPE_KEYNOTE;
        isGzipped = false;
        isKeynote1 = true;
        info.m_input.reset(input->getSubStreamByName("presentation.apxl"));
      }
      else if (input->existsSubStream("presentation.apxl.gz"))
      {
        checkTypes = CHECK_TYPE_KEYNOTE;
        isGzipped = true;
        isKeynote1 = true;
        info.m_input.reset(input->getSubStreamByName("presentation.apxl.gz"));
      }
    }

    if ((CHECK_TYPE_NUMBERS | CHECK_TYPE_PAGES) & checkTypes)
    {
      if (input->existsSubStream("index.xml"))
      {
        checkTypes &= (CHECK_TYPE_NUMBERS | CHECK_TYPE_PAGES);
        isGzipped = false;
        info.m_input.reset(input->getSubStreamByName("index.xml"));
      }
      else if (input->existsSubStream("index.xml.gz"))
      {
        checkTypes &= (CHECK_TYPE_NUMBERS | CHECK_TYPE_PAGES);
        isGzipped = false;
        info.m_input.reset(input->getSubStreamByName("index.xml.gz"));
      }
    }

    if (!info.m_input && (CHECK_TYPE_ANY & checkTypes))
    {
      if (input->existsSubStream("Index.zip"))
      {
        isXML = false;
        info.m_input.reset(input->getSubStreamByName("Index.zip"));
      }
    }

    if (!info.m_input)
    {
      // nothing detected
      // TODO: this might also be Index.zip...
      return EtonyekDocument::CONFIDENCE_NONE;
    }

    info.m_confidence = EtonyekDocument::CONFIDENCE_EXCELLENT; // this is either a valid package of a false positive
  }
  else
  {
    info.m_input = input;
  }

  assert(bool(info.m_input));

  if (isXML)
  {
    assert(CHECK_TYPE_ANY & checkTypes);
    assert(!info.m_input->isStructured());

    info.m_input->seek(0, RVNG_SEEK_SET);

    if (CHECK_TYPE_KEYNOTE & checkTypes)
    {
      const ProbeXMLFun_t probe = (isKeynote1 ? probeKeynote1XML : ((!isKeynote1) ? probeKeynote2XML : probeKeynoteXML));
      if (probeXML(probe, EtonyekDocument::TYPE_KEYNOTE, isGzipped, info))
        return true;

      info.m_input->seek(0, RVNG_SEEK_SET);
    }

    if (CHECK_TYPE_NUMBERS & checkTypes)
    {
      if (probeXML(probeNumbersXML, EtonyekDocument::TYPE_NUMBERS, isGzipped, info))
        return true;

      info.m_input->seek(0, RVNG_SEEK_SET);
    }

    if (CHECK_TYPE_PAGES & checkTypes)
    {
      if (probeXML(probePagesXML, EtonyekDocument::TYPE_PAGES, isGzipped, info))
        return true;
    }
  }
  else
  {
    // TODO: detect type in binary format
  }

  return EtonyekDocument::CONFIDENCE_NONE;
}

}

namespace
{

shared_ptr<IWORKParser> makeKeynoteParser(const unsigned version, const RVNGInputStreamPtr_t &input, const RVNGInputStreamPtr_t &package, KEYCollector &collector, KEYDictionary &dict)
{
  shared_ptr<IWORKParser> parser;

  if (1 == version)
    parser.reset(new KEY1Parser(input, package, collector));
  else if ((2 <= version) && (5 >= version))
    parser.reset(new KEY2Parser(input, package, collector, dict));
  else
    assert(0);

  return parser;
}

}

ETONYEKAPI EtonyekDocument::Confidence EtonyekDocument::isSupported(librevenge::RVNGInputStream *const input, EtonyekDocument::Type *type) try
{
  if (!input)
    return CONFIDENCE_NONE;

  if (type)
    *type = TYPE_UNKNOWN;

  DetectionInfo info;

  if (detect(RVNGInputStreamPtr_t(input, EtonyekDummyDeleter()), CHECK_TYPE_ANY, info))
  {
    assert(TYPE_UNKNOWN != info.m_type);
    assert(CONFIDENCE_NONE != info.m_confidence);
    assert(bool(info.m_input));

    if (type)
      *type = info.m_type;
    return info.m_confidence;
  }

  return CONFIDENCE_NONE;
}
catch (...)
{
  return CONFIDENCE_NONE;
}

ETONYEKAPI bool EtonyekDocument::parse(librevenge::RVNGInputStream *const input, librevenge::RVNGPresentationInterface *const generator) try
{
  if (!input || !generator)
    return false;

  DetectionInfo info;

  if (!detect(RVNGInputStreamPtr_t(input, EtonyekDummyDeleter()), CHECK_TYPE_KEYNOTE, info))
    return false;

  assert(TYPE_UNKNOWN != info.m_type);
  assert(CONFIDENCE_NONE != info.m_confidence);
  assert(bool(info.m_input));
  assert(FORMAT_UNKNOWN != info.m_format);

  info.m_input->seek(0, librevenge::RVNG_SEEK_SET);

  KEYDictionary dict;
  IWORKPresentationRedirector redirector(generator);
  KEYCollector collector(&redirector);
  const shared_ptr<IWORKParser> parser = makeKeynoteParser(info.m_format, info.m_input, info.m_package, collector, dict);
  return parser->parse();
}
catch (...)
{
  return false;
}

ETONYEKAPI bool EtonyekDocument::parse(librevenge::RVNGInputStream *const input, librevenge::RVNGSpreadsheetInterface *const document) try
{
  if (!input || !document)
    return false;

  DetectionInfo info;

  if (!detect(RVNGInputStreamPtr_t(input, EtonyekDummyDeleter()), CHECK_TYPE_NUMBERS, info))
    return false;

  assert(TYPE_UNKNOWN != info.m_type);
  assert(CONFIDENCE_NONE != info.m_confidence);
  assert(bool(info.m_input));
  assert(FORMAT_UNKNOWN != info.m_format);

  info.m_input->seek(0, librevenge::RVNG_SEEK_SET);

  IWORKSpreadsheetRedirector redirector(document);
  NUMCollector collector(&redirector);
  NUMDictionary dict;
  NUM1Parser parser(info.m_input, info.m_package, collector, &dict);
  return parser.parse();
}
catch (...)
{
  return false;
}

ETONYEKAPI bool EtonyekDocument::parse(librevenge::RVNGInputStream *const input, librevenge::RVNGTextInterface *const document) try
{
  if (!input || !document)
    return false;

  DetectionInfo info;

  if (!detect(RVNGInputStreamPtr_t(input, EtonyekDummyDeleter()), CHECK_TYPE_PAGES, info))
    return false;

  assert(TYPE_UNKNOWN != info.m_type);
  assert(CONFIDENCE_NONE != info.m_confidence);
  assert(bool(info.m_input));
  assert(FORMAT_UNKNOWN != info.m_format);

  info.m_input->seek(0, librevenge::RVNG_SEEK_SET);

  IWORKTextRedirector redirector(document);
  PAGCollector collector(&redirector);
  PAGDictionary dict;
  PAG1Parser parser(info.m_input, info.m_package, collector, &dict);
  return parser.parse();
}
catch (...)
{
  return false;
}

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<|endoftext|>


<commit_before>#pragma once

#include <cstdint>
#include <vector>
#include <string>

#if __BIG_ENDIAN
#define RTP_HEADER(port, subclass, ack, sfs)                                 \
    (((port & 0x0F) << 4) | ((subclass & 0x03) << 2) | ((ack & 0x01) << 1) | \
     (sfs & 0x01))
#else
#define RTP_HEADER(port, subclass, ack, sfs)                                \
    (((sfs & 0x01) << 7) | ((ack & 0x01) << 6) | ((subclass & 0x03) << 4) | \
     (port & 0x0F))
#endif

#define BASE_STATION_ADDR (1)
#define LOOPBACK_ADDR (127)

namespace rtp {

///
static const unsigned int MAX_DATA_SZ = 120;

/**
 * @brief      { port enumerations for different communication protocols }
 */
enum port {
    SINK = 0x00,
    LINK = 0x01,
    CONTROL = 0x02,
    SETPOINT = 0x03,
    GSTROBE = 0x04,
    DISCOVER = 0x05,
    LOGGER = 0x06,
    TCP = 0x07,
    LEGACY = 0x0E
};

namespace {
// type of data field used in all packet classes
// - must be 8 bits, (typedef used for eaiser compiler
// type error debugging)
typedef uint8_t packet_data_t;
}

/**
 * @brief [brief description]
 * @details [long description]
 * @return [description]
 */
class layer_map {
public:
    typedef packet_data_t data_t;

protected:
    typedef std::vector<data_t> datav_t;
    typedef datav_t::iterator datav_it_t;
    std::vector<data_t> d;

public:
    layer_map(size_t resv) { d.reserve(resv); }

    datav_it_t pack() {
        // make sure all files are in contiguous memory,
        // then return iterator to beginning
        return d.begin();
    }

    data_t* data() { return d.data(); }

    void show_data() {
        for (auto const& i : d) printf("%02X ", i);
    }

    const size_t size() const { return static_cast<const int>(d.size()); }
};

/**
 * @brief [brief description]
 * @details [long description]
 *
 * @param p [description]
 * @return [description]
 */
class header_data : public layer_map {
public:
    enum type { control, tuning, ota, misc };

    header_data() : layer_map(3), t(control), address(0), port_fields(0){};

    datav_it_t pack(size_t payload_size) {
        if (d.size()) return d.begin();
        // payload size + number of bytes in header is top byte
        // since that's required for the cc1101/cc1201 with
        // variable packet sizes
        d.push_back(payload_size + 2);
        d.push_back(address);
        d.push_back(port_fields);
        return d.begin();
    }

    type t;
    data_t address;

    friend class payload_data;

    // common header byte - union so it's easier to put into vector
    struct {
        union {
            struct {
                data_t port_fields;
            } __attribute__((packed));
            struct {
#if __BIG_ENDIAN
                data_t sfs : 1, ack : 1, subclass : 2, port : 4;
#else
                data_t port : 4, subclass : 2, ack : 1, sfs : 1;
#endif
            } __attribute__((packed));
        };
    };
};

/**
 * @brief [brief description]
 * @details [long description]
 *
 * @param p [description]
 * @return [description]
 */
class payload_data : public layer_map {
public:
    payload_data() : layer_map(MAX_DATA_SZ){};

    datav_it_t pack() { return d.begin(); }

    datav_it_t add_header(const header_data& h) {
        d.insert(d.begin(), h.d.begin(), h.d.end());
        return d.begin();
    }

    template <class T>
    void fill(const std::vector<T>& v) {
        d = v;
    }
    void fill(const std::string& str) {
        for (const char& c : str) d.push_back(c);
        d.push_back('\0');
    }
};

/**
 * @brief      { Real-Time packet definition }
 */
class packet {
public:
    rtp::header_data header;
    rtp::payload_data payload;
    bool _packed;

    packet(){};
    packet(const std::string& s) { payload.fill(s); }

    template <class T>
    packet(const std::vector<T>& v) {
        payload.fill(v);
    }

    packet_data_t* packed() { return payload.data(); }

    size_t size() {
        if (_packed == true)
            return payload.size();
        else
            return payload.size() + header.size();
    }

    const int port() const { return static_cast<const int>(header.port); }
    template <class T>
    void port(T p) {
        header.port = static_cast<unsigned int>(p);
    }

    int subclass() { return header.subclass; }
    template <class T>
    void subclass(T c) {
        header.subclass = static_cast<unsigned int>(c);
    }

    bool ack() { return header.ack; }
    void ack(bool b) { header.ack = b; }

    bool sfs() { return header.sfs; }
    void sfs(bool b) { header.sfs = b; }

    int address() { return header.address; }
    void address(int a) { header.address = static_cast<unsigned int>(a); }

    template <class T>
    void recv(const std::vector<T>& v) {
        payload.fill(v);
        // sort out header
    }

private:
    void pack() {
        payload.pack();
        header.pack(payload.size());
        payload.add_header(header);
        _packed = true;
    }
};
}
<commit_msg>adding support for selective header attachment to packets<commit_after>#pragma once

#include <cstdint>
#include <vector>
#include <string>

#if __BIG_ENDIAN
#define RTP_HEADER(port, subclass, ack, sfs)                                 \
    (((port & 0x0F) << 4) | ((subclass & 0x03) << 2) | ((ack & 0x01) << 1) | \
     (sfs & 0x01))
#else
#define RTP_HEADER(port, subclass, ack, sfs)                                \
    (((sfs & 0x01) << 7) | ((ack & 0x01) << 6) | ((subclass & 0x03) << 4) | \
     (port & 0x0F))
#endif

#define BASE_STATION_ADDR (1)
#define LOOPBACK_ADDR (127)

namespace rtp {

///
static const unsigned int MAX_DATA_SZ = 120;

/**
 * @brief      { port enumerations for different communication protocols }
 */
enum port {
    SINK = 0x00,
    LINK = 0x01,
    CONTROL = 0x02,
    SETPOINT = 0x03,
    GSTROBE = 0x04,
    DISCOVER = 0x05,
    LOGGER = 0x06,
    TCP = 0x07,
    LEGACY = 0x0E
};

namespace {
// type of data field used in all packet classes
// - must be 8 bits, (typedef used for eaiser compiler
// type error debugging)
typedef uint8_t packet_data_t;
}

/**
 * @brief [brief description]
 * @details [long description]
 * @return [description]
 */
class layer_map {
public:
    typedef packet_data_t data_t;

protected:
    typedef std::vector<data_t> datav_t;
    typedef datav_t::iterator datav_it_t;
    std::vector<data_t> d;

public:
    layer_map(size_t resv) { d.reserve(resv); }

    datav_it_t pack() {
        // make sure all files are in contiguous memory,
        // then return iterator to beginning
        return d.begin();
    }

    data_t* data() { return d.data(); }

    void show_data() {
        for (auto const& i : d) printf("%02X ", i);
    }

    const size_t size() const { return static_cast<const int>(d.size()); }
};

/**
 * @brief [brief description]
 * @details [long description]
 *
 * @param p [description]
 * @return [description]
 */
class header_data : public layer_map {
public:
    enum type { control, tuning, ota, misc };

    header_data() : layer_map(3), t(control), address(0), port_fields(0){};

    datav_it_t pack(size_t payload_size, bool headless = false) {
        if (d.size()) return d.begin();
        // payload size + number of bytes in header is top byte
        // since that's required for the cc1101/cc1201 with
        // variable packet sizes
        d.push_back(payload_size + (headless ? 0 : 2));
        if (headless == false) {
            d.push_back(address);
            d.push_back(port_fields);
        }
        return d.begin();
    }

    type t;
    data_t address;

    friend class payload_data;

    // common header byte - union so it's easier to put into vector
    struct {
        union {
            struct {
                data_t port_fields;
            } __attribute__((packed));
            struct {
#if __BIG_ENDIAN
                data_t sfs : 1, ack : 1, subclass : 2, port : 4;
#else
                data_t port : 4, subclass : 2, ack : 1, sfs : 1;
#endif
            } __attribute__((packed));
        };
    };
};

/**
 * @brief [brief description]
 * @details [long description]
 *
 * @param p [description]
 * @return [description]
 */
class payload_data : public layer_map {
public:
    payload_data() : layer_map(MAX_DATA_SZ){};

    datav_it_t pack() { return d.begin(); }

    datav_it_t add_header(const header_data& h) {
        d.insert(d.begin(), h.d.begin(), h.d.end());
        return d.begin();
    }

    template <class T>
    void fill(const std::vector<T>& v) {
        d = v;
    }
    void fill(const std::string& str) {
        for (const char& c : str) d.push_back(c);
        d.push_back('\0');
    }
};

/**
 * @brief      { Real-Time packet definition }
 */
class packet {
public:
    rtp::header_data header;
    rtp::payload_data payload;
    bool _packed;

    packet(){};
    packet(const std::string& s) { payload.fill(s); }

    template <class T>
    packet(const std::vector<T>& v) {
        payload.fill(v);
    }

    packet_data_t* packed() {
        if (_packed == false)
            pack();

        return payload.data();
    }

    size_t size() {
        if (_packed == true)
            return payload.size();
        else
            return payload.size() + header.size();
    }

    const int port() const { return static_cast<const int>(header.port); }
    template <class T>
    void port(T p) {
        header.port = static_cast<unsigned int>(p);
    }

    int subclass() { return header.subclass; }
    template <class T>
    void subclass(T c) {
        header.subclass = static_cast<unsigned int>(c);
    }

    bool ack() { return header.ack; }
    void ack(bool b) { header.ack = b; }

    bool sfs() { return header.sfs; }
    void sfs(bool b) { header.sfs = b; }

    int address() { return header.address; }
    void address(int a) { header.address = static_cast<unsigned int>(a); }

    template <class T>
    void recv(const std::vector<T>& v) {
        payload.fill(v);
        // sort out header
    }

private:
    void pack() {
        payload.pack();
        // pack the header, but do a "headless" pack
        header.pack(payload.size(), true);
        payload.add_header(header);
        _packed = true;
    }
};
}
<|endoftext|>


<commit_before>/// @page AutoFilterTutorial00 AutoFilter Tutorial 00
/// This tutorial is intended to teach blah blah blah.
/// @code

// AutoFilterTutorial00.cpp created by Victor Dods on 2015/06/03
// Copyright (C) Leap Motion, Inc. All rights reserved.

/// @endcode
///
/// Testing
///
/// # Markdown test heading 1
/// ## Heading 2
/// ### Heading 3
///
/// List:
/// - item1
/// - item2
///   - item2.1
///   - item2.2
///   - item2.3
/// - item3
///
/// Numbered list:
/// 1. Blah 1
/// 2. Blah 2
/// 3. Blah 3
///
/// @code

int main () {
  return 0;
}

/// @endcode
<commit_msg>Implemented AutoFilter tutorial 00.  Having trouble with the doxygen indentation of @code blocks (it strips the common indentation).<commit_after>/// @page AutoFilterTutorial00 AutoFilter Tutorial 00
/// This tutorial will introduce the reader to the AutoFilter concept and how to implement a rudimentary
/// AutoFilter network.  It is recommended that the reader become familiar with the concept of a context
/// (see XXX TODO context tutorial) before reading this tutorial.
/// @code
// AutoFilterTutorial00.cpp created by Victor Dods on 2015/06/03
// Copyright (C) Leap Motion, Inc. All rights reserved.
/// @endcode
/// A filter network can be thought of as a directed acyclic graph, where the nodes of the graph represent
/// data structures and the collection of arrows pointing at each graph node represent a function which
/// populates the data structure which that node represents.  That collection of arrows will be refered to
/// as a filter.
///
/// In Autowiring, a filter is implemented as context members having an AutoFilter method.  Its parameters
/// are what define the inputs and outputs.  The inputs and outputs of these AutoFilter methods are what
/// define the nodes of the filter network.
///
/// Particular C++ idioms are used to differentiate the input and output parameters for an AutoFilter method,
/// as well as certain usage semantics.  These will be fully covered in later tutorials.  For now we will
/// deal only with ordinary input and output.
///
/// This tutorial will define and instantiate a simple filter network.
/// @code{.cpp}
#include <autowiring/Autowired.h> // Needed for Autowiring classes.
#include <cmath>                  // Needed for std::round.
#include <cstdlib>                // Needed for std::atof.
#include <iostream>               // Needed for std::cout.
/// @endcode
/// We will define several filters connecting several data structures (really they can be any C++ type), rendering
/// a linear sequence of processing.
///
/// This filter takes a std::string as input and produces a double as output.  Notice that the input is passed
/// to the AutoFilter method by value (other, more efficient semantics will be introduced later), and that the
/// output is passed by reference.  These type semantics are what define what the inputs and outputs of the
/// filter are.  Instead of returning a value, the AutoFilter method need only assign to its output parameters.
///
/// In particular, this filter parses the string as a decimal value and stores it in double-precision floating
/// point format in the output parameter.
/// @code
class StringToDouble {
public:
  void AutoFilter (std::string input, double &output) {
    output = std::atof(input.c_str());
    std::cout << "StringToDouble received std::string value \"" << input << "\" and has set its output param to double value " << output << ".\n";
  }
};
/// @endcode
/// This filter takes a double as input and produces an int as output.  In particular, the output is the rounded
/// value of the input.
/// @code
class DoubleRounder {
public:
  void AutoFilter (double input, int &output) {
    output = static_cast<int>(std::round(input));
    std::cout << "DoubleRounder received double value " << input << " and has set its output param to int value " << output << ".\n";
  }
};
/// @endcode
/// This filter takes an int as input and has no output.  It simply prints the value of the input.
/// and
/// @code
class IntPrinter {
public:
  void AutoFilter (int value) {
    std::cout << "IntPrinter received int value " << value << ".\n";
  }
};
/// @endcode
/// To demonstrate this filter network, we will perform the necessary initialization and context member injection
/// within the main function.
/// @code
int main () {
/// @endcode
/// A global context is created by default, and is the default current context.  We must initialize that context
/// before proceeding.
/// @code
  AutoCurrentContext()->Initiate();
/// @endcode
/// Each of the filters must be injected into the context in which they'll operate.  In this case, we're only working
/// with the global context.  The `AutoRequired` method is what accomplishes that injection.
/// @code
  AutoRequired<StringToDouble>();
  AutoRequired<DoubleRounder>();
  AutoRequired<IntPrinter>();
/// @endcode
/// If a context has any members, then the context automatically includes an AutoPacketFactory type. This
/// can be used to create new packets in the AutoFilter network.
/// @code
  Autowired<AutoPacketFactory> factory;
/// @endcode
/// `AutoPacket` is the mechanism which runs filter networks.  An instance of AutoPacket corresponds with one execution
/// of the corresponding filter network.  The packet can be 'decorated' with a value of a particular type.  This means
/// that that type is present during this execution of the filter network as an input parameter to whatever AutoFilter
/// methods are present in the filter network.  Only one value of any given type can be present in a packet at a time.
/// The AutoFilter method of a context member will only be called once all of its inputs have been decorated onto the
/// packet.
///
/// Using the factory, create a new AutoPacket so that we may run the filter network.
/// @code
  std::shared_ptr<AutoPacket> packet = factory->NewPacket();
/// @endcode
/// Now decorate the packet with an `int`.  This will cause the `AutoFilter` methods which only require a single `int`
/// input to be called.  We should expect to see "IntPrinter received int value 42." printed to std::cout at this point.
/// @code
  packet->Decorate(42);
  std::cout << '\n'; // To make the separation between packets' executions clear in the console output.
/// @endcode
/// Create a new packet so that we may run the filter network again.  Note that `packet` is a `std::shared_ptr<AutoPacket>`,
/// and so this assignment deletes the old instance.  Decorate the packet again, but this time with a `double` value, thereby
/// calling the `DoubleRounder` filter, which in turn outputs an `int`, which calls the `IntPrinter` filter, generating output
/// to std::cout.  This demonstrates that a filter network doesn't have a fixed input interface -- inputs can be provided at
/// any point.  Of course, an `AutoFilter` method will be called only when all of its inputs are present on a packet.
/// @code
  packet = factory->NewPacket();
  packet->Decorate(101.1);
  std::cout << '\n';
/// @endcode
/// Repeat the process, but decorate the packet with a value whose rounded value is different.
/// @code
  packet = factory->NewPacket();
  packet->Decorate(101.9);
  std::cout << '\n';
/// @endcode
/// Repeat the process, but decorate the packet with a std::string value.
/// @code
  packet = factory->NewPacket();
  packet->Decorate(std::string("45954.1"));
}
/// @endcode
/// The output of this program is:
///
///     IntPrinter received int value 42.
///
///     DoubleRounder received double value 101.1 and has set its output param to int value 101.
///     IntPrinter received int value 101.
///
///     DoubleRounder received double value 101.9 and has set its output param to int value 102.
///     IntPrinter received int value 102.
///
///     StringToDouble received std::string value "45954.1" and has set its output param to double value 45954.1.
///     DoubleRounder received double value 45954.1 and has set its output param to int value 45954.
///     IntPrinter received int value 45954.
<|endoftext|>


<commit_before>/* utility.ino */

#include "utility.h"
#include <LiquidTWI2.h>
#include <Ethernet2.h>          // https://github.com/adafruit/Ethernet2
#include <EthernetUdp2.h>       // https://github.com/adafruit/Ethernet2

void LCD_clearLine(LiquidTWI2 lcdref, int line) {
    lcdref.setCursor(0, line);
    for (int i=0;i<17;i++)
        lcdref.print(" ");
    lcdref.setCursor(0, line);
}

// Maintainbe our DHCP Lease
// Based on examples from the Ethernet2 Library
void dhcp_maintain() {
    switch (Ethernet.maintain()) {
        case DHCP_RENEW_FAIL:
            Serial.println("DHCP Renew Failed");
            // Turn off NTP Fetching
            break;
        case DHCP_RENEW_SUCCESS:
            Serial.println("DHCP Renew Success");
            break;
        case DHCP_REBIND_FAIL:
            // how is this diff to Renew fail?
            Serial.println("DHCP Rebind Failed");
            // Assume turn off NTP Fetching
            break;
        case DHCP_REBIND_SUCCESS:
            Serial.println("DHCP Rebind Success");
            break;
        default:
            break;
    }
}
<commit_msg>Improved clearLine<commit_after>/* utility.ino */

#include "utility.h"
#include <LiquidTWI2.h>
#include <Ethernet2.h>          // https://github.com/adafruit/Ethernet2
#include <EthernetUdp2.h>       // https://github.com/adafruit/Ethernet2

void LCD_clearLine(LiquidTWI2 lcdref, int line) {
    lcdref.setCursor(0, line);
    char row[16];
    memset(row, ' ', 16);
    lcdref.print(row);
    lcdref.setCursor(0, line);
}

// Maintainbe our DHCP Lease
// Based on examples from the Ethernet2 Library
void dhcp_maintain() {
    switch (Ethernet.maintain()) {
        case DHCP_RENEW_FAIL:
            Serial.println("DHCP Renew Failed");
            // Turn off NTP Fetching
            break;
        case DHCP_RENEW_SUCCESS:
            Serial.println("DHCP Renew Success");
            break;
        case DHCP_REBIND_FAIL:
            // how is this diff to Renew fail?
            Serial.println("DHCP Rebind Failed");
            // Assume turn off NTP Fetching
            break;
        case DHCP_REBIND_SUCCESS:
            Serial.println("DHCP Rebind Success");
            break;
        default:
            break;
    }
}
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
//    File:             DateTime.cpp
//
//    Title:            DateTime Class
//
//    Description:	This file contains the class definition for DateTime
//
//    Programmer:	Paul Bladek & Norton Pengra
//
//    Date:             4/24/2017
//
//    Version:          1.0
//
//    Environment:   Hardware: IBM Pentium
//                   Software:  WinXP or later or .NET for execution;
//
//    Compiles under Microsoft C++ 2005
//
//	  class DateTime:
//
//	  Virtual Non-inline:
//		virtual bool operator==(const Comparable &other)const;
//		virtual bool operator<(const Comparable &other)const;
//		virtual void input(istream& sin);
//		virtual void print(ostream& sout)const;
//
//    History Log:
//                      4/7/08  PB  completed version 1.0
// ----------------------------------------------------------------------------
#include "DateTime.h"

using namespace std;
namespace NP_DATETIME {

}<commit_msg>add == comparison<commit_after>//-----------------------------------------------------------------------------
//    File:             DateTime.cpp
//
//    Title:            DateTime Class
//
//    Description:	This file contains the class definition for DateTime
//
//    Programmer:	Paul Bladek & Norton Pengra
//
//    Date:             4/24/2017
//
//    Version:          1.0
//
//    Environment:   Hardware: IBM Pentium
//                   Software:  WinXP or later or .NET for execution;
//
//    Compiles under Microsoft C++ 2005
//
//	  class DateTime:
//
//	  Virtual Non-inline:
//		virtual bool operator==(const Comparable &other)const;
//		virtual bool operator<(const Comparable &other)const;
//		virtual void input(istream& sin);
//		virtual void print(ostream& sout)const;
//
//    History Log:
//                      4/7/08  PB  completed version 1.0
// ----------------------------------------------------------------------------
#include "DateTime.h"

using namespace std;
namespace NP_DATETIME {

	bool DateTime::operator==(const Comparable &other) const {
		bool returnValue = false;
		try
		{
			bool dateEqual = Date::operator==(other);
			bool timeEqual = CTime::operator==(other);
			returnValue = dateEqual && timeEqual;
		}
		catch (bad_cast e)
		{
			// Should something happen here?
		}
		return returnValue;
	}

}<|endoftext|>