📄 parser.cpp
字号:
// USN header
if (Result->Headers[SSDP_USN] == NULL || Result->Headers[SSDP_USN][0] == '\x0')
{
TraceTag(ttidSsdpParser, "USN header missing or empty for ssdp:alive NOTIFY message.");
return FALSE;
}
// ssdp:alive
if (Result->Headers[SSDP_NTS] != NULL && 0 == _stricmp(Result->Headers[SSDP_NTS], "ssdp:alive"))
{
// CACHE-CONTROL header
if (Result->Headers[SSDP_CACHECONTROL] == NULL || Result->Headers[SSDP_CACHECONTROL][0] == '\x0')
{
TraceTag(ttidSsdpParser, "CACHE-CONTROL header missing or empty for ssdp:alive NOTIFY message.");
return FALSE;
}
// LOCATION header
if (Result->Headers[SSDP_LOCATION] == NULL || Result->Headers[SSDP_LOCATION][0] == '\x0')
{
TraceTag(ttidSsdpParser, "LOCATION header missing or empty for ssdp:alive NOTIFY message.");
return FALSE;
}
// SERVER header
if (Result->Headers[SSDP_SERVER] == NULL || Result->Headers[SSDP_SERVER][0] == '\x0')
{
TraceTag(ttidSsdpParser, "SERVER header missing or empty for ssdp:alive NOTIFY message.");
return FALSE;
}
}
else
// ssdp:byebye
if (Result->Headers[SSDP_NTS] == NULL || 0 != _stricmp(Result->Headers[SSDP_NTS], "ssdp:byebye"))
{
TraceTag(ttidSsdpParser, "NTS header must be one of ssdp:alive, ssdp:byebye for a SSDP NOTIFY message.");
return FALSE;
}
}
return TRUE;
}
// VerifySsdpResponseHeaders
BOOL VerifySsdpResponseHeaders(SSDP_REQUEST *Result)
{
// CACHE-CONTROL header
if (Result->Headers[SSDP_CACHECONTROL] == NULL || Result->Headers[SSDP_CACHECONTROL][0] == '\x0')
{
TraceTag(ttidSsdpParser, "CACHE-CONTROL header missing or empty for ssdp response.");
return FALSE;
}
// EXT header
if (Result->Headers[SSDP_EXT] == NULL)
{
TraceTag(ttidSsdpParser, "EXT header missing in SSDP response.");
return FALSE;
}
// LOCATION header
if (Result->Headers[SSDP_LOCATION] == NULL || Result->Headers[SSDP_LOCATION][0] == '\x0')
{
TraceTag(ttidSsdpParser, "LOCATION header missing or empty for ssdp response.");
return FALSE;
}
// SERVER header
if (Result->Headers[SSDP_SERVER] == NULL || Result->Headers[SSDP_SERVER][0] == '\x0')
{
TraceTag(ttidSsdpParser, "SERVER header missing or empty for ssdp response.");
return FALSE;
}
// ST header
if(Result->Headers[SSDP_ST] == NULL || Result->Headers[SSDP_ST][0] == '\x0')
{
TraceTag(ttidSsdpParser, "ST header missing or empty for ssdp response");
return FALSE;
}
// USN header
if (Result->Headers[SSDP_USN] == NULL || Result->Headers[SSDP_USN][0] == '\x0')
{
TraceTag(ttidSsdpParser, "USN header missing or empty for ssdp response.");
return FALSE;
}
return TRUE;
}
BOOL HasContentBody(PSSDP_REQUEST Result)
{
return (Result->Headers[CONTENT_LENGTH] != NULL);
}
BOOL ParseSsdpRequest(CHAR * szMessage, PSSDP_REQUEST Result)
{
CHAR *szHeaders;
CHAR pszHeaderPrefix[100] = {0};
szHeaders = ParseRequestLine(szMessage, Result);
if (szHeaders == NULL)
{
return FALSE;
}
else
{
if(VerifyRequestLine(Result) == FALSE)
return FALSE;
}
{
// make a copy of headers and parse them to get value of OPT header
CHAR* pszHeadersCopy;
pszHeadersCopy = (CHAR*)malloc(strlen(szHeaders) + 1);
if(pszHeadersCopy)
{
SSDP_REQUEST Temp;
memset(&Temp, 0, sizeof(Temp));
strcpy(pszHeadersCopy, szHeaders);
if(ParseHeaders(pszHeadersCopy, &Temp))
{
if(Temp.Headers[SSDP_OPT] && strlen(Temp.Headers[SSDP_OPT]) < sizeof(pszHeaderPrefix) - 2)
{
strcpy(pszHeaderPrefix, Temp.Headers[SSDP_OPT]);
strcat(pszHeaderPrefix, DASH);
}
}
FreeSsdpRequest(&Temp);
free(pszHeadersCopy);
}
}
char *pContent = ParseHeaders(szHeaders, Result, pszHeaderPrefix);
if ( pContent == NULL)
{
return FALSE;
}
else
{
if (VerifySsdpHeaders(Result) == FALSE)
{
return FALSE;
}
// Headers are OK.
if (Result->Headers[CONTENT_LENGTH] != NULL)
{
// To-Do: Maybe we can share the this routine with those
// in ProcessTcpReceiveData();
// In that case, we need catch the return value of ParseContent
// and probably return a more meaningful error code.
ParseContent(pContent, Result);
}
return TRUE;
}
}
// Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
// Returns a pointer to the first CHAR after the status line
// Returns NULL if fail to parse status line
BOOL ParseSsdpResponse(CHAR *szMessage, SSDP_REQUEST *Result)
{
CHAR *token;
CHAR *szHeaders;
CHAR pszHeaderPrefix[100] = {0};
// get the version
token = strtok(szMessage," \t\n");
if (token == NULL)
{
TraceTag(ttidSsdpParser, "Response: Parser could not locate the "
"seperator, space, tab or eol");
return FALSE;
}
if (_stricmp(token, "HTTP/1.1") != 0)
{
TraceTag(ttidSsdpParser, "The version specified in the response "
"message is not HTTP/1.1");
return FALSE;
}
// get the response code
token = strtok(NULL," ");
if (token == NULL)
{
TraceTag(ttidSsdpParser, "Parser could not find response code in the "
"message.");
return FALSE;
}
if (_stricmp(token, "200") != 0)
{
TraceTag(ttidSsdpParser, "The response code in the response message "
"is not HTTP/1.1");
return FALSE;
}
// get the response message, no need for now.
token = strtok(NULL," \t\r");
if (token == NULL)
{
TraceTag(ttidSsdpParser, "Response: Parser could not locate the "
"seperator, space, tab or eol");
return FALSE;
}
szHeaders = token + strlen(token) + 1;
{
// make a copy of headers and parse them to get value of OPT header
CHAR* pszHeadersCopy;
pszHeadersCopy = (CHAR*)malloc(strlen(szHeaders) + 1);
if(pszHeadersCopy)
{
SSDP_REQUEST Temp;
memset(&Temp, 0, sizeof(Temp));
strcpy(pszHeadersCopy, szHeaders);
if(ParseHeaders(pszHeadersCopy, &Temp))
{
if(Temp.Headers[SSDP_OPT] && strlen(Temp.Headers[SSDP_OPT]) < sizeof(pszHeaderPrefix) - 2)
{
strcpy(pszHeaderPrefix, Temp.Headers[SSDP_OPT]);
strcat(pszHeaderPrefix, DASH);
}
}
FreeSsdpRequest(&Temp);
free(pszHeadersCopy);
}
}
char *pContent = ParseHeaders(szHeaders, Result, pszHeaderPrefix);
if (pContent == NULL || Result->Headers[SSDP_USN] == NULL)
{
return FALSE;
}
else
{
if (VerifySsdpResponseHeaders(Result) == FALSE)
{
return FALSE;
}
if (Result->Headers[CONTENT_LENGTH] != NULL)
{
ParseContent(pContent, Result);
}
return TRUE;
}
}
char * ParseHeaders(CHAR *szMessage, SSDP_REQUEST *Result, CHAR* pszHeaderPrefix/* = NULL*/)
{
CHAR *token;
INT i;
INT nHeaderPrefix = 0;
if(pszHeaderPrefix && *pszHeaderPrefix)
{
nHeaderPrefix = strlen(pszHeaderPrefix);
ASSERT(pszHeaderPrefix[nHeaderPrefix - 1] == '-');
}
// Get the next header
token = strtok(szMessage, "\r\n");
while (token != NULL)
{
CHAR * pHeaderSep; // points to the ':' that seperates the header and its content.
CHAR * pBeyondTokenEnd;
pBeyondTokenEnd = token + strlen(token) + 1;
pHeaderSep = strchr( token, ':' );
if (pHeaderSep == NULL)
{
TraceTag(ttidSsdpParser, "Token %s does not have a ':', ignored.",
token);
}
else
{
*pHeaderSep = '\0';
strtrim(&token);
for (i = 0; i < NUM_OF_HEADERS; i++)
{
CHAR* pszHeader = token;
// if we have a recognized extension skip the headr prefix
PREFAST_SUPPRESS(387, "if pszHeaderPrefix == NULL then nHeaderPrefix == 0");
if(0 == _strnicmp(pszHeaderPrefix, pszHeader, nHeaderPrefix))
pszHeader += nHeaderPrefix;
if (_stricmp(SsdpHeaderStr[i], pszHeader) == 0)
{
CHAR *szValue;
szValue = pHeaderSep + 1;
strtrim(&szValue);
if (SSDP_CACHECONTROL == i)
{
// Further parse the cache-control header
//
szValue = strstr(szValue, c_szMaxAge);
if (szValue)
{
CHAR * szTemp = szValue + c_cchMaxAge;
strtrim(&szTemp);
if (*szTemp != '=')
{
TraceTag(ttidSsdpParser, "Invalid max-age directive"
" in cache-control header.");
break;
}
else
{
szTemp++;
strtrim(&szTemp);
while (isdigit(*szTemp))
{
szTemp++;
}
// Nul term the string so the cache-control
// header should now be "max-age=398733" and
// nothing more or less
*szTemp = 0;
}
}
else
{
TraceTag(ttidSsdpParser, "Cache-control header"
"did not include max-age directive.");
break;
}
}
if(SSDP_OPT == i)
{
// check if we recognize this extension
if(0 != _strnicmp(szValue, g_pszExtensionURI, strlen(g_pszExtensionURI)))
break;
if(!(szValue = strstr(szValue, "ns")))
break;
szValue += 2; // skip ns
while(*szValue && (*szValue == ' ' || *szValue == '=')) // skip white spaces and =
szValue++;
if(*szValue == '\x0')
break;
}
Result->Headers[i] = (CHAR *) SsdpAlloc(
sizeof(CHAR) * (strlen(szValue) + 1));
if (Result->Headers[i] == NULL)
{
TraceTag(ttidSsdpParser, "Failed to allocate memory "
"for szValue %s",szValue);
FreeSsdpRequest(Result);
Result->status = HTTP_STATUS_SERVER_ERROR;
return NULL;
}
strcpy(Result->Headers[i], szValue);
break;
}
}
if (i == NUM_OF_HEADERS && pszHeaderPrefix != NULL) // don't display trace if pszHeaderPrefix because it is pre-pass to get extension prefix
{
// Ignore not recognized header
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -