🐞 fix(ftpserver): 修改被动模式端口号的分配方式
添加端口号区间,设置可重复绑定属性,使得端口号可控
This commit is contained in:
parent
2aa1c499d1
commit
e5ff70b22a
|
@ -6,6 +6,7 @@
|
|||
#include <map>
|
||||
#include <functional>
|
||||
#include <fstream>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "filesystem.h"
|
||||
|
||||
|
@ -13,6 +14,21 @@ namespace fineftp
|
|||
{
|
||||
|
||||
const std::string DEVICEID_FILE_LOACLPATH = getenv("HOME") + std::string("/.connectivitycache/DeviceId");
|
||||
const int MAX_PORT_NUM = 6;
|
||||
const unsigned short INITIAL_PORT = 27193;
|
||||
|
||||
std::queue<unsigned short> FtpSession::s_freePorts = FtpSession::initPortQueue();
|
||||
|
||||
std::queue<unsigned short> FtpSession::initPortQueue()
|
||||
{
|
||||
std::queue<unsigned short> freePorts;
|
||||
for (int i = 0; i < MAX_PORT_NUM; i++) {
|
||||
freePorts.push(INITIAL_PORT + i);
|
||||
}
|
||||
|
||||
return freePorts;
|
||||
}
|
||||
|
||||
|
||||
FtpSession::FtpSession(asio::io_service &io_service, const UserDatabase &user_database,
|
||||
const std::function<void()> &completion_handler)
|
||||
|
@ -313,39 +329,56 @@ void FtpSession::handleFtpCommandPASV(const std::string & /*param*/)
|
|||
}
|
||||
}
|
||||
|
||||
asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), 0);
|
||||
|
||||
{
|
||||
asio::error_code ec;
|
||||
data_acceptor_.open(endpoint.protocol(), ec);
|
||||
if (ec) {
|
||||
std::cerr << "Error opening data acceptor: " << ec.message() << std::endl;
|
||||
sendFtpMessage(FtpReplyCode::SERVICE_NOT_AVAILABLE, "Failed to enter passive mode.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
asio::error_code ec;
|
||||
data_acceptor_.bind(endpoint);
|
||||
if (ec) {
|
||||
std::cerr << "Error binding data acceptor: " << ec.message() << std::endl;
|
||||
sendFtpMessage(FtpReplyCode::SERVICE_NOT_AVAILABLE, "Failed to enter passive mode.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
asio::error_code ec;
|
||||
data_acceptor_.listen(asio::socket_base::max_connections, ec);
|
||||
if (ec) {
|
||||
std::cerr << "Error listening on data acceptor: " << ec.message() << std::endl;
|
||||
sendFtpMessage(FtpReplyCode::SERVICE_NOT_AVAILABLE, "Failed to enter passive mode.");
|
||||
return;
|
||||
if (!s_freePorts.empty()) {
|
||||
m_currentPort = s_freePorts.front();
|
||||
s_freePorts.pop();
|
||||
try {
|
||||
asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), m_currentPort);
|
||||
{
|
||||
asio::error_code ec;
|
||||
data_acceptor_.open(endpoint.protocol(), ec);
|
||||
if (ec) {
|
||||
std::cerr << "Error opening data acceptor: " << ec.message() << std::endl;
|
||||
sendFtpMessage(FtpReplyCode::SERVICE_NOT_AVAILABLE, "Failed to enter passive mode.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
data_acceptor_.set_option(asio::ip::tcp::acceptor::reuse_address(true));
|
||||
{
|
||||
asio::error_code ec;
|
||||
data_acceptor_.bind(endpoint);
|
||||
if (ec) {
|
||||
std::cerr << "Error binding data acceptor: " << ec.message() << std::endl;
|
||||
sendFtpMessage(FtpReplyCode::SERVICE_NOT_AVAILABLE, "Failed to enter passive mode.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
asio::error_code ec;
|
||||
data_acceptor_.listen(asio::socket_base::max_connections, ec);
|
||||
if (ec) {
|
||||
std::cerr << "Error listening on data acceptor: " << ec.message() << std::endl;
|
||||
sendFtpMessage(FtpReplyCode::SERVICE_NOT_AVAILABLE, "Failed to enter passive mode.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (std::exception &_e) {
|
||||
#ifndef NDEBUG
|
||||
std::cout << _e.what() << std::endl;
|
||||
#endif
|
||||
s_freePorts.push(m_currentPort);
|
||||
handleFtpCommandPASV("PASV");
|
||||
}
|
||||
} else {
|
||||
#ifndef NDEBUG
|
||||
std::cerr << "More than the maximum number of ports that can be allocated." << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// Split address and port into bytes and get the port the OS chose for us
|
||||
auto ip_bytes = command_socket_.local_endpoint().address().to_v4().to_bytes();
|
||||
auto port = data_acceptor_.local_endpoint().port();
|
||||
// auto port = data_acceptor_.local_endpoint().port();
|
||||
|
||||
std::ifstream file;
|
||||
|
||||
|
@ -356,8 +389,8 @@ void FtpSession::handleFtpCommandPASV(const std::string & /*param*/)
|
|||
getline(file, deviceId);
|
||||
std::cout << deviceId << std::endl;
|
||||
if (!deviceId.empty()) {
|
||||
std::string common = std::string("adb -s ") + deviceId + std::string(" reverse tcp:") + std::to_string(port)
|
||||
+ std::string(" tcp:") + std::to_string(port);
|
||||
std::string common = std::string("adb -s ") + deviceId + std::string(" reverse tcp:")
|
||||
+ std::to_string(m_currentPort) + std::string(" tcp:") + std::to_string(m_currentPort);
|
||||
system(common.c_str());
|
||||
}
|
||||
}
|
||||
|
@ -369,9 +402,10 @@ void FtpSession::handleFtpCommandPASV(const std::string & /*param*/)
|
|||
for (size_t i = 0; i < 4; i++) {
|
||||
stream << static_cast<int>(ip_bytes[i]) << ",";
|
||||
}
|
||||
stream << ((port >> 8) & 0xff) << "," << (port & 0xff) << ")";
|
||||
stream << ((m_currentPort >> 8) & 0xff) << "," << (m_currentPort & 0xff) << ")";
|
||||
|
||||
sendFtpMessage(FtpReplyCode::ENTERING_PASSIVE_MODE, "Entering passive mode " + stream.str());
|
||||
|
||||
return;
|
||||
} // namespace fineftp
|
||||
|
||||
|
@ -1053,7 +1087,8 @@ void FtpSession::addDataToBufferAndSend(std::shared_ptr<std::vector<char>> data,
|
|||
void FtpSession::writeDataToSocket(std::shared_ptr<asio::ip::tcp::socket> data_socket,
|
||||
std::function<void(void)> fetch_more)
|
||||
{
|
||||
data_buffer_strand_.post([me = shared_from_this(), data_socket, fetch_more]() {
|
||||
auto port = m_currentPort;
|
||||
data_buffer_strand_.post([me = shared_from_this(), data_socket, fetch_more, port]() {
|
||||
auto data = me->data_buffer_.front();
|
||||
|
||||
if (data) {
|
||||
|
@ -1078,6 +1113,9 @@ void FtpSession::writeDataToSocket(std::shared_ptr<asio::ip::tcp::socket> data_s
|
|||
// we got to the end of transmission
|
||||
me->data_buffer_.pop_front();
|
||||
me->sendFtpMessage(FtpReplyCode::CLOSING_DATA_CONNECTION, "Done");
|
||||
s_freePorts.push(port);
|
||||
data_socket->close();
|
||||
// delete data_socket;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <asio.hpp>
|
||||
|
||||
#include <deque>
|
||||
#include <queue>
|
||||
#include <fstream>
|
||||
|
||||
#include "ftp_message.h"
|
||||
|
@ -59,6 +60,8 @@ private:
|
|||
|
||||
void handleFtpCommand(const std::string &command);
|
||||
|
||||
static std::queue<unsigned short> initPortQueue();
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// FTP Commands
|
||||
////////////////////////////////////////////////////////
|
||||
|
@ -199,5 +202,9 @@ private:
|
|||
|
||||
// Current state
|
||||
std::string ftp_working_directory_;
|
||||
|
||||
unsigned short m_currentPort;
|
||||
|
||||
static std::queue<unsigned short> s_freePorts;
|
||||
};
|
||||
} // namespace fineftp
|
||||
|
|
Loading…
Reference in New Issue