added experimental multi thread support
[NeonServV5.git] / src / ChanUser.c
1 /* ChanUser.c - NeonServ v5.3
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "ChanUser.h"
19 #include "ChanNode.h"
20 #include "UserNode.h"
21
22 struct ChanUser* addChanUser(struct ChanNode *chan, struct UserNode *user) {
23     struct ChanUser *chanuser = malloc(sizeof(*chan));
24     if (!chanuser)
25     {
26         perror("malloc() failed");
27         return NULL;
28     }
29     chanuser->flags = 0;
30     chanuser->user = user;
31     chanuser->chan = chan;
32     
33     chanuser->changeTime = 0;
34     chanuser->spamnode = NULL;
35
36     SYNCHRONIZE(cache_sync);
37
38     chanuser->next_user = chan->user;
39     chan->user = chanuser;
40     chan->usercount++;
41
42     chanuser->next_chan = user->channel;
43     user->channel = chanuser;
44
45     DESYNCHRONIZE(cache_sync);
46
47     return chanuser;
48 }
49
50 struct ChanUser* addInvisibleChanUser(struct ChanNode *chan, struct UserNode *user) {
51     struct ChanUser *chanuser = malloc(sizeof(*chan));
52     if (!chanuser)
53     {
54         perror("malloc() failed");
55         return NULL;
56     }
57     chanuser->flags = CHANUSERFLAG_INVISIBLE;
58     chanuser->user = user;
59     chanuser->chan = chan;
60     
61     chanuser->changeTime = 0;
62     chanuser->spamnode = NULL;
63
64     SYNCHRONIZE(cache_sync);
65     chanuser->next_user = chan->user;
66     chan->user = chanuser;
67     DESYNCHRONIZE(cache_sync);
68     chan->usercount++;
69
70     return chanuser;
71 }
72
73 int isUserOnChan(struct UserNode *user, struct ChanNode *chan) {
74     struct ChanUser *chanuser;
75     for(chanuser = user->channel; chanuser; chanuser = chanuser->next_chan) {
76         if(chanuser->chan == chan)
77             return 1;
78     }
79     return 0;
80 }
81
82 struct ChanUser* getChanUser(struct UserNode *user, struct ChanNode *chan) {
83     struct ChanUser *chanuser;
84     for(chanuser = user->channel; chanuser; chanuser = chanuser->next_chan) {
85         if(chanuser->chan == chan)
86             return chanuser;
87     }
88     return NULL;
89 }
90
91 struct ChanUser* getChannelUsers(struct ChanNode *chan, struct ChanUser *last) {
92     if(last == NULL)
93         return chan->user;
94     else
95         return last->next_user;
96 }
97
98 struct ChanUser* getUserChannels(struct UserNode *user, struct ChanUser *last) {
99     if(last == NULL)
100         return user->channel;
101     else
102         return last->next_chan;
103 }
104
105 void delChanUser(struct ChanUser *chanuser, int do_freeChanUser) {
106     SYNCHRONIZE(cache_sync);
107     struct ChanUser *cchanuser, *last;
108     //remove it from the user's channel-list
109     if(!(chanuser->flags & CHANUSERFLAG_INVISIBLE)) {
110         last = NULL;
111         for(cchanuser = chanuser->user->channel; cchanuser; cchanuser = cchanuser->next_chan) {
112             if(cchanuser == chanuser) {
113                 if(last) 
114                     last->next_chan = chanuser->next_chan;
115                 else
116                     chanuser->user->channel = chanuser->next_chan;
117                 break;
118             } else
119                 last = cchanuser;
120         }
121     }
122
123     //remove it from the channel's user-list
124     last = NULL;
125     for(cchanuser = chanuser->chan->user; cchanuser; cchanuser = cchanuser->next_user) {
126         if(cchanuser == chanuser) {
127             chanuser->chan->usercount--;
128             if(last) 
129                 last->next_user = chanuser->next_user;
130             else
131                 chanuser->chan->user = chanuser->next_user;
132             break;
133         } else
134             last = cchanuser;
135     }
136     
137     if(do_freeChanUser) {
138         freeChanUser(chanuser);
139     } else {
140         chanuser->next_chan = NULL;
141         chanuser->next_user = NULL;
142     }
143     DESYNCHRONIZE(cache_sync);
144 }
145
146 void removeChanUserFromLists(struct ChanUser *chanuser, int remove_from_userlist, int remove_from_channellist, int do_freeChanUser) {
147     SYNCHRONIZE(cache_sync);
148     struct ChanUser *cchanuser, *last;
149     if(remove_from_userlist) {
150         //remove it from the channel's user-list
151         last = NULL;
152         for(cchanuser = chanuser->chan->user; cchanuser; cchanuser = cchanuser->next_user) {
153             if(cchanuser == chanuser) {
154                 chanuser->chan->usercount--;
155                 if(last) 
156                     last->next_user = chanuser->next_user;
157                 else
158                     chanuser->chan->user = chanuser->next_user;
159                 break;
160             } else
161                 last = cchanuser;
162         }
163         chanuser->next_user = NULL;
164     }
165     if(remove_from_channellist) {
166         //remove it from the user's channel-list
167         last = NULL;
168         for(cchanuser = chanuser->user->channel; cchanuser; cchanuser = cchanuser->next_chan) {
169             if(cchanuser == chanuser) {
170                 if(last) 
171                     last->next_chan = chanuser->next_chan;
172                 else
173                     chanuser->user->channel = chanuser->next_chan;
174                 break;
175             } else
176                 last = cchanuser;
177         }
178         chanuser->next_chan = NULL;
179     }
180     
181     if(do_freeChanUser) {
182         freeChanUser(chanuser);
183     }
184     DESYNCHRONIZE(cache_sync);
185 }
186
187 void freeChanUser(struct ChanUser *chanuser) {
188     if(chanuser->spamnode)
189         free(chanuser->spamnode);
190     free(chanuser);
191 }
192