/*----------------------------------------------------------------------------*/
/*                                                                            */
/*  Copyright (c) 1997, 1998 by                                               */
/*  blaxxun interactive Inc, San Francisco, California, USA                   */
/*  All rights reserved                                                       */
/*                                                                            */
/*  This software is furnished under a license  and may be  used and  copied  */
/*  only in  accordance of the  terms of such license and with the inclusion  */
/*  of the above copyright notice.  This software or any other copies therof  */
/*  may not be provided or otherwise made available to any other person.  No  */
/*  title to and ownership of the software is hereby transferred.             */
/*                                                                            */
/*  The information in this software is subject to change without notice and  */
/*  should not be construed as a commitment by blaxxun interactive Inc.       */
/*                                                                            */
/*----------------------------------------------------------------------------*/

/*
------------------------------------------------------------------------------

  MODULE NAME:  $RCSfile: raserver.c,v $
  REVISION:     $Revision: 1.7 $
  DATE:         $Date: 2001/02/15 17:47:40 $
  AUTHOR:       $Author: peter $
  STATE:        $State: Exp $

  CREATION DATE:       Jul 11, 1996

  =DocStart= Module raserver.c

  PROJECT:            VWP         - blaxxun virtual worlds platform
  SYSTEM:             server      - server processes
  COMPONENT:          apserver    - Community Server API server

  DESCRIPTION:
      The Main of the raserver as an NT service.

  =DocEnd=

------------------------------------------------------------------------------
*/

/*
 * make sure the rcsid shows up in the executable
 */
#if !defined (lint)
static char rcsid[] = "@(#) $Id: raserver.c,v 1.7 2001/02/15 17:47:40 peter Exp $";

/*
 * the following function is needed to suppress compiler warnings, don't call it
 */
static void rcsid_fkt()
{
    if( ! *rcsid )
        *rcsid = 0;
    if( 0 )
        rcsid_fkt();
}
#endif

/*----------------------------------------------------------------------------*/
/*             GLOBAL INCLUDE FILES                                           */
/*----------------------------------------------------------------------------*/

#include "raextern.h"
#include "rantserv.h"       /* NT services include for RA  server             */

/*----------------------------------------------------------------------------*/
/*             MODULE MACROS/CONSTANTS                                        */
/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/*             MODULE TYPE DECLARATIONS                                       */
/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/*             MODULE VARIABLE DECLARATIONS                                   */
/*----------------------------------------------------------------------------*/
/*
 * the usage string ot the service
 */
static char usage[] =
    "Usage: %s -p port [ application specific options ][ -TRACE -D ]\n\
       where\n\
        -p port: is the port the RA server should work with\n\
        -TRACE: enables the trace flag\n\
        -D: is for debugging\n";

/*
 * the global datastructure of the service, the three functions below
 * communicate via this structure
 */
static raserver_t raServer;

/*----------------------------------------------------------------------------*/
/*             FUNCTION PROTOTYPES                                            */
/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/*             FUNCTIONS                                                      */
/*----------------------------------------------------------------------------*/

/*  =DocStart= Function raserverInitFunction
------------------------------------------------------------------------------
  FUNCTION NAME:        raserverInitFunction

  DESCRIPTION:
    This function is called when the RA server is started.

    It should read all needed parameters from the registry.
    And put them into argc, argv. The service specific init
    function should then parse them from there.

  NOTE: In order to make the process run correctly on NT this function must
        not perform any exits, use a positive return code as the
        example does.

  RETURN VALUES:
    int rc == 0: ok process started successfully
        rc != 0: the startup failed, the process will go down with
                 the exitcode returned
------------------------------------------------------------------------------
*/
static int raserverInitFunction(
int argc,
char ** argv
)
/*  =DocEnd= */
{
    static DWORD  myargc = 0;
    static char * myargv[ 255 ];
    static char   port[ 255 ];
    static char   regvalport[ 256 ];
    static char   installdirectory[ 255 ];
    char          buffer[ 1024 ];
    int           rc = 0;
    int           i = 0;
    char        * ptr = NULL;

    long          portlen = sizeof( port );
    long          installdirectorylen = sizeof( installdirectory );

    memset( port, 0, sizeof( port ));
    memset( installdirectory, 0, sizeof( installdirectory ));

    /*
     * set an own argc, argv
     * use the service name as argv[ 0 ].
     */
    myargv[ myargc++ ] = RANT_SERVICE_NAME;

    /* 
     * read the values that are needed from the registry
     * 1. The install directory, i.e. BSIROOT
     */ 
    if( 0 == ivntserv_RegQueryKeyByName( IVNT_REGKEY_PRODUCT,
                                         IVNT_REGVAL_INSTALLDIR,
                                         installdirectory,
                                         &installdirectorylen ))
    {
        installdirectory[ installdirectorylen ] = 0;
    }

    strcpy( buffer, installdirectory );
    if( strlen( buffer ) + strlen("/chstart") + 1 < sizeof( buffer ) )
    {
        strcat( buffer, "/chstart" );
    }
    else
    {
        return( 244 );
    }

    process_get_chstart_line( RANT_SERVICE_NAME, buffer );
    
    i = 1;
    while( (ptr= process_startArg( i )) )
    {
        myargv[ myargc++ ] = ptr;
        i++;
    }
    /*
     * make sure argv is terminated by a NULL
     */
    myargv[ myargc ]   = NULL;
    
    /*
     * The init function should expect all parameters it needs on
     * argc, argv. It should never exit. If it encounters a problem
     * it has to return an error code, a positive integer below 255
     * This integer has to be documented because it will appear on
     * the NT interface. As service specific error.
     */
    rc = ra_initfct( &myargc, myargv, &raServer, usage );
    if( rc )
    {
        return( rc );
    }

    /*
     * set the event handlers of the raServer
     */
    raServer.ra_handler  = raEventUdpRequest;
    raServer.ra_shutdown = raEventShutdown;
    raServer.ra_periodic = raEventPeriodic;

    /*
     * call the startup event function of the RA server
     */
    return( raEventStartup( myargc, myargv ));

} /* End of Function raserverInitFunction */

/*  =DocStart= Function raserverExitProc
------------------------------------------------------------------------------
  FUNCTION NAME:        raserverExitProc

  DESCRIPTION:
    This function is called when the RA goes down.

    Do whatever needed in order to close files, print your status, ...

    It should never exit, if the funtion wants to change the
    exit status of the process it can do so by setting the global
    variable process.exitrc

  RETURN VALUES:
    void.

------------------------------------------------------------------------------
*/
static void raserverExitProc(
int exitrc
)
/*  =DocEnd= */
{
    ra_exitproc( &raServer, exitrc );

    /*
     * DO NOT EXIT HERE!!!!
     */
} /* End of Function raserverExitProc */

/*  =DocStart= Function raserverRunFunction
------------------------------------------------------------------------------
  FUNCTION NAME:        raserverRunFunction

  DESCRIPTION:
    This function is the main loop. It should loop while the global
    variable process.dowork is true.

    If the process encounters an error, it should go down with
    process_exit and a documented exit code.

    If some external interface demands a shutdown, e.g. you receive
    a shutdown request via a socket, the process should go down via
    process_exit with an exit code of 0.

    If process.dowork becomes 0, the function should return.

  RETURN VALUES:
    void.

------------------------------------------------------------------------------
*/
static void raserverRunFunction()
/*  =DocEnd= */
{
    /*
     * call the main loop function of the service
     */
    ivsrun( ( char * )&raServer,
            raServer.socket,
            &(raServer.iperiod),
            raserver_periodic,
            raserver_reply,
            raserver_status_print,
            stderr,
            NULL
          );

} /* End of Function raserverRunFunction */

/*  =DocStart= Function main
------------------------------------------------------------------------------
  FUNCTION NAME:        main

  DESCRIPTION:
    Main for an NT Service

  RETURN VALUES:
    VOID

------------------------------------------------------------------------------
*/
void main(void)
/*  =DocEnd= */
{
    /*
     * prepare the service manager dispatch table
     */
    SERVICE_TABLE_ENTRY   DispatchTable[] =
    {
        { TEXT(RANT_SERVICE_NAME), ivntserv_ServiceStart       },
        { NULL,                    NULL                        }
    };

    /*
     * set your own functions
     */
    ntserviceInitFunction  = raserverInitFunction;
    ntserviceRunFunction   = raserverRunFunction;
    ntserviceExitProc      = raserverExitProc;

    /*
     * all we do here is calling the service dispatcher
     */
    if( !StartServiceCtrlDispatcher( DispatchTable ))
    {
        /*
         * not sure if anybody ever sees that string
         */
        fprintf( stderr,
                 "raserver: StartServiceCtrlDispatcher error = %d\n",
                 GetLastError()
               );
    }

} /* End of Function main */
