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