📄 miniserver.c
字号:
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 + -