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

📄 parser.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++


Module Name:

    parser.cpp

Abstract:

    This module encode and decode ssdp notify and search messages.

Author:

    Ting Cai (tingcai) creation-date-07-25-99

--*/

/* Note:

  Use midl memory routines for SSDP_REQUEST

*/

#include <ssdppch.h>
#pragma hdrstop

#include "ipexport.h"
#include "ssdpparserp.h"

#define HTTP_VERSION_STR "HTTP/1.1"

#define END_HEADERS_SIZE 3
const char * szEndOfHeaders = "\n\r\n";

#define HEADER_END_SIZE 4
const char * szHeaderEnd = "\r\n\r\n"; 

BOOL IsStrDigits(LPSTR pszStr);
VOID strtrim(CHAR ** pszStr);

static const CHAR c_szMaxAge[] = "max-age";
static const DWORD c_cchMaxAge = celems(c_szMaxAge) - 1;
static const CHAR c_szExtHeader[] = "EXT:\r\n";

extern CHAR g_pszExtensionURI[500];
extern CHAR g_pszHeaderPrefix[10];
extern CHAR g_pszNlsHeader[50];

// Keep in sync with SSDP_METHOD in ssdp.idl
CHAR *SsdpMethodStr[] =
{
    "NOTIFY",
    "M-SEARCH",
    "SUBSCRIBE",
    "UNSUBSCRIBE",
    "INVALID",
};


// Keep in sync with SSDP_HEADER in ssdp.idl
CHAR *SsdpHeaderStr[] =
{
    "Host",
    "NT",
    "NTS",
    "ST",
    "Man",
    "MX",
    "Location",
    "AL",
    "USN",
    "Cache-Control",
    "Callback",
    "Timeout",
    "Scope",
    "SID",
    "SEQ",
    "Content-Length",
    "Content-Type",
    "Server",
    "Ext",
    "Opt",
    g_pszNlsHeader
};


BOOL ComposeSsdp(char* pszFirstLine1, char* pszFirstLine2, char* pszFirstLine3, SSDP_REQUEST *Source, SSDP_HEADER* pIncludeHeaders, int nHeaders, CHAR **pszBytes)
{
    INT iLength = 0;
    INT iNumOfBytes = 0;
    CHAR * szBytes;
    INT i;
    SSDP_HEADER Header;

    ////////////////////////////////////
    // Step 1. calculate size of SSDP message
    ////////////////////////////////////
    
    // calculate size of first line
    assert(pszFirstLine1 && pszFirstLine2 && pszFirstLine3);
    
    iLength += strlen(pszFirstLine1) + strlen(SP) +
               strlen(pszFirstLine2) + strlen(SP) +
               strlen(pszFirstLine3) + strlen(CRLF);
    
    // calculate size of headers
    for (i = 0, Header = pIncludeHeaders[0]; i < nHeaders; Header = pIncludeHeaders[++i])
    {
        assert(Header < NUM_OF_HEADERS);
        __assume(Header < NUM_OF_HEADERS);
        
        // for NLS header include prefix + dash
        if(SSDP_NLS == Header && g_pszHeaderPrefix[0])
            iLength += strlen(g_pszHeaderPrefix) + strlen(DASH);
            
        // header name + colon + crlf
        iLength += strlen(SsdpHeaderStr[Header]) + strlen(COLON) + strlen(CRLF);
        
        // value for headers other than EXT
        if(SSDP_EXT != Header)
        {
            assert(Source->Headers[Header] != NULL);
            iLength += strlen(Source->Headers[Header]);
        }
    }

    // terminating CRLF
    iLength += strlen(CRLF);

    ////////////////////////////////////
    // Step 2. compose SSDP message
    ////////////////////////////////////
    
    // allocate memory for the message
    if(NULL == (szBytes = (CHAR *) malloc(sizeof(CHAR) * iLength + 1)))
    {
        TraceTag(ttidSsdpParser, "Failed to allocate memory for the ssdp message.");
        return FALSE;
    }

    // write first line
    iNumOfBytes += sprintf(szBytes + iNumOfBytes, "%s%s%s%s%s%s", pszFirstLine1, SP, pszFirstLine2, SP, pszFirstLine3, CRLF);

    // write headers
    for (i = 0, Header = pIncludeHeaders[0]; i < nHeaders; Header = pIncludeHeaders[++i])
    {
        assert(Header < NUM_OF_HEADERS);
        
        // prefix + dash for NLS header
        if(SSDP_NLS == Header && g_pszHeaderPrefix[0])
            iNumOfBytes += sprintf(szBytes + iNumOfBytes, "%s%s", g_pszHeaderPrefix, DASH);
        
        // header name + colon
        iNumOfBytes += sprintf(szBytes + iNumOfBytes, "%s%s", SsdpHeaderStr[Header], COLON);
        
        // value for headers other than EXT
        if(SSDP_EXT != Header)
        {
            assert(Source->Headers[Header] != NULL);
            PREFAST_SUPPRESS(69, "sprintf returns number of bytes written, strcpy doesn't");
            iNumOfBytes += sprintf(szBytes + iNumOfBytes, "%s", Source->Headers[Header]);
        }
            
        // crlf
        PREFAST_SUPPRESS(69, "sprintf returns number of bytes written, strcpy doesn't");
        iNumOfBytes += sprintf(szBytes + iNumOfBytes, "%s", CRLF);
    }

    // write terminating CRLF
    PREFAST_SUPPRESS(69, "sprintf returns number of bytes written, strcpy doesn't");
    iNumOfBytes += sprintf(szBytes + iNumOfBytes, "%s",CRLF);
    
    Assert(iNumOfBytes <= iLength);

    *pszBytes = szBytes;

    return TRUE;
}


// SSDP response
BOOL ComposeSsdpResponse(SSDP_REQUEST *Source, SSDP_HEADER* pIncludeHeaders, int nHeaders, CHAR **pszBytes)
{
    return ComposeSsdp(HTTP_VERSION_STR, "200", "OK", Source, pIncludeHeaders, nHeaders, pszBytes);
}

// SSDP request (NOTIFY or M-SEARCH)
BOOL ComposeSsdpRequest(SSDP_REQUEST *Source, SSDP_HEADER* pIncludeHeaders, int nHeaders, CHAR **pszBytes)
{
    return ComposeSsdp(SsdpMethodStr[Source->Method], Source->RequestUri, HTTP_VERSION_STR, Source, pIncludeHeaders, nHeaders, pszBytes);
}


// Pre-Conditions: 
// Result->Headers[CONTENT_LENGTH] contains only digits.
// pContent points to the first char "\r\n\r\n".
// Return Value: 
// returns FALSE if there not enough content. 

BOOL ParseContent(const char *pContent, SSDP_REQUEST *Result)
{
    if(!Result->Headers[CONTENT_LENGTH])
    {
        return TRUE;
    }

    long lContentLength = atol(Result->Headers[CONTENT_LENGTH]);
    if (lContentLength == 0)
    {
        // If it can't be conver to a number or it is 0.
        TraceTag(ttidSsdpParser, "Content-Length is 0.");
        return TRUE;
    }
    else
    {
        // better, but may break WinME: if ((long)strlen(pContent) != lContentLength)
        if (((long) strlen(pContent) + 1) < lContentLength)
        {
            TraceTag(ttidSsdpParser, "Not enough bytes for content as specified in "
                     "Content-Length: %d vs %d", strlen(pContent) + 1,
                     lContentLength);
            return FALSE;
        }

        // lContentLength is length of actual string so the condition below will always be true
        __assume(lContentLength < ULONG_MAX);
        
        Result->Content = (CHAR*) SsdpAlloc(lContentLength + 1);
        if (Result->Content == NULL)
        {
            // To-Do: ? 
            TraceTag(ttidSsdpParser, "Failed to allocate memory for Content");
            return FALSE;
        }
        else
        {
            strncpy(Result->Content,pContent, lContentLength);
            // NTRAID#NTBUG-166137-2000/08/18-danielwe: Add the NULL terminator
            Result->Content[lContentLength] = 0;
            return TRUE;
        }
    }
}

BOOL VerifySsdpMethod(CHAR *szMethod, SSDP_REQUEST *Result)
{
    INT i;

    for (i = 0; i < NUM_OF_METHODS; i++)
    {
        if (_stricmp(SsdpMethodStr[i],szMethod) == 0)
        {
            Result->Method = (SSDP_METHOD)i;
            break;
        }
    }

    if (i == NUM_OF_METHODS)
    {
        TraceTag(ttidSsdpParser, "Parser could not find method . "
                 "Received %s", szMethod);
        Result->status = HTTP_STATUS_BAD_METHOD;
        return FALSE;
    }
    return TRUE;
}    

CHAR * ParseRequestLine(CHAR * szMessage, SSDP_REQUEST *Result)
{
    CHAR *token;

    //  Get the HTTP method
    token = strtok(szMessage," \t\n");
    if (token == NULL)
    {
        TraceTag(ttidSsdpParser, "Parser could not locate the seperator, "
                 "space, tab or eol");
        return NULL;
    }

    if (!VerifySsdpMethod(token, Result))
        return NULL;
    
    // Get the Request-URI
    token = strtok(NULL," ");
    if (token == NULL)
    {
        TraceTag(ttidSsdpParser, "Parser could not find the url in the "
                 "message.");
        return NULL;
    }

    // Ingore the name space parsing for now, get the string after the last '/'.

    Result->RequestUri = (CHAR*) SsdpAlloc(strlen(token) + 1);

    if (Result->RequestUri == NULL)
    {
        TraceTag(ttidSsdpParser, "Parser could not allocate memory for url.");
        return NULL;
    }

    // Record the service.
    strcpy(Result->RequestUri, token);

    // Get the version number
    token = strtok(NULL,"  \t\r");

    // To-Do: Record the version number when necessary.

    if (token == NULL)
    {
        TraceTag(ttidSsdpParser, "Failed to get the version in the request "
                 "header.");
        FreeSsdpRequest(Result);
        return NULL;
    }

    if (_stricmp(token, "HTTP/1.1") != 0)
    {
        TraceTag(ttidSsdpParser, "The version specified in the request "
                 "message is not HTTP/1.1");
        FreeSsdpRequest(Result);
        return NULL;
    }

    return (token + strlen(token) + 1);

}


// VerifyRequestLine
BOOL VerifyRequestLine(SSDP_REQUEST *Result)
{
    if (0 != _stricmp(Result->RequestUri, "*"))
    {
        TraceTag(ttidSsdpParser, "Requested resource is not * in SSDP request");
        
        return FALSE;
    }
    
    return TRUE;
}


BOOL VerifySsdpHeaders(SSDP_REQUEST *Result)
{
    // M_SEARCH
    if (Result->Method == SSDP_M_SEARCH)
    {
        // MAN
        if(Result->Headers[SSDP_MAN] == NULL || 0 != _stricmp("\"ssdp:discover\"", Result->Headers[SSDP_MAN]))
        {
            TraceTag(ttidSsdpParser, "MAN header must be \"ssdp:discover\" for M-SEARCH");
            return FALSE;
        }
        
        // MX header
        if(Result->Headers[SSDP_MX] == NULL || Result->Headers[SSDP_MX][0] == '\x0')
        {
            TraceTag(ttidSsdpParser, "MX header missing or empty for M-SEARCH");
            return FALSE;
        }
        
        if(Result->Headers[SSDP_MX] == NULL || IsStrDigits(Result->Headers[SSDP_MX]) == FALSE)
        {
            TraceTag(ttidSsdpParser, "MX header should be all digits for M-SEARCH");
            return FALSE;
        }

        // ST header
        if(Result->Headers[SSDP_ST] == NULL || Result->Headers[SSDP_ST][0] == '\x0')
        {
            TraceTag(ttidSsdpParser, "ST header missing or empty for M-SEARCH");
            return FALSE;
        }
    }

    // NOTIFY
    if (Result->Method == SSDP_NOTIFY)
    {
        // NT header
        if (Result->Headers[SSDP_NT] == NULL || Result->Headers[SSDP_NT][0] == '\x0')
        {
            TraceTag(ttidSsdpParser, "NT header missing or empty for a NOTIFY message."); 
            return FALSE;
        }

⌨️ 快捷键说明

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