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

📄 miniserver2.cpp

📁 UPnP的SDK源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    // refill empty buffer      if ( !bufferHasData() )    {        status = refillBuffer();                if ( status <= 0 )            return status;                    if ( !bufferHasData() )            return 0;                    dataLeft = buflen;    }    else    {        dataLeft = buflen - offset;    }        if ( bufferLen < dataLeft )    {        copyLen = bufferLen;    }    else    {        copyLen = dataLeft;    }        memcpy( buf, &data[offset], copyLen );        offset += copyLen;        return copyLen;}ssize_t NetReader1::refillBuffer(){    ssize_t numRead;        // test version    //numRead = DoRead( sockfd, data, maxbufsize );        numRead = read( sockfd, data, maxbufsize );        if ( numRead >= 0 )    {        buflen = numRead;    }    else    {        buflen = 0;    }        offset = 0;            return numRead;}static void WriteNetData( const char* s, int sockfd ){    write( sockfd, s, strlen(s) );    }    // determines type of UPNP command from request line, lnstatic HTTP_COMMAND_TYPE GetCommandType( const xstring& ln ){    // commands GET, POST, M-POST, SUBSCRIBE, UNSUBSCRIBE, NOTIFY        xstring line = ln;    int i;    char c;        char * getStr = "GET";    char * postStr = "POST";    char * mpostStr = "M-POST";    char * subscribeStr = "SUBSCRIBE";    char * unsubscribeStr = "UNSUBSCRIBE";    char * notifyStr = "NOTIFY";    char * pattern;    HTTP_COMMAND_TYPE retCode=CMD_HTTP_UNKNOWN;        try    {        line.toUppercase();            c = line[0];                switch (c)        {            case 'G':                pattern = getStr;                retCode = CMD_HTTP_GET;                break;                            case 'P':                pattern = postStr;                retCode = CMD_SOAP_POST;                break;                            case 'M':                pattern = mpostStr;                retCode = CMD_SOAP_MPOST;                break;                            case 'S':                pattern = subscribeStr;                retCode = CMD_GENA_SUBSCRIBE;                break;                            case 'U':                pattern = unsubscribeStr;                retCode = CMD_GENA_UNSUBSCRIBE;                break;                            case 'N':                pattern = notifyStr;                retCode = CMD_GENA_UNSUBSCRIBE;                break;                        default:                // unknown method                throw -1;                        }                int patLength = strlen( pattern );                for ( i = 1; i < patLength; i++ )        {            if ( line[i] != pattern[i] )                throw -1;        }    }    catch ( OutOfBoundsException& e )    {        return CMD_HTTP_UNKNOWN;    }    catch ( int parseCode )    {        if ( parseCode == -1 )        {            return CMD_HTTP_UNKNOWN;        }    }        return retCode;}static int ParseContentLength( const xstring& textLine, bool& malformed ){    xstring line;    xstring asciiNum;    char *pattern = "CONTENT-LENGTH";    int patlen = strlen( pattern );    int i;    int contentLength;        malformed = false;        contentLength = -1;    line = textLine;    line.toUppercase();        if ( strncmp(line.c_str(), pattern, patlen) != 0 )    {        // unknown header        return -1;    }        i = patlen;        try    {        // skip whitespace        while ( line[i] == ' ' || line [i] == '\t' )        {            i++;        }                // ":"        if ( line[i] != ':' )        {            throw -1;        }        i++;                char* invalidChar = NULL;                contentLength = strtol( &line[i], &invalidChar, 10 );        // anything other than crlf or whitespace after number is invalid        if ( *invalidChar != '\0' )        {            // see if there is an invalid number            while ( *invalidChar )            {                char c;                                c = *invalidChar;                                if ( !(c == ' ' || c == '\t' || c == '\r' || c == '\n') )                {                    // invalid char in number                    throw -1;                }                                invalidChar++;            }        }    }    catch ( OutOfBoundsException& e )    {        malformed = true;        return -1;    }    catch ( int errCode )    {        if ( errCode == -1 )        {            malformed = true;            return -1;        }    }        return contentLength;   }static 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 );            buf[ bytesRead ] = 0;   // null terminate string            if ( bytesRead > 0 )            {                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;}static void HandleError( int errCode, int sockfd ){    xstring errMsg;        switch (errCode)    {    case RCODE_NETWORK_READ_ERROR:        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( printf( "HandleError: unknown code %d\n", errCode ); )        break;    };        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( printf( "http error: %s\n", msg.c_str() ); )    ///////}static 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;    }        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        DBG( e.print(); )        DBG( printf( "error code = %d\n", e.getErrorCode() ); )        //////                HandleError( e.getErrorCode(), sockfd );                // destroy connection        close( sockfd );    }   }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 request            while ( true )            {                connectfd = accept( listenfd, (sockaddr*) &clientAddr,                        &clientLen );                if ( connectfd > 0 )                {                    // valid connection                    break;                }                if ( connectfd == -1 && errno == EINTR )                {                    // 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 )    {        e.print();        free(StartMiniServer); //temporarily crashes if                                //miniserver doesn't start up                               //needs a better way to detect this case    }}int StartMiniServer( unsigned short listen_port ){    struct sockaddr_in serverAddr;    int listenfd;    int success;    //printf("listen port: %d\n",listen_port);    listenfd = socket( AF_INET, SOCK_STREAM, 0 );    if ( listenfd <= 0 )    {        return -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 )    {        return -1;  // bind failed    }        success = listen( listenfd, 10 );    if ( success == -1 )    {        return -1; // listen failed    }        tpool_Schedule( RunMiniServer, (void *)listenfd );        return 0;}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////#endif

⌨️ 快捷键说明

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