⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 miniserver.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 3 页
字号:
    memset( ( void * )&genaAddr, 0, sizeof( struct sockaddr_in ) );
    genaAddr.sin_family = AF_INET;
    //  genaAddr.sin_addr.s_addr = inet_addr(LOCAL_HOST);
    genaAddr.sin_addr.s_addr = htonl( INADDR_ANY );
    genaAddr.sin_port = htons( GENA_PORT );
    if( bind
        ( genaEventSock, ( struct sockaddr * )&genaAddr,
          sizeof( genaAddr ) ) != 0 ) {
	  shutdown( genaEventSock, SD_BOTH );
	  UpnpCloseSocket( genaEventSock );
	  return UPNP_E_SOCKET_BIND;
    }

    memset( ( void * )&genaMcastAddr, 0, sizeof( struct ip_mreq ) );
    genaMcastAddr.imr_interface.s_addr = htonl( INADDR_ANY );
    genaMcastAddr.imr_multiaddr.s_addr = inet_addr( GENA_IP );
    if( setsockopt( genaEventSock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                    ( char * )&genaMcastAddr,
                    sizeof( struct ip_mreq ) ) != 0 ) {
		    shutdown( genaEventSock, SD_BOTH );
		    UpnpCloseSocket( genaEventSock );
		    return UPNP_E_SOCKET_ERROR;
    }
    // result is not checked becuase it will fail in WinMe and Win9x.
    setsockopt( genaEventSock, IPPROTO_IP,
                IP_MULTICAST_TTL, &ttl, sizeof( ttl ) );
    if( setsockopt( genaEventSock, SOL_SOCKET, SO_BROADCAST,
                    ( char * )&option, sizeof( option ) ) != 0 ) {
		    shutdown( genaEventSock, SD_BOTH );
		    UpnpCloseSocket( genaEventSock );
		    return UPNP_E_NETWORK_ERROR;
    }
    out->genaEventSock = genaEventSock;
*/
    
    listenfd = socket( AF_INET, SOCK_STREAM, 0 );
    if( listenfd == UPNP_INVALID_SOCKET || listenfd == 0) {
        return UPNP_E_OUTOF_SOCKET; // error creating socket
    }
    // As per the IANA specifications for the use of ports by applications
    // override the listen port passed in with the first available 
    if( listen_port < APPLICATION_LISTENING_PORT )
        listen_port = APPLICATION_LISTENING_PORT;

    memset( &serverAddr, 0, sizeof( serverAddr ) );
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = htonl( INADDR_ANY );

    // Getting away with implementation of re-using address:port and instead 
    // choosing to increment port numbers.
    // Keeping the re-use address code as an optional behaviour that can be 
    // turned on if necessary. 
    // TURN ON the reuseaddr_on option to use the option.
    if( reuseaddr_on ) {
        //THIS IS ALLOWS US TO BIND AGAIN IMMEDIATELY
        //AFTER OUR SERVER HAS BEEN CLOSED
        //THIS MAY CAUSE TCP TO BECOME LESS RELIABLE
        //HOWEVER IT HAS BEEN SUGESTED FOR TCP SERVERS

        DBGONLY( UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
                             "mserv start: resuseaddr set\n" );
             )

            sockError = setsockopt( listenfd,
                                    SOL_SOCKET,
                                    SO_REUSEADDR,
                                    ( const char * )&reuseaddr_on,
                                    sizeof( int )
             );
        if( sockError == UPNP_SOCKETERROR ) {
            shutdown( listenfd, SD_BOTH );
            UpnpCloseSocket( listenfd );
            return UPNP_E_SOCKET_BIND;
        }

        sockError = bind( listenfd,
                          ( struct sockaddr * )&serverAddr,
                          sizeof( struct sockaddr_in )
             );
    } else {
        do {
            serverAddr.sin_port = htons( listen_port++ );
            sockError = bind( listenfd,
                              ( struct sockaddr * )&serverAddr,
                              sizeof( struct sockaddr_in )
                 );
            if( sockError == UPNP_SOCKETERROR ) {
#ifndef _WIN32
                if( errno == EADDRINUSE )
                    errCode = 1;
#endif
				printf("Socket error in miniserver line 780\n");
            } else
                errCode = 0;

        } while( errCode != 0 );
    }

    if( sockError == UPNP_SOCKETERROR ) {
        DBGONLY( perror( "mserv start: bind failed" );
             )
            shutdown( listenfd, SD_BOTH );
        UpnpCloseSocket( listenfd );
        return UPNP_E_SOCKET_BIND;  // bind failed
    }

    DBGONLY( UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
                         "mserv start: bind success\n" );
         )

        success = listen( listenfd, SOMAXCONN );
    if( success == UPNP_SOCKETERROR ) {
        shutdown( listenfd, SD_BOTH );
        UpnpCloseSocket( listenfd );
        return UPNP_E_LISTEN;   // listen failed
    }

    actual_port = get_port( listenfd );
    if( actual_port <= 0 ) {
        shutdown( listenfd, SD_BOTH );
        UpnpCloseSocket( listenfd );
        return UPNP_E_INTERNAL_ERROR;
    }

    out->miniServerPort = actual_port;

    if( ( miniServerStopSock = socket( AF_INET, SOCK_DGRAM, 0 ) ) ==
        UPNP_INVALID_SOCKET ) {
        DBGONLY( UpnpPrintf( UPNP_CRITICAL,
                             MSERV, __FILE__, __LINE__,
                             "Error in socket operation !!!\n" );
             )
            shutdown( listenfd, SD_BOTH );
        UpnpCloseSocket( listenfd );
        return UPNP_E_OUTOF_SOCKET;
    }

    // bind to local socket
    memset( ( char * )&serverAddr, 0, sizeof( struct sockaddr_in ) );
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );

    if( bind( miniServerStopSock, ( struct sockaddr * )&serverAddr,
              sizeof( serverAddr ) ) == UPNP_SOCKETERROR ) {

        DBGONLY( UpnpPrintf( UPNP_CRITICAL,
                             MSERV, __FILE__, __LINE__,
                             "Error in binding localhost!!!\n" );
             )
            shutdown( listenfd, SD_BOTH );
        UpnpCloseSocket( listenfd );
        shutdown( miniServerStopSock, SD_BOTH );
        UpnpCloseSocket( miniServerStopSock );
        return UPNP_E_SOCKET_BIND;
    }

    miniStopSockPort = get_port( miniServerStopSock );
    if( miniStopSockPort <= 0 ) {
        shutdown( miniServerStopSock, SD_BOTH );
        shutdown( listenfd, SD_BOTH );
        UpnpCloseSocket( miniServerStopSock );
        UpnpCloseSocket( listenfd );
        return UPNP_E_INTERNAL_ERROR;
    }

    out->stopPort = miniStopSockPort;

    out->miniServerSock = listenfd;
    out->miniServerStopSock = miniServerStopSock;

    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 UPNP_E_XXX - On Error   			
*	Note :
************************************************************************/
int
StartMiniServer( unsigned short listen_port )
{

    int success;

    int count;
    int max_count = 10000;

    MiniServerSockArray *miniSocket;
    ThreadPoolJob job;

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

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

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

    if( ( success = get_ssdp_sockets( miniSocket ) ) != UPNP_E_SUCCESS ) {

        free( miniSocket );
        shutdown( miniSocket->miniServerSock, SD_BOTH );
        UpnpCloseSocket( miniSocket->miniServerSock );
        shutdown( miniSocket->miniServerStopSock, SD_BOTH );
        UpnpCloseSocket( miniSocket->miniServerStopSock );
        return success;
    }

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

    TPJobSetFreeFunction( &job, ( free_routine ) free );

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

    if( success < 0 ) {
        shutdown( miniSocket->miniServerSock, SD_BOTH );
        shutdown( miniSocket->miniServerStopSock, SD_BOTH );
        shutdown( miniSocket->ssdpSock, SD_BOTH );
        CLIENTONLY( shutdown( miniSocket->ssdpReqSock, SD_BOTH ) );
        UpnpCloseSocket( miniSocket->miniServerSock );
        UpnpCloseSocket( miniSocket->miniServerStopSock );
        UpnpCloseSocket( miniSocket->ssdpSock );

        CLIENTONLY( UpnpCloseSocket( miniSocket->ssdpReqSock ) );

        return UPNP_E_OUTOF_MEMORY;
    }
    // wait for miniserver to start
    count = 0;
    while( gMServState != MSERV_RUNNING && count < max_count ) {
#ifndef _WIN32
        usleep( 50 * 1000 );    // 0.05s
#else
        SleepEx( 50, TRUE );
#endif
        count++;
    }

    // taking too long to start that thread
    if( count >= max_count ) {

        shutdown( miniSocket->miniServerSock, SD_BOTH );
        shutdown( miniSocket->miniServerStopSock, SD_BOTH );
        shutdown( miniSocket->ssdpSock, SD_BOTH );
        CLIENTONLY( shutdown( miniSocket->ssdpReqSock, SD_BOTH ) );

        UpnpCloseSocket( miniSocket->miniServerSock );
        UpnpCloseSocket( miniSocket->miniServerStopSock );
        UpnpCloseSocket( miniSocket->ssdpSock );
        CLIENTONLY( UpnpCloseSocket( miniSocket->ssdpReqSock ) );

        return UPNP_E_INTERNAL_ERROR;
    }

    return miniSocket->miniServerPort;
}

/************************************************************************
*	Function :	StopMiniServer
*
*	Parameters :
*		void ;	
*
*	Description :	Stop and Shutdown the MiniServer and free socket 
*		resources.
*
*	Return : int ;
*		Always returns 0 
*
*	Note :
************************************************************************/
int
StopMiniServer( void )
{

    int socklen = sizeof( struct sockaddr_in );
    SOCKET sock;
    struct sockaddr_in ssdpAddr;
    char buf[256] = "ShutDown";
    int bufLen = strlen( buf );

    if( gMServState == MSERV_RUNNING )
        gMServState = MSERV_STOPPING;
    else
        return 0;

    sock = socket( AF_INET, SOCK_DGRAM, 0 );
    if( sock == UPNP_INVALID_SOCKET ) {
        DBGONLY( UpnpPrintf
                 ( UPNP_INFO, SSDP, __FILE__, __LINE__,
                   "SSDP_SERVER:StopSSDPServer: Error in socket operation !!!\n" );
             )
            return 0;
    }

    while( gMServState != MSERV_IDLE ) {
        ssdpAddr.sin_family = AF_INET;
        ssdpAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
        ssdpAddr.sin_port = htons( miniStopSockPort );
        sendto( sock, buf, bufLen, 0, ( struct sockaddr * )&ssdpAddr,
                socklen );
#ifndef _WIN32
        usleep( 1000 );    // 0.05s
#else
        SleepEx( 1, TRUE );
#endif
        if( gMServState == MSERV_IDLE )
            break;
#ifndef _WIN32
        isleep( 1 );
#else
        SleepEx( 1000, TRUE );
#endif
    }
    shutdown( sock, SD_BOTH );
    UpnpCloseSocket( sock );
    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -