基于前面两篇及B站上大牛小方的解析视频:
【1】【Filezilla】 dispatch函数重载的例子-CSDN博客
【2】【C++】【FileZilla】事件调用机制代码解析-CSDN博客
当线程entry()调用process_event()时,通过语句 (*std::get<0>(ev0))(*std::get<1>(ev0))调用operator 方法,当元组 ev0 的第零个元素 event_handler 类型匹配 CSftpControlSocket 时,语句调用重载的 CSftpControlSocket::operator() ,元组 ev0 的第一个元素 event_base 作为形参 ev传入operator(参考【2】),而当 ev 的实际类型匹配 CSftpEvent 时,实际调用下面重载的分发方法中的CSftpControlSocket::OnSftpEvent(参考【1】)。元组 ev 第零个元素的实际类型还有可能是 process_event, CCommandEvent等。
// In event_loop.hpp
typedef std::deque<std::tuple<event_handler*, event_base*, bool>> Events;
// Events::value_type ev{};
// In sftpcontrolsocket.cpp
void CSftpControlSocket::operator()(fz::event_base const& ev)
{
if (fz::dispatch<fz::process_event, CSftpEvent, CSftpListEvent, SftpRateAvailableEvent>(ev, this,
&CSftpControlSocket::OnProcessEvent,
&CSftpControlSocket::OnSftpEvent,
&CSftpControlSocket::OnSftpListEvent,
&CSftpControlSocket::OnQuotaRequest)) {
return;
}
CControlSocket::operator()(ev);
}
关注CSftpControlSocket::OnSftpEvent()方法:
void CSftpControlSocket::OnSftpEvent(sftp_message const& message)
{
......
switch (message.type)
{
......
case sftpEvent::Recv:......break;
case sftpEvent::Send:......break;
case sftpEvent::Transfer:......break;
case sftpEvent::io_nextbuf:
if (!operations_.empty() && operations_.back()->opId == Command::transfer) {
auto & data = static_cast<CSftpFileTransferOpData&>(*operations_.back());
data.OnNextBufferRequested(fz::to_integral<uint64_t>(message.text[0]));
}
break;
case sftpEvent::io_open:
if (!operations_.empty() && operations_.back()->opId == Command::transfer) {
auto & data = static_cast<CSftpFileTransferOpData&>(*operations_.back());
data.OnOpenRequested(fz::to_integral<uint64_t>(message.text[0]));
}
break;
case sftpEvent::io_size:
if (!operations_.empty() && operations_.back()->opId == Command::transfer) {
auto & data = static_cast<CSftpFileTransferOpData&>(*operations_.back());
data.OnSizeRequested();
}
break;
case sftpEvent::io_finalize:
if (!operations_.empty() && operations_.back()->opId == Command::transfer) {
auto & data = static_cast<CSftpFileTransferOpData&>(*operations_.back());
data.OnFinalizeRequested(fz::to_integral<uint64_t>(message.text[0]));
}
break;
default:......
}
......
}
可以注意到其中 case sftpEvent::io_nextbuf 处理了数据的传输。
- 上传:std::tie(r, buffer_) = reader_->get_buffer(*this);
- 下载:auto r = writer_->add_buffer(std::move(buffer_), *this);
void CSftpFileTransferOpData::OnNextBufferRequested(uint64_t processed)
{
if (reader_) {
fz::aio_result r;
std::tie(r, buffer_) = reader_->get_buffer(*this);
if (r == fz::aio_result::wait) {
return;
}
if (r == fz::aio_result::error) {
controlSocket_.AddToSendBuffer("--1\n");
return;
}
if (buffer_->size()) {
controlSocket_.AddToSendBuffer(fz::sprintf("-%d %d\n", buffer_->get() - base_address_, buffer_->size()));
}
else {
controlSocket_.AddToSendBuffer(fz::sprintf("-0\n"));
}
}
else if (writer_) {
buffer_->resize(processed);
auto r = writer_->add_buffer(std::move(buffer_), *this);
if (r == fz::aio_result::ok) {
buffer_ = controlSocket_.buffer_pool_->get_buffer(*this);
if (!buffer_) {
r = fz::aio_result::wait;
}
}
if (r == fz::aio_result::wait) {
return;
}
if (r == fz::aio_result::error) {
controlSocket_.AddToSendBuffer("--1\n");
return;
}
controlSocket_.AddToSendBuffer(fz::sprintf("-%d %d\n", buffer_->get() - base_address_, buffer_->capacity()));
}
else {
controlSocket_.AddToSendBuffer("--1\n");
return;
}
}