From: Tom Peters Date: Tue, 5 Aug 2014 17:38:43 +0000 (-0400) Subject: checkpoint prior to pulling latest with flow in reassemble X-Git-Tag: 3.0.0-233~1431 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=04b583be57e23d46bf1e157fc0dacf0b63f26ae1;p=thirdparty%2Fsnort3.git checkpoint prior to pulling latest with flow in reassemble --- diff --git a/src/service_inspectors/nhttp_inspect/CMakeLists.txt b/src/service_inspectors/nhttp_inspect/CMakeLists.txt index f86115607..6ad38673a 100644 --- a/src/service_inspectors/nhttp_inspect/CMakeLists.txt +++ b/src/service_inspectors/nhttp_inspect/CMakeLists.txt @@ -12,8 +12,8 @@ set (FILE_LIST nhttp_msg_status.h nhttp_msg_head_shared.cc nhttp_msg_head_shared.h - nhttp_msg_head.cc - nhttp_msg_head.h + nhttp_msg_header.cc + nhttp_msg_header.h nhttp_msg_body.cc nhttp_msg_body.h nhttp_msg_chunk_head.cc diff --git a/src/service_inspectors/nhttp_inspect/Makefile.am b/src/service_inspectors/nhttp_inspect/Makefile.am index b53e2908f..b810bfe0d 100644 --- a/src/service_inspectors/nhttp_inspect/Makefile.am +++ b/src/service_inspectors/nhttp_inspect/Makefile.am @@ -7,7 +7,7 @@ nhttp_msg_start.cc nhttp_msg_start.h \ nhttp_msg_request.cc nhttp_msg_request.h \ nhttp_msg_status.cc nhttp_msg_status.h \ nhttp_msg_head_shared.cc nhttp_msg_head_shared.h \ -nhttp_msg_head.cc nhttp_msg_head.h \ +nhttp_msg_header.cc nhttp_msg_header.h \ nhttp_msg_body.cc nhttp_msg_body.h \ nhttp_msg_chunk_head.cc nhttp_msg_chunk_head.h \ nhttp_msg_chunk_body.cc nhttp_msg_chunk_body.h \ diff --git a/src/service_inspectors/nhttp_inspect/nhttp_field.cc b/src/service_inspectors/nhttp_inspect/nhttp_field.cc index b0b5fefac..6c0011c05 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_field.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_field.cc @@ -35,6 +35,8 @@ using namespace NHttpEnums; +const Field Field::FIELD_NULL { STAT_NOSOURCE }; + void Field::print(FILE *output, const char* name, bool intVals) const { if ((length == STAT_NOTPRESENT) || (length == STAT_NOTCOMPUTE) || (length == STAT_NOSOURCE)) return; int outCount = fprintf(output, "%s, length = %d, ", name, length); diff --git a/src/service_inspectors/nhttp_inspect/nhttp_field.h b/src/service_inspectors/nhttp_inspect/nhttp_field.h index 3d7b5e2e0..8bc7c65a9 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_field.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_field.h @@ -31,6 +31,7 @@ #include #include +#include // Individual pieces of the message found during parsing // Length values <= 0 are StatusCode values and imply that the start pointer is meaningless. @@ -40,7 +41,10 @@ public: int32_t length = NHttpEnums::STAT_NOTCOMPUTE; const uint8_t* start = nullptr; + static const Field FIELD_NULL; + Field(int32_t length_, const uint8_t* start_) : length(length_), start(start_) {}; + explicit Field(int32_t length_) : length(length_) { assert(length<=0); }; Field() = default; void print(FILE *output, const char* name, bool intVals = false) const; }; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_flow_data.cc b/src/service_inspectors/nhttp_inspect/nhttp_flow_data.cc index 9e5fdfeec..f4669e53c 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_flow_data.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_flow_data.cc @@ -35,7 +35,7 @@ #include "nhttp_msg_section.h" #include "nhttp_msg_request.h" #include "nhttp_msg_status.h" -#include "nhttp_msg_head.h" +#include "nhttp_msg_header.h" using namespace NHttpEnums; @@ -44,8 +44,9 @@ unsigned NHttpFlowData::nhttp_flow_id = 0; NHttpFlowData::NHttpFlowData() : FlowData(nhttp_flow_id) {} NHttpFlowData::~NHttpFlowData() { + delete requestLine; + delete statusLine; for(int k=0; k <= 1; k++) { - delete startLine[k]; delete headers[k]; delete latestOther[k]; } diff --git a/src/service_inspectors/nhttp_inspect/nhttp_flow_data.h b/src/service_inspectors/nhttp_inspect/nhttp_flow_data.h index fb0c04639..379c20430 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_flow_data.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_flow_data.h @@ -31,18 +31,6 @@ #include "stream/stream_api.h" -class NHttpInspect; -class NHttpMsgSection; -class NHttpMsgStart; -class NHttpMsgRequest; -class NHttpMsgStatus; -class NHttpMsgHeader; -class NHttpMsgBody; -class NHttpMsgChunkHead; -class NHttpMsgChunkBody; -class NHttpMsgTrailer; -class NHttpTestInput; - class NHttpFlowData : public FlowData { public: @@ -92,9 +80,10 @@ private: // Stored message sections from this session // You must reset to nullptr after deleting a section // Never put one section in two places. latestOther is only for things not otherwise listed - NHttpMsgStart* startLine[2] = { nullptr, nullptr }; - NHttpMsgHeader* headers[2] = { nullptr, nullptr }; - NHttpMsgSection* latestOther[2] = { nullptr, nullptr }; + class NHttpMsgRequest* requestLine = nullptr; + class NHttpMsgStatus* statusLine = nullptr; + class NHttpMsgHeader* headers[2] = { nullptr, nullptr }; + class NHttpMsgSection* latestOther[2] = { nullptr, nullptr }; }; #endif diff --git a/src/service_inspectors/nhttp_inspect/nhttp_inspect.cc b/src/service_inspectors/nhttp_inspect/nhttp_inspect.cc index 476d540a9..b8b175ccd 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_inspect.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_inspect.cc @@ -117,12 +117,10 @@ void NHttpInspect::show(SnortConfig*) LogMessage("NHttpInspect\n"); } -void NHttpInspect::eval(Packet* p) +void NHttpInspect::eval(Packet*) { - // Only packets from the StreamSplitter can be processed - if (!PacketHasPAFPayload(p)) return; - - process(p->data, p->dsize, p->flow, (p->packet_flags & PKT_FROM_CLIENT) ? SRC_CLIENT : SRC_SERVER); + printf("eval()\n"); fflush(nullptr); /* &&& */ + return; } void NHttpInspect::process(const uint8_t* data, const uint16_t dsize, Flow* const flow, SourceId sourceId) diff --git a/src/service_inspectors/nhttp_inspect/nhttp_inspect.h b/src/service_inspectors/nhttp_inspect/nhttp_inspect.h index 30c3df024..53b33a524 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_inspect.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_inspect.h @@ -30,7 +30,7 @@ #include "framework/inspector.h" #include "nhttp_msg_request.h" #include "nhttp_msg_status.h" -#include "nhttp_msg_head.h" +#include "nhttp_msg_header.h" #include "nhttp_msg_body.h" #include "nhttp_msg_chunk_head.h" #include "nhttp_msg_chunk_body.h" @@ -54,7 +54,7 @@ public: bool enabled(); void pinit(); void pterm(); - NHttpStreamSplitter* get_splitter(bool isClientToServer) { return new NHttpStreamSplitter(isClientToServer); }; + NHttpStreamSplitter* get_splitter(bool isClientToServer) { return new NHttpStreamSplitter(isClientToServer, this); }; private: friend NHttpApi; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_chunk_body.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_chunk_body.cc index 73b31a47c..551c69ad8 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_chunk_body.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_chunk_body.cc @@ -39,7 +39,7 @@ using namespace NHttpEnums; NHttpMsgChunkBody::NHttpMsgChunkBody(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, SourceId sourceId_) : - NHttpMsgBody(buffer, bufSize, sessionData_, sourceId_), numChunks(sessionData->numChunks[sourceId]), + NHttpMsgBody(buffer, bufSize, sessionData_, sourceId_), /* numChunks(sessionData->numChunks[sourceId]), &&& */ chunkSections(sessionData->chunkSections[sourceId]), chunkOctets(sessionData->chunkOctets[sourceId]) {} void NHttpMsgChunkBody::analyze() { diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_chunk_body.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_chunk_body.h index 0430affa4..5a122775b 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_chunk_body.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_chunk_body.h @@ -44,7 +44,7 @@ public: void updateFlow(); private: - int64_t numChunks; + // int64_t numChunks; // will be needed in future commented out to please compiler &&& int64_t chunkSections; int64_t chunkOctets; }; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_head.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_header.cc similarity index 99% rename from src/service_inspectors/nhttp_inspect/nhttp_msg_head.cc rename to src/service_inspectors/nhttp_inspect/nhttp_msg_header.cc index 31969d29b..2bf58e164 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_head.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_header.cc @@ -34,7 +34,7 @@ #include "snort.h" #include "nhttp_enum.h" -#include "nhttp_msg_head.h" +#include "nhttp_msg_header.h" using namespace NHttpEnums; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_head.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_header.h similarity index 96% rename from src/service_inspectors/nhttp_inspect/nhttp_msg_head.h rename to src/service_inspectors/nhttp_inspect/nhttp_msg_header.h index 2e9934934..876d91fb8 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_head.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_header.h @@ -26,8 +26,8 @@ // @brief NHttpMsgHeader class declaration // -#ifndef NHTTP_MSG_HEAD_H -#define NHTTP_MSG_HEAD_H +#ifndef NHTTP_MSG_HEADER_H +#define NHTTP_MSG_HEADER_H #include "nhttp_msg_head_shared.h" diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_request.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_request.cc index 1ded924be..c3d1dda3f 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_request.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_request.cc @@ -36,14 +36,14 @@ #include "nhttp_enum.h" #include "nhttp_normalizers.h" #include "nhttp_msg_request.h" -#include "nhttp_msg_head.h" +#include "nhttp_msg_header.h" using namespace NHttpEnums; NHttpMsgRequest::NHttpMsgRequest(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, SourceId sourceId_) : NHttpMsgStart(buffer, bufSize, sessionData_, sourceId_) { - delete sessionData->startLine[SRC_CLIENT]; - sessionData->startLine[SRC_CLIENT] = this; + delete sessionData->requestLine; + sessionData->requestLine = this; delete sessionData->headers[SRC_CLIENT]; sessionData->headers[SRC_CLIENT] = nullptr; delete sessionData->latestOther[SRC_CLIENT]; @@ -87,6 +87,20 @@ void NHttpMsgRequest::deriveMethodId() { methodId = (MethodId) strToCode(method.start, method.length, methodList); } +const Field& NHttpMsgRequest::getUri() { + if (uri != nullptr) { + return uri->getUri(); + } + return Field::FIELD_NULL; +} + +const Field& NHttpMsgRequest::getUriNormLegacy() { + if (uri != nullptr) { + return uri->getNormLegacy(); + } + return Field::FIELD_NULL; +} + void NHttpMsgRequest::genEvents() { if (methodId == METH__OTHER) createEvent(EVENT_UNKNOWN_METHOD); diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_request.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_request.h index d4118900a..260ba58f9 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_request.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_request.h @@ -47,6 +47,9 @@ public: void genEvents(); void updateFlow(); void legacyClients(); + const Field& getMethod() { return method; }; + const Field& getUri(); + const Field& getUriNormLegacy(); private: static const StrCode methodList[]; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_status.cc b/src/service_inspectors/nhttp_inspect/nhttp_msg_status.cc index f4bf98755..70121533e 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_status.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_status.cc @@ -35,14 +35,15 @@ #include "snort.h" #include "nhttp_enum.h" #include "nhttp_msg_status.h" -#include "nhttp_msg_head.h" +#include "nhttp_msg_request.h" +#include "nhttp_msg_header.h" using namespace NHttpEnums; NHttpMsgStatus::NHttpMsgStatus(const uint8_t *buffer, const uint16_t bufSize, NHttpFlowData *sessionData_, SourceId sourceId_) : - NHttpMsgStart(buffer, bufSize, sessionData_, sourceId_) { - delete sessionData->startLine[SRC_SERVER]; - sessionData->startLine[SRC_SERVER] = this; + NHttpMsgStart(buffer, bufSize, sessionData_, sourceId_), request(sessionData->requestLine) { + delete sessionData->statusLine; + sessionData->statusLine = this; delete sessionData->headers[SRC_SERVER]; sessionData->headers[SRC_SERVER] = nullptr; delete sessionData->latestOther[SRC_SERVER]; @@ -132,8 +133,21 @@ void NHttpMsgStatus::updateFlow() { // Legacy support function. Puts message fields into the buffers used by old Snort. void NHttpMsgStatus::legacyClients() { ClearHttpBuffers(); - if (statusCode.length > 0) SetHttpBuffer(HTTP_BUFFER_STAT_CODE, statusCode.start, (unsigned)statusCode.length); - if (reasonPhrase.length > 0) SetHttpBuffer(HTTP_BUFFER_STAT_MSG, reasonPhrase.start, (unsigned)reasonPhrase.length); + if ((request != nullptr) && (request->getMethod().length > 0)) { + SetHttpBuffer(HTTP_BUFFER_METHOD, request->getMethod().start, (unsigned)request->getMethod().length); + } + if ((request != nullptr) && (request->getUri().length > 0)) { + SetHttpBuffer(HTTP_BUFFER_RAW_URI, request->getUri().start, (unsigned)request->getUri().length); + } + if ((request != nullptr) && (request->getUriNormLegacy().length > 0)) { + SetHttpBuffer(HTTP_BUFFER_URI, request->getUriNormLegacy().start, (unsigned)request->getUriNormLegacy().length); + } + if (statusCode.length > 0) { + SetHttpBuffer(HTTP_BUFFER_STAT_CODE, statusCode.start, (unsigned)statusCode.length); + } + if (reasonPhrase.length > 0) { + SetHttpBuffer(HTTP_BUFFER_STAT_MSG, reasonPhrase.start, (unsigned)reasonPhrase.length); + } } diff --git a/src/service_inspectors/nhttp_inspect/nhttp_msg_status.h b/src/service_inspectors/nhttp_inspect/nhttp_msg_status.h index e534121d1..2ea777a30 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_msg_status.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_msg_status.h @@ -51,6 +51,7 @@ private: Field statusCode; Field reasonPhrase; + NHttpMsgRequest* request; }; #endif diff --git a/src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.cc b/src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.cc index 071549796..847da436c 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.cc @@ -30,6 +30,7 @@ #include #include #include "snort.h" +#include "protocols/packet.h" #include "nhttp_enum.h" #include "nhttp_test_input.h" #include "nhttp_stream_splitter.h" @@ -55,6 +56,22 @@ void NHttpStreamSplitter::createEvent(EventSid sid) { eventsGenerated |= 1 << (sid-1); } +const StreamBuffer* NHttpStreamSplitter::reassemble(unsigned offset, const uint8_t* data, unsigned len, uint32_t flags, unsigned& copied) { + static THREAD_LOCAL StreamBuffer nhttp_buf; + if (flags & PKT_PDU_HEAD) { + sectionBuffer = new uint8_t[65536]; + } + memcpy(sectionBuffer+offset, data, len); + copied = len; + if (flags & PKT_PDU_TAIL) { + process(sectionBuffer, offset + len, p->flow, to_server() ? SRC_CLIENT : SRC_SERVER); + nhttp_buf.data = sectionBuffer; + nhttp_buf.length = offset + len; + return &nhttp_buf; + } + return nullptr; +} + PAF_Status NHttpStreamSplitter::scan (Flow* flow, const uint8_t* data, uint32_t length, uint32_t flags, uint32_t* flushOffset) { // When the system begins providing TCP connection close information this won't always be false. &&& bool tcpClose = false; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.h b/src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.h index 607f8ab97..cd9be24ef 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_stream_splitter.h @@ -32,17 +32,23 @@ #include "stream/stream_splitter.h" #include "nhttp_flow_data.h" +class NHttpInspect; + class NHttpStreamSplitter : public StreamSplitter { public: - NHttpStreamSplitter(bool isClientToServer) : StreamSplitter(isClientToServer) {}; + NHttpStreamSplitter(bool isClientToServer, NHttpInspect* myInspector_) : StreamSplitter(isClientToServer), myInspector(myInspector_) {}; PAF_Status scan(Flow* flow, const uint8_t* data, uint32_t length, uint32_t flags, uint32_t* flushOffset); bool is_paf() { return true; }; uint32_t max() { return pafMax; }; + const StreamBuffer* reassemble(unsigned offset, const uint8_t* data, unsigned len, uint32_t flags, unsigned& copied); private: void prepareFlush(NHttpFlowData* sessionData, uint32_t* flushOffset, NHttpEnums::SourceId sourceId, NHttpEnums::SectionType sectionType, bool tcpClose, uint64_t infractions, uint32_t numOctets); void createEvent(NHttpEnums::EventSid sid); + NHttpInspect* const myInspector; + + uint8_t *sectionBuffer = nullptr; uint64_t eventsGenerated = 0; int64_t octetsSeen = 0; int numCrlf = 0; diff --git a/src/service_inspectors/nhttp_inspect/nhttp_tables.cc b/src/service_inspectors/nhttp_inspect/nhttp_tables.cc index 21b8ecc43..d9421a265 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_tables.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_tables.cc @@ -40,7 +40,7 @@ #include "nhttp_normalizers.h" #include "nhttp_head_norm.h" #include "nhttp_msg_request.h" -#include "nhttp_msg_head.h" +#include "nhttp_msg_header.h" #include "nhttp_module.h" #include "nhttp_uri_norm.h" diff --git a/src/service_inspectors/nhttp_inspect/nhttp_uri.cc b/src/service_inspectors/nhttp_inspect/nhttp_uri.cc index dc83e7047..2567d8569 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_uri.cc +++ b/src/service_inspectors/nhttp_inspect/nhttp_uri.cc @@ -118,7 +118,7 @@ SchemeId NHttpUri::getSchemeId() { return schemeId; } -Field NHttpUri::getNormHost() { +const Field& NHttpUri::getNormHost() { if (hostNorm.length != STAT_NOTCOMPUTE) return hostNorm; if (getHost().length < 0) { hostNorm.length = STAT_NOSOURCE; @@ -128,7 +128,7 @@ Field NHttpUri::getNormHost() { return hostNorm; } -Field NHttpUri::getNormPath() { +const Field& NHttpUri::getNormPath() { if (pathNorm.length != STAT_NOTCOMPUTE) return pathNorm; if (getPath().length < 0) { pathNorm.length = STAT_NOSOURCE; @@ -138,7 +138,7 @@ Field NHttpUri::getNormPath() { return pathNorm; } -Field NHttpUri::getNormQuery() { +const Field& NHttpUri::getNormQuery() { if (queryNorm.length != STAT_NOTCOMPUTE) return queryNorm; if (getQuery().length < 0) { queryNorm.length = STAT_NOSOURCE; @@ -148,7 +148,7 @@ Field NHttpUri::getNormQuery() { return queryNorm; } -Field NHttpUri::getNormFragment() { +const Field& NHttpUri::getNormFragment() { if (fragmentNorm.length != STAT_NOTCOMPUTE) return fragmentNorm; if (getFragment().length < 0) { fragmentNorm.length = STAT_NOSOURCE; @@ -222,7 +222,7 @@ void NHttpUri::parseAbsPath() { } // Glue normalized URI fields back together -Field NHttpUri::getNormLegacy() { +const Field& NHttpUri::getNormLegacy() { if (legacyNorm.length != STAT_NOTCOMPUTE) return legacyNorm; if (getPath().length >= 0) UriNormalizer::normalize(path, pathNorm, true, scratchPad, pathInfractions); diff --git a/src/service_inspectors/nhttp_inspect/nhttp_uri.h b/src/service_inspectors/nhttp_inspect/nhttp_uri.h index 07d384425..65f350b99 100644 --- a/src/service_inspectors/nhttp_inspect/nhttp_uri.h +++ b/src/service_inspectors/nhttp_inspect/nhttp_uri.h @@ -42,16 +42,16 @@ class NHttpUri { public: NHttpUri(const uint8_t* start, int32_t length, NHttpEnums::MethodId method) : uri(length, start), methodId(method), scratchPad(2*length+200) {}; - Field getUri() const { return uri; }; + const Field& getUri() const { return uri; }; NHttpEnums::UriType getUriType() { parseUri(); return uriType; }; - Field getScheme() { parseUri(); return scheme; }; - Field getAuthority() { parseUri(); return authority; }; - Field getHost() { parseAuthority(); return host; }; - Field getPort() { parseAuthority(); return port; }; - Field getAbsPath() { parseUri(); return absPath; }; - Field getPath() { parseAbsPath(); return path; }; - Field getQuery() { parseAbsPath(); return query; }; - Field getFragment() { parseAbsPath(); return fragment; }; + const Field& getScheme() { parseUri(); return scheme; }; + const Field& getAuthority() { parseUri(); return authority; }; + const Field& getHost() { parseAuthority(); return host; }; + const Field& getPort() { parseAuthority(); return port; }; + const Field& getAbsPath() { parseUri(); return absPath; }; + const Field& getPath() { parseAbsPath(); return path; }; + const Field& getQuery() { parseAbsPath(); return query; }; + const Field& getFragment() { parseAbsPath(); return fragment; }; uint64_t getFormatInfractions() { parseUri(); return formatInfractions; }; uint64_t getSchemeInfractions() { getSchemeId(); return schemeInfractions; }; @@ -64,12 +64,12 @@ public: getPortInfractions() | getPathInfractions() | getQueryInfractions() | getFragmentInfractions(); }; NHttpEnums::SchemeId getSchemeId(); - Field getNormHost(); + const Field& getNormHost(); int32_t getPortValue(); - Field getNormPath(); - Field getNormQuery(); - Field getNormFragment(); - Field getNormLegacy(); + const Field& getNormPath(); + const Field& getNormQuery(); + const Field& getNormFragment(); + const Field& getNormLegacy(); private: static const StrCode schemeList[];