diff options
author | attilamolnar <attilamolnar@hush.com> | 2013-04-14 18:20:02 +0200 |
---|---|---|
committer | attilamolnar <attilamolnar@hush.com> | 2013-04-14 18:20:02 +0200 |
commit | 48f7fa6b11a0a6b1526c54914e60ddbe51ede8c4 (patch) | |
tree | 2f913e22d7de15e80b8a269bb4213bfd3d7b1406 | |
parent | f8127cf8c51d7991e4cf809f161701aac5276975 (diff) |
Extract UID/SID generation logic into a new class: UIDGenerator
-rw-r--r-- | include/inspircd.h | 18 | ||||
-rw-r--r-- | include/testsuite.h | 1 | ||||
-rw-r--r-- | include/uid.h | 32 | ||||
-rw-r--r-- | src/inspircd.cpp | 21 | ||||
-rw-r--r-- | src/server.cpp | 66 | ||||
-rw-r--r-- | src/testsuite.cpp | 35 | ||||
-rw-r--r-- | src/users.cpp | 2 |
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) |