Rabbit Remote Control 0.1.0-bate10
Loading...
Searching...
No Matches
BackendFtpServer.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QSslSocket>
4#include <QLoggingCategory>
5#include "BackendFtpServer.h"
6#include "OperateFtpServer.h"
7#include "ParameterFtpServer.h"
8#include "Backend.h"
9
10static Q_LOGGING_CATEGORY(log, "Backend.FtpServer")
11CBackendFtpServer::CBackendFtpServer(COperateFtpServer* pOperate, bool bStopSignal)
12 : CBackendServer(pOperate, bStopSignal)
13 , m_pOperate(pOperate)
14 , m_pServer(nullptr)
15{
16 qDebug(log) << Q_FUNC_INFO;
17 m_pPara = m_pOperate->GetParameter();
18}
19
20CBackendFtpServer::~CBackendFtpServer()
21{
22 qDebug(log) << Q_FUNC_INFO;
23}
24
41CBackend::OnInitReturnValue CBackendFtpServer::OnInit()
42{
43 qDebug(log) << Q_FUNC_INFO;
44 if(m_pServer) {
45 qCritical(log) << "Server is exist";
46 return OnInitReturnValue::Fail;
47 }
48
49 m_Sockets.clear();
50
51 CSecurityLevel::Levels securityLevel;
52 QString szUser;
53 QString szPassword;
54 auto &net = m_pPara->m_Net;
55 if(!m_pPara->GetAnonymousLogin()) {
56 auto &user = net.m_User;
57 szUser = user.GetUser();
58 szPassword = user.GetPassword();
59 if(!szPassword.isEmpty())
60 securityLevel |= CSecurityLevel::Level::Authentication;
61 }
62
63 m_pServer = new CFtpServer(this, m_pPara->GetRoot(), net.GetPort(),
64 szUser, szPassword,
65 m_pPara->GetReadOnly());
66 if(!m_pServer) {
67 qCritical(log) << "Failed to new CFtpServer";
68 return OnInitReturnValue::Fail;
69 }
70
71 m_pServer->SetFilter(this);
72 bool bListen = false;
73 if(m_pPara->GetListenAll()) {
74 bListen = m_pServer->Listening();
75 if(bListen) {
76 QString szMsg = tr("Ftp server listen on all address port %1. the lan ip is %2")
77 .arg(net.GetPort()).arg(m_pServer->lanIp());
78 qInfo(log) << szMsg;
79 emit sigInformation(szMsg);
80 } else {
81 QString szErr = tr("Failed to Ftp server is listening on %1")
82 .arg(net.GetPort());
83 qCritical(log) << szErr;
84 emit sigError(-1, szErr);
85 return OnInitReturnValue::Fail;
86 }
87 } else {
88 QString szErr;
89 if(m_pPara->GetListen().isEmpty()) {
90 szErr = tr("Failed: Ftp server is not set to listen on any address");
91 qCritical(log) << szErr;
92 emit sigError(-1, szErr);
93 return OnInitReturnValue::Fail;
94 }
95 foreach (auto a, m_pPara->GetListen()) {
96 QHostAddress addr(a);
97 bListen = m_pServer->Listening(addr);
98 if(!bListen) {
99 szErr = tr("Failed to Ftp server is listening on %1:%2")
100 .arg(addr.toString()).arg(net.GetPort());
101 qCritical(log) << szErr;
102 emit sigError(-1, szErr);
103 return OnInitReturnValue::Fail;
104 }
105 if(!szErr.isEmpty())
106 szErr += "; ";
107 szErr += addr.toString() + ":" + QString::number(net.GetPort());
108 }
109 if(bListen) {
110 QString szMsg = tr("Ftp server is listening on ") + szErr;
111 qInfo(log) << szMsg;
112 emit sigInformation(szMsg);
113 }
114 }
115
116 emit sigSecurityLevel(securityLevel);
117 return OnInitReturnValue::NotUseOnProcess;
118}
119
121{
122 qDebug(log) << Q_FUNC_INFO;
123 if(m_pServer) {
124 delete m_pServer;
125 m_pServer = nullptr;
126 }
127 return 0;
128}
129
130bool CBackendFtpServer::onFilter(QSslSocket *socket)
131{
132 bool bFilte = false;
133 if(!socket) return true;
134 QString szIP = socket->peerAddress().toString();
135
136 auto& white = m_pPara->m_WhiteFilter;
137 auto& black = m_pPara->m_BlackFilter;
138
139 bool bInWhite = false;
140 if(!white.isEmpty()) {
141 white.OnProcess([&](const QString& szKey)->int {
142 QHostAddress addr(szIP);
143 auto sub = QHostAddress::parseSubnet(szKey);
144 if(addr.isInSubnet(sub.first, sub.second)) {
145 bInWhite = true;
146 return -1;
147 }
148 return 0;
149 }, true);
150 }
151
152 if(!bInWhite && !black.isEmpty()) {
153 black.OnProcess([&](const QString& szKey)->int {
154 QHostAddress addr(szIP);
155 auto sub = QHostAddress::parseSubnet(szKey);
156 if(addr.isInSubnet(sub.first, sub.second)) {
157 qInfo(log) << "Filtered" << szIP << "in blacklist";
158 bFilte = true;
159 return -1;
160 }
161 return 0;
162 }, true);
163 }
164
165 if(bFilte) return true;
166
167 if(m_pPara->GetConnectCount() >= 0 && m_pPara->GetConnectCount() <= m_Sockets.size()) {
168 qDebug(log) << "Exceeded the allowed number of connections:" << m_pPara->GetConnectCount();
169 return true;
170 }
171
172 bool check = false;
173 check = connect(socket, SIGNAL(disconnected()),
174 this, SLOT(slotDisconnected()));
175 Q_ASSERT(check);
176
177 quint16 port = socket->peerPort();
178 m_Sockets.append(socket);
179 emit sigConnected(szIP, port);
180 qDebug(log) << "Current connect count:" << m_Sockets.size()
181 << "; new connect from:" << szIP + ":" + QString::number(port);
182 return false;
183}
184
185void CBackendFtpServer::slotDisconnected()
186{
187 QSslSocket *socket = qobject_cast<QSslSocket*>(sender());
188 if(!socket) return;
189 m_Sockets.removeAll(socket);
190 QString ip = socket->peerAddress().toString();
191 quint16 port = socket->peerPort();
192 emit sigDisconnected(ip, port);
193 qDebug(log) << "Current connect count:" << m_Sockets.size()
194 << "; remove connect:" << socket->peerAddress().toString();
195}
196
197void CBackendFtpServer::slotDisconnect(const QString &szIp, const quint16 port)
198{
199 foreach (auto s, m_Sockets) {
200 if(s->peerAddress().toString() == szIp && s->peerPort() == port){
201 s->disconnectFromHost();
202 }
203 }
204}
virtual int OnClean() override
Clean.
virtual OnInitReturnValue OnInit() override
Initialization.
Server interface.
void sigConnected(const QString &szIp, const quint16 port)
emit when new client connected
void sigDisconnected(const QString &szIp, const quint16 port)
emit when the client disconnected
void sigInformation(const QString &szInfo)
Triggering from a background thread displays information in the main thread without blocking the back...
void sigError(const int nError, const QString &szError=QString())
Triggered when an error is generated.
void sigSecurityLevel(CSecurityLevel::Levels level)
Triggered when the security level changes.
CParameterUser m_User
[Instance user]
int GetConnectCount() const
Connect count.