miniserver.c
来自「原来由英特尔制定的UPnP SDK的」· C语言 代码 · 共 853 行 · 第 1/2 页
C
853 行
} else { if( FD_ISSET( miniServSock, &rdSet ) ) { clientLen = sizeof( struct sockaddr_in ); connectHnd = accept( miniServSock, ( struct sockaddr * )&clientAddr, &clientLen ); if( connectHnd == -1 ) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__, "miniserver: Error in accept(): %s\n", errorBuffer ); continue; } schedule_request_job( connectHnd, &clientAddr ); }#ifdef INCLUDE_CLIENT_APIS // ssdp if( FD_ISSET( ssdpReqSock, &rdSet ) ) { readFromSSDPSocket( ssdpReqSock ); }#endif if( FD_ISSET( ssdpSock, &rdSet ) ) { readFromSSDPSocket( ssdpSock ); } 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'; UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__, "Received response: %s From host %s \n", requestBuf, inet_ntoa( clientAddr.sin_addr ) ); 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 );#ifdef INCLUDE_CLIENT_APIS shutdown( ssdpReqSock, SD_BOTH ); UpnpCloseSocket( ssdpReqSock );#endif 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 ************************************************************************/static intget_port( int sockfd ){ struct sockaddr_in sockinfo; socklen_t len; int code; int port; len = sizeof( struct sockaddr_in ); code = getsockname( sockfd, ( struct sockaddr * )&sockinfo, &len ); if( code == -1 ) { return -1; } port = ntohs( sockinfo.sin_port ); 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 ************************************************************************/intget_miniserver_sockets( MiniServerSockArray * out, unsigned short listen_port ){ char errorBuffer[ERROR_BUFFER_LEN]; struct sockaddr_in serverAddr; int listenfd; int success; unsigned short actual_port; int reuseaddr_on = 0; int sockError = UPNP_E_SUCCESS; int errCode = 0; int miniServerStopSock; int ret = 0; listenfd = socket( AF_INET, SOCK_STREAM, 0 ); if ( listenfd == -1 ) { 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 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 == -1 ) { 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 == -1 ) {#ifdef WIN32 errCode = WSAGetLastError();#else errCode = errno; #endif if( errno == EADDRINUSE ) { errCode = 1; } } else errCode = 0; } while ( errCode != 0 ); } if ( sockError == -1 ) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__, "mserv start: Error in bind(): %s\n", errorBuffer ); shutdown( listenfd, SD_BOTH ); UpnpCloseSocket( listenfd ); return UPNP_E_SOCKET_BIND; // bind failed } UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__, "mserv start: bind success\n" ); success = listen( listenfd, SOMAXCONN ); if ( success == -1 ) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__, "mserv start: Error in listen(): %s\n", errorBuffer ); shutdown( listenfd, SD_BOTH ); UpnpCloseSocket( listenfd ); return UPNP_E_LISTEN; } actual_port = get_port( listenfd ); if( actual_port <= 0 ) { shutdown( listenfd, SD_BOTH ); UpnpCloseSocket( listenfd ); return UPNP_E_INTERNAL_ERROR; } out->miniServerPort = actual_port; miniServerStopSock = socket( AF_INET, SOCK_DGRAM, 0 ); if ( miniServerStopSock == -1 ) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_CRITICAL, MSERV, __FILE__, __LINE__, "Error in socket(): %s\n", errorBuffer ); 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" ); ret = bind( miniServerStopSock, (struct sockaddr *)&serverAddr, sizeof (serverAddr) ); if ( ret == -1 ) { 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 ); UpnpCloseSocket( miniServerStopSock ); shutdown( listenfd, SD_BOTH ); 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 ************************************************************************/intStartMiniServer( 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; } success = get_miniserver_sockets( miniSocket, listen_port ); if( success != UPNP_E_SUCCESS ) { free( miniSocket ); return success; } success = get_ssdp_sockets( miniSocket ); if( success != UPNP_E_SUCCESS ) { shutdown( miniSocket->miniServerSock, SD_BOTH ); UpnpCloseSocket( miniSocket->miniServerSock ); shutdown( miniSocket->miniServerStopSock, SD_BOTH ); UpnpCloseSocket( 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 ); UpnpCloseSocket( miniSocket->miniServerSock ); shutdown( miniSocket->miniServerStopSock, SD_BOTH ); UpnpCloseSocket( miniSocket->miniServerStopSock ); shutdown( miniSocket->ssdpSock, SD_BOTH ); UpnpCloseSocket( miniSocket->ssdpSock );#ifdef INCLUDE_CLIENT_APIS shutdown( miniSocket->ssdpReqSock, SD_BOTH ); UpnpCloseSocket( miniSocket->ssdpReqSock );#endif return UPNP_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 ); UpnpCloseSocket( miniSocket->miniServerSock ); shutdown( miniSocket->miniServerStopSock, SD_BOTH ); UpnpCloseSocket( miniSocket->miniServerStopSock ); shutdown( miniSocket->ssdpSock, SD_BOTH ); UpnpCloseSocket( miniSocket->ssdpSock );#ifdef INCLUDE_CLIENT_APIS shutdown( miniSocket->ssdpReqSock, SD_BOTH ); UpnpCloseSocket( miniSocket->ssdpReqSock );#endif 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 ************************************************************************/intStopMiniServer(){ char errorBuffer[ERROR_BUFFER_LEN]; int socklen = sizeof( struct sockaddr_in ); int 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 == -1 ) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, "SSDP_SERVER: StopSSDPServer: Error in socket() %s\n", errorBuffer ); 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 ); usleep( 1000 ); if( gMServState == MSERV_IDLE ) { break; } isleep( 1 ); } shutdown( sock, SD_BOTH ); UpnpCloseSocket( sock ); return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?