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

📄 miniserver.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 3 页
字号:
************************************************************************/
static XINLINE void
schedule_request_job( IN int connfd,
                      IN struct sockaddr_in *clientAddr )
{
    struct mserv_request_t *request;
    ThreadPoolJob job;

    request =
        ( struct mserv_request_t * )
        malloc( sizeof( struct mserv_request_t ) );
    if( request == NULL ) {
        DBGONLY( UpnpPrintf
                 ( UPNP_INFO, MSERV, __FILE__, __LINE__,
                   "mserv %d: out of memory\n", connfd );
             )
            shutdown( request->connfd, SD_BOTH );
        UpnpCloseSocket( connfd );
        return;
    }

    request->connfd = connfd;
    request->foreign_ip_addr = clientAddr->sin_addr;
    request->foreign_ip_port = ntohs( clientAddr->sin_port );

    TPJobInit( &job, ( start_routine ) handle_request, ( void * )request );
    TPJobSetFreeFunction( &job, free_handle_request_arg );
    TPJobSetPriority( &job, MED_PRIORITY );

    if( ThreadPoolAdd( &gRecvThreadPool, &job, NULL ) != 0 ) {
        DBGONLY( UpnpPrintf
                 ( UPNP_INFO, MSERV, __FILE__, __LINE__,
                   "mserv %d: cannot schedule request\n", connfd );
             )
            free( request );
        shutdown( connfd, SD_BOTH );
        UpnpCloseSocket( connfd );
        return;
    }

}

/************************************************************************
*	Function :	RunMiniServer
*
*	Parameters :
*		MiniServerSockArray *miniSock ;	Socket Array
*
*	Description :	Function runs the miniserver. The MiniServer accepts a 
*		new request and schedules a thread to handle the new request.
*		Checks for socket state and invokes appropriate read and shutdown 
*		actions for the Miniserver and SSDP sockets 
*
*	Return :	void
*
*	Note :
************************************************************************/
static void
RunMiniServer( MiniServerSockArray * miniSock )
{
    struct sockaddr_in clientAddr;
    int clientLen;
    SOCKET miniServSock,
      connectHnd;
    SOCKET miniServStopSock;
    SOCKET ssdpSock;
// MTY!!!
// note that this socket will not be available when this
// is called, and will need to be added into the select
// set later
    SOCKET genaEventSock;


    CLIENTONLY( SOCKET ssdpReqSock;
         )

    fd_set expSet;
    fd_set rdSet;
    unsigned int maxMiniSock;
    int byteReceived;
    char requestBuf[256];
    struct timeval aTime;
    struct timeval * timePtr;
#ifdef _WIN32
    int retVal;
#endif
    int genaSocketSet = 0;
#ifdef _WIN32
    FILE * outFile;
#endif

    aTime.tv_sec = 1;
    aTime.tv_usec = 0;
    timePtr = 0;

    miniServSock = miniSock->miniServerSock;
    miniServStopSock = miniSock->miniServerStopSock;

    ssdpSock = miniSock->ssdpSock;

    genaEventSock = miniSock->genaEventSock;

    CLIENTONLY( ssdpReqSock = miniSock->ssdpReqSock;
         );

    gMServState = MSERV_RUNNING;
    maxMiniSock = max( miniServSock, miniServStopSock );
    maxMiniSock = max( maxMiniSock, ( SOCKET ) ( ssdpSock ) );

    CLIENTONLY( maxMiniSock =
                max( maxMiniSock, ( SOCKET ) ( ssdpReqSock ) ) );

    ++maxMiniSock;

    while( TRUE ) {

        FD_ZERO( &rdSet );
        FD_ZERO( &expSet );

        FD_SET( miniServStopSock, &expSet );

        FD_SET( miniServSock, &rdSet );
        FD_SET( miniServStopSock, &rdSet );
        FD_SET( ssdpSock, &rdSet );
	// MTY!!!
	// check if the gena socket is available now
	// if it is, add it to the set and change the maxMiniSock
	// value

	if (!genaSocketSet) {
	    if (gGenaSock != UPNP_INVALID_SOCKET) {

		genaEventSock = gGenaSock;
		maxMiniSock = max(maxMiniSock, genaEventSock);
		genaSocketSet = 1;
		FD_SET( genaEventSock, &rdSet );
	    }
	} else {
	    FD_SET( genaEventSock, &rdSet );
	}
        CLIENTONLY( FD_SET( ssdpReqSock, &rdSet ) );

#ifdef _WIN32
	if (gGenaSock == UPNP_INVALID_SOCKET) {
	    timePtr = &aTime;
	} else {
	    timePtr = 0;
	}

        if( select( maxMiniSock, &rdSet, NULL, &expSet, timePtr ) ==
            UPNP_SOCKETERROR ) {
#else
        if( select( maxMiniSock, &rdSet, NULL, &expSet, NULL ) ==
            UPNP_SOCKETERROR ) {
#endif
#ifdef _WIN32
			retVal = WSAGetLastError();
#endif
#ifdef _WIN32
            DBGONLY( UpnpPrintf
                     ( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
                       "Error (%d) in select call !!!\n", retVal );
                 )
#else
            DBGONLY( UpnpPrintf
                     ( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
                       "Error in select call !!!\n" );
                 )
#endif
                continue;
        } else {

            if( FD_ISSET( miniServSock, &rdSet ) ) {
                clientLen = sizeof( struct sockaddr_in );
                connectHnd = accept( miniServSock,
                                     ( struct sockaddr * )&clientAddr,
                                     &clientLen );
                if( connectHnd == UPNP_INVALID_SOCKET ) {
                    DBGONLY( UpnpPrintf
                             ( UPNP_INFO, MSERV, __FILE__, __LINE__,
                               "miniserver: Error"
                               " in accepting connection\n" );
                         )
                        continue;
                }
                schedule_request_job( connectHnd, &clientAddr );
            }
            //ssdp
            CLIENTONLY( if( FD_ISSET( ssdpReqSock, &rdSet ) ) {

                        readFromSSDPSocket( ssdpReqSock );}
             )

                if( FD_ISSET( ssdpSock, &rdSet ) ) {
                    readFromSSDPSocket( ssdpSock );
                }

	    // MTY!!!
	    if (genaSocketSet) {
		if (FD_ISSET( genaEventSock, &rdSet )) {
		    readFromGenaEventSocket( genaEventSock );
		}
	    }

            if( FD_ISSET( miniServStopSock, &rdSet ) ) {

                clientLen = sizeof( struct sockaddr_in );
                memset( ( char * )&clientAddr, 0,
                        sizeof( struct sockaddr_in ) );
                byteReceived =
                    recvfrom( miniServStopSock, requestBuf, 25, 0,
                              ( struct sockaddr * )&clientAddr,
                              &clientLen );
                if( byteReceived > 0 ) {
                    requestBuf[byteReceived] = '\0';
                    DBGONLY( UpnpPrintf
                             ( UPNP_INFO, MSERV, __FILE__, __LINE__,
                               "Received response !!!  %s From host %s \n",
                               requestBuf,
                               inet_ntoa( clientAddr.sin_addr ) );
                         )
                        DBGONLY( UpnpPrintf
                                 ( UPNP_PACKET, MSERV, __FILE__, __LINE__,
                                   "Received multicast packet: \n %s\n",
                                   requestBuf );
                         )

                        if( NULL != strstr( requestBuf, "ShutDown" ) )
                        break;
                }
            }
        }

    }

    shutdown( miniServSock, SD_BOTH );
    UpnpCloseSocket( miniServSock );
    shutdown( miniServStopSock, SD_BOTH );
    UpnpCloseSocket( miniServStopSock );
    shutdown( ssdpSock, SD_BOTH );
    UpnpCloseSocket( ssdpSock );
    // MTY!!!
    if (genaSocketSet) {
	shutdown( genaEventSock, SD_BOTH );
	UpnpCloseSocket( genaEventSock );
    }
    CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ) );
    CLIENTONLY( UpnpCloseSocket( ssdpReqSock ) );

    free( miniSock );

    gMServState = MSERV_IDLE;

    return;

}

/************************************************************************
*	Function :	get_port
*
*	Parameters :
*		int sockfd ; Socket Descriptor 
*
*	Description :	Returns port to which socket, sockfd, is bound.
*
*	Return :	int, 
*		-1 on error; check errno
*		 > 0 means port number
*
*	Note :
************************************************************************/
static int
get_port( int sockfd )
{
    struct sockaddr_in sockinfo;
    int len;
    int code;
    int port;

    len = sizeof( struct sockaddr_in );
    code = getsockname( sockfd, ( struct sockaddr * )&sockinfo, &len );
    if( code == UPNP_SOCKETERROR ) {
        return -1;
    }

    port = ntohs( sockinfo.sin_port );
    DBGONLY( UpnpPrintf
             ( UPNP_INFO, MSERV, __FILE__, __LINE__,
               "sockfd = %d, .... port = %d\n", sockfd, port );
         )

        return port;
}

/************************************************************************
*	Function :	get_miniserver_sockets
*
*	Parameters :
*		MiniServerSockArray *out ;	Socket Array
*		unsigned short listen_port ; port on which the server is listening 
*									for incoming connections	
*
*	Description :	Creates a STREAM socket, binds to INADDR_ANY and 
*		listens for incoming connecttions. Returns the actual port which 
*		the sockets sub-system returned. 
*		Also creates a DGRAM socket, binds to the loop back address and 
*		returns the port allocated by the socket sub-system.
*
*	Return :	int : 
*		UPNP_E_OUTOF_SOCKET - Failed to create a socket
*		UPNP_E_SOCKET_BIND - Bind() failed
*		UPNP_E_LISTEN	- Listen() failed	
*		UPNP_E_INTERNAL_ERROR - Port returned by the socket layer is < 0
*		UPNP_E_SUCCESS	- Success
*		
*	Note :
************************************************************************/
//#define  GENA_IP   "239.255.255.250"
//#define GENA_PORT 1901
int
get_miniserver_sockets( MiniServerSockArray * out,
                        unsigned short listen_port )
{
    struct sockaddr_in serverAddr;
    SOCKET listenfd;
    int success;
    unsigned short actual_port;
    int reuseaddr_on = 0;
    int sockError = UPNP_E_SUCCESS;
    int errCode = 0;
    SOCKET miniServerStopSock;

    // MTY!!!
/*
    
    SOCKET genaEventSock;
    struct sockaddr_in genaAddr;
    struct ip_mreq genaMcastAddr;
    u_char ttl = 4;
    int option = 1;

    if( ( genaEventSock = socket( AF_INET, SOCK_DGRAM, 0 ) )
	== UPNP_INVALID_SOCKET ) {
	return UPNP_E_OUTOF_SOCKET;
    }

⌨️ 快捷键说明

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