summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorattilamolnar <attilamolnar@hush.com>2013-04-14 18:20:02 +0200
committerattilamolnar <attilamolnar@hush.com>2013-04-14 18:20:02 +0200
commit48f7fa6b11a0a6b1526c54914e60ddbe51ede8c4 (patch)
tree2f913e22d7de15e80b8a269bb4213bfd3d7b1406
parentf8127cf8c51d7991e4cf809f161701aac5276975 (diff)
Extract UID/SID generation logic into a new class: UIDGenerator
-rw-r--r--include/inspircd.h18
-rw-r--r--include/testsuite.h1
-rw-r--r--include/uid.h32
-rw-r--r--src/inspircd.cpp21
-rw-r--r--src/server.cpp66
-rw-r--r--src/testsuite.cpp35
-rw-r--r--src/users.cpp2
7 files changed, 87 insertions, 88 deletions
diff --git a/include/inspircd.h b/include/inspircd.h
index b0fadb336..929674eb3 100644
--- a/include/inspircd.h
+++ b/include/inspircd.h
@@ -294,8 +294,6 @@ DEFINE_HANDLER2(IsChannelHandler, bool, const std::string&, size_t);
DEFINE_HANDLER1(RehashHandler, void, const std::string&);
DEFINE_HANDLER3(OnCheckExemptionHandler, ModResult, User*, Channel*, const std::string&);
-class TestSuite;
-
/** The main class of the irc server.
* This class contains instances of all the other classes in this software.
* Amongst other things, it contains a ModeParser, a DNS object, a CommandParser
@@ -305,10 +303,6 @@ class TestSuite;
class CoreExport InspIRCd
{
private:
- /** Holds the current UID. Used to generate the next one.
- */
- char current_uid[UUID_LENGTH];
-
/** Set up the signal handlers
*/
void SetSignals();
@@ -323,10 +317,6 @@ class CoreExport InspIRCd
*/
void DoSocketTimeouts(time_t TIME);
- /** Increments the current UID by one.
- */
- void IncrementUID(int pos);
-
/** Perform background user events such as PING checks
*/
void DoBackgroundUserStuff();
@@ -348,6 +338,8 @@ class CoreExport InspIRCd
public:
+ UIDGenerator UIDGen;
+
/** Global cull list, will be processed on next iteration
*/
CullList GlobalCulls;
@@ -373,10 +365,6 @@ class CoreExport InspIRCd
*/
FakeUser* FakeClient;
- /** Returns the next available UID for this server.
- */
- std::string GetUID();
-
static const char LogHeader[];
/** Find a user in the UUID hash
@@ -828,8 +816,6 @@ class CoreExport InspIRCd
{
return this->ReadBuffer;
}
-
- friend class TestSuite;
};
ENTRYPOINT;
diff --git a/include/testsuite.h b/include/testsuite.h
index 43064b063..7f0b2236a 100644
--- a/include/testsuite.h
+++ b/include/testsuite.h
@@ -20,7 +20,6 @@
class TestSuite
{
- bool RealGenerateUIDTests();
public:
TestSuite();
~TestSuite();
diff --git a/include/uid.h b/include/uid.h
index 3783e7ada..8be003628 100644
--- a/include/uid.h
+++ b/include/uid.h
@@ -25,3 +25,35 @@
*/
#define UUID_LENGTH 10
+class TestSuite;
+
+class CoreExport UIDGenerator
+{
+ friend class TestSuite;
+
+ /** Holds the current UID. Used to generate the next one.
+ */
+ char current_uid[UUID_LENGTH];
+
+ /** Increments the current UID by one.
+ */
+ void IncrementUID(unsigned int pos);
+
+ public:
+ /** Initializes this UID generator with the given SID
+ * @param sid SID that conforms to InspIRCd::IsSID()
+ */
+ void init(const std::string& sid);
+
+ /** Returns the next available UID for this server.
+ */
+ std::string GetUID();
+
+ /** Generates a pseudorandom SID based on a servername and a description
+ * Guaranteed to return the same if invoked with the same parameters
+ * @param servername The server name to use as seed
+ * @param serverdesc The server description to use as seed
+ * @return A valid SID
+ */
+ static std::string GenerateSID(const std::string& servername, const std::string& serverdesc);
+};
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index bd1562473..aa9bfb65c 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -514,25 +514,12 @@ InspIRCd::InspIRCd(int argc, char** argv) :
this->Res = new DNS();
- /*
- * Initialise SID/UID.
- * For an explanation as to exactly how this works, and why it works this way, see GetUID().
- * -- w00t
- */
+ // If we don't have a SID, generate one based on the server name and the server description
if (Config->sid.empty())
- {
- // Generate one
- unsigned int sid = 0;
- char sidstr[4];
-
- for (const char* x = Config->ServerName.c_str(); *x; ++x)
- sid = 5 * sid + *x;
- for (const char* y = Config->ServerDesc.c_str(); *y; ++y)
- sid = 5 * sid + *y;
- sprintf(sidstr, "%03d", sid % 1000);
+ Config->sid = UIDGenerator::GenerateSID(Config->ServerName, Config->ServerDesc);
- Config->sid = sidstr;
- }
+ // Initialize the UID generator with our sid
+ this->UIDGen.init(Config->sid);
/* set up fake client again this time with the correct uid */
this->FakeClient = new FakeUser(Config->sid, Config->ServerName);
diff --git a/src/server.cpp b/src/server.cpp
index 0536d36a8..d4797dce6 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -83,7 +83,21 @@ const char InspIRCd::LogHeader[] =
"Log started for " VERSION " (" REVISION ", " MODULE_INIT_STR ")"
" - compiled on " SYSTEM;
-void InspIRCd::IncrementUID(int pos)
+
+std::string UIDGenerator::GenerateSID(const std::string& servername, const std::string& serverdesc)
+{
+ unsigned int sid = 0;
+
+ for (std::string::const_iterator i = servername.begin(); i != servername.end(); ++i)
+ sid = 5 * sid + *i;
+ for (std::string::const_iterator i = serverdesc.begin(); i != serverdesc.end(); ++i)
+ sid = 5 * sid + *i;
+
+ std::string sidstr = ConvToStr(sid % 1000);
+ return sidstr;
+}
+
+void UIDGenerator::IncrementUID(unsigned int pos)
{
/*
* Okay. The rules for generating a UID go like this...
@@ -124,52 +138,46 @@ void InspIRCd::IncrementUID(int pos)
}
}
-/*
- * Retrieve the next valid UUID that is free for this server.
- */
-std::string InspIRCd::GetUID()
+void UIDGenerator::init(const std::string& sid)
{
- static bool inited = false;
-
/*
- * If we're setting up, copy SID into the first three digits, 9's to the rest, null term at the end
+ * Copy SID into the first three digits, 9's to the rest, null term at the end
* Why 9? Well, we increment before we find, otherwise we have an unnecessary copy, and I want UID to start at AAA..AA
* and not AA..AB. So by initialising to 99999, we force it to rollover to AAAAA on the first IncrementUID call.
* Kind of silly, but I like how it looks.
* -- w
*/
- if (!inited)
- {
- inited = true;
- current_uid[0] = Config->sid[0];
- current_uid[1] = Config->sid[1];
- current_uid[2] = Config->sid[2];
- for (int i = 3; i < (UUID_LENGTH - 1); i++)
- current_uid[i] = '9';
+ current_uid[0] = sid[0];
+ current_uid[1] = sid[1];
+ current_uid[2] = sid[2];
- // Null terminator. Important.
- current_uid[UUID_LENGTH - 1] = '\0';
- }
+ for (int i = 3; i < (UUID_LENGTH - 1); i++)
+ current_uid[i] = '9';
+
+ // Null terminator. Important.
+ current_uid[UUID_LENGTH - 1] = '\0';
+}
+/*
+ * Retrieve the next valid UUID that is free for this server.
+ */
+std::string UIDGenerator::GetUID()
+{
while (1)
{
// Add one to the last UID
this->IncrementUID(UUID_LENGTH - 2);
- if (this->FindUUID(current_uid))
- {
- /*
- * It's in use. We need to try the loop again.
- */
- continue;
- }
+ if (!ServerInstance->FindUUID(current_uid))
+ break;
- return current_uid;
+ /*
+ * It's in use. We need to try the loop again.
+ */
}
- /* not reached. */
- return "";
+ return current_uid;
}
void ISupportManager::Build()
diff --git a/src/testsuite.cpp b/src/testsuite.cpp
index 58b72ee3e..c107217b7 100644
--- a/src/testsuite.cpp
+++ b/src/testsuite.cpp
@@ -331,29 +331,16 @@ bool TestSuite::DoThreadTests()
bool TestSuite::DoGenerateUIDTests()
{
- bool success = RealGenerateUIDTests();
-
- // Reset the UID generation state so running the tests multiple times won't mess things up
- for (unsigned int i = 0; i < 3; i++)
- ServerInstance->current_uid[i] = ServerInstance->Config->sid[i];
- for (unsigned int i = 3; i < UUID_LENGTH-1; i++)
- ServerInstance->current_uid[i] = '9';
-
- ServerInstance->current_uid[UUID_LENGTH-1] = '\0';
-
- return success;
-}
-
-bool TestSuite::RealGenerateUIDTests()
-{
- std::string first_uid = ServerInstance->GetUID();
+ UIDGenerator uidgen;
+ uidgen.init(ServerInstance->Config->GetSID());
+ std::string first_uid = uidgen.GetUID();
if (first_uid.length() != UUID_LENGTH-1)
{
std::cout << "GENERATEUID: Generated UID is " << first_uid.length() << " characters long instead of " << UUID_LENGTH-1 << std::endl;
return false;
}
- if (ServerInstance->current_uid[UUID_LENGTH-1] != '\0')
+ if (uidgen.current_uid[UUID_LENGTH-1] != '\0')
{
std::cout << "GENERATEUID: The null terminator is missing from the end of current_uid" << std::endl;
return false;
@@ -368,13 +355,13 @@ bool TestSuite::RealGenerateUIDTests()
}
// Set current_uid to be ...Z99999
- ServerInstance->current_uid[3] = 'Z';
+ uidgen.current_uid[3] = 'Z';
for (unsigned int i = 4; i < UUID_LENGTH-1; i++)
- ServerInstance->current_uid[i] = '9';
+ uidgen.current_uid[i] = '9';
// Store the UID we'll be incrementing so we can display what's wrong later if necessary
- std::string before_increment(ServerInstance->current_uid);
- std::string generated_uid = ServerInstance->GetUID();
+ std::string before_increment(uidgen.current_uid);
+ std::string generated_uid = uidgen.GetUID();
// Correct UID after incrementing ...Z99999 is ...0AAAAA
correct_uid = ServerInstance->Config->sid + "0" + std::string(UUID_LENGTH - 5, 'A');
@@ -387,10 +374,10 @@ bool TestSuite::RealGenerateUIDTests()
// Set current_uid to be ...999999 to see if it rolls over correctly
for (unsigned int i = 3; i < UUID_LENGTH-1; i++)
- ServerInstance->current_uid[i] = '9';
+ uidgen.current_uid[i] = '9';
- before_increment.assign(ServerInstance->current_uid);
- generated_uid = ServerInstance->GetUID();
+ before_increment.assign(uidgen.current_uid);
+ generated_uid = uidgen.GetUID();
// Correct UID after rolling over is the first UID we've generated (...AAAAAA)
if (generated_uid != first_uid)
diff --git a/src/users.cpp b/src/users.cpp
index c53fb7853..899ccecc6 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -215,7 +215,7 @@ User::User(const std::string &uid, const std::string& sid, int type)
}
LocalUser::LocalUser(int myfd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* servaddr)
- : User(ServerInstance->GetUID(), ServerInstance->Config->ServerName, USERTYPE_LOCAL), eh(this),
+ : User(ServerInstance->UIDGen.GetUID(), ServerInstance->Config->ServerName, USERTYPE_LOCAL), eh(this),
localuseriter(ServerInstance->Users->local_users.end()),
bytes_in(0), bytes_out(0), cmds_in(0), cmds_out(0), nping(0), CommandFloodPenalty(0),
already_sent(0)