⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 miniserver.cpp

📁 UPnP的SDK源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// throws //	OutOfMemoryException//	MiniServerReadException//		RCODE_NETWORK_READ_ERROR//		RCODE_MALFORMED_LINE//		RCODE_METHOD_NOT_IMPLEMENTED //		RCODE_LENGTH_NOT_SPECIFIEDstatic void ReadRequest( int sockfd, xstring& document,    HTTP_COMMAND_TYPE& command ){    NetReader1 reader( sockfd );    xstring reqLine;    xstring line;    bool newlineNotFound;    int status;    HTTP_COMMAND_TYPE cmd;    int contentLength;    const int BUFSIZE = 3;    char buf[ BUFSIZE + 1 ];    MiniServerReadException excep;        document = "";        // read request-line    status = reader.getLine( reqLine, newlineNotFound );        if ( status < 0 )    {        // read error        excep.setErrorCode( RCODE_NETWORK_READ_ERROR );        throw excep;    }        if ( newlineNotFound )    {        // format error        excep.setErrorCode( RCODE_MALFORMED_LINE );        throw excep;    }            cmd = GetCommandType( reqLine );        if ( cmd == CMD_HTTP_UNKNOWN )    {        // unknown or unsupported cmd        excep.setErrorCode( RCODE_METHOD_NOT_IMPLEMENTED );        throw excep;    }        document += reqLine;        contentLength = -1;     // init        // read headers    while ( true )    {        status = reader.getLine( line, newlineNotFound );                if ( status < 0 )        {            // network error            excep.setErrorCode( RCODE_NETWORK_READ_ERROR );            throw excep;        }                   if ( newlineNotFound )        {            // bad format            excep.setErrorCode( RCODE_MALFORMED_LINE );            throw excep;        }                // get content-length if not obtained already        if ( contentLength < 0 )        {            bool malformed;                        contentLength = ParseContentLength( line, malformed );                        if ( malformed )            {                excep.setErrorCode( RCODE_MALFORMED_LINE );                throw excep;            }        }                document += line;                // done ?        if ( line == "\n" || line == "\r\n" )        {            break;        }    }        // must have body for POST and M-POST msgs    if ( contentLength < 0 &&         (cmd == CMD_SOAP_POST || cmd == CMD_SOAP_MPOST)       )    {        // HTTP: length reqd        excep.setErrorCode( RCODE_LENGTH_NOT_SPECIFIED );        throw excep;    }        if ( contentLength > 0 )    {        int totalBytesRead = 0;                // read body        while ( true )        {            int bytesRead;                        bytesRead = reader.readData( buf, BUFSIZE );             if ( bytesRead > 0 )            {                buf[ bytesRead ] = 0;   // null terminate string                document.appendLimited( buf, bytesRead );                totalBytesRead += bytesRead;                                if ( totalBytesRead >= contentLength )                {                    // done reading data                    break;                }            }            else if ( bytesRead == 0 )            {                // done                break;            }            else            {                // error reading                excep.setErrorCode( RCODE_NETWORK_READ_ERROR );                throw excep;            }        }    }        command = cmd;}// throws OutOfMemoryExceptionstatic void HandleError( int errCode, int sockfd ){    xstring errMsg;        switch (errCode)    {    case RCODE_NETWORK_READ_ERROR:        break;    case RCODE_TIMEDOUT:        break;            case RCODE_MALFORMED_LINE:        errMsg = "400 Bad Request";        break;            case RCODE_LENGTH_NOT_SPECIFIED:        errMsg = "411 Length Required";        break;            case RCODE_METHOD_NOT_ALLOWED:        errMsg = "405 Method Not Allowed";        break;    case RCODE_INTERNAL_SERVER_ERROR:        errMsg = "500 Internal Server Error";        break;                    case RCODE_METHOD_NOT_IMPLEMENTED:        errMsg = "511 Not Implemented";        break;            default:        DBG(            UpnpPrintf( UPNP_CRITICAL, MSERV, __FILE__, __LINE__,            "HandleError: unknown code %d\n", errCode ); )        break;    };    // no error msg to send; done    if ( errMsg.length() == 0 )        return;            xstring msg;        msg = "HTTP/1.1 ";    msg += errMsg;    msg += "\r\n\r\n";        // send msg    WriteNetData( msg.c_str(), sockfd );        // dbg    // sleep so that client does get connection reset    //sleep( 3 );    ///////        // dbg    DBG(        UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,            "http error: %s\n", msg.c_str() ); )    ///////}// throws MiniServerReadException.RCODE_METHOD_NOT_IMPLEMENTEDstatic void MultiplexCommand( HTTP_COMMAND_TYPE cmd, const xstring& document,        int sockfd ){    MiniServerCallback callback;        switch ( cmd )    {    case CMD_SOAP_POST:    case CMD_SOAP_MPOST:        callback = gSoapCallback;        break;                case CMD_GENA_NOTIFY:    case CMD_GENA_SUBSCRIBE:    case CMD_GENA_UNSUBSCRIBE:        callback = gGenaCallback;        break;                case CMD_HTTP_GET:        callback = gGetCallback;        break;                default:        callback = NULL;    }    //DBG(printf("READ>>>>>>\n%s\n<<<<<<READ\n", document.c_str()));        if ( callback == NULL )    {        MiniServerReadException e( "callback not defined or unknown method" );        e.setErrorCode( RCODE_METHOD_NOT_IMPLEMENTED );        throw e;    }        callback( document.c_str(), sockfd );}static void HandleRequest( void *args ){    int sockfd;    xstring document;    HTTP_COMMAND_TYPE cmd;        sockfd = (int) args;        try    {        ReadRequest( sockfd, document, cmd );                // pass data to callback        MultiplexCommand( cmd, document, sockfd );                //printf( "input document:\n%s\n", document.c_str() );    }    catch ( MiniServerReadException& e )    {        //DBG( e.print(); )        DBG(            UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,                "error code = %d\n", e.getErrorCode()); )        HandleError( e.getErrorCode(), sockfd );                // destroy connection        close( sockfd );    }   	catch ( ... )	{		DBG(		    UpnpPrintf( UPNP_CRITICAL, MSERV, __FILE__, __LINE__,		        "HandleRequest(): unknown error\n"); )		close( sockfd );	}}static void RunMiniServer( void* args ){    struct sockaddr_in clientAddr;    int listenfd;    listenfd = (int)args;       gMServThread = pthread_self();    gMServState = MSERV_RUNNING;    try    {        while ( true )        {            int connectfd;            socklen_t clientLen;                        DBG(                UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,                    "Waiting...\n" ); )                        // get a client request            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;                    }                    else                    {                        // ignore interruption                        continue;                    }                }                else                {                    xstring errStr =  "Error: RunMiniServer: accept(): ";                    errStr = strerror( errno );                    throw BasicException( errStr.c_str() );                }            }                        int sched_stat;            sched_stat = tpool_Schedule( HandleRequest, (void*)connectfd );            if ( sched_stat < 0 )            {                HandleError( RCODE_INTERNAL_SERVER_ERROR, connectfd );                          }            //HandleRequest( (void *)connectfd );        }    }    catch ( GenericException& e )    {        //DBG( e.print(); )    }    catch ( int code )    {        if ( code == -9 )        {            // stop miniserver            assert( gMServState == MSERV_STOPPING );                        DBG(                UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,                    "Miniserver: recvd STOP signal\n"); )                        close( listenfd );                        gMServState = MSERV_IDLE;            gMServThread = 0;        }    }}// returns port to which socket, sockfd, is bound.// -1 on error; check errno// > 0 means port numberstatic int get_port( int sockfd ){    sockaddr_in sockinfo;    socklen_t len;    int code;    int port;	len = sizeof(sockinfo);    code = getsockname( sockfd, (sockaddr*)&sockinfo, &len );    if ( code == -1 )    {        return -1;    }    port = htons( sockinfo.sin_port );    DBG(        UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,            "sockfd = %d, .... port = %d\n", sockfd, port ); )    return port;}// if listen port is 0, port is dynamically picked// returns://   on success: actual port socket is bound to//   on error:   a negative number UPNP_E_XXXint StartMiniServer( unsigned short listen_port ){    struct sockaddr_in serverAddr;    int listenfd = 0;    int success;    int actual_port;    int on =1;    int retCode = 0;    if ( gMServState != MSERV_IDLE )    {        return UPNP_E_INTERNAL_ERROR;  // miniserver running    }    try    {        //printf("listen port: %d\n",listen_port);        listenfd = socket( AF_INET, SOCK_STREAM, 0 );        if ( listenfd <= 0 )        {            throw UPNP_E_OUTOF_SOCKET; // 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 );        //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        if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on, sizeof(int))==-1)        {	        throw UPNP_E_SOCKET_BIND;        }                success = bind( listenfd, (sockaddr*)&serverAddr,            sizeof(serverAddr) );        if ( success == -1 )        {            throw UPNP_E_SOCKET_BIND;  // bind failed        }            success = listen( listenfd, 10 );        if ( success == -1 )        {            throw UPNP_E_LISTEN; // listen failed        }        actual_port = get_port( listenfd );        if ( actual_port <= 0 )        {            throw UPNP_E_INTERNAL_ERROR;        }            success = tpool_Schedule( RunMiniServer, (void *)listenfd );        if ( success < 0 )        {            throw UPNP_E_OUTOF_MEMORY;        }            // wait for miniserver to start        while ( gMServState != MSERV_RUNNING )        {            sleep(1);        }        retCode = actual_port;    }    catch ( int catchCode )    {        retCode = catchCode;        if ( listenfd != 0 )        {            close( listenfd );        }    }    return retCode;}// returns 0: success; -2 if miniserver is idleint StopMiniServer( void ){    if ( gMServState == MSERV_IDLE )        return -2;            gMServState = MSERV_STOPPING;        // keep sending signals until server stops    while ( true )    {        if ( gMServState == MSERV_IDLE )        {            break;        }        DBG(            UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,                "StopMiniServer(): sending interrupt\n"); )                int code = tintr_Interrupt( gMServThread );        if ( code < 0 )        {            DBG(                UpnpPrintf( UPNP_CRITICAL, MSERV, __FILE__, __LINE__,                    "%s: StopMiniServer(): interrupt failed",                    strerror(errno) ); )            //DBG( perror("StopMiniServer(): interrupt failed"); )        }                if ( gMServState == MSERV_IDLE )        {            break;        }                sleep( 1 );     // pause before signalling again    }        return 0;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -