lib/net: Simplify handling of socket multiplexer jobs

This commit is contained in:
Povilas Kanapickas 2021-11-01 06:16:34 +02:00
parent d2c106db53
commit d7de571fdc
5 changed files with 60 additions and 89 deletions

View File

@ -20,7 +20,7 @@
#include "SecureSocket.h"
#include "net/NetworkAddress.h"
#include "net/SocketMultiplexer.h"
#include "net/TSocketMultiplexerMethodJob.h"
#include "arch/Arch.h"
#include "arch/XArch.h"
#include "common/DataDirectories.h"
#include "base/String.h"

View File

@ -140,16 +140,16 @@ std::unique_ptr<ISocketMultiplexerJob> SecureSocket::newJob()
void
SecureSocket::secureConnect()
{
setJob(std::make_unique<TSocketMultiplexerMethodJob<SecureSocket>>(
this, &SecureSocket::serviceConnect,
setJob(std::make_unique<TSocketMultiplexerMethodJob>([this](auto j, auto r, auto w, auto e)
{ return serviceConnect(j, r, w, e); },
getSocket(), isReadable(), isWritable()));
}
void
SecureSocket::secureAccept()
{
setJob(std::make_unique<TSocketMultiplexerMethodJob<SecureSocket>>(
this, &SecureSocket::serviceAccept,
setJob(std::make_unique<TSocketMultiplexerMethodJob>([this](auto j, auto r, auto w, auto e)
{ return serviceAccept(j, r, w, e); },
getSocket(), isReadable(), isWritable()));
}
@ -772,8 +772,8 @@ MultiplexerJobStatus SecureSocket::serviceConnect(ISocketMultiplexerJob* job,
// Retry case
return {
true,
std::make_unique<TSocketMultiplexerMethodJob<SecureSocket>>(
this, &SecureSocket::serviceConnect,
std::make_unique<TSocketMultiplexerMethodJob>([this](auto j, auto r, auto w, auto e)
{ return serviceConnect(j, r, w, e); },
getSocket(), isReadable(), isWritable())
};
}
@ -802,9 +802,12 @@ MultiplexerJobStatus SecureSocket::serviceAccept(ISocketMultiplexerJob* job,
}
// Retry case
return {true, std::make_unique<TSocketMultiplexerMethodJob<SecureSocket>>(
this, &SecureSocket::serviceAccept,
getSocket(), isReadable(), isWritable())};
return {
true,
std::make_unique<TSocketMultiplexerMethodJob>([this](auto j, auto r, auto w, auto e)
{ return serviceAccept(j, r, w, e); },
getSocket(), isReadable(), isWritable())
};
}
void

View File

@ -70,8 +70,10 @@ TCPListenSocket::bind(const NetworkAddress& addr)
ARCH->bindSocket(m_socket, addr.getAddress());
ARCH->listenOnSocket(m_socket);
auto new_job = std::make_unique<TSocketMultiplexerMethodJob<TCPListenSocket>>(
this, &TCPListenSocket::serviceListening, m_socket, true, false);
auto new_job = std::make_unique<TSocketMultiplexerMethodJob>(
[this](auto j, auto r, auto w, auto e)
{ return serviceListening(j, r, w, e); },
m_socket, true, false);
m_socketMultiplexer->addSocket(this, std::move(new_job));
}
@ -136,8 +138,10 @@ TCPListenSocket::accept()
void
TCPListenSocket::setListeningJob()
{
auto new_job = std::make_unique<TSocketMultiplexerMethodJob<TCPListenSocket>>(
this, &TCPListenSocket::serviceListening, m_socket, true, false);
auto new_job = std::make_unique<TSocketMultiplexerMethodJob>(
[this](auto j, auto r, auto w, auto e)
{ return serviceListening(j, r, w, e); },
m_socket, true, false);
m_socketMultiplexer->addSocket(this, std::move(new_job));
}

View File

@ -426,18 +426,20 @@ std::unique_ptr<ISocketMultiplexerJob> TCPSocket::newJob()
if (!(m_readable || m_writable)) {
return {};
}
return std::make_unique<TSocketMultiplexerMethodJob<TCPSocket>>(
this, &TCPSocket::serviceConnecting,
return std::make_unique<TSocketMultiplexerMethodJob>(
[this](auto j, auto r, auto w, auto e)
{ return serviceConnecting(j, r, w, e); },
m_socket, m_readable, m_writable);
}
else {
if (!(m_readable || (m_writable && (m_outputBuffer.getSize() > 0)))) {
auto writable = m_writable && (m_outputBuffer.getSize() > 0);
if (!(m_readable || writable)) {
return {};
}
return std::make_unique<TSocketMultiplexerMethodJob<TCPSocket>>(
this, &TCPSocket::serviceConnected,
m_socket, m_readable,
m_writable && (m_outputBuffer.getSize() > 0));
return std::make_unique<TSocketMultiplexerMethodJob>(
[this](auto j, auto r, auto w, auto e)
{ return serviceConnected(j, r, w, e); },
m_socket, m_readable, writable);
}
}

View File

@ -25,81 +25,43 @@
/*!
A socket multiplexer job class that invokes a member function.
*/
template <class T>
class TSocketMultiplexerMethodJob : public ISocketMultiplexerJob {
public:
using Method = MultiplexerJobStatus (T::*)(ISocketMultiplexerJob*, bool, bool, bool);
using RunFunction = std::function<MultiplexerJobStatus(ISocketMultiplexerJob*, bool, bool, bool)>;
//! run() invokes \c object->method(arg)
TSocketMultiplexerMethodJob(T* object, Method method,
ArchSocket socket, bool readable, bool writeable);
virtual ~TSocketMultiplexerMethodJob();
// IJob overrides
virtual MultiplexerJobStatus run(bool readable, bool writable, bool error) override;
virtual ArchSocket getSocket() const override;
virtual bool isReadable() const override;
virtual bool isWritable() const override;
private:
T* m_object;
Method m_method;
ArchSocket m_socket;
bool m_readable;
bool m_writable;
void* m_arg;
};
template <class T>
inline
TSocketMultiplexerMethodJob<T>::TSocketMultiplexerMethodJob(T* object,
Method method, ArchSocket socket,
bool readable, bool writable) :
m_object(object),
m_method(method),
TSocketMultiplexerMethodJob(const RunFunction& func,
ArchSocket socket, bool readable, bool writable) :
func_{func},
m_socket(ARCH->copySocket(socket)),
m_readable(readable),
m_writable(writable)
{
// do nothing
}
template <class T>
inline
TSocketMultiplexerMethodJob<T>::~TSocketMultiplexerMethodJob()
~TSocketMultiplexerMethodJob() override
{
ARCH->closeSocket(m_socket);
}
template <class T>
inline MultiplexerJobStatus TSocketMultiplexerMethodJob<T>::run(bool read, bool write, bool error)
// IJob overrides
virtual MultiplexerJobStatus run(bool readable, bool writable, bool error) override
{
if (m_object != NULL) {
return (m_object->*m_method)(this, read, write, error);
if (func_) {
return func_(this, readable, writable, error);
}
return {false, {}};
}
template <class T>
inline
ArchSocket
TSocketMultiplexerMethodJob<T>::getSocket() const
{
return m_socket;
}
virtual ArchSocket getSocket() const override { return m_socket; }
virtual bool isReadable() const override { return m_readable; }
virtual bool isWritable() const override { return m_writable; }
private:
RunFunction func_;
ArchSocket m_socket;
bool m_readable;
bool m_writable;
};
template <class T>
inline
bool
TSocketMultiplexerMethodJob<T>::isReadable() const
{
return m_readable;
}
template <class T>
inline
bool
TSocketMultiplexerMethodJob<T>::isWritable() const
{
return m_writable;
}