📄 httpconnection.cpp
字号:
// (normally) have message bodies. The RFC is vague regarding which // response codes support or require bodies. These are being reported by // class (4xx, 5xx, etc) because the CIM client should be able to handle // any status code, including those not explicitly defined in RFC 2616. // Therefore, listing codes individually will not work because the client // socket will hang on a code not in this list if no content length is // specified. // See bugzilla 1586 const char* RESPONSE_CODES[] = { "HTTP/1.1 3XX", "HTTP/1.0 3XX", "HTTP/1.1 4XX", "HTTP/1.0 4XX", "HTTP/1.1 5XX", "HTTP/1.0 5XX" }; // Check for bodyless HTTP request method const Uint32 METHOD_NAMES_SIZE = sizeof(METHOD_NAMES) / sizeof(char*); for (Uint32 i = 0; i < METHOD_NAMES_SIZE; i++) { Uint32 n = strlen(METHOD_NAMES[i]); if (strncmp(line, METHOD_NAMES[i], n) == 0 && isspace(line[n])) return true; } // Check for bodyless HTTP status code const Uint32 RESPONSE_CODES_SIZE = sizeof(RESPONSE_CODES) / sizeof(char*); for (Uint32 i = 0; i < RESPONSE_CODES_SIZE; i++) { Uint32 n = strlen(RESPONSE_CODES[i]); if (strncmp(line, RESPONSE_CODES[i], n - 2) == 0 && isspace(line[n])) return true; } return false;}/*Boolean _IsBodylessMessage(const char* line){ //ATTN: Make sure this is the right place to check for HTTP/1.1 and // HTTP/1.0 that is part of the authentication challenge header. // ATTN-RK-P2-20020305: How do we make sure we have the complete list? const char* METHOD_NAMES[] = { "GET", "HTTP/1.1 400", "HTTP/1.0 400", "HTTP/1.1 401", "HTTP/1.0 401", "HTTP/1.1 413", "HTTP/1.0 413", "HTTP/1.1 500", "HTTP/1.0 500", "HTTP/1.1 501", "HTTP/1.0 501", "HTTP/1.1 503", "HTTP/1.0 503" }; const Uint32 METHOD_NAMES_SIZE = sizeof(METHOD_NAMES) / sizeof(char*); for (Uint32 i = 0; i < METHOD_NAMES_SIZE; i++) { Uint32 n = strlen(METHOD_NAMES[i]); if (strncmp(line, METHOD_NAMES[i], n) == 0 && isspace(line[n])) return true; } return false;}*/void HTTPConnection::_getContentLengthAndContentOffset(){ static const char func[] = "HTTPConnection::_getContentLengthAndContentOffset"; Uint32 size = _incomingBuffer.size(); if (size == 0) return; char* data = (char*)_incomingBuffer.getData(); char* line = (char*)data; char* sep; Uint32 lineNum = 0; Boolean bodylessMessage = false; Boolean gotContentLength = false; Boolean gotTransferEncoding = false; Boolean gotContentLanguage = false; Boolean gotTransferTE = false; while ((sep = _FindSeparator(line, size - (line - data)))) { char save = *sep; *sep = '\0'; // Did we find the double separator which terminates the headers? if (line == sep) { *sep = save; line = sep + ((save == '\r') ? 2 : 1); _contentOffset = line - _incomingBuffer.getData(); // reserve space for entire non-chunked message if (_contentLength > 0) { try { Uint32 capacity = (Uint32)(_contentLength + _contentOffset + 1); _incomingBuffer.reserveCapacity(capacity); data = (char *)_incomingBuffer.getData(); data[capacity-1] = 0; } catch (const PEGASUS_STD(bad_alloc)&) { _throwEventFailure(HTTP_STATUS_REQUEST_TOO_LARGE, "Error reserving space for non-chunked message"); } catch (...) { _throwEventFailure( httpStatusInternal, "unexpected exception"); } } break; } // If this is one of the bodyless methods, then we can assume the // message is complete when the "\r\n\r\n" is encountered. if (lineNum == 0 && _IsBodylessMessage(line)) bodylessMessage = true; // Look for the content-length if not already found: char* colon = strchr(line, ':'); if (colon) { *colon = '\0'; // remove whitespace after colon before value char *valueStart = colon + 1; while (*valueStart == ' ' || *valueStart == '\t') valueStart++; // we found some non-whitespace token if (valueStart != sep) { char *valueEnd = sep - 1; // now remove whitespace from end of line back to last byte // of value while (*valueEnd == ' ' || *valueEnd == '\t') valueEnd--; char valueSave = *(valueEnd+1); if (System::strcasecmp(line, headerNameContentLength) == 0) { if (gotContentLength) { _throwEventFailure(HTTP_STATUS_BADREQUEST, "Duplicate Content-Length header detected"); } gotContentLength = true; if (_transferEncodingValues.size() == 0) { // Use a dummy character conversion to catch an // invalid character in the value. char dummy; if (sscanf(valueStart, "%d%c", &_contentLength, &dummy) != 1) { _throwEventFailure(HTTP_STATUS_BADREQUEST, "Invalid Content-Length header detected"); } } else { _contentLength = -1; } } else if (System::strcasecmp( line, headerNameTransferEncoding) == 0) { if (gotTransferEncoding) { _throwEventFailure(HTTP_STATUS_BADREQUEST, "Duplicate Transfer-Encoding header detected"); } gotTransferEncoding = true; _transferEncodingValues.clear(); if (strcmp(valueStart, headerValueTransferEncodingChunked) == 0) _transferEncodingValues.append( headerValueTransferEncodingChunked); else if (strcmp(valueStart, headerValueTransferEncodingIdentity) == 0) ; // do nothing else _throwEventFailure(HTTP_STATUS_NOTIMPLEMENTED, "unimplemented transfer-encoding value"); _contentLength = -1; } else if (System::strcasecmp( line, headerNameContentLanguage) == 0) { // note: if this is a chunked header, then this will be // ignored later String contentLanguagesString( valueStart, valueEnd - valueStart + 1); try { ContentLanguageList contentLanguagesValue = LanguageParser::parseContentLanguageHeader( contentLanguagesString); if (gotContentLanguage) { // Append these content languages to the existing // list. for (Uint32 i = 0; i < contentLanguagesValue.size(); i++) { contentLanguages.append( contentLanguagesValue.getLanguageTag(i)); } } else { contentLanguages = contentLanguagesValue; gotContentLanguage = true; } } catch (...) { Tracer::trace(TRC_HTTP, Tracer::LEVEL2, "HTTPConnection: ERROR: contentLanguages had " "parsing failure. clearing languages. error " "data=%s", (const char *)contentLanguagesString.getCString()); contentLanguages.clear(); } } else if (System::strcasecmp(line, headerNameTransferTE) == 0) { if (gotTransferTE) { _throwEventFailure(HTTP_STATUS_BADREQUEST, "Duplicate TE header detected"); } gotTransferTE = true; _transferEncodingTEValues.clear(); static const char valueDelimiter = ','; char *valuesStart = valueStart; // now tokenize the values while (*valuesStart) { // strip off whitepsace from the front while (*valuesStart == ' ' || *valuesStart == '\t') valuesStart++; if (valuesStart == valueEnd) break; char *v = strchr(valuesStart, valueDelimiter); if (v) { if (v == valuesStart) { valuesStart++; continue; } v--; // strip off whitespace from the end while (*v == ' ' || *v == '\t') v--; v++; *v = 0; } _transferEncodingTEValues.append(valuesStart); if (v) { *v = valueDelimiter; valuesStart = v+1; } else break; } } *(valueEnd+1) = valueSave; } // if some value tokens *colon = ':'; } *sep = save; line = sep + ((save == '\r') ? 2 : 1); lineNum++; } if (_contentOffset != -1 && bodylessMessage) _contentLength = 0;}void HTTPConnection::_clearIncoming(){ _contentOffset = -1; _contentLength = -1; _incomingBuffer.clear(); _mpostPrefix.clear(); contentLanguages.clear();}void HTTPConnection::_closeConnection(){ // return - don't send the close connection message. // let the monitor dispatch function do the cleanup. PEG_METHOD_ENTER(TRC_HTTP, "HTTPConnection::_closeConnection");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -