📄 miniserver.c
字号:
/////////////////////////////////////////////////////////////////////////////// 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 <arpa/inet.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/wait.h>#include <unistd.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/wait.h>#include <unistd.h>#include <arpa/inet.h>#include <netinet/in.h>#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 "upnp.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** Note :************************************************************************/voidSetHTTPGetCallback( MiniServerCallback callback ){ gGetCallback = callback;}/************************************************************************* Function : SetSoapCallback** Parameters :* MiniServerCallback callback ; - SOAP Callback to be invoked ** Description : Set SOAP Callback** Return : void** Note :************************************************************************/voidSetSoapCallback( MiniServerCallback callback ){ gSoapCallback = callback;}/************************************************************************* Function : SetGenaCallback** Parameters :* MiniServerCallback callback ; - GENA Callback to be invoked** Description : Set GENA Callback** Return : void** Note :************************************************************************/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** Note :************************************************************************/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: DBGONLY( 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;** Note :************************************************************************/static XINLINE 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 unitial-* -ize socket functionality** Return : void** Note :************************************************************************/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** Note :************************************************************************/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; DBGONLY( 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; } DBGONLY( 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 ); } DBGONLY( 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** Note :************************************************************************/static XINLINE 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 ) { 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 voidRunMiniServer( MiniServerSockArray * miniSock ){ struct sockaddr_in clientAddr; int clientLen; SOCKET miniServSock, connectHnd; SOCKET miniServStopSock; SOCKET ssdpSock; CLIENTONLY( SOCKET ssdpReqSock; ) fd_set expSet; fd_set rdSet; unsigned int maxMiniSock; int byteReceived; char requestBuf[256]; miniServSock = miniSock->miniServerSock; miniServStopSock = miniSock->miniServerStopSock; ssdpSock = miniSock->ssdpSock; 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 ); CLIENTONLY( FD_SET( ssdpReqSock, &rdSet ) ); if( select( maxMiniSock, &rdSet, NULL, &expSet, NULL ) == UPNP_SOCKETERROR ) { DBGONLY( UpnpPrintf
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -