FileAnalysis: insert explicit event queue flush points.

And added an event called "event_queue_flush_point" to mark where that
occured in the event stream.  The FAF now uses an explicit event queue
flush instead of buffering input in order to wait for a file handle to
be returned from script-layer.
This commit is contained in:
Jon Siwek 2013-04-10 16:48:10 -05:00
parent d9321e2203
commit 2747e839fb
15 changed files with 128 additions and 382 deletions

View file

@ -5,46 +5,43 @@
module FTP; module FTP;
export { export {
## Determines whether the default :bro:see:`get_file_handle` handler
## is used to return file handles to the file analysis framework.
## Redefine to true in order to provide a custom handler which overrides
## the default for FTP.
const disable_default_file_handle_provider: bool = F &redef;
## Default file handle provider for FTP. ## Default file handle provider for FTP.
function get_file_handle(c: connection, is_orig: bool): string global get_file_handle: function(c: connection, is_orig: bool): string;
{
if ( [c$id$resp_h, c$id$resp_p] !in ftp_data_expected ) return "";
local info: FTP::Info = ftp_data_expected[c$id$resp_h, c$id$resp_p];
local rval = fmt("%s %s %s", ANALYZER_FTP_DATA, c$start_time,
id_string(c$id));
if ( info$passive )
# FTP client initiates data channel.
if ( is_orig )
# Don't care about FTP client data.
return "";
else
# Do care about FTP server data.
return rval;
else
# FTP server initiates dta channel.
if ( is_orig )
# Do care about FTP server data.
return rval;
else
# Don't care about FTP client data.
return "";
}
} }
function get_handle_string(c: connection): string
{
return fmt("%s %s %s", ANALYZER_FTP_DATA, c$start_time, id_string(c$id));
}
function get_file_handle(c: connection, is_orig: bool): string
{
if ( [c$id$resp_h, c$id$resp_p] !in ftp_data_expected ) return "";
local info: FTP::Info = ftp_data_expected[c$id$resp_h, c$id$resp_p];
if ( info$passive )
# FTP client initiates data channel.
if ( is_orig )
# Don't care about FTP client data.
return "";
else
# Do care about FTP server data.
return get_handle_string(c);
else
# FTP server initiates dta channel.
if ( is_orig )
# Do care about FTP server data.
return get_handle_string(c);
else
# Don't care about FTP client data.
return "";
}
module GLOBAL; module GLOBAL;
event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool)
{ {
if ( tag != ANALYZER_FTP_DATA ) return; if ( tag != ANALYZER_FTP_DATA ) return;
if ( FTP::disable_default_file_handle_provider ) return; set_file_handle(FTP::get_file_handle(c, is_orig));
return_file_handle(FTP::get_file_handle(c, is_orig));
} }

View file

@ -6,31 +6,26 @@
module HTTP; module HTTP;
export { export {
## Determines whether the default :bro:see:`get_file_handle` handler
## is used to return file handles to the file analysis framework.
## Redefine to true in order to provide a custom handler which overrides
## the default HTTP.
const disable_default_file_handle_provider: bool = F &redef;
## Default file handle provider for HTTP. ## Default file handle provider for HTTP.
function get_file_handle(c: connection, is_orig: bool): string global get_file_handle: function(c: connection, is_orig: bool): string;
{
if ( ! c?$http ) return "";
if ( c$http$range_request )
return fmt("%s %s %s %s", ANALYZER_HTTP, is_orig, c$id$orig_h,
build_url(c$http));
return fmt("%s %s %s %s %s", ANALYZER_HTTP, c$start_time, is_orig,
c$http$trans_depth, id_string(c$id));
}
} }
function get_file_handle(c: connection, is_orig: bool): string
{
if ( ! c?$http ) return "";
if ( c$http$range_request )
return fmt("%s %s %s %s", ANALYZER_HTTP, is_orig, c$id$orig_h,
build_url(c$http));
return fmt("%s %s %s %s %s", ANALYZER_HTTP, c$start_time, is_orig,
c$http$trans_depth, id_string(c$id));
}
module GLOBAL; module GLOBAL;
event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool)
{ {
if ( tag != ANALYZER_HTTP ) return; if ( tag != ANALYZER_HTTP ) return;
if ( HTTP::disable_default_file_handle_provider ) return; set_file_handle(HTTP::get_file_handle(c, is_orig));
return_file_handle(HTTP::get_file_handle(c, is_orig));
} }

View file

@ -5,26 +5,20 @@
module IRC; module IRC;
export { export {
## Determines whether the default :bro:see:`get_file_handle` handler
## is used to return file handles to the file analysis framework.
## Redefine to true in order to provide a custom handler which overrides
## the default for IRC.
const disable_default_file_handle_provider: bool = F &redef;
## Default file handle provider for IRC. ## Default file handle provider for IRC.
function get_file_handle(c: connection, is_orig: bool): string global get_file_handle: function(c: connection, is_orig: bool): string;
{
if ( is_orig ) return "";
return fmt("%s %s %s", ANALYZER_IRC_DATA, c$start_time,
id_string(c$id));
}
} }
function get_file_handle(c: connection, is_orig: bool): string
{
if ( is_orig ) return "";
return fmt("%s %s %s", ANALYZER_IRC_DATA, c$start_time, id_string(c$id));
}
module GLOBAL; module GLOBAL;
event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool)
{ {
if ( tag != ANALYZER_IRC_DATA ) return; if ( tag != ANALYZER_IRC_DATA ) return;
if ( IRC::disable_default_file_handle_provider ) return; set_file_handle(IRC::get_file_handle(c, is_orig));
return_file_handle(IRC::get_file_handle(c, is_orig));
} }

View file

@ -6,27 +6,21 @@
module SMTP; module SMTP;
export { export {
## Determines whether the default :bro:see:`get_file_handle` handler
## is used to return file handles to the file analysis framework.
## Redefine to true in order to provide a custom handler which overrides
## the default for SMTP.
const disable_default_file_handle_provider: bool = F &redef;
## Default file handle provider for SMTP. ## Default file handle provider for SMTP.
function get_file_handle(c: connection, is_orig: bool): string global get_file_handle: function(c: connection, is_orig: bool): string;
{
if ( ! c?$smtp ) return "";
return fmt("%s %s %s %s", ANALYZER_SMTP, c$start_time,
c$smtp$trans_depth, c$smtp_state$mime_level);
}
} }
function get_file_handle(c: connection, is_orig: bool): string
{
if ( ! c?$smtp ) return "";
return fmt("%s %s %s %s", ANALYZER_SMTP, c$start_time,
c$smtp$trans_depth, c$smtp_state$mime_level);
}
module GLOBAL; module GLOBAL;
event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool)
{ {
if ( tag != ANALYZER_SMTP ) return; if ( tag != ANALYZER_SMTP ) return;
if ( SMTP::disable_default_file_handle_provider ) return; set_file_handle(SMTP::get_file_handle(c, is_orig));
return_file_handle(SMTP::get_file_handle(c, is_orig));
} }

View file

@ -452,7 +452,6 @@ set(bro_SRCS
file_analysis/Manager.cc file_analysis/Manager.cc
file_analysis/File.cc file_analysis/File.cc
file_analysis/FileTimer.cc file_analysis/FileTimer.cc
file_analysis/PendingFile.cc
file_analysis/FileID.h file_analysis/FileID.h
file_analysis/Action.h file_analysis/Action.h
file_analysis/ActionSet.cc file_analysis/ActionSet.cc

View file

@ -6,7 +6,6 @@
#include "Func.h" #include "Func.h"
#include "NetVar.h" #include "NetVar.h"
#include "Trigger.h" #include "Trigger.h"
#include "file_analysis/Manager.h"
EventMgr mgr; EventMgr mgr;
@ -111,6 +110,9 @@ void EventMgr::Dispatch()
void EventMgr::Drain() void EventMgr::Drain()
{ {
if ( event_queue_flush_point )
QueueEvent(event_queue_flush_point, new val_list());
SegmentProfiler(segment_logger, "draining-events"); SegmentProfiler(segment_logger, "draining-events");
draining = true; draining = true;
@ -125,8 +127,6 @@ void EventMgr::Drain()
// processing, we ensure that it's done at a regular basis by checking // processing, we ensure that it's done at a regular basis by checking
// them here. // them here.
Trigger::EvaluatePending(); Trigger::EvaluatePending();
file_mgr->EventDrainDone();
} }
void EventMgr::Describe(ODesc* d) const void EventMgr::Describe(ODesc* d) const

View file

@ -6981,12 +6981,15 @@ event reporter_error%(t: time, msg: string, location: string%) &error_handler;
## recursively for each ``@load``. ## recursively for each ``@load``.
event bro_script_loaded%(path: string, level: count%); event bro_script_loaded%(path: string, level: count%);
## Marks a point in the event stream at which the event queue started flushing.
event event_queue_flush_point%(%);
## This event is handled to provide feedback to the file analysis framework ## This event is handled to provide feedback to the file analysis framework
## about how to identify the logical "file" to which some data/input ## about how to identify the logical "file" to which some data/input
## belongs. All incoming data to the framework is buffered, and depends ## belongs. All incoming data to the framework is buffered, and depends
## on a handler for this event to return a string value that uniquely ## on a handler for this event to return a string value that uniquely
## identifies a file. Among all handlers of this event, exactly one must ## identifies a file. Among all handlers of this event, the last one to
## call :bro:see:`return_file_handle`. ## call :bro:see:`set_file_handle` will "win".
## ##
## tag: The analyzer which is carrying the file data. ## tag: The analyzer which is carrying the file data.
## ##
@ -6994,7 +6997,7 @@ event bro_script_loaded%(path: string, level: count%);
## ##
## is_orig: The direction the file data is flowing over the connection. ## is_orig: The direction the file data is flowing over the connection.
## ##
## .. bro:see:: return_file_handle ## .. bro:see:: set_file_handle
event get_file_handle%(tag: count, c: connection, is_orig: bool%); event get_file_handle%(tag: count, c: connection, is_orig: bool%);
# TODO: document # TODO: document

View file

@ -92,8 +92,8 @@ module GLOBAL;
## handle: A string that uniquely identifies a file. ## handle: A string that uniquely identifies a file.
## ##
## .. bro:see:: get_file_handle FileAnalysis::policy ## .. bro:see:: get_file_handle FileAnalysis::policy
function return_file_handle%(handle: string%): any function set_file_handle%(handle: string%): any
%{ %{
file_mgr->ReceiveHandle(handle->CheckString()); file_mgr->SetHandle(handle->CheckString());
return 0; return 0;
%} %}

View file

@ -47,7 +47,8 @@ bool DataEvent::DeliverChunk(const u_char* data, uint64 len, uint64 offset)
args->append(file->GetVal()->Ref()); args->append(file->GetVal()->Ref());
args->append(new StringVal(new BroString(data, len, 0))); args->append(new StringVal(new BroString(data, len, 0)));
args->append(new Val(offset, TYPE_COUNT)); args->append(new Val(offset, TYPE_COUNT));
mgr.Dispatch(new Event(chunk_event, args));
mgr.QueueEvent(chunk_event, args);
return true; return true;
} }
@ -59,7 +60,8 @@ bool DataEvent::DeliverStream(const u_char* data, uint64 len)
val_list* args = new val_list; val_list* args = new val_list;
args->append(file->GetVal()->Ref()); args->append(file->GetVal()->Ref());
args->append(new StringVal(new BroString(data, len, 0))); args->append(new StringVal(new BroString(data, len, 0)));
mgr.Dispatch(new Event(stream_event, args));
mgr.QueueEvent(stream_event, args);
return true; return true;
} }

View file

@ -267,7 +267,7 @@ void File::ReplayBOF()
DetectTypes(bs->Bytes(), bs->Len()); DetectTypes(bs->Bytes(), bs->Len());
file_mgr->FileEvent(file_new, this); file_mgr->FileEvent(file_new, this);
//mgr.Drain(); mgr.Drain(); // need immediate feedback about actions to add
for ( size_t i = 0; i < bof_buffer.chunks.size(); ++i ) for ( size_t i = 0; i < bof_buffer.chunks.size(); ++i )
DataIn(bof_buffer.chunks[i]->Bytes(), bof_buffer.chunks[i]->Len()); DataIn(bof_buffer.chunks[i]->Bytes(), bof_buffer.chunks[i]->Len());
@ -282,7 +282,7 @@ void File::DataIn(const u_char* data, uint64 len, uint64 offset)
// TODO: this should all really be delayed until we attempt reassembly // TODO: this should all really be delayed until we attempt reassembly
DetectTypes(data, len); DetectTypes(data, len);
file_mgr->FileEvent(file_new, this); file_mgr->FileEvent(file_new, this);
//mgr.Drain(); mgr.Drain(); // need immediate feedback about actions to add
actions.DrainModifications(); actions.DrainModifications();
first_chunk = false; first_chunk = false;
} }
@ -319,7 +319,7 @@ void File::DataIn(const u_char* data, uint64 len)
{ {
DetectTypes(data, len); DetectTypes(data, len);
file_mgr->FileEvent(file_new, this); file_mgr->FileEvent(file_new, this);
//mgr.Drain(); mgr.Drain(); // need immediate feedback about actions to add
actions.DrainModifications(); actions.DrainModifications();
missed_bof = false; missed_bof = false;
} }

View file

@ -48,5 +48,5 @@ void Hash::Finalize()
vl->append(new StringVal(kind)); vl->append(new StringVal(kind));
vl->append(hash->Get()); vl->append(hash->Get());
mgr.Dispatch(new Event(file_hash, vl)); mgr.QueueEvent(file_hash, vl);
} }

View file

@ -29,38 +29,18 @@ void Manager::Terminate()
Timeout(keys[i], true); Timeout(keys[i], true);
} }
void Manager::ReceiveHandle(const string& handle) void Manager::SetHandle(const string& handle)
{ {
if ( pending.empty() ) current_handle = handle;
reporter->InternalError("File analysis underflow");
PendingFile* pf = pending.front();
if ( ! handle.empty() )
pf->Finish(handle);
delete pf;
pending.pop();
}
void Manager::EventDrainDone()
{
if ( pending.empty() ) return;
reporter->Error("Too few return_file_handle() calls, discarding pending"
" file analysis input.");
while ( ! pending.empty() )
{
delete pending.front();
pending.pop();
}
} }
void Manager::DataIn(const u_char* data, uint64 len, uint64 offset, void Manager::DataIn(const u_char* data, uint64 len, uint64 offset,
AnalyzerTag::Tag tag, Connection* conn, bool is_orig) AnalyzerTag::Tag tag, Connection* conn, bool is_orig)
{ {
if ( IsDisabled(tag) ) return; if ( IsDisabled(tag) ) return;
if ( ! QueueHandleEvent(tag, conn, is_orig) ) return;
pending.push(new PendingDataInChunk(data, len, offset, tag, conn)); GetFileHandle(tag, conn, is_orig);
DataIn(data, len, offset, GetFile(current_handle, conn, tag));
} }
void Manager::DataIn(const u_char* data, uint64 len, uint64 offset, void Manager::DataIn(const u_char* data, uint64 len, uint64 offset,
@ -84,8 +64,8 @@ void Manager::DataIn(const u_char* data, uint64 len, AnalyzerTag::Tag tag,
Connection* conn, bool is_orig) Connection* conn, bool is_orig)
{ {
if ( IsDisabled(tag) ) return; if ( IsDisabled(tag) ) return;
if ( ! QueueHandleEvent(tag, conn, is_orig) ) return; GetFileHandle(tag, conn, is_orig);
pending.push(new PendingDataInStream(data, len, tag, conn)); DataIn(data, len, GetFile(current_handle, conn, tag));
} }
void Manager::DataIn(const u_char* data, uint64 len, const string& unique) void Manager::DataIn(const u_char* data, uint64 len, const string& unique)
@ -112,8 +92,9 @@ void Manager::EndOfFile(AnalyzerTag::Tag tag, Connection* conn)
void Manager::EndOfFile(AnalyzerTag::Tag tag, Connection* conn, bool is_orig) void Manager::EndOfFile(AnalyzerTag::Tag tag, Connection* conn, bool is_orig)
{ {
if ( IsDisabled(tag) ) return; if ( IsDisabled(tag) ) return;
if ( ! QueueHandleEvent(tag, conn, is_orig) ) return;
pending.push(new PendingEOF(tag, conn)); GetFileHandle(tag, conn, is_orig);
EndOfFile(current_handle);
} }
void Manager::EndOfFile(const string& unique) void Manager::EndOfFile(const string& unique)
@ -125,8 +106,9 @@ void Manager::Gap(uint64 offset, uint64 len, AnalyzerTag::Tag tag,
Connection* conn, bool is_orig) Connection* conn, bool is_orig)
{ {
if ( IsDisabled(tag) ) return; if ( IsDisabled(tag) ) return;
if ( ! QueueHandleEvent(tag, conn, is_orig) ) return;
pending.push(new PendingGap(offset, len, tag, conn)); GetFileHandle(tag, conn, is_orig);
Gap(offset, len, GetFile(current_handle, conn, tag));
} }
void Manager::Gap(uint64 offset, uint64 len, const string& unique) void Manager::Gap(uint64 offset, uint64 len, const string& unique)
@ -145,8 +127,9 @@ void Manager::SetSize(uint64 size, AnalyzerTag::Tag tag, Connection* conn,
bool is_orig) bool is_orig)
{ {
if ( IsDisabled(tag) ) return; if ( IsDisabled(tag) ) return;
if ( ! QueueHandleEvent(tag, conn, is_orig) ) return;
pending.push(new PendingSize(size, tag, conn)); GetFileHandle(tag, conn, is_orig);
SetSize(size, GetFile(current_handle, conn, tag));
} }
void Manager::SetSize(uint64 size, const string& unique) void Manager::SetSize(uint64 size, const string& unique)
@ -166,12 +149,13 @@ void Manager::SetSize(uint64 size, File* file)
void Manager::FileEvent(EventHandlerPtr h, File* file) void Manager::FileEvent(EventHandlerPtr h, File* file)
{ {
if ( IsIgnored(file->GetUnique()) ) return;
if ( ! h ) return; if ( ! h ) return;
if ( IsIgnored(file->GetUnique()) ) return;
val_list * vl = new val_list(); val_list * vl = new val_list();
vl->append(file->GetVal()->Ref()); vl->append(file->GetVal()->Ref());
mgr.Dispatch(new Event(h, vl));
mgr.QueueEvent(h, vl);
} }
bool Manager::PostponeTimeout(const FileID& file_id) const bool Manager::PostponeTimeout(const FileID& file_id) const
@ -205,6 +189,7 @@ bool Manager::RemoveAction(const FileID& file_id, const RecordVal* args) const
File* Manager::GetFile(const string& unique, Connection* conn, File* Manager::GetFile(const string& unique, Connection* conn,
AnalyzerTag::Tag tag) AnalyzerTag::Tag tag)
{ {
if ( unique.empty() ) return 0;
if ( IsIgnored(unique) ) return 0; if ( IsIgnored(unique) ) return 0;
File* rval = str_map[unique]; File* rval = str_map[unique];
@ -251,6 +236,7 @@ void Manager::Timeout(const FileID& file_id, bool is_terminating)
file->postpone_timeout = false; file->postpone_timeout = false;
FileEvent(file_timeout, file); FileEvent(file_timeout, file);
mgr.Drain(); // need immediate feedback about whether to postpone
if ( file->postpone_timeout && ! is_terminating ) if ( file->postpone_timeout && ! is_terminating )
{ {
@ -306,6 +292,21 @@ bool Manager::IsIgnored(const string& unique)
return ignored.find(unique) != ignored.end(); return ignored.find(unique) != ignored.end();
} }
void Manager::GetFileHandle(AnalyzerTag::Tag tag, Connection* c, bool is_orig)
{
current_handle.clear();
if ( ! get_file_handle ) return;
val_list* vl = new val_list();
vl->append(new Val(tag, TYPE_COUNT));
vl->append(c->BuildConnVal());
vl->append(new Val(is_orig, TYPE_BOOL));
mgr.QueueEvent(get_file_handle, vl);
mgr.Drain(); // need file handle immediately so we don't have to buffer data
}
bool Manager::IsDisabled(AnalyzerTag::Tag tag) bool Manager::IsDisabled(AnalyzerTag::Tag tag)
{ {
if ( ! disabled ) if ( ! disabled )
@ -322,17 +323,3 @@ bool Manager::IsDisabled(AnalyzerTag::Tag tag)
return rval; return rval;
} }
bool Manager::QueueHandleEvent(AnalyzerTag::Tag tag, Connection* conn,
bool is_orig)
{
if ( ! get_file_handle ) return false;
val_list* vl = new val_list();
vl->append(new Val(tag, TYPE_COUNT));
vl->append(conn->BuildConnVal());
vl->append(new Val(is_orig, TYPE_BOOL));
mgr.QueueEvent(get_file_handle, vl);
return true;
}

View file

@ -17,7 +17,6 @@
#include "File.h" #include "File.h"
#include "FileTimer.h" #include "FileTimer.h"
#include "FileID.h" #include "FileID.h"
#include "PendingFile.h"
namespace file_analysis { namespace file_analysis {
@ -26,7 +25,6 @@ namespace file_analysis {
*/ */
class Manager { class Manager {
friend class FileTimer; friend class FileTimer;
friend class PendingFile;
public: public:
@ -40,17 +38,9 @@ public:
void Terminate(); void Terminate();
/** /**
* Associates a handle with the next element in the #pending queue, which * Take in a unique file handle string to identifiy incoming file data.
* will immediately push that element all the way through the file analysis
* framework, possibly evaluating any policy hooks.
*/ */
void ReceiveHandle(const string& handle); void SetHandle(const string& handle);
/**
* Called when all events have been drained from the event queue.
* There should be no pending file input/data at this point.
*/
void EventDrainDone();
/** /**
* Pass in non-sequential file data. * Pass in non-sequential file data.
@ -121,7 +111,7 @@ public:
bool RemoveAction(const FileID& file_id, const RecordVal* args) const; bool RemoveAction(const FileID& file_id, const RecordVal* args) const;
/** /**
* Dispatches an event related to the file's life-cycle. * Queues an event related to the file's life-cycle.
*/ */
void FileEvent(EventHandlerPtr h, File* file); void FileEvent(EventHandlerPtr h, File* file);
@ -130,7 +120,6 @@ protected:
typedef map<string, File*> StrMap; typedef map<string, File*> StrMap;
typedef set<string> StrSet; typedef set<string> StrSet;
typedef map<FileID, File*> IDMap; typedef map<FileID, File*> IDMap;
typedef queue<PendingFile*> PendingQueue;
/** /**
* @return the File object mapped to \a unique or a null pointer if analysis * @return the File object mapped to \a unique or a null pointer if analysis
@ -165,22 +154,22 @@ protected:
*/ */
bool IsIgnored(const string& unique); bool IsIgnored(const string& unique);
/**
* Sets #current_handle to a unique file handle string based on what the
* \c get_file_handle event derives from the connection params. The
* event queue is flushed so that we can get the handle value immediately.
*/
void GetFileHandle(AnalyzerTag::Tag tag, Connection* c, bool is_orig);
/** /**
* @return whether file analysis is disabled for the given analyzer. * @return whether file analysis is disabled for the given analyzer.
*/ */
static bool IsDisabled(AnalyzerTag::Tag tag); static bool IsDisabled(AnalyzerTag::Tag tag);
/**
* Queues \c get_file_handle event in order to retrieve unique file handle.
* @return true if there is a handler for the event, else false.
*/
static bool QueueHandleEvent(AnalyzerTag::Tag tag, Connection* conn,
bool is_orig);
StrMap str_map; /**< Map unique string to file_analysis::File. */ StrMap str_map; /**< Map unique string to file_analysis::File. */
IDMap id_map; /**< Map file ID to file_analysis::File records. */ IDMap id_map; /**< Map file ID to file_analysis::File records. */
StrSet ignored; /**< Ignored files. Will be finally removed on EOF. */ StrSet ignored; /**< Ignored files. Will be finally removed on EOF. */
PendingQueue pending; /**< Files awaiting a unique handle. */ string current_handle; /**< Last file handle set by get_file_handle event.*/
static TableVal* disabled; /**< Table of disabled analyzers. */ static TableVal* disabled; /**< Table of disabled analyzers. */
}; };

View file

@ -1,111 +0,0 @@
#include "PendingFile.h"
#include "Manager.h"
using namespace file_analysis;
static void copy_data(const u_char** dst, const u_char* src, uint64 len)
{
u_char* tmp = new u_char[len];
memcpy(tmp, src, len);
*dst = tmp;
}
static string conn_str(Connection* c)
{
char op[256], rp[256];
modp_ulitoa10(ntohs(c->OrigPort()), op);
modp_ulitoa10(ntohs(c->RespPort()), rp);
string rval = c->OrigAddr().AsString() + ":" + op + "->" +
c->RespAddr().AsString() + ":" + rp;
return rval;
}
PendingFile::PendingFile(Connection* arg_conn, AnalyzerTag::Tag arg_tag)
: conn(arg_conn), tag(arg_tag)
{
Ref(conn);
DBG_LOG(DBG_FILE_ANALYSIS, "New pending file: %s", conn_str(conn).c_str());
}
PendingFile::~PendingFile()
{
Unref(conn);
DBG_LOG(DBG_FILE_ANALYSIS, "Delete pending file: %s",
conn_str(conn).c_str());
}
File* PendingFile::GetFile(const string& handle) const
{
return file_mgr->GetFile(handle, conn, tag);
}
PendingDataInChunk::PendingDataInChunk(const u_char* arg_data, uint64 arg_len,
uint64 arg_offset,
AnalyzerTag::Tag arg_tag,
Connection* arg_conn)
: PendingFile(arg_conn, arg_tag), len(arg_len),
offset(arg_offset)
{
copy_data(&data, arg_data, len);
}
void PendingDataInChunk::Finish(const string& handle) const
{
file_mgr->DataIn(data, len, offset, GetFile(handle));
}
PendingDataInChunk::~PendingDataInChunk()
{
delete [] data;
}
PendingDataInStream::PendingDataInStream(const u_char* arg_data, uint64 arg_len,
AnalyzerTag::Tag arg_tag,
Connection* arg_conn)
: PendingFile(arg_conn, arg_tag), len(arg_len)
{
copy_data(&data, arg_data, len);
}
void PendingDataInStream::Finish(const string& handle) const
{
file_mgr->DataIn(data, len, GetFile(handle));
}
PendingDataInStream::~PendingDataInStream()
{
delete [] data;
}
PendingGap::PendingGap(uint64 arg_offset, uint64 arg_len,
AnalyzerTag::Tag arg_tag, Connection* arg_conn)
: PendingFile(arg_conn, arg_tag), offset(arg_offset),
len(arg_len)
{
}
void PendingGap::Finish(const string& handle) const
{
file_mgr->Gap(offset, len, GetFile(handle));
}
PendingEOF::PendingEOF(AnalyzerTag::Tag arg_tag, Connection* arg_conn)
: PendingFile(arg_conn, arg_tag)
{
}
void PendingEOF::Finish(const string& handle) const
{
file_mgr->EndOfFile(handle);
}
PendingSize::PendingSize(uint64 arg_size, AnalyzerTag::Tag arg_tag,
Connection* arg_conn)
: PendingFile(arg_conn, arg_tag), size(arg_size)
{
}
void PendingSize::Finish(const string& handle) const
{
file_mgr->SetSize(size, GetFile(handle));
}

View file

@ -1,103 +0,0 @@
#ifndef FILE_ANALYSIS_PENDINGFILE_H
#define FILE_ANALYSIS_PENDINGFILE_H
#include "AnalyzerTags.h"
#include "Conn.h"
#include "File.h"
namespace file_analysis {
/**
* Provides buffering for file contents until the script-layer is able to
* return a unique file handle for it.
*/
class PendingFile {
public:
virtual ~PendingFile();
virtual void Finish(const string& handle) const = 0;
protected:
PendingFile(Connection* arg_conn,
AnalyzerTag::Tag arg_tag = AnalyzerTag::Error);
File* GetFile(const string& handle) const;
Connection* conn;
AnalyzerTag::Tag tag;
};
class PendingDataInChunk : public PendingFile {
public:
PendingDataInChunk(const u_char* arg_data, uint64 arg_len,
uint64 arg_offset, AnalyzerTag::Tag arg_tag,
Connection* arg_conn);
virtual ~PendingDataInChunk();
virtual void Finish(const string& handle) const;
protected:
const u_char* data;
uint64 len;
uint64 offset;
};
class PendingDataInStream : public PendingFile {
public:
PendingDataInStream(const u_char* arg_data, uint64 arg_len,
AnalyzerTag::Tag arg_tag, Connection* arg_conn);
virtual ~PendingDataInStream();
virtual void Finish(const string& handle) const;
protected:
const u_char* data;
uint64 len;
};
class PendingGap : public PendingFile {
public:
PendingGap(uint64 arg_offset, uint64 arg_len, AnalyzerTag::Tag arg_tag,
Connection* arg_conn);
virtual void Finish(const string& handle) const;
protected:
uint64 offset;
uint64 len;
};
class PendingEOF : public PendingFile {
public:
PendingEOF(AnalyzerTag::Tag arg_tag, Connection* arg_conn);
virtual void Finish(const string& handle) const;
};
class PendingSize : public PendingFile {
public:
PendingSize(uint64 arg_size, AnalyzerTag::Tag arg_tag,
Connection* arg_conn);
virtual void Finish(const string& handle) const;
protected:
uint64 size;
};
} // namespace file_analysis
#endif