]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_spanningtree/nickcollide.cpp
Split treesocket1 into a number of smaller files
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / nickcollide.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
6  * See: http://www.inspircd.org/wiki/index.php/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd.h"
15 #include "commands/cmd_whois.h"
16 #include "commands/cmd_stats.h"
17 #include "socket.h"
18 #include "wildcard.h"
19 #include "xline.h"
20 #include "transport.h"
21 #include "m_hash.h"
22 #include "socketengine.h"
23
24 #include "m_spanningtree/main.h"
25 #include "m_spanningtree/utils.h"
26 #include "m_spanningtree/treeserver.h"
27 #include "m_spanningtree/link.h"
28 #include "m_spanningtree/treesocket.h"
29 #include "m_spanningtree/resolvers.h"
30 #include "m_spanningtree/handshaketimer.h"
31
32 /* $ModDep: m_spanningtree/timesynctimer.h m_spanningtree/resolvers.h m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/link.h m_spanningtree/treesocket.h m_hash.h */
33
34 /*
35  * Yes, this function looks a little ugly.
36  * However, in some circumstances we may not have a User, so we need to do things this way.
37  * Returns 1 if colliding local client, 2 if colliding remote, 3 if colliding both.
38  * Sends SVSNICKs as appropriate and forces nickchanges too.
39  */
40 int TreeSocket::DoCollision(User *u, time_t remotets, const char *remoteident, const char *remoteip, const char *remoteuid)
41 {
42         /*
43          *  Under old protocol rules, we would have had to kill both clients.
44          *  Really, this sucks.
45          * These days, we have UID. And, so what we do is, force nick change client(s)
46          * involved according to timestamp rules.
47          *
48          * RULES:        
49          *  user@ip equal:       
50          *   Force nick change on OLDER timestamped client       
51          *  user@ip differ:      
52          *   Force nick change on NEWER timestamped client       
53          *  TS EQUAL:    
54          *   FNC both.   
55          *       
56          * This stops abusive use of collisions, simplifies problems with loops, and so on.      
57          *   -- w00t
58          */
59         bool bChangeLocal = true;
60         bool bChangeRemote = true;
61
62         /* for brevity, don't use the User */
63         time_t localts = u->age;
64         const char *localident = u->ident;
65         const char *localip = u->GetIPString();
66
67         /* mmk. let's do this again. */
68         if (remotets == localts)
69         {
70                 /* equal. fuck them both! do nada, let the handler at the bottom figure this out. */
71         }
72         else
73         {
74                 /* fuck. now it gets complex. */
75
76                 /* first, let's see if ident@host matches. */
77                 bool SamePerson = !strcmp(localident, remoteident)
78                                 && !strcmp(localip, remoteip);
79
80                 /*
81                  * if ident@ip is equal, and theirs is newer, or
82                  * ident@ip differ, and ours is newer
83                  */
84                 if((SamePerson && remotets < localts) ||
85                    (!SamePerson && remotets > localts))
86                 {
87                         /* remote needs to change */
88                         bChangeLocal = false;
89                 }
90                 else
91                 {
92                         /* ours needs to change */
93                         bChangeRemote = false;
94                 }
95         }
96
97
98         if (bChangeLocal)
99         {
100                 u->ForceNickChange(u->uuid);
101
102                 if (!bChangeRemote)
103                         return 1;
104         }
105         if (bChangeRemote)
106         {
107                 /*
108                  * Cheat a little here. Instead of a dedicated command to change UID,
109                  * use SVSNICK and accept their client with it's UID (as we know the SVSNICK will
110                  * not fail under any circumstances -- UIDs are netwide exclusive).
111                  *
112                  * This means that each side of a collide will generate one extra NICK back to where
113                  * they have just linked (and where it got the SVSNICK from), however, it will
114                  * be dropped harmlessly as it will come in as :928AAAB NICK 928AAAB, and we already
115                  * have 928AAAB's nick set to that.
116                  *   -- w00t
117                  */
118                 User *remote = this->Instance->FindUUID(remoteuid);
119
120                 if (remote)
121                 {
122                         /* buh.. nick change collide. force change their nick. */
123                         remote->ForceNickChange(remote->uuid);
124                 }
125                 else
126                 {
127                         /* user has not been introduced yet, just inform their server */
128                         this->WriteLine(std::string(":")+this->Instance->Config->GetSID()+" SVSNICK "+remoteuid+" " + remoteuid + " " + ConvToStr(remotets));
129                 }
130
131                 if (!bChangeLocal)
132                         return 2;
133         }
134
135         return 3;
136 }
137