summaryrefslogtreecommitdiff
path: root/modules/extra/m_ldap.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-10-10 23:08:00 -0400
committerAdam <Adam@anope.org>2012-10-10 23:08:00 -0400
commit757ff06011c9b6ac8f66da7a5cac03597194d97a (patch)
tree89553068f751967fe741da50bb835beb589b9552 /modules/extra/m_ldap.cpp
parent06defe014bf4f74b645429593670fa74803c6758 (diff)
Fix m_ldap to reconnect automatically if the ldap server goes away
Diffstat (limited to 'modules/extra/m_ldap.cpp')
-rw-r--r--modules/extra/m_ldap.cpp83
1 files changed, 72 insertions, 11 deletions
diff --git a/modules/extra/m_ldap.cpp b/modules/extra/m_ldap.cpp
index e6e65e85c..d53e04992 100644
--- a/modules/extra/m_ldap.cpp
+++ b/modules/extra/m_ldap.cpp
@@ -15,6 +15,8 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
LDAP *con;
+ time_t last_connect;
+
LDAPMod **BuildMods(const LDAPMods &attributes)
{
LDAPMod **mods = new LDAPMod*[attributes.size() + 1];
@@ -54,19 +56,34 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
delete [] mods;
}
+ void Reconnect()
+ {
+ /* Only try one connect a minute. It is an expensive blocking operation */
+ if (last_connect > Anope::CurTime - 60)
+ throw LDAPException("Unable to connect to LDAP service " + this->name + ": reconnecting too fast");
+ last_connect = Anope::CurTime;
+
+ ldap_unbind_ext(this->con, NULL, NULL);
+ int i = ldap_initialize(&this->con, this->server.c_str());
+ if (i != LDAP_SUCCESS)
+ throw LDAPException("Unable to connect to LDAP service " + this->name + ": " + ldap_err2string(i));
+ }
+
public:
typedef std::map<int, LDAPInterface *> query_queue;
typedef std::vector<std::pair<LDAPInterface *, LDAPResult *> > result_queue;
query_queue queries;
result_queue results;
- LDAPService(Module *o, const Anope::string &n, const Anope::string &s, int po, const Anope::string &b, const Anope::string &p) : LDAPProvider(o, "ldap/" + n), server(s), port(po), admin_binddn(b), admin_pass(p)
+ LDAPService(Module *o, const Anope::string &n, const Anope::string &s, int po, const Anope::string &b, const Anope::string &p) : LDAPProvider(o, "ldap/" + n), server(s), port(po), admin_binddn(b), admin_pass(p), last_connect(0)
{
- if (ldap_initialize(&this->con, this->server.c_str()) != LDAP_SUCCESS)
- throw LDAPException("Unable to connect to LDAP service " + this->name + ": " + Anope::LastError());
+ int i = ldap_initialize(&this->con, this->server.c_str());
+ if (i != LDAP_SUCCESS)
+ throw LDAPException("Unable to connect to LDAP service " + this->name + ": " + ldap_err2string(i));
static const int version = LDAP_VERSION3;
- if (ldap_set_option(this->con, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS)
- throw LDAPException("Unable to set protocol version for " + this->name + ": " + Anope::LastError());
+ i = ldap_set_option(this->con, LDAP_OPT_PROTOCOL_VERSION, &version);
+ if (i != LDAP_OPT_SUCCESS)
+ throw LDAPException("Unable to set protocol version for " + this->name + ": " + ldap_err2string(i));
}
~LDAPService()
@@ -76,7 +93,7 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
for (query_queue::iterator it = this->queries.begin(), it_end = this->queries.end(); it != it_end; ++it)
{
ldap_abandon_ext(this->con, it->first, NULL, NULL);
- delete it->second;
+ it->second->OnDelete();
}
this->queries.clear();
@@ -107,7 +124,15 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
int ret = ldap_sasl_bind(con, who.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, &msgid);
free(cred.bv_val);
if (ret != LDAP_SUCCESS)
- throw LDAPException(ldap_err2string(ret));
+ {
+ if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
+ {
+ this->Reconnect();
+ return this->Bind(i, who, pass);
+ }
+ else
+ throw LDAPException(ldap_err2string(ret));
+ }
if (i != NULL)
{
@@ -128,7 +153,15 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
LDAPQuery msgid;
int ret = ldap_search_ext(this->con, base.c_str(), LDAP_SCOPE_SUBTREE, filter.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msgid);
if (ret != LDAP_SUCCESS)
- throw LDAPException(ldap_err2string(ret));
+ {
+ if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
+ {
+ this->Reconnect();
+ return this->Search(i, base, filter);
+ }
+ else
+ throw LDAPException(ldap_err2string(ret));
+ }
this->Lock();
this->queries[msgid] = i;
@@ -146,7 +179,15 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
this->FreeMods(mods);
if (ret != LDAP_SUCCESS)
- throw LDAPException(ldap_err2string(ret));
+ {
+ if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
+ {
+ this->Reconnect();
+ return this->Add(i, dn, attributes);
+ }
+ else
+ throw LDAPException(ldap_err2string(ret));
+ }
if (i != NULL)
{
@@ -165,7 +206,15 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
int ret = ldap_delete_ext(this->con, dn.c_str(), NULL, NULL, &msgid);
if (ret != LDAP_SUCCESS)
- throw LDAPException(ldap_err2string(ret));
+ {
+ if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
+ {
+ this->Reconnect();
+ return this->Del(i, dn);
+ }
+ else
+ throw LDAPException(ldap_err2string(ret));
+ }
if (i != NULL)
{
@@ -186,7 +235,15 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
this->FreeMods(mods);
if (ret != LDAP_SUCCESS)
- throw LDAPException(ldap_err2string(ret));
+ {
+ if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
+ {
+ this->Reconnect();
+ return this->Modify(i, base, attributes);
+ }
+ else
+ throw LDAPException(ldap_err2string(ret));
+ }
if (i != NULL)
{
@@ -435,8 +492,12 @@ class ModuleLDAP : public Module, public Pipe
int msgid = it2->first;
LDAPInterface *i = it2->second;
++it2;
+
if (i->owner == m)
+ {
+ i->OnDelete();
s->queries.erase(msgid);
+ }
}
for (unsigned i = s->results.size(); i > 0; --i)
{