Split CTCPListener from CListener

This splits up CListener into a TCP-specific class and a general class.
The intention is to later add another class inheriting from CListener
that listens on unix sockets.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter
2017-01-12 10:45:54 +01:00
parent b68fbc64a2
commit 35da5784ca
5 changed files with 93 additions and 55 deletions
+33 -15
View File
@@ -29,27 +29,19 @@ class CListener {
public:
typedef enum { ACCEPT_IRC, ACCEPT_HTTP, ACCEPT_ALL } EAcceptType;
CListener(unsigned short uPort, const CString& sBindHost,
const CString& sURIPrefix, bool bSSL, EAddrType eAddr,
EAcceptType eAccept)
CListener(const CString& sURIPrefix, bool bSSL, EAcceptType eAccept)
: m_bSSL(bSSL),
m_eAddr(eAddr),
m_uPort(uPort),
m_sBindHost(sBindHost),
m_sURIPrefix(sURIPrefix),
m_pListener(nullptr),
m_eAcceptType(eAccept) {}
~CListener();
virtual ~CListener();
CListener(const CListener&) = delete;
CListener& operator=(const CListener&) = delete;
// Getters
bool IsSSL() const { return m_bSSL; }
EAddrType GetAddrType() const { return m_eAddr; }
unsigned short GetPort() const { return m_uPort; }
const CString& GetBindHost() const { return m_sBindHost; }
CRealListener* GetRealListener() const { return m_pListener; }
const CString& GetURIPrefix() const { return m_sURIPrefix; }
EAcceptType GetAcceptType() const { return m_eAcceptType; }
@@ -59,21 +51,47 @@ class CListener {
// except this one, so don't add other setters!
void SetAcceptType(EAcceptType eType) { m_eAcceptType = eType; }
bool Listen();
virtual bool Listen() = 0;
void ResetRealListener();
CConfig ToConfig() const;
virtual CConfig ToConfig() const = 0;
private:
protected:
bool m_bSSL;
EAddrType m_eAddr;
unsigned short m_uPort;
CString m_sBindHost;
CString m_sURIPrefix;
CRealListener* m_pListener;
EAcceptType m_eAcceptType;
};
class CTCPListener : public CListener {
public:
CTCPListener(unsigned short uPort, const CString& sBindHost,
const CString& sURIPrefix, bool bSSL, EAddrType eAddr,
EAcceptType eAccept)
: CListener(sURIPrefix, bSSL, eAccept),
m_eAddr(eAddr),
m_uPort(uPort),
m_sBindHost(sBindHost) {}
~CTCPListener();
CTCPListener(const CTCPListener&) = delete;
CTCPListener& operator=(const CTCPListener&) = delete;
// Getters
EAddrType GetAddrType() const { return m_eAddr; }
unsigned short GetPort() const { return m_uPort; }
const CString& GetBindHost() const { return m_sBindHost; }
// !Getters
bool Listen() override;
CConfig ToConfig() const override;
protected:
EAddrType m_eAddr;
unsigned short m_uPort;
CString m_sBindHost;
};
class CRealListener : public CZNCSock {
public:
CRealListener(CListener& listener) : CZNCSock(), m_Listener(listener) {}
+29 -22
View File
@@ -161,7 +161,7 @@ class CWebAdminMod : public CModule {
}
// Now turn that into a listener instance
CListener* pListener = new CListener(
CListener* pListener = new CTCPListener(
uPort, sListenHost, sURIPrefix, bSSL,
(!bIPv6 ? ADDR_IPV4ONLY : ADDR_ALL), CListener::ACCEPT_HTTP);
@@ -1883,8 +1883,18 @@ class CWebAdminMod : public CModule {
for (const CListener* pListener : vpListeners) {
CTemplate& l = Tmpl.AddRow("ListenLoop");
l["Port"] = CString(pListener->GetPort());
l["BindHost"] = pListener->GetBindHost();
const CTCPListener* pTCPListener = dynamic_cast<const CTCPListener*>(pListener);
if (pTCPListener != nullptr) {
l["Port"] = CString(pTCPListener->GetPort());
l["BindHost"] = pTCPListener->GetBindHost();
// simple protection for user from shooting his own foot
// TODO check also for hosts/families
// such check is only here, user still can forge HTTP request to
// delete web port
l["SuggestDeletion"] =
CString(pTCPListener->GetPort() != WebSock.GetLocalPort());
}
l["IsHTTP"] = CString(pListener->GetAcceptType() !=
CListener::ACCEPT_IRC);
@@ -1893,13 +1903,6 @@ class CWebAdminMod : public CModule {
l["URIPrefix"] = pListener->GetURIPrefix() + "/";
// simple protection for user from shooting his own foot
// TODO check also for hosts/families
// such check is only here, user still can forge HTTP request to
// delete web port
l["SuggestDeletion"] =
CString(pListener->GetPort() != WebSock.GetLocalPort());
#ifdef HAVE_LIBSSL
if (pListener->IsSSL()) {
l["IsSSL"] = "true";
@@ -1907,20 +1910,24 @@ class CWebAdminMod : public CModule {
#endif
#ifdef HAVE_IPV6
switch (pListener->GetAddrType()) {
case ADDR_IPV4ONLY:
l["IsIPV4"] = "true";
break;
case ADDR_IPV6ONLY:
l["IsIPV6"] = "true";
break;
case ADDR_ALL:
l["IsIPV4"] = "true";
l["IsIPV6"] = "true";
break;
if (pTCPListener != nullptr) {
switch (pTCPListener->GetAddrType()) {
case ADDR_IPV4ONLY:
l["IsIPV4"] = "true";
break;
case ADDR_IPV6ONLY:
l["IsIPV6"] = "true";
break;
case ADDR_ALL:
l["IsIPV4"] = "true";
l["IsIPV6"] = "true";
break;
}
}
#else
l["IsIPV4"] = "true";
if (pTCPListener != nullptr) {
l["IsIPV4"] = "true";
}
#endif
}
+19 -11
View File
@@ -1543,17 +1543,25 @@ void CClient::UserPortCommand(CString& sLine) {
for (const CListener* pListener : vpListeners) {
Table.AddRow();
Table.SetCell("Port", CString(pListener->GetPort()));
Table.SetCell("BindHost", (pListener->GetBindHost().empty()
? CString("*")
: pListener->GetBindHost()));
Table.SetCell("SSL", CString(pListener->IsSSL()));
EAddrType eAddr = pListener->GetAddrType();
Table.SetCell("Proto",
(eAddr == ADDR_ALL
? "All"
: (eAddr == ADDR_IPV4ONLY ? "IPv4" : "IPv6")));
const CTCPListener* pTCPListener = dynamic_cast<const CTCPListener*>(pListener);
if (pTCPListener != nullptr) {
Table.SetCell("Port", CString(pTCPListener->GetPort()));
Table.SetCell("BindHost", (pTCPListener->GetBindHost().empty()
? CString("*")
: pTCPListener->GetBindHost()));
EAddrType eAddr = pTCPListener->GetAddrType();
Table.SetCell("Proto",
(eAddr == ADDR_ALL
? "All"
: (eAddr == ADDR_IPV4ONLY ? "IPv4" : "IPv6")));
} else {
Table.SetCell("Port", "unknown");
}
Table.SetCell("SSL", CString(pListener->IsSSL()));
CListener::EAcceptType eAccept = pListener->GetAcceptType();
Table.SetCell(
@@ -1608,7 +1616,7 @@ void CClient::UserPortCommand(CString& sLine) {
const CString sBindHost = sLine.Token(4);
const CString sURIPrefix = sLine.Token(5);
CListener* pListener = new CListener(uPort, sBindHost, sURIPrefix,
CListener* pListener = new CTCPListener(uPort, sBindHost, sURIPrefix,
bSSL, eAddr, eAccept);
if (!pListener->Listen()) {
+5 -2
View File
@@ -22,7 +22,10 @@ CListener::~CListener() {
if (m_pListener) CZNC::Get().GetManager().DelSockByAddr(m_pListener);
}
bool CListener::Listen() {
CTCPListener::~CTCPListener() {
}
bool CTCPListener::Listen() {
if (!m_uPort || m_pListener) {
errno = EINVAL;
return false;
@@ -49,7 +52,7 @@ bool CListener::Listen() {
m_pListener, 0, m_eAddr);
}
CConfig CListener::ToConfig() const {
CConfig CTCPListener::ToConfig() const {
CConfig listenerConfig;
listenerConfig.AddKeyValuePair("Host", GetBindHost());
+7 -5
View File
@@ -669,7 +669,7 @@ bool CZNC::WriteNewConfig(const CString& sConfigFile) {
// Don't ask for listen host, it may be configured later if needed.
CUtils::PrintAction("Verifying the listener");
CListener* pListener = new CListener(
CListener* pListener = new CTCPListener(
(unsigned short int)uListenPort, sListenHost, sURIPrefix,
bListenSSL, b6 ? ADDR_ALL : ADDR_IPV4ONLY, CListener::ACCEPT_ALL);
if (!pListener->Listen()) {
@@ -1568,9 +1568,11 @@ bool CZNC::AddUser(CUser* pUser, CString& sErrorRet, bool bStartup) {
CListener* CZNC::FindListener(u_short uPort, const CString& sBindHost,
EAddrType eAddr) {
for (CListener* pListener : m_vpListeners) {
if (pListener->GetPort() != uPort) continue;
if (pListener->GetBindHost() != sBindHost) continue;
if (pListener->GetAddrType() != eAddr) continue;
CTCPListener* pTCPListener = dynamic_cast<CTCPListener*>(pListener);
if (!pTCPListener) continue;
if (pTCPListener->GetPort() != uPort) continue;
if (pTCPListener->GetBindHost() != sBindHost) continue;
if (pTCPListener->GetAddrType() != eAddr) continue;
return pListener;
}
return nullptr;
@@ -1700,7 +1702,7 @@ bool CZNC::AddListener(unsigned short uPort, const CString& sBindHost,
}
CListener* pListener =
new CListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept);
new CTCPListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept);
if (!pListener->Listen()) {
sError = FormatBindError();