forked from pEp.foundation/libAccountSettings
start with the generic protocol state machine
parent
ddb405d480
commit
afbcf7421a
|
@ -43,6 +43,8 @@ typedef enum _AS_FLAGS
|
|||
//! Combination of protocol, socket type & authentication type
|
||||
typedef enum _AS_ACCESS
|
||||
{
|
||||
AS_ACCESS_UNKNOWN = 0, ///< unknown / undetermined authentication type. Used as error value.
|
||||
|
||||
/// protocols
|
||||
AS_PROTO_POP3 = 0x00011, ///< incoming
|
||||
AS_PROTO_IMAP = 0x00012, ///< incoming
|
||||
|
|
|
@ -14,21 +14,92 @@ public:
|
|||
{}
|
||||
};
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace bio = boost::asio;
|
||||
using bio::ip::tcp;
|
||||
|
||||
// TODO: implement!
|
||||
class Protocol
|
||||
{
|
||||
public:
|
||||
Protocol() = default;
|
||||
Protocol() {}
|
||||
virtual ~Protocol() {}
|
||||
|
||||
/// (re)initialize the protocol and thet the AS_Server to initial state
|
||||
virtual void init(AS_Server& ass) = 0;
|
||||
|
||||
/// say something to the server. if nothing to say in this state, it returns empty string
|
||||
virtual std::string put() = 0;
|
||||
|
||||
/// return true if guessing was successful
|
||||
virtual bool get(const std::string& s) = 0;
|
||||
};
|
||||
|
||||
|
||||
AS_Server probe_server(const std::string& domain, std::initializer_list<std::string> names, Protocol p=Protocol() )
|
||||
class Imap : public Protocol
|
||||
{
|
||||
AS_Server ass { "", -1, AS_ACCESS(-1), "" };
|
||||
public:
|
||||
Imap() {}
|
||||
virtual ~Imap() {}
|
||||
virtual void init(AS_Server& ass) override { /* TODO: implement! */ }
|
||||
virtual std::string put() override { return ""; }
|
||||
virtual bool get(const std::string& s) override { return s.empty(); }
|
||||
};
|
||||
|
||||
|
||||
AS_Server pingpong(const std::string& server, int port, Protocol& p)
|
||||
{
|
||||
AS_Server ass{ "", -1, AS_ACCESS_UNKNOWN, "" };
|
||||
try{
|
||||
std::vector<char> buffer(2048);
|
||||
bio::io_service ios;
|
||||
tcp::resolver res(ios);
|
||||
tcp::resolver::query query( server, std::to_string(port) );
|
||||
for(auto iter = res.resolve(query); iter != tcp::resolver::iterator(); ++iter)
|
||||
{
|
||||
p.init(ass);
|
||||
tcp::socket s(ios);
|
||||
bio::connect(s, iter);
|
||||
boost::system::error_code err;
|
||||
|
||||
while(ass.access == AS_ACCESS_UNKNOWN)
|
||||
{
|
||||
const std::string output = p.put();
|
||||
if(!output.empty())
|
||||
{
|
||||
bio::write(s, bio::buffer(output), err);
|
||||
}
|
||||
|
||||
const size_t length = s.read_some( boost::asio::buffer(buffer), err);
|
||||
if(!err || err == bio::error::eof)
|
||||
{
|
||||
if( p.get( std::string( buffer.data(), buffer.data()+length) ) )
|
||||
{
|
||||
return ass;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(std::runtime_error&) { /* just return what we have so far */ }
|
||||
|
||||
throw protocol_error{};
|
||||
return ass;
|
||||
}
|
||||
|
||||
|
||||
AS_Server probe_server(const std::string& domain, std::initializer_list<std::string> names, std::initializer_list<int> ports, Protocol& p )
|
||||
{
|
||||
for(auto port : ports)
|
||||
for(auto name : names)
|
||||
{
|
||||
const std::string server = domain + "." + name;
|
||||
const AS_Server ass = pingpong(server, port, p);
|
||||
if(ass.access != AS_ACCESS_UNKNOWN)
|
||||
return ass;
|
||||
}
|
||||
|
||||
return AS_Server{ "", -1, AS_ACCESS_UNKNOWN, "" };
|
||||
}
|
||||
|
||||
} //end of anonymous namespace
|
||||
|
@ -43,7 +114,8 @@ AccountSettings* get_settings_from_heuristics(AccountSettings* as, const std::st
|
|||
|
||||
// fprintf(stderr, "== IMAP ==\n");
|
||||
try{
|
||||
as->incoming = probe_server( domain, {"imap", "mail", "imaps", "imapmail", "imap-mail", "mx", "", "mbox",} );
|
||||
Imap imap_protocol;
|
||||
as->incoming = probe_server( domain, {"imap", "mail", "imaps", "imapmail", "imap-mail", "mx", "", "mbox"}, {143, 993}, imap_protocol );
|
||||
}catch( const protocol_error& )
|
||||
{
|
||||
// ignore protocol errors
|
||||
|
@ -51,7 +123,8 @@ AccountSettings* get_settings_from_heuristics(AccountSettings* as, const std::st
|
|||
|
||||
// fprintf(stderr, "== SMTP ==\n");
|
||||
try{
|
||||
as->outgoing = probe_server( domain, {"smtp", "mail", "smtps", "smtpmail", "smtp-mail", "mx", "", "smtpauth",} );
|
||||
Imap smtp_protocol;
|
||||
as->outgoing = probe_server( domain, {"smtp", "mail", "smtps", "smtpmail", "smtp-mail", "mx", "", "smtpauth",}, {25, 587, 465}, smtp_protocol );
|
||||
}catch( const protocol_error& )
|
||||
{
|
||||
// ignore protocol errors
|
||||
|
|
Loading…
Reference in New Issue