玉兔远程控制 0.1.0-bate11
载入中...
搜索中...
未找到
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
26{
27 return 0;
28}
29
46CBackend::OnInitReturnValue CBackendFtpServer::OnInit()
47{
48 qDebug(log) << Q_FUNC_INFO;
49 if(m_pServer) {
50 qCritical(log) << "Server is exist";
51 return OnInitReturnValue::Fail;
52 }
53
54 m_Sockets.clear();
55
56 CSecurityLevel::Levels securityLevel;
57 QString szUser;
58 QString szPassword;
59 auto &net = m_pPara->m_Net;
60 if(!m_pPara->GetAnonymousLogin()) {
61 auto &user = net.m_User;
62 szUser = user.GetUser();
63 szPassword = user.GetPassword();
64 if(!szPassword.isEmpty())
65 securityLevel |= CSecurityLevel::Level::Authentication;
66 }
67
68 m_pServer = new CFtpServer(this, m_pPara->GetRoot(), net.GetPort(),
69 szUser, szPassword,
70 m_pPara->GetReadOnly());
71 if(!m_pServer) {
72 qCritical(log) << "Failed to new CFtpServer";
73 return OnInitReturnValue::Fail;
74 }
75
76 m_pServer->SetFilter(this);
77 bool bListen = false;
78 if(m_pPara->GetListenAll()) {
79 bListen = m_pServer->Listening();
80 if(bListen) {
81 QString szMsg = tr("Ftp server listen on all address port %1. the lan ip is %2")
82 .arg(net.GetPort()).arg(m_pServer->lanIp());
83 qInfo(log) << szMsg;
84 emit sigInformation(szMsg);
85 } else {
86 QString szErr = tr("Failed to Ftp server is listening on %1")
87 .arg(net.GetPort());
88 qCritical(log) << szErr;
89 emit sigError(-1, szErr);
90 return OnInitReturnValue::Fail;
91 }
92 } else {
93 QString szErr;
94 if(m_pPara->GetListen().isEmpty()) {
95 szErr = tr("Failed: Ftp server is not set to listen on any address");
96 qCritical(log) << szErr;
97 emit sigError(-1, szErr);
98 return OnInitReturnValue::Fail;
99 }
100 foreach (auto a, m_pPara->GetListen()) {
101 QHostAddress addr(a);
102 bListen = m_pServer->Listening(addr);
103 if(!bListen) {
104 szErr = tr("Failed to Ftp server is listening on %1:%2")
105 .arg(addr.toString()).arg(net.GetPort());
106 qCritical(log) << szErr;
107 emit sigError(-1, szErr);
108 return OnInitReturnValue::Fail;
109 }
110 if(!szErr.isEmpty())
111 szErr += "; ";
112 szErr += addr.toString() + ":" + QString::number(net.GetPort());
113 }
114 if(bListen) {
115 QString szMsg = tr("Ftp server is listening on ") + szErr;
116 qInfo(log) << szMsg;
117 emit sigInformation(szMsg);
118 }
119 }
120
121 emit sigSecurityLevel(securityLevel);
122 return OnInitReturnValue::NotUseOnProcess;
123}
124
126{
127 qDebug(log) << Q_FUNC_INFO;
128 if(m_pServer) {
129 delete m_pServer;
130 m_pServer = nullptr;
131 }
132 return 0;
133}
134
135bool CBackendFtpServer::onFilter(QSslSocket *socket)
136{
137 bool bFilte = false;
138 if(!socket) return true;
139 QString szIP = socket->peerAddress().toString();
140
141 auto& white = m_pPara->m_WhiteFilter;
142 auto& black = m_pPara->m_BlackFilter;
143
144 bool bInWhite = false;
145 if(!white.isEmpty()) {
146 white.OnProcess([&](const QString& szKey)->int {
147 QHostAddress addr(szIP);
148 auto sub = QHostAddress::parseSubnet(szKey);
149 if(addr.isInSubnet(sub.first, sub.second)) {
150 bInWhite = true;
151 return -1;
152 }
153 return 0;
154 }, true);
155 }
156
157 if(!bInWhite && !black.isEmpty()) {
158 black.OnProcess([&](const QString& szKey)->int {
159 QHostAddress addr(szIP);
160 auto sub = QHostAddress::parseSubnet(szKey);
161 if(addr.isInSubnet(sub.first, sub.second)) {
162 qInfo(log) << "Filtered" << szIP << "in blacklist";
163 bFilte = true;
164 return -1;
165 }
166 return 0;
167 }, true);
168 }
169
170 if(bFilte) return true;
171
172 if(m_pPara->GetConnectCount() >= 0 && m_pPara->GetConnectCount() <= m_Sockets.size()) {
173 qDebug(log) << "Exceeded the allowed number of connections:" << m_pPara->GetConnectCount();
174 return true;
175 }
176
177 bool check = false;
178 check = connect(socket, SIGNAL(disconnected()),
179 this, SLOT(slotDisconnected()));
180 Q_ASSERT(check);
181
182 quint16 port = socket->peerPort();
183 m_Sockets.append(socket);
184 emit sigConnected(szIP, port);
185 qDebug(log) << "Current connect count:" << m_Sockets.size()
186 << "; new connect from:" << szIP + ":" + QString::number(port);
187 return false;
188}
189
190void CBackendFtpServer::slotDisconnected()
191{
192 QSslSocket *socket = qobject_cast<QSslSocket*>(sender());
193 if(!socket) return;
194 m_Sockets.removeAll(socket);
195 QString ip = socket->peerAddress().toString();
196 quint16 port = socket->peerPort();
197 emit sigDisconnected(ip, port);
198 qDebug(log) << "Current connect count:" << m_Sockets.size()
199 << "; remove connect:" << socket->peerAddress().toString();
200}
201
202void CBackendFtpServer::slotDisconnect(const QString &szIp, const quint16 port)
203{
204 foreach (auto s, m_Sockets) {
205 if(s->peerAddress().toString() == szIp && s->peerPort() == port){
206 s->disconnectFromHost();
207 }
208 }
209}
virtual int OnClean() override
清理
virtual OnInitReturnValue OnInit() override
初始化
virtual int WakeUp() override
唤醒后台线程。
服务接口。它由协议插件实现。
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)
从后台线程中触发在主线程中显示信息,不阻塞后台线程
void sigError(const int nError, const QString &szError=QString())
当有错误产生时触发
void sigSecurityLevel(CSecurityLevel::Levels level)
当安全级别改变时触发