Exemple #1
0
/************************************************************************
 * Function: TimerThreadInit
 * 
 *  Description:
 *     Initializes and starts timer thread.
 *
 *  Parameters:
 *             timer - valid timer thread pointer.
 *             tp  - valid thread pool to use. Must be
 *                   started. Must be valid for lifetime
 *                   of timer.  Timer must be shutdown
 *                   BEFORE thread pool.
 *  Return:
 *            0 on success, nonzero on failure
 *            Returns error from ThreadPoolAddPersistent if failure.
 ************************************************************************/
int
TimerThreadInit( TimerThread * timer,
                 ThreadPool * tp )
{

    int rc = 0;

    ThreadPoolJob timerThreadWorker;

    assert( timer != NULL );
    assert( tp != NULL );

    if( ( timer == NULL ) || ( tp == NULL ) ) {
        return EINVAL;
    }

    rc += ithread_mutex_init( &timer->mutex, NULL );

    assert( rc == 0 );

    rc += ithread_mutex_lock( &timer->mutex );
    assert( rc == 0 );

    rc += ithread_cond_init( &timer->condition, NULL );
    assert( rc == 0 );

    rc += FreeListInit( &timer->freeEvents, sizeof( TimerEvent ), 100 );
    assert( rc == 0 );

    timer->shutdown = 0;
    timer->tp = tp;
    timer->lastEventId = 0;
    rc += ListInit( &timer->eventQ, NULL, NULL );

    assert( rc == 0 );

    if( rc != 0 ) {
        rc = EAGAIN;
    } else {

        TPJobInit( &timerThreadWorker, TimerThreadWorker, timer );
        TPJobSetPriority( &timerThreadWorker, HIGH_PRIORITY );

        rc = ThreadPoolAddPersistent( tp, &timerThreadWorker, NULL );
    }

    ithread_mutex_unlock( &timer->mutex );

    if( rc != 0 ) {
        ithread_cond_destroy( &timer->condition );
        ithread_mutex_destroy( &timer->mutex );
        FreeListDestroy( &timer->freeEvents );
        ListDestroy( &timer->eventQ, 0 );
    }

    return rc;

}
Exemple #2
0
int StartMiniServer(
	/*! [in,out] Port on which the server listens for incoming IPv4
	 * connections. */
	uint16_t *listen_port4, 
	/*! [in,out] Port on which the server listens for incoming IPv6
	 * connections. */
	uint16_t *listen_port6)
{
	int ret_code;
	int count;
	int max_count = 10000;
	MiniServerSockArray *miniSocket;
	ThreadPoolJob job;

	memset(&job, 0, sizeof(job));

	switch (gMServState) {
	case MSERV_IDLE:
		break;
	default:
		/* miniserver running. */
		return UPNP_E_INTERNAL_ERROR;
	}
	miniSocket = (MiniServerSockArray *)malloc(
		sizeof (MiniServerSockArray));
	if (!miniSocket) {
		return UPNP_E_OUTOF_MEMORY;
	}
	InitMiniServerSockArray(miniSocket);
#ifdef INTERNAL_WEB_SERVER
	/* V4 and V6 http listeners. */
	ret_code = get_miniserver_sockets(
		miniSocket, *listen_port4, *listen_port6);
	if (ret_code != UPNP_E_SUCCESS) {
		free(miniSocket);
		return ret_code;
	}
#endif
	/* Stop socket (To end miniserver processing). */
	ret_code = get_miniserver_stopsock(miniSocket);
	if (ret_code != UPNP_E_SUCCESS) {
		sock_close(miniSocket->miniServerSock4);
		sock_close(miniSocket->miniServerSock6);
		free(miniSocket);
		return ret_code;
	}
	/* SSDP socket for discovery/advertising. */
	ret_code = get_ssdp_sockets(miniSocket);
	if (ret_code != UPNP_E_SUCCESS) {
		sock_close(miniSocket->miniServerSock4);
		sock_close(miniSocket->miniServerSock6);
		sock_close(miniSocket->miniServerStopSock);
		free(miniSocket);
		return ret_code;
	}
	TPJobInit(&job, (start_routine)RunMiniServer, (void *)miniSocket);
	TPJobSetPriority(&job, MED_PRIORITY);
	TPJobSetFreeFunction(&job, (free_routine)free);
	ret_code = ThreadPoolAddPersistent(&gMiniServerThreadPool, &job, NULL);
	if (ret_code < 0) {
		sock_close(miniSocket->miniServerSock4);
		sock_close(miniSocket->miniServerSock6);
		sock_close(miniSocket->miniServerStopSock);
		sock_close(miniSocket->ssdpSock4);
		sock_close(miniSocket->ssdpSock6);
		sock_close(miniSocket->ssdpSock6UlaGua);
#ifdef INCLUDE_CLIENT_APIS
		sock_close(miniSocket->ssdpReqSock4);
		sock_close(miniSocket->ssdpReqSock6);
#endif /* INCLUDE_CLIENT_APIS */
		return UPNP_E_OUTOF_MEMORY;
	}
	/* Wait for miniserver to start. */
	count = 0;
	while (gMServState != (MiniServerState)MSERV_RUNNING && count < max_count) {
		/* 0.05s */
		usleep(50u * 1000u);
		count++;
	}
	if (count >= max_count) {
		/* Took it too long to start that thread. */
		sock_close(miniSocket->miniServerSock4);
		sock_close(miniSocket->miniServerSock6);
		sock_close(miniSocket->miniServerStopSock);
		sock_close(miniSocket->ssdpSock4);
		sock_close(miniSocket->ssdpSock6);
		sock_close(miniSocket->ssdpSock6UlaGua);
#ifdef INCLUDE_CLIENT_APIS
		sock_close(miniSocket->ssdpReqSock4);
		sock_close(miniSocket->ssdpReqSock6);
#endif /* INCLUDE_CLIENT_APIS */
		return UPNP_E_INTERNAL_ERROR;
	}
#ifdef INTERNAL_WEB_SERVER
	*listen_port4 = miniSocket->miniServerPort4;
	*listen_port6 = miniSocket->miniServerPort6;
#endif

	return UPNP_E_SUCCESS;
}
Exemple #3
0
/************************************************************************
 * Function: StartMiniServer
 *
 * Parameters :
 *	unsigned short listen_port - Port on which the server listens for 
 *		incoming connections
 *
 * Description:
 * 	Initialize the sockets functionality for the 
 *	Miniserver. Initialize a thread pool job to run the MiniServer
 *	and the job to the thread pool. If listen port is 0, port is 
 *	dynamically picked
 *
 *	Use timer mechanism to start the MiniServer, failure to meet the 
 *	allowed delay aborts the attempt to launch the MiniServer.
 *
 * Return: int
 *	Actual port socket is bound to - On Success
 *	A negative number DLNA_E_XXX - On Error
 ************************************************************************/
int
StartMiniServer( unsigned short listen_port )
{
    int success;
    int count;
    int max_count = 10000;

    MiniServerSockArray *miniSocket;
    ThreadPoolJob job;

    if( gMServState != MSERV_IDLE ) {
        return DLNA_E_INTERNAL_ERROR;   // miniserver running
    }

    miniSocket =
        ( MiniServerSockArray * ) malloc( sizeof( MiniServerSockArray ) );
    if( miniSocket == NULL )
        return DLNA_E_OUTOF_MEMORY;

    if( ( success = get_miniserver_sockets( miniSocket, listen_port ) )
        != DLNA_E_SUCCESS ) {
        free( miniSocket );
        return success;
    }

    if( ( success = get_ssdp_sockets( miniSocket ) ) != DLNA_E_SUCCESS ) {
        shutdown( miniSocket->miniServerSock, SD_BOTH );
        dlnaCloseSocket( miniSocket->miniServerSock );
        shutdown( miniSocket->miniServerStopSock, SD_BOTH );
        dlnaCloseSocket( miniSocket->miniServerStopSock );
        free( miniSocket );

        return success;
    }

    TPJobInit( &job, ( start_routine ) RunMiniServer,
               ( void * )miniSocket );
    TPJobSetPriority( &job, MED_PRIORITY );

    TPJobSetFreeFunction( &job, ( free_routine ) free );

    success = ThreadPoolAddPersistent( &gMiniServerThreadPool, &job, NULL );

    if( success < 0 ) {
        shutdown( miniSocket->miniServerSock, SD_BOTH );
        dlnaCloseSocket( miniSocket->miniServerSock );
        shutdown( miniSocket->miniServerStopSock, SD_BOTH );
        dlnaCloseSocket( miniSocket->miniServerStopSock );
        shutdown( miniSocket->ssdpSock, SD_BOTH );
        dlnaCloseSocket( miniSocket->ssdpSock );
#ifdef INCLUDE_CLIENT_APIS
        shutdown( miniSocket->ssdpReqSock, SD_BOTH );
        dlnaCloseSocket( miniSocket->ssdpReqSock );
#endif

        return DLNA_E_OUTOF_MEMORY;
    }
    // wait for miniserver to start
    count = 0;
    while( gMServState != MSERV_RUNNING && count < max_count ) {
        usleep( 50 * 1000 );    // 0.05s
        count++;
    }

    // taking too long to start that thread
    if( count >= max_count ) {
        shutdown( miniSocket->miniServerSock, SD_BOTH );
        dlnaCloseSocket( miniSocket->miniServerSock );
        shutdown( miniSocket->miniServerStopSock, SD_BOTH );
        dlnaCloseSocket( miniSocket->miniServerStopSock );
        shutdown( miniSocket->ssdpSock, SD_BOTH );
        dlnaCloseSocket( miniSocket->ssdpSock );
#ifdef INCLUDE_CLIENT_APIS
        shutdown( miniSocket->ssdpReqSock, SD_BOTH );
        dlnaCloseSocket( miniSocket->ssdpReqSock );
#endif

        return DLNA_E_INTERNAL_ERROR;
    }

    return miniSocket->miniServerPort;
}
Exemple #4
0
/****************************************************************************
 * Function: TimerThreadWorker
 *
 *  Description:
 *      Implements timer thread.
 *      Waits for next event to occur and schedules
 *      associated job into threadpool.
 *      Internal Only.
 *  Parameters:
 *      void * arg -> is cast to TimerThread *
 *****************************************************************************/
static void *
TimerThreadWorker( void *arg )
{
    TimerThread *timer = ( TimerThread * ) arg;
    ListNode *head = NULL;

    TimerEvent *nextEvent = NULL;

    time_t currentTime = 0;
    time_t nextEventTime = 0;
    struct timespec timeToWait;

    int tempId;

    assert( timer != NULL );

    ithread_mutex_lock( &timer->mutex );

    while( 1 )
    {

        //mutex should always be locked at top of loop

        //Check for shutdown

        if( timer->shutdown )
        {

            timer->shutdown = 0;
            ithread_cond_signal( &timer->condition );
            ithread_mutex_unlock( &timer->mutex );
            return NULL;

        }

        nextEvent = NULL;

        //Get the next event if possible
        if( timer->eventQ.size > 0 )
        {
            head = ListHead( &timer->eventQ );

            nextEvent = ( TimerEvent * ) head->item;
            nextEventTime = nextEvent->eventTime;
        }

        currentTime = time( NULL );

        //If time has elapsed, schedule job

        if( ( nextEvent != NULL ) && ( currentTime >= nextEventTime ) )
        {

            if( nextEvent->persistent ) {

                ThreadPoolAddPersistent( timer->tp, &nextEvent->job,
                                         &tempId );
            } else {

                ThreadPoolAdd( timer->tp, &nextEvent->job, &tempId );
            }

            ListDelNode( &timer->eventQ, head, 0 );
            FreeTimerEvent( timer, nextEvent );

            continue;

        }

        if( nextEvent != NULL ) {
            timeToWait.tv_nsec = 0;
            timeToWait.tv_sec = nextEvent->eventTime;

            ithread_cond_timedwait( &timer->condition, &timer->mutex,
                                    &timeToWait );

        } else {
            ithread_cond_wait( &timer->condition, &timer->mutex );
        }

    }
}