📄 miniserver2.cpp
字号:
/////////////////////////////////////////////////////////////////////////////// Copyright (c) 2000 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./////////////////////////////////////////////////////////////////////////////// $Revision: 1.1.1.2 $// $Date: 2001/06/15 00:21:34 $#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/socket.h>#include <errno.h>#include <sys/types.h>#include <sys/wait.h>#include <genlib/util/utilall.h>#include <genlib/util/util.h>#include <genlib/tpool/scheduler.h>#include <genlib/net/netexception.h>#include <genlib/net/http/statuscodes.h>#include <genlib/net/http/parseutil2.h>#include <genlib/net/http/readwrite.h>#include <genlib/miniserver/miniserver2.h>enum MiniServerState { MSERV_IDLE, MSERV_RUNNING, MSERV_STOPPING };CREATE_NEW_EXCEPTION_TYPE( MiniServerException, BasicException, "MiniServerReadException" )enum READ_EXCEPTION_CODE { RCODE_SUCCESS = 0, RCODE_NETWORK_READ_ERROR = -1, RCODE_BAD_FORMAT = -2, RCODE_LENGTH_NOT_SPECIFIED = -3, RCODE_METHOD_NOT_ALLOWED = -4, RCODE_INTERNAL_SERVER_ERROR = -5, RCODE_METHOD_NOT_IMPLEMENTED = -6, };// module vars ////////////////////static MiniServerState gMServState = MSERV_IDLE;static minisvr_Callback gGetCallback = NULL;static minisvr_Callback gSoapCallback = NULL;static minisvr_Callback gGenaCallback = NULL;static minisvr_LogCallback gLogCallback = NULL;///////////////////////////////////void minisvr_SetSoapHandler( minisvr_Callback callback ){ gSoapCallback = callback;}minisvr_Callback minsvr_GetSoapHandler(){ return gSoapCallback;}void minisvr_SetGenaHandler( minisvr_Callback callback ){ gGenaCallback = callback;}minisvr_Callback minisvr_GetGenaHandler(){ return gGenaCallback;}void minisvr_SetHttpGetHandler( minisvr_Callback callback ){ gGetCallback = callback;}minisvr_Callback minisvr_GetHttpGetHandler(){ return gGetCallback;}void minisvr_SetLogHandler( minisvr_LogCallback callback ){ gLogCallback = callback;}minisvr_LogCallback minisvr_GetLogHandler(){ return gLogCallback;}// throws MiniserverException.RCODE_INTERNAL_SERVER_ERRORstatic void DispatchRequest( HttpMessage& request, int sockfd ){ minisvr_Callback callback; switch ( request.requestLine.method ) { case UPNP_POST: case UPNP_MPOST: callback = gSoapCallback; break; case UPNP_NOTIFY: case UPNP_SUBSCRIBE: case UPNP_UNSUBSCRIBE: callback = gGenaCallback; break; default: // GET, HEAD and unknown methods handled by HTTP web server callback = gGetCallback; } if ( callback == NULL ) { MiniServerException e( "callback not defined or unknown method" ); e.setErrorCode( RCODE_INTERNAL_SERVER_ERROR ); throw e; } callback( request, sockfd );}static void HandleError( int errCode, int sockfd ){ xstring errMsg; int statusCode = -1; HttpMessage response; switch (errCode) { case RCODE_BAD_FORMAT: statusCode = HTTP_BAD_REQUEST; break; case RCODE_INTERNAL_SERVER_ERROR: statusCode = HTTP_INTERNAL_SERVER_ERROR; break; default: DBG( printf( "HandleError: unknown code %d\n", errCode ); ) break; }; if ( statusCode > 0 ) { response.responseLine.setValue( statusCode ); response.isRequest = false; http_SendMessage( sockfd, response ); } DBG( printf("http error: %s\n", http_GetCodeText(statusCode)); )}static void HandleRequest( void *args ){ int sockfd; HttpMessage request; int status; MiniServerException e( "HandleRequest(): " ); sockfd = (int) args; try { status = http_RecvMessage( sockfd, request ); switch ( status ) { case 0: // ok break; case HTTP_E_BAD_MSG_FORMAT: e.setErrorCode( RCODE_BAD_FORMAT ); throw e; break; case HTTP_E_OUT_OF_MEMORY: e.setErrorCode( RCODE_INTERNAL_SERVER_ERROR ); throw e; break; case HTTP_E_TIMEDOUT: // nothing to do break; default: DBG( printf("HandleRequest(): got unknown status %d", status); ) break; } // pass data to callback DispatchRequest( request, sockfd ); } catch ( MiniServerException& e ) { DBG( e.print(); ) DBG( printf("error code = %d\n", e.getErrorCode()); ) HandleError( e.getErrorCode(), sockfd ); close( sockfd ); } // note: callback responsible for closing socket}static void RunMiniServer( void* args ){ struct sockaddr_in clientAddr; int listenfd; listenfd = (int)args; try { while ( true ) { int connectfd; socklen_t clientLen; //DBG( printf( "Waiting...\n" ); ) // get a client connection while ( true ) { // stop server if ( gMServState == MSERV_STOPPING ) { throw -9; } connectfd = accept( listenfd, (sockaddr*) &clientAddr, &clientLen ); if ( connectfd > 0 ) { // valid connection break; } if ( connectfd == -1 && errno == EINTR ) { // interrupted. -- stop? if ( gMServState == MSERV_STOPPING ) { throw -9; // signal to stop } else { // ignore interruption continue; } } else { xstring errStr = "Error: RunMiniServer: accept(): "; errStr = strerror( errno ); NetException e( errStr.c_str() ); e.setErrorCode( errno ); throw e; } } int sched_stat; sched_stat = tpool_Schedule( HandleRequest, (void*)connectfd ); if ( sched_stat < 0 ) { HandleError( RCODE_INTERNAL_SERVER_ERROR, connectfd ); } } } catch ( GenericException& e ) { DBG( e.print(); ) } catch ( int code ) { if ( code == -9 ) { // miniserver to be stopped assert( gMServState == MSERV_STOPPING ); // free resources close( listenfd ); gMServState = MSERV_IDLE; } }}static int GetListenQueueSize(){ return 10;}// return;// 0 - ok// -1 - check errno// -2 - miniserver not idle// -3 - can't start server threadint minisvr_Start( unsigned short listen_port ){ struct sockaddr_in serverAddr; int listenfd = 0; int success; int retCode = 0; //DBG( printf("listen port: %d\n",listen_port); ) try { // idle --> running only if ( gMServState != MSERV_IDLE ) { throw -2; } listenfd = socket( AF_INET, SOCK_STREAM, 0 ); if ( listenfd <= 0 ) { throw -1; // error creating socket } bzero( &serverAddr, sizeof(serverAddr) ); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = htonl( INADDR_ANY ); serverAddr.sin_port = htons( listen_port ); success = bind( listenfd, (sockaddr*)&serverAddr, sizeof(serverAddr) ); if ( success == -1 ) { throw -1; // bind failed } success = listen( listenfd, GetListenQueueSize() ); if ( success == -1 ) { throw -1; // listen failed } success = tpool_Schedule( RunMiniServer, (void *)listenfd ); if ( success < 0 ) throw -3; // schedule failed gMServState = MSERV_RUNNING; // OK } catch ( int code ) { // error occured assert( code < 0 ); if ( listenfd != 0 ) close( listenfd ); retCode = code; } return retCode;}int minsvr_Stop(){ if ( gMServState == MSERV_IDLE ) return -2; gMServState = MSERV_STOPPING; // interrupt miniserver thread return 0;}#if 0/////////////////////////////////////////////////////////////////////////// **********#)))))))))))))))))))))###################************#####// (*(*&(&(*&%#(&(*&%#(*%&##*************%&!{*&%#)*&%#*&%)#*@&%)#// (*%&#)*#&)%(#*)(*#)(*@$)(#@*$)(*#@)$(*@#)(&%)@#&)($&*@)(#&$)(#@$)(CREATE_NEW_EXCEPTION_TYPE( MiniServerReadException, BasicException, "MiniServerReadException" )enum READ_EXCEPTION_CODE { RCODE_SUCCESS = 0, RCODE_NETWORK_READ_ERROR = -1, RCODE_MALFORMED_LINE = -2, RCODE_LENGTH_NOT_SPECIFIED = -3, RCODE_METHOD_NOT_ALLOWED = -4, RCODE_INTERNAL_SERVER_ERROR = -5, RCODE_METHOD_NOT_IMPLEMENTED = -6, }; enum HTTP_COMMAND_TYPE { CMD_HTTP_GET, CMD_SOAP_POST, CMD_SOAP_MPOST, CMD_GENA_SUBSCRIBE, CMD_GENA_UNSUBSCRIBE, CMD_GENA_NOTIFY, CMD_HTTP_UNKNOWN, CMD_HTTP_MALFORMED };// module varsstatic MiniServerCallback gGetCallback = NULL;static MiniServerCallback gSoapCallback = NULL;static MiniServerCallback gGenaCallback = NULL;//////////////void SetHTTPGetCallback( MiniServerCallback callback ){ gGetCallback = callback;}MiniServerCallback GetHTTPGetCallback( void ){ return gGetCallback;}void SetSoapCallback( MiniServerCallback callback ){ gSoapCallback = callback;}MiniServerCallback GetSoapCallback( void ){ return gSoapCallback;}void SetGenaCallback( MiniServerCallback callback ){ gGenaCallback = callback;}MiniServerCallback GetGenaCallback( void ){ return gGenaCallback;}class NetReader1{public: NetReader1( int socketfd ); virtual ~NetReader1(); int getChar( char& c ); int getLine( xstring& s, bool& newlineNotFound ); int readData( void* buf, size_t bufferLen ); int getMaxBufSize() const { return maxbufsize; } private: bool bufferHasData() const { return offset < buflen; } ssize_t refillBuffer(); private: int sockfd; char data[5 + 1]; int offset; int buflen; int maxbufsize;};NetReader1::NetReader1( int socketfd ){ sockfd = socketfd; offset = 0; maxbufsize = 5; buflen = 0; data[maxbufsize] = 0;}NetReader1::~NetReader1(){}int NetReader1::getChar( char& c ){ int status; if ( !bufferHasData() ) { status = refillBuffer(); if ( status <= 0 ) return status; if ( !bufferHasData() ) return 0; } c = data[offset]; offset++; return 1; // length of data returned}int NetReader1::getLine( xstring& s, bool& newlineNotFound ){ int startOffset; char c; int status; bool crFound; startOffset = offset; s = ""; newlineNotFound = false; crFound = false; while ( true ) { status = getChar( c ); if ( status == 0 ) { // no more chars in stream newlineNotFound = true; return s.length(); } if ( status < 0 ) { // some kind of error return status; } s += c; if ( c == 0xA ) { return s.length(); } else if ( c == 0xD ) // CR { crFound = true; } else { // wanted to see LF after CR; error if ( crFound ) { newlineNotFound = true; return s.length(); } } } return 0;}// read dataint NetReader1::readData( void* buf, size_t bufferLen ){ int status; int copyLen; size_t dataLeft; // size of data left in buffer if ( bufferLen <= 0 ) return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -