int AddMiniServerInterface(const char *ip, int *iface, uint16_t *listen_port4) { int i; int error; ithread_mutex_lock(&gMiniServerMutex); for (i = 0; i < MAX_NETWORK_INTERFACES; ++i) { if (gMiniSocket->miniServerSock4[i] == INVALID_SOCKET) break; } if (i == MAX_NETWORK_INTERFACES) { UpnpPrintf(UPNP_CRITICAL, MSERV, __FILE__, __LINE__, "AddMiniServerInterface: no free interface slots"); ithread_mutex_unlock(&gMiniServerMutex); return UPNP_E_OUTOF_SOCKET; } error = get_miniserver_sockets(gMiniSocket, ip, i, *listen_port4); if (error != UPNP_E_SUCCESS) { UpnpPrintf(UPNP_CRITICAL, MSERV, __FILE__, __LINE__, "AddMiniServerInterface: get_miniserver_sockets failed with error %d", error); ithread_mutex_unlock(&gMiniServerMutex); return error; } error = get_ssdp_sockets(gMiniSocket, ip, i); if (error != UPNP_E_SUCCESS) { UpnpPrintf(UPNP_CRITICAL, MSERV, __FILE__, __LINE__, "AddMiniServerInterface: get_ssdp_sockets failed with error %d", error); ithread_mutex_unlock(&gMiniServerMutex); return error; } *listen_port4 = gMiniSocket->miniServerPort4[i]; *iface = i; ithread_mutex_unlock(&gMiniServerMutex); wake_miniserver(); UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__, "AddMiniServerInterface: %s:%d added successfully to slot %d", ip, *listen_port4, i); return UPNP_E_SUCCESS; }
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; }
/************************************************************************ * 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; }