Пример #1
0
HavokResponse *db_mysql_save_account( HavokRequest *req )
{
    MYSQL_BIND         *data;
    pthread_mutex_t    *mutex;
    HavokResponse      *resp;
    ProtectedData_t    *protect;
    volatile int        id;

    if( !req || !req->account_data ) {
        return;
    }

    mutex = CREATE(pthread_mutex_t);
    thread_mutex_init( mutex );

    protect = ProtectedDataCreate();
    protect->data = (void *)&id;
    ProtectedDataLock( protect );

    data = CREATEN(MYSQL_BIND, 7);

    bind_numeric( &data[0], req->account_data->id, MYSQL_TYPE_LONG );
    bind_string( &data[1], req->account_data->email, MYSQL_TYPE_VAR_STRING );
    bind_string( &data[2], req->account_data->passwd, MYSQL_TYPE_VAR_STRING );
    bind_numeric( &data[3], (req->account_data->ansi ? 1 : 0), 
                            MYSQL_TYPE_TINY );
    bind_numeric( &data[4], (req->account_data->confirmed ? 1 : 0), 
                            MYSQL_TYPE_TINY );
    bind_string( &data[5], (req->account_data->confcode ? 
                            req->account_data->confcode : ""), 
                           MYSQL_TYPE_VAR_STRING );
    bind_null_blob( &data[6], protect );

    db_queue_query( 5, QueryTable, data, 7, NULL, NULL, mutex );

    pthread_mutex_unlock( mutex );
    pthread_mutex_destroy( mutex );
    memfree( mutex );

    ProtectedDataLock( protect );
    ProtectedDataDestroy( protect );

    resp = protobufCreateResponse();
    if( !resp ) {
        return( NULL );
    }

    resp->request_type = REQ_TYPE__SAVE_ACCOUNT;
    resp->account_data = CREATE(ReqAccountType);
    req_account_type__init( resp->account_data );
    memcpy( resp->account_data, req->account_data, sizeof(ReqAccountType) );
    resp->account_data->id = id;
    resp->account_data->email    = memstrlink( req->account_data->email );
    resp->account_data->passwd   = memstrlink( req->account_data->passwd );
    resp->account_data->confcode = memstrlink( req->account_data->confcode );

    return( resp );
}
Пример #2
0
/**
 * @brief Thread to handle WebService requests
 * @return never returns until shutdown
 *
 * Receives requests over a web socket and acts on them.
 */
void *WebServiceThread( void *arg )
{
    char               *port;
    char               *logdir;
    char                buf[1024];
    char              **options;
    struct mg_context  *ctx;

    pthread_mutex_lock( startupMutex );

    port = pb_get_setting( "webServicePort" );
    if( !port || !atoi(port) ) {
        LogPrintNoArg( LOG_CRIT, "No WebService Port defined.  Aborting!" );
        return;
    }

    logdir = pb_get_setting( "webServiceLogDir" );
    if( !logdir ) {
        logdir = memstrlink( "/tmp" );
    }

    LogPrint( LOG_DEBUG, "Web Service listening on port %s", port );
    LogPrint( LOG_DEBUG, "Web Logs in %s", logdir );

    options = CREATEN(char *, 7);
    options[0] = memstrlink("ports");
    options[1] = memstrdup(port);
    options[2] = memstrlink("access_log");
    sprintf( buf, "%s/access.log", logdir );
    options[3] = memstrdup(buf);
    options[4] = memstrlink("error_log");
    sprintf( buf, "%s/error.log", logdir );
    options[5] = memstrdup(buf);
    options[6] = NULL;

    memfree( port );
    memfree( logdir );

    mg_set_allocs( &webServiceAllocs );

    /*
     * Initialize mongoose context.
     * Start listening on port specified.
     */
    ctx = mg_start(webServiceCallback, NULL, (const char **)options);

    while( !GlobalAbort ) {
        sleep(1);
    }
    
    mg_stop(ctx);

    LogPrintNoArg(LOG_INFO, "Ending WebServiceThread");
    return( NULL );
}
Пример #3
0
void result_get_setting( MYSQL_RES *res, MYSQL_BIND *input, void *arg,
                         long insertid )
{
    HavokResponse **resp;
    int             count;
    MYSQL_ROW       row;

    resp = (HavokResponse **)arg;

    if( !res || !(count = mysql_num_rows(res)) ) {
        *resp = NULL;
        return;
    }
    row = mysql_fetch_row(res);

    *resp = protobufCreateResponse();
    if( !*resp ) {
        return;
    }

    (*resp)->request_type = REQ_TYPE__GET_SETTING;
    (*resp)->settings_data = CREATE(ReqSettingsType);
    req_settings_type__init( (*resp)->settings_data );
    (*resp)->settings_data->setting_name  = memstrlink( input[0].buffer );
    (*resp)->settings_data->setting_value = COL_STRING(row, 0);
}
Пример #4
0
HavokResponse *db_mysql_save_pc( HavokRequest *req )
{
    MYSQL_BIND         *data;
    pthread_mutex_t    *mutex;
    HavokResponse      *resp;
    ProtectedData_t    *protect;
    volatile int        id;

    if( !req || !req->pc_data ) {
        return( NULL );
    }

    mutex = CREATE(pthread_mutex_t);
    thread_mutex_init( mutex );

    protect = ProtectedDataCreate();
    protect->data = (void *)&id;
    ProtectedDataLock( protect );

    data = CREATEN(MYSQL_BIND, 4);

    bind_numeric( &data[0], req->pc_data->id, MYSQL_TYPE_LONG );
    bind_numeric( &data[1], req->pc_data->account_id, MYSQL_TYPE_LONG );
    bind_string( &data[2], req->pc_data->name, MYSQL_TYPE_VAR_STRING );
    bind_null_blob( &data[3], protect );

    db_queue_query( 10, QueryTable, data, 4, NULL, NULL, mutex );

    pthread_mutex_unlock( mutex );
    pthread_mutex_destroy( mutex );
    memfree( mutex );

    ProtectedDataLock( protect );
    ProtectedDataDestroy( protect );

    db_mysql_save_pc_attribs( id, req->pc_data->attribs );

    resp = protobufCreateResponse();
    if( !resp ) {
        return( NULL );
    }

    resp->request_type = REQ_TYPE__SAVE_PC;
    resp->n_pc_data = 1;
    resp->pc_data = CREATE(ReqPCType *);
    resp->pc_data[0] = CREATE(ReqPCType);
    req_pctype__init( resp->pc_data[0] );
    memcpy( resp->pc_data[0], req->pc_data, sizeof(ReqPCType) );
    resp->pc_data[0]->id   = id;
    resp->pc_data[0]->name = memstrlink( req->pc_data->name );

    return( resp );
}
Пример #5
0
void StartThreads( void )
{
    pthread_mutex_t     spinLockMutex;
    pid_t               childPid;
    struct sigaction    sa;
    sigset_t            sigmsk;
    size_t              len;
    ThreadCallback_t    callbacks;

    GlobalAbort = FALSE;

#ifndef __CYGWIN__
    len = confstr( _CS_GNU_LIBPTHREAD_VERSION, NULL, 0 );
    if( len ) {
        pthreadsVersion = CREATEN(char, len);
        confstr( _CS_GNU_LIBPTHREAD_VERSION, pthreadsVersion, len );
    }
#else
    (void)len;
    pthreadsVersion = memstrlink( "Cygwin" );
#endif

    if( !pthreadsVersion || strstr( pthreadsVersion, "linuxthreads" ) ) {
        fprintf( stderr, "havokmud requires NPTL to operate correctly.\n\n"
                         "The signal handling in linuxthreads is just too "
                         "broken to use.\n\n" );
        exit( 1 );
    }

    /* Do we need to detach? */
    if( Daemon ) {
        childPid = fork();
        if( childPid < 0 ) {
            perror( "Couldn't detach in daemon mode" );
            _exit( 1 );
        }

        if( childPid != 0 ) {
            /* This is still the parent, report the child's pid and exit */
            printf( "[Detached as PID %d]\n", childPid );
            /* And exit the parent */
            _exit( 0 );
        }

        /* After this is in the detached child */

        /* Close stdin, stdout, stderr to release the tty */
        close(0);
        close(1);
        close(2);
    }

    LoggingQ      = QueueCreate( 1024 );
    ConnectInputQ = QueueCreate( 256 );
    ConnectDnsQ   = QueueCreate( 64 );
    InputLoginQ   = QueueCreate( 256 );
    InputEditorQ  = QueueCreate( 256 );
    InputPlayerQ  = QueueCreate( 256 );
    InputImmortQ  = QueueCreate( 256 );
    MailQ         = QueueCreate( 128 );
    QueryQ        = QueueCreate( 1024 );
    ProtobufQ     = QueueCreate( 1024 );

    mainThreadId = pthread_self();
    /* 
     * Setup the sigmasks for this thread (which is the parent to all others).
     * This will propogate to all children.
     */
    sigfillset( &sigmsk );
    sigdelset( &sigmsk, SIGUSR1 );
    sigdelset( &sigmsk, SIGUSR2 );
    sigdelset( &sigmsk, SIGHUP );
    sigdelset( &sigmsk, SIGWINCH );
    sigdelset( &sigmsk, SIGINT );
    sigdelset( &sigmsk, SIGSEGV );
    sigdelset( &sigmsk, SIGILL );
    sigdelset( &sigmsk, SIGFPE );
    pthread_sigmask( SIG_SETMASK, &sigmsk, NULL );

    memset( &callbacks, 0, sizeof(ThreadCallback_t) );
    callbacks.sighupFunc = mainSighup;
    thread_register( &mainThreadId, "MainThread", NULL );

    /* Setup signal handler for SIGUSR1 (toggles Debug) */
    sa.sa_sigaction = (sigAction_t)logging_toggle_debug;
    sigemptyset( &sa.sa_mask );
    sa.sa_flags = SA_RESTART;
    sigaction( SIGUSR1, &sa, NULL );

    /* Setup the exit handler */
    atexit( MainDelayExit );

    /* Setup signal handler for SIGINT (shut down cleanly) */
    sa.sa_sigaction = (sigAction_t)signal_interrupt;
    sigemptyset( &sa.sa_mask );
    sa.sa_flags = SA_RESTART;
    sigaction( SIGINT, &sa, NULL );
    
    /* Setup signal handlers that are to be propogated to all threads */
    sa.sa_sigaction = (sigAction_t)signal_everyone;
    sigemptyset( &sa.sa_mask );
    sa.sa_flags = SA_RESTART | SA_SIGINFO;
    sigaction( SIGUSR2, &sa, NULL );
    sigaction( SIGHUP, &sa, NULL );
    sigaction( SIGWINCH, &sa, NULL );

    /* Setup signal handlers for SEGV, ILL, FPE */
    sa.sa_sigaction = (sigAction_t)signal_death;
    sigemptyset( &sa.sa_mask );
    sa.sa_flags = SA_RESTART | SA_SIGINFO;
    sigaction( SIGSEGV, &sa, NULL );
    sigaction( SIGILL, &sa, NULL );
    sigaction( SIGFPE, &sa, NULL );

    versionAdd( "pthreads", pthreadsVersion );
    versionAdd( "TERM", getenv("TERM") );

    thread_create( &loggingThreadId, LoggingThread, NULL, "LoggingThread", 
                   NULL );

#if 0
    curses_start();
    cursesMenuItemAdd( 2, MENU_SYSTEM, "About", mainAbout, NULL );
    cursesMenuItemAdd( 2, MENU_SYSTEM, "Licensing", mainLicensing, NULL );
    cursesMenuItemAdd( 2, MENU_SYSTEM, "Versions", mainVersions, NULL );
    cursesMenuItemAdd( 2, MENU_SYSTEM, "Reload All", mainReloadAll, NULL );
#endif

    LogBanner();

    db_init();
    db_mysql_init();

    memset( &callbacks, 0, sizeof(ThreadCallback_t) );
    callbacks.sigusr2Func = memoryStats;
    thread_create( &memoryThreadId, MemoryCoalesceThread, NULL, 
                   "MemoryCoalesceThread", &callbacks );
    thread_create( &dnsThreadId, DnsThread, NULL, "DnsThread", NULL );
    thread_create( &inputThreadId, InputThread, NULL, "InputThread", NULL );
    thread_create( &loginThreadId, LoginThread, NULL, "LoginThread", NULL );
    thread_create( &editorThreadId, EditorThread, NULL, "EditorThread", NULL );

    mortalPlayingArgs.inputQ = InputPlayerQ;
    thread_create( &mortalPlayingThreadId, PlayingThread, &mortalPlayingArgs,
                   "MortalPlayingThread", NULL );
    
    immortPlayingArgs.inputQ = InputImmortQ;
    thread_create( &immortPlayingThreadId, PlayingThread, &immortPlayingArgs,
                   "ImmortPlayingThread", NULL );

    thread_create( &mysqlThreadId, MysqlThread, NULL, "MySQLThread", NULL );
    thread_create( &protobufThreadId, ProtobufThread, NULL, "ProtobufThread", 
                   NULL );

    pthread_mutex_lock( startupMutex );
    pthread_mutex_unlock( startupMutex );
    db_check_schema_main();

    thread_create( &smtpThreadId, SmtpThread, NULL, "SMTPThread", NULL );

    connectThreadArgs.port = mud_port;
    connectThreadArgs.timeout_sec = 0;
    connectThreadArgs.timeout_usec = 100000;
    thread_create( &connectionThreadId, ConnectionThread, &connectThreadArgs,
                   "ConnectionThread", NULL );

    pthread_mutex_lock( startupMutex );
    pthread_mutex_unlock( startupMutex );

    /* Sit on this and rotate - this causes an intentional deadlock, this
     * thread should stop dead in its tracks
     */
    thread_mutex_init( &spinLockMutex );
    pthread_mutex_lock( &spinLockMutex );
    pthread_mutex_lock( &spinLockMutex );
}