Discussion:
text/html MIME filter with separate thread
(too old to reply)
Alexander
2008-07-01 13:52:01 UTC
Permalink
I am trying to implement text/html MIME filter. The problem is what filtering
algorithm is complex and I don't want to do filtering directly in ReportData
function. So I implemented the algorithm described below(using C++):

func IInternetProtocolSink::report_data {
if must_be_filtered {
create_thread(filter_thread);
return s_ok;
} else return sink->report_data();
}

func filter_thread {

CoInitializeEx(0, COINIT_MULTITHREADED);

do prot->read() until all is read;
filter_read_data();
sink->report_data();
sink->report_result();

}

When reportData return S_OK, IE remains active, displaying "loading"
progress in status string. But "report_data" being called from filter thread
results in only one "read" call. IE does not wake up, freezing in "loading
forever" state.

I tried another scheme:

func filter_thread {

CoInitializeEx(0, COINIT_MULTITHREADED);

do prot->read() until all is read;
filter_read_data();

PROTOCOLDATA pd;
pd.grfFlags = PD_FORCE_SWITCH;
pd.dwState = 1234;
pd.pData = 0;
pd.cbData = 0;
HRESULT hr;

hr = sink->Switch(&pd);

}

func IInternetProtocol::continue {

if from filter thread {
sink->report_data();
sink->report_result();
}

}

But IInternetProtocolSink::Switch returns E_FAIL!

Where is my fault? What I am doing wrong? Direct solution without a thread
works fine, but IE UI freezes(don't respond to mouse events) until
ReportData returns and it is unacceptable for me.

thanks.
Igor Tandetnik
2008-07-01 14:47:57 UTC
Permalink
Post by Alexander
When reportData return S_OK, IE remains active, displaying "loading"
progress in status string. But "report_data" being called from filter
thread results in only one "read" call.
What parameters are you passing when calling ReportData?

What are you returning from your implementation of
IInternetProtocol::Read? Make sure to fill the buffer with no more data
than the specified buffer size, and return S_OK if you have more data to
report, and S_FALSE otherwise.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Alexander
2008-07-02 08:54:03 UTC
Permalink
Post by Igor Tandetnik
What parameters are you passing when calling ReportData?
Here is the code being executed after filter thread having its job done:
(code is executed from filter thread!)

data.object->outgoing_prot_sink->ReportData
(BSCF_FIRSTDATANOTIFICATION |
BSCF_LASTDATANOTIFICATION |
BSCF_DATAFULLYAVAILABLE,
data.object->buffer.size(), data.object->buffer.size());

data.object->outgoing_prot_sink->ReportResult(S_OK, S_OK, NULL);


data.object->buffer is buffer with filtered data.

This results in one Read call, with 8196 bytes of data requested(total
amount is ~30000 bytes in my test case).

As far as I understand there must be the serie if reads, until my Read
handler return S_FALSE.
Post by Igor Tandetnik
What are you returning from your implementation of
IInternetProtocol::Read? Make sure to fill the buffer with no more data
than the specified buffer size, and return S_OK if you have more data to
report, and S_FALSE otherwise.
here is my Read implementation:

if(buffer_p < buffer.size()){
int to_read = (buffer.size() - buffer_p) <= cb ? (buffer.size() -
buffer_p) : cb;
copy(buffer.begin() + buffer_p , buffer.begin() + buffer_p + to_read,
(char*)pv);
buffer_p += to_read;
*pcbRead = to_read;
return buffer_p >= buffer.size() ? S_FALSE : S_OK;
} else {
return S_FALSE;
}
Igor Tandetnik
2008-07-02 12:07:38 UTC
Permalink
Post by Alexander
data.object->outgoing_prot_sink->ReportData
(BSCF_FIRSTDATANOTIFICATION |
BSCF_LASTDATANOTIFICATION |
BSCF_DATAFULLYAVAILABLE,
data.object->buffer.size(), data.object->buffer.size());
data.object->outgoing_prot_sink->ReportResult(S_OK, S_OK, NULL);
if(buffer_p < buffer.size()){
int to_read = (buffer.size() - buffer_p) <= cb ? (buffer.size() -
buffer_p) : cb;
copy(buffer.begin() + buffer_p , buffer.begin() + buffer_p + to_read,
(char*)pv);
buffer_p += to_read;
*pcbRead = to_read;
return buffer_p >= buffer.size() ? S_FALSE : S_OK;
} else {
return S_FALSE;
}
I don't see anything obviously wrong in your code (assuming buffer_p is
initialized to 0 at some point). If you have a small sample that
reproduces the problem, you can email it to me at ***@mvps.org,
I'll look at it.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Alexander
2008-07-04 16:51:00 UTC
Permalink
Igor, I have emailed you a simple project that illustrates my problem.
Post by Igor Tandetnik
I don't see anything obviously wrong in your code (assuming buffer_p is
initialized to 0 at some point). If you have a small sample that
I'll look at it.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Loading...