mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Improve HTTP version number comparisons
Previous use of floating point comparisons was not always stable.
This commit is contained in:
parent
aa4185cfff
commit
4375aa150f
2 changed files with 44 additions and 25 deletions
|
@ -472,14 +472,16 @@ void HTTP_Entity::SubmitHeader(mime::MIME_Header* h)
|
||||||
|
|
||||||
else if ( mime::istrequal(h->get_name(), "transfer-encoding") )
|
else if ( mime::istrequal(h->get_name(), "transfer-encoding") )
|
||||||
{
|
{
|
||||||
double http_version = 0;
|
HTTP_Analyzer::HTTP_VersionNumber http_version;
|
||||||
|
|
||||||
if (http_message->analyzer->GetRequestOngoing())
|
if (http_message->analyzer->GetRequestOngoing())
|
||||||
http_version = http_message->analyzer->GetRequestVersion();
|
http_version = http_message->analyzer->GetRequestVersionNumber();
|
||||||
else // reply_ongoing
|
else // reply_ongoing
|
||||||
http_version = http_message->analyzer->GetReplyVersion();
|
http_version = http_message->analyzer->GetReplyVersionNumber();
|
||||||
|
|
||||||
data_chunk_t vt = h->get_value_token();
|
data_chunk_t vt = h->get_value_token();
|
||||||
if ( mime::istrequal(vt, "chunked") && http_version == 1.1 )
|
if ( mime::istrequal(vt, "chunked") &&
|
||||||
|
http_version == HTTP_Analyzer::HTTP_VersionNumber{1, 1} )
|
||||||
chunked_transfer_state = BEFORE_CHUNK;
|
chunked_transfer_state = BEFORE_CHUNK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,7 +844,6 @@ HTTP_Analyzer::HTTP_Analyzer(Connection* conn)
|
||||||
{
|
{
|
||||||
num_requests = num_replies = 0;
|
num_requests = num_replies = 0;
|
||||||
num_request_lines = num_reply_lines = 0;
|
num_request_lines = num_reply_lines = 0;
|
||||||
request_version = reply_version = 0.0; // unknown version
|
|
||||||
keep_alive = 0;
|
keep_alive = 0;
|
||||||
connection_close = 0;
|
connection_close = 0;
|
||||||
|
|
||||||
|
@ -1184,8 +1185,8 @@ void HTTP_Analyzer::GenStats()
|
||||||
RecordVal* r = new RecordVal(http_stats_rec);
|
RecordVal* r = new RecordVal(http_stats_rec);
|
||||||
r->Assign(0, val_mgr->GetCount(num_requests));
|
r->Assign(0, val_mgr->GetCount(num_requests));
|
||||||
r->Assign(1, val_mgr->GetCount(num_replies));
|
r->Assign(1, val_mgr->GetCount(num_replies));
|
||||||
r->Assign(2, new Val(request_version, TYPE_DOUBLE));
|
r->Assign(2, new Val(request_version.ToDouble(), TYPE_DOUBLE));
|
||||||
r->Assign(3, new Val(reply_version, TYPE_DOUBLE));
|
r->Assign(3, new Val(reply_version.ToDouble(), TYPE_DOUBLE));
|
||||||
|
|
||||||
// DEBUG_MSG("%.6f http_stats\n", network_time);
|
// DEBUG_MSG("%.6f http_stats\n", network_time);
|
||||||
ConnectionEventFast(http_stats, {BuildConnVal(), r});
|
ConnectionEventFast(http_stats, {BuildConnVal(), r});
|
||||||
|
@ -1318,14 +1319,14 @@ int HTTP_Analyzer::ParseRequest(const char* line, const char* end_of_line)
|
||||||
if ( version_start >= end_of_line )
|
if ( version_start >= end_of_line )
|
||||||
{
|
{
|
||||||
// If no version is found
|
// If no version is found
|
||||||
SetVersion(request_version, 0.9);
|
SetVersion(&request_version, {0, 9});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( version_start + 8 <= end_of_line )
|
if ( version_start + 8 <= end_of_line )
|
||||||
{
|
{
|
||||||
version_start += 5; // "HTTP/"
|
version_start += 5; // "HTTP/"
|
||||||
SetVersion(request_version,
|
SetVersion(&request_version,
|
||||||
HTTP_Version(end_of_line - version_start,
|
HTTP_Version(end_of_line - version_start,
|
||||||
version_start));
|
version_start));
|
||||||
|
|
||||||
|
@ -1348,31 +1349,33 @@ int HTTP_Analyzer::ParseRequest(const char* line, const char* end_of_line)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only recognize [0-9][.][0-9].
|
// Only recognize [0-9][.][0-9].
|
||||||
double HTTP_Analyzer::HTTP_Version(int len, const char* data)
|
HTTP_Analyzer::HTTP_VersionNumber HTTP_Analyzer::HTTP_Version(int len, const char* data)
|
||||||
{
|
{
|
||||||
if ( len >= 3 &&
|
if ( len >= 3 &&
|
||||||
data[0] >= '0' && data[0] <= '9' &&
|
data[0] >= '0' && data[0] <= '9' &&
|
||||||
data[1] == '.' &&
|
data[1] == '.' &&
|
||||||
data[2] >= '0' && data[2] <= '9' )
|
data[2] >= '0' && data[2] <= '9' )
|
||||||
{
|
{
|
||||||
return double(data[0] - '0') + 0.1 * double(data[2] - '0');
|
uint8_t major = data[0] - '0';
|
||||||
|
uint8_t minor = data[2] - '0';
|
||||||
|
return {major, minor};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HTTP_Event("bad_HTTP_version", mime::new_string_val(len, data));
|
HTTP_Event("bad_HTTP_version", mime::new_string_val(len, data));
|
||||||
return 0;
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTP_Analyzer::SetVersion(double& version, double new_version)
|
void HTTP_Analyzer::SetVersion(HTTP_VersionNumber* version, HTTP_VersionNumber new_version)
|
||||||
{
|
{
|
||||||
if ( version == 0.0 )
|
if ( *version == HTTP_VersionNumber{} )
|
||||||
version = new_version;
|
*version = new_version;
|
||||||
|
|
||||||
else if ( version != new_version )
|
else if ( *version != new_version )
|
||||||
Weird("HTTP_version_mismatch");
|
Weird("HTTP_version_mismatch");
|
||||||
|
|
||||||
if ( version > 1.05 )
|
if ( version->major > 1 || (version->major == 1 && version->minor > 0) )
|
||||||
keep_alive = 1;
|
keep_alive = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1434,7 +1437,7 @@ void HTTP_Analyzer::HTTP_Request()
|
||||||
request_method,
|
request_method,
|
||||||
TruncateURI(request_URI->AsStringVal()),
|
TruncateURI(request_URI->AsStringVal()),
|
||||||
TruncateURI(unescaped_URI->AsStringVal()),
|
TruncateURI(unescaped_URI->AsStringVal()),
|
||||||
new StringVal(fmt("%.1f", request_version)),
|
new StringVal(fmt("%.1f", request_version.ToDouble())),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1445,7 +1448,7 @@ void HTTP_Analyzer::HTTP_Reply()
|
||||||
{
|
{
|
||||||
ConnectionEventFast(http_reply, {
|
ConnectionEventFast(http_reply, {
|
||||||
BuildConnVal(),
|
BuildConnVal(),
|
||||||
new StringVal(fmt("%.1f", reply_version)),
|
new StringVal(fmt("%.1f", reply_version.ToDouble())),
|
||||||
val_mgr->GetCount(reply_code),
|
val_mgr->GetCount(reply_code),
|
||||||
reply_reason_phrase ?
|
reply_reason_phrase ?
|
||||||
reply_reason_phrase->Ref() :
|
reply_reason_phrase->Ref() :
|
||||||
|
@ -1565,7 +1568,7 @@ int HTTP_Analyzer::HTTP_ReplyLine(const char* line, const char* end_of_line)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetVersion(reply_version, HTTP_Version(end_of_line - rest, rest));
|
SetVersion(&reply_version, HTTP_Version(end_of_line - rest, rest));
|
||||||
|
|
||||||
for ( ; rest < end_of_line; ++rest )
|
for ( ; rest < end_of_line; ++rest )
|
||||||
if ( mime::is_lws(*rest) )
|
if ( mime::is_lws(*rest) )
|
||||||
|
|
|
@ -175,8 +175,24 @@ public:
|
||||||
void ConnectionReset() override;
|
void ConnectionReset() override;
|
||||||
void PacketWithRST() override;
|
void PacketWithRST() override;
|
||||||
|
|
||||||
double GetRequestVersion() { return request_version; };
|
struct HTTP_VersionNumber {
|
||||||
double GetReplyVersion() { return reply_version; };
|
uint8_t major = 0;
|
||||||
|
uint8_t minor = 0;
|
||||||
|
|
||||||
|
bool operator==(const HTTP_VersionNumber& other) const
|
||||||
|
{ return minor == other.minor && major == other.major; }
|
||||||
|
|
||||||
|
bool operator!=(const HTTP_VersionNumber& other) const
|
||||||
|
{ return ! operator==(other); }
|
||||||
|
|
||||||
|
double ToDouble() const
|
||||||
|
{ return major + minor * 0.1; }
|
||||||
|
};
|
||||||
|
|
||||||
|
double GetRequestVersion() { return request_version.ToDouble(); };
|
||||||
|
double GetReplyVersion() { return reply_version.ToDouble(); };
|
||||||
|
HTTP_VersionNumber GetRequestVersionNumber() { return request_version; };
|
||||||
|
HTTP_VersionNumber GetReplyVersionNumber() { return reply_version; };
|
||||||
int GetRequestOngoing() { return request_ongoing; };
|
int GetRequestOngoing() { return request_ongoing; };
|
||||||
int GetReplyOngoing() { return reply_ongoing; };
|
int GetReplyOngoing() { return reply_ongoing; };
|
||||||
|
|
||||||
|
@ -204,9 +220,9 @@ protected:
|
||||||
const char* prefix);
|
const char* prefix);
|
||||||
|
|
||||||
int ParseRequest(const char* line, const char* end_of_line);
|
int ParseRequest(const char* line, const char* end_of_line);
|
||||||
double HTTP_Version(int len, const char* data);
|
HTTP_VersionNumber HTTP_Version(int len, const char* data);
|
||||||
|
|
||||||
void SetVersion(double& version, double new_version);
|
void SetVersion(HTTP_VersionNumber* version, HTTP_VersionNumber new_version);
|
||||||
|
|
||||||
int RequestExpected() const { return num_requests == 0 || keep_alive; }
|
int RequestExpected() const { return num_requests == 0 || keep_alive; }
|
||||||
|
|
||||||
|
@ -227,7 +243,7 @@ protected:
|
||||||
int request_state, reply_state;
|
int request_state, reply_state;
|
||||||
int num_requests, num_replies;
|
int num_requests, num_replies;
|
||||||
int num_request_lines, num_reply_lines;
|
int num_request_lines, num_reply_lines;
|
||||||
double request_version, reply_version;
|
HTTP_VersionNumber request_version, reply_version;
|
||||||
int keep_alive;
|
int keep_alive;
|
||||||
int connection_close;
|
int connection_close;
|
||||||
int request_ongoing, reply_ongoing;
|
int request_ongoing, reply_ongoing;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue