miniserver.c
来自「原来由英特尔制定的UPnP SDK的」· C语言 代码 · 共 853 行 · 第 1/2 页
C
853 行
/////////////////////////////////////////////////////////////////////////////// Copyright (c) 2000-2003 Intel Corporation // All rights reserved. //// Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: //// * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither name of Intel Corporation nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission.// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.//////////////////////////////////////////////////////////////////////////////************************************************************************* Purpose: This file implements the functionality and utility functions* used by the Miniserver module.************************************************************************/#include "config.h"#ifndef WIN32 #include <arpa/inet.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/wait.h> #include <unistd.h> #include <sys/time.h>#else /* WIN32 */ #include <winsock2.h> typedef int socklen_t; #define EAFNOSUPPORT 97#endif /* WIN32 */#include "unixutil.h"#include "ithread.h"#include <assert.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include "ssdplib.h"#include "util.h"#include "miniserver.h"#include "ThreadPool.h"#include "httpreadwrite.h"#include "statcodes.h"#include "upnpapi.h"#define APPLICATION_LISTENING_PORT 49152struct mserv_request_t { int connfd; // connection handle struct in_addr foreign_ip_addr; unsigned short foreign_ip_port;};typedef enum { MSERV_IDLE, MSERV_RUNNING, MSERV_STOPPING } MiniServerState;unsigned short miniStopSockPort;////////////////////////////////////////////////////////////////////////////// module varsstatic MiniServerCallback gGetCallback = NULL;static MiniServerCallback gSoapCallback = NULL;static MiniServerCallback gGenaCallback = NULL;static MiniServerState gMServState = MSERV_IDLE;/************************************************************************ * Function: SetHTTPGetCallback * * Parameters : * MiniServerCallback callback - HTTP Callback to be invoked * * Description: * Set HTTP Get Callback * * Return: void ************************************************************************/voidSetHTTPGetCallback( MiniServerCallback callback ){ gGetCallback = callback;}/************************************************************************ * Function: SetSoapCallback * * Parameters: * MiniServerCallback callback - SOAP Callback to be invoked * * Description: * Set SOAP Callback * * Return: void ************************************************************************/#ifdef INCLUDE_DEVICE_APISvoidSetSoapCallback( MiniServerCallback callback ){ gSoapCallback = callback;}#endif /* INCLUDE_DEVICE_APIS *//************************************************************************ * Function: SetGenaCallback * * Parameters: * MiniServerCallback callback - GENA Callback to be invoked * * Description: * Set GENA Callback * * Return: void ************************************************************************/voidSetGenaCallback( MiniServerCallback callback ){ gGenaCallback = callback;}/************************************************************************ * Function : dispatch_request * * Parameters : * IN SOCKINFO *info - Socket Information object. * http_parser_t* hparser - HTTP parser object. * * Description : * Based on the type pf message, appropriate callback is issued * * Return: int * 0 - On Success * HTTP_INTERNAL_SERVER_ERROR - Callback is NULL ************************************************************************/static intdispatch_request( IN SOCKINFO * info, http_parser_t * hparser ){ MiniServerCallback callback; switch ( hparser->msg.method ) { //Soap Call case SOAPMETHOD_POST: case HTTPMETHOD_MPOST: callback = gSoapCallback; break; //Gena Call case HTTPMETHOD_NOTIFY: case HTTPMETHOD_SUBSCRIBE: case HTTPMETHOD_UNSUBSCRIBE: UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__, "miniserver %d: got GENA msg\n", info->socket ); callback = gGenaCallback; break; //HTTP server call case HTTPMETHOD_GET: case HTTPMETHOD_POST: case HTTPMETHOD_HEAD: case HTTPMETHOD_SIMPLEGET: callback = gGetCallback; break; default: callback = NULL; } if( callback == NULL ) { return HTTP_INTERNAL_SERVER_ERROR; } callback( hparser, &hparser->msg, info ); return 0;}/************************************************************************ * Function: handle_error * * Parameters: * IN SOCKINFO *info - Socket Inforamtion Object * int http_error_code - HTTP Error Code * int major - Major Version Number * int minor - Minor Version Number * * Description: * Send Error Message * * Return: void ************************************************************************/static UPNP_INLINE voidhandle_error( IN SOCKINFO * info, int http_error_code, int major, int minor ){ http_SendStatusResponse( info, http_error_code, major, minor );}/************************************************************************ * Function: free_handle_request_arg * * Parameters: * void *args ; Request Message to be freed * * Description: * Free memory assigned for handling request and unitialize socket * functionality * * Return: void ************************************************************************/static voidfree_handle_request_arg( void *args ){ struct mserv_request_t *request = ( struct mserv_request_t * )args; shutdown( request->connfd, SD_BOTH ); UpnpCloseSocket( request->connfd ); free( request );}/************************************************************************ * Function: handle_request * * Parameters: * void *args - Request Message to be handled * * Description: * Receive the request and dispatch it for handling * * Return: void ************************************************************************/static voidhandle_request( void *args ){ SOCKINFO info; int http_error_code; int ret_code; int major = 1; int minor = 1; http_parser_t parser; http_message_t *hmsg = NULL; int timeout = HTTP_DEFAULT_TIMEOUT; struct mserv_request_t *request = ( struct mserv_request_t * )args; int connfd = request->connfd; UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__, "miniserver %d: READING\n", connfd ); //parser_request_init( &parser ); ////LEAK_FIX_MK hmsg = &parser.msg; if( sock_init_with_ip( &info, connfd, request->foreign_ip_addr, request->foreign_ip_port ) != UPNP_E_SUCCESS ) { free( request ); httpmsg_destroy( hmsg ); return; } // read ret_code = http_RecvMessage( &info, &parser, HTTPMETHOD_UNKNOWN, &timeout, &http_error_code ); if( ret_code != 0 ) { goto error_handler; } UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__, "miniserver %d: PROCESSING...\n", connfd ); // dispatch http_error_code = dispatch_request( &info, &parser ); if( http_error_code != 0 ) { goto error_handler; } http_error_code = 0; error_handler: if( http_error_code > 0 ) { if( hmsg ) { major = hmsg->major_version; minor = hmsg->minor_version; } handle_error( &info, http_error_code, major, minor ); } UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__, "miniserver %d: COMPLETE\n", connfd ); sock_destroy( &info, SD_BOTH ); //should shutdown completely httpmsg_destroy( hmsg ); free( request );}/************************************************************************ * Function: schedule_request_job * * Parameters: * IN int connfd - Socket Descriptor on which connection is accepted * IN struct sockaddr_in* clientAddr - Clients Address information * * Description: * Initilize the thread pool to handle a request. * Sets priority for the job and adds the job to the thread pool * * Return: void ************************************************************************/static UPNP_INLINE voidschedule_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 ) { 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( &gMiniServerThreadPool, &job, NULL ) != 0 ) { 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 ************************************************************************/static voidRunMiniServer( MiniServerSockArray *miniSock ){ char errorBuffer[ERROR_BUFFER_LEN]; struct sockaddr_in clientAddr; socklen_t clientLen; SOCKET connectHnd; SOCKET miniServSock = miniSock->miniServerSock; SOCKET miniServStopSock = miniSock->miniServerStopSock; SOCKET ssdpSock = miniSock->ssdpSock;#ifdef INCLUDE_CLIENT_APIS SOCKET ssdpReqSock = miniSock->ssdpReqSock;#endif fd_set expSet; fd_set rdSet; unsigned int maxMiniSock; int byteReceived; char requestBuf[256]; int ret = 0; maxMiniSock = max( miniServSock, miniServStopSock) ; maxMiniSock = max( maxMiniSock, (SOCKET)(ssdpSock) );#ifdef INCLUDE_CLIENT_APIS maxMiniSock = max( maxMiniSock, (SOCKET)(ssdpReqSock) );#endif ++maxMiniSock; gMServState = MSERV_RUNNING; while( TRUE ) { FD_ZERO( &rdSet ); FD_ZERO( &expSet ); FD_SET( miniServStopSock, &expSet ); FD_SET( miniServSock, &rdSet ); FD_SET( miniServStopSock, &rdSet ); FD_SET( ssdpSock, &rdSet );#ifdef INCLUDE_CLIENT_APIS FD_SET( ssdpReqSock, &rdSet );#endif ret = select( maxMiniSock, &rdSet, NULL, &expSet, NULL ); if ( ret == -1 ) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, "Error in select(): %s\n", errorBuffer ); /* Avoid 100% CPU in case of repeated error in select() */ isleep( 1 ); continue;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?