00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: partychan.c,v 1.25 2007-04-18 01:45:52 sven Exp $";
00022 #endif
00023
00024 #include <eggdrop/eggdrop.h>
00025
00026
00027 #define CID_WRAPAROUND 100000
00028
00029 static hash_table_t *cid_ht = NULL;
00030 static partychan_t *partychan_head = NULL;
00031 static int g_cid = 0;
00032 static partymember_common_t *common_list_head = NULL;
00033
00034
00035 static bind_table_t *BT_partyjoin = NULL,
00036 *BT_partypart = NULL,
00037 *BT_partypub = NULL;
00038
00039 int partychan_init(void)
00040 {
00041 cid_ht = hash_table_create(NULL, NULL, 13, HASH_TABLE_INTS);
00042
00043
00044
00045 BT_partyjoin = bind_table_add(BTN_PARTYLINE_JOIN, 3, "siP", MATCH_NONE, BIND_STACKABLE);
00046 BT_partypart = bind_table_add(BTN_PARTYLINE_PART, 5, "siPsi", MATCH_NONE, BIND_STACKABLE);
00047 BT_partypub = bind_table_add(BTN_PARTYLINE_PUBLIC, 5, "siEsi", MATCH_NONE, BIND_STACKABLE);
00048 return(0);
00049 }
00050
00051 int partychan_shutdown(void)
00052 {
00053 partychan_t *chan, *next;
00054 partymember_common_t *common, *next_common;
00055
00056 if (partychan_head != NULL) {
00057 for (chan = partychan_head; chan; ) {
00058 next = chan->next;
00059 partychan_delete(chan);
00060 chan = next;
00061 }
00062 partychan_head = NULL;
00063 }
00064
00065 if (common_list_head) {
00066 for (common = common_list_head; common; ) {
00067 next_common = common->next;
00068
00069 free(common->members);
00070 free(common);
00071
00072 common = next_common;
00073 }
00074 common_list_head = NULL;
00075 }
00076
00077 bind_table_del(BT_partypub);
00078 bind_table_del(BT_partypart);
00079 bind_table_del(BT_partyjoin);
00080
00081
00082 garbage_run();
00083
00084 hash_table_delete(cid_ht);
00085
00086 return (0);
00087 }
00088
00089 int partychan_get_cid()
00090 {
00091 int cid;
00092
00093 while (partychan_lookup_cid(g_cid)) {
00094 g_cid++;
00095 if (g_cid >= CID_WRAPAROUND) g_cid = 0;
00096 }
00097 cid = g_cid++;
00098 if (g_cid >= CID_WRAPAROUND) g_cid = 0;
00099 return(cid);
00100 }
00101
00102 partychan_t *partychan_new(int cid, const char *name)
00103 {
00104 partychan_t *chan;
00105
00106 chan = calloc(1, sizeof(*chan));
00107 if (cid == -1) cid = partychan_get_cid();
00108 chan->cid = cid;
00109 chan->name = strdup(name);
00110 chan->next = partychan_head;
00111 if (partychan_head) partychan_head->prev = chan;
00112 partychan_head = chan;
00113 return(chan);
00114 }
00115
00116 static int partychan_cleanup(partychan_t *chan)
00117 {
00118 int i;
00119
00120 if (chan->flags & PARTY_DELETED) {
00121
00122
00123
00124
00125
00126
00127 for (i = 0; i < chan->nmembers; i++) {
00128 int j;
00129 for (j = 0; j < chan->members[i].p->nchannels; j++) {
00130 if (chan == chan->members[i].p->channels[j]) {
00131 if (j + 1 < chan->members[i].p->nchannels)
00132 memmove(chan->members[i].p->channels[j], chan->members[i].p->channels[j+1],
00133 (chan->members[i].p->nchannels-j-1) * sizeof(*chan));
00134 chan->members[i].p->nchannels--;
00135 break;
00136 }
00137 }
00138 }
00139
00140 if (chan->prev) {
00141 chan->prev->next = chan->next;
00142 if (chan->next)
00143 chan->next->prev = chan->prev;
00144 }
00145 else if (chan->next)
00146 chan->next->prev = NULL;
00147
00148 free(chan->name);
00149 free(chan->members);
00150 free(chan);
00151 return(0);
00152 }
00153
00154 for (i = 0; i < chan->nmembers; i++) {
00155 if (chan->members[i].flags & PARTY_DELETED) {
00156 memmove(chan->members+i, chan->members+i+1, sizeof(*chan->members) * (chan->nmembers-i-1));
00157 chan->nmembers--;
00158 i--;
00159 }
00160 }
00161
00162 return(0);
00163 }
00164
00165 void partychan_delete(partychan_t *chan)
00166 {
00167 chan->flags |= PARTY_DELETED;
00168 hash_table_remove(cid_ht, (void *)chan->cid, NULL);
00169 garbage_add((garbage_proc_t)partychan_cleanup, chan, GARBAGE_ONCE);
00170 }
00171
00172 partychan_t *partychan_lookup_cid(int cid)
00173 {
00174 partychan_t *chan = NULL;
00175
00176 hash_table_find(cid_ht, (void *)cid, &chan);
00177 if (chan && chan->flags & PARTY_DELETED) chan = NULL;
00178 return(chan);
00179 }
00180
00181 partychan_t *partychan_lookup_name(const char *name)
00182 {
00183 partychan_t *chan = NULL;
00184
00185 for (chan = partychan_head; chan; chan = chan->next) {
00186 if (chan->flags & PARTY_DELETED) continue;
00187 if (!strcasecmp(name, chan->name)) break;
00188 }
00189 return(chan);
00190 }
00191
00192 partychan_t *partychan_get_default(partymember_t *p)
00193 {
00194 if (p->nchannels > 0) return(p->channels[p->nchannels-1]);
00195 return(NULL);
00196 }
00197
00198 int partychan_ison_name(const char *chan, partymember_t *p)
00199 {
00200 partychan_t *chanptr;
00201
00202 if (!chan) return(0);
00203 chanptr = partychan_lookup_name(chan);
00204 if (!chanptr) return(0);
00205 return partychan_ison(chanptr, p);
00206 }
00207
00208 int partychan_ison(partychan_t *chan, partymember_t *p)
00209 {
00210 int i;
00211
00212 egg_assert_val (chan != NULL, 0);
00213 egg_assert_val (p != NULL, 0);
00214
00215 for (i = 0; i < chan->nmembers; i++) {
00216 if (chan->members[i].flags & PARTY_DELETED) continue;
00217 if (chan->members[i].p == p) return(1);
00218 }
00219
00220 return(0);
00221 }
00222
00223 int partychan_join_name(const char *chan, partymember_t *p, int linking)
00224 {
00225 partychan_t *chanptr;
00226
00227 if (!chan) return(-1);
00228 chanptr = partychan_lookup_name(chan);
00229 if (!chanptr) chanptr = partychan_new(-1, chan);
00230 return partychan_join(chanptr, p, linking);
00231 }
00232
00233 int partychan_join_cid(int cid, partymember_t *p, int linking)
00234 {
00235 partychan_t *chanptr;
00236
00237 chanptr = partychan_lookup_cid(cid);
00238 return partychan_join(chanptr, p, linking);
00239 }
00240
00241 int partychan_join(partychan_t *chan, partymember_t *p, int linking)
00242 {
00243 partychan_member_t *mem;
00244 int i;
00245
00246 if (!chan || !p) return(-1);
00247
00248
00249
00250 for (i = 0; i < chan->nmembers; i++) {
00251 if (chan->members[i].flags & PARTY_DELETED) continue;
00252 if (chan->members[i].p == p) return(-1);
00253 }
00254
00255
00256 chan->members = realloc(chan->members, sizeof(*chan->members) * (chan->nmembers+1));
00257 chan->members[chan->nmembers].p = p;
00258 chan->members[chan->nmembers].flags = 0;
00259 chan->nmembers++;
00260
00261
00262 p->channels = realloc(p->channels, sizeof(chan) * (p->nchannels+1));
00263 p->channels[p->nchannels] = chan;
00264 p->nchannels++;
00265
00266
00267 bind_check(BT_partyjoin, NULL, NULL, chan->name, chan->cid, p);
00268
00269
00270 for (i = 0; i < chan->nmembers; i++) {
00271 mem = chan->members+i;
00272 if (mem->flags & PARTY_DELETED || mem->p->flags & PARTY_DELETED) continue;
00273 if (mem->p->handler && mem->p->handler->on_join)
00274 (mem->p->handler->on_join)(mem->p->client_data, chan, p, linking);
00275 }
00276
00277 botnet_member_join(chan, p, linking);
00278
00279 return(0);
00280 }
00281
00282 int partychan_part_name(const char *chan, partymember_t *p, const char *text)
00283 {
00284 partychan_t *chanptr;
00285
00286 if (!chan) return(-1);
00287 chanptr = partychan_lookup_name(chan);
00288 return partychan_part(chanptr, p, text);
00289 }
00290
00291 int partychan_part_cid(int cid, partymember_t *p, const char *text)
00292 {
00293 partychan_t *chanptr;
00294
00295 chanptr = partychan_lookup_cid(cid);
00296 return partychan_part(chanptr, p, text);
00297 }
00298
00299 int partychan_part(partychan_t *chan, partymember_t *p, const char *text)
00300 {
00301 int i, len;
00302 partychan_member_t *mem;
00303
00304 if (!chan || !p) return(-1);
00305
00306
00307 if (!(p->flags & PARTY_DELETED)) for (i = 0; i < p->nchannels; i++) {
00308 if (p->channels[i] == chan) {
00309 memmove(p->channels+i, p->channels+i+1, sizeof(chan) * (p->nchannels-i-1));
00310 p->nchannels--;
00311 break;
00312 }
00313 }
00314
00315
00316 for (i = 0; i < chan->nmembers; i++) {
00317 if (chan->members[i].flags & PARTY_DELETED) continue;
00318 if (chan->members[i].p == p) {
00319 chan->members[i].flags |= PARTY_DELETED;
00320 garbage_add((garbage_proc_t)partychan_cleanup, chan, GARBAGE_ONCE);
00321 break;
00322 }
00323 }
00324
00325
00326
00327 if (p->flags & PARTY_DELETED) return(0);
00328
00329 if (!text) text = "";
00330 len = strlen(text);
00331
00332
00333 bind_check(BT_partypart, NULL, NULL, chan->name, chan->cid, p, text, len);
00334
00335 if (p->handler && p->handler->on_part) p->handler->on_part(p->client_data, chan, p, text, len);
00336
00337
00338 for (i = 0; i < chan->nmembers; i++) {
00339 mem = chan->members+i;
00340 if (mem->flags & PARTY_DELETED || mem->p->flags & PARTY_DELETED) continue;
00341 if (mem->p->handler && mem->p->handler->on_part)
00342 (mem->p->handler->on_part)(mem->p->client_data, chan, p, text, len);
00343 }
00344
00345 botnet_member_part(chan, p, text, len);
00346
00347 return(0);
00348 }
00349
00350 static int chan_msg(partychan_t *chan, botnet_entity_t *src, const char *text, int len, int local)
00351 {
00352 partychan_member_t *mem;
00353 int i;
00354
00355 if (!chan || chan->flags & PARTY_DELETED) return(-1);
00356
00357 if (len < 0) len = strlen(text);
00358
00359
00360 bind_check(BT_partypub, NULL, NULL, chan->name, chan->cid, src, text, len);
00361
00362 for (i = 0; i < chan->nmembers; i++) {
00363 mem = chan->members+i;
00364 if (mem->flags & PARTY_DELETED || mem->p->flags & PARTY_DELETED) continue;
00365 if (mem->p->handler && mem->p->handler->on_chanmsg)
00366 (mem->p->handler->on_chanmsg)(mem->p->client_data, chan, src, text, len);
00367 }
00368
00369 if (!local) botnet_chanmsg(chan, src, text, len);
00370
00371 return(0);
00372 }
00373
00374 int partychan_msg_name(const char *name, botnet_entity_t *src, const char *text, int len)
00375 {
00376 partychan_t *chan;
00377
00378 chan = partychan_lookup_name(name);
00379 return chan_msg(chan, src, text, len, 0);
00380 }
00381
00382 int partychan_msg_cid(int cid, botnet_entity_t *src, const char *text, int len)
00383 {
00384 partychan_t *chan;
00385
00386 chan = partychan_lookup_cid(cid);
00387 return chan_msg(chan, src, text, len, 0);
00388 }
00389
00390 int partychan_msg(partychan_t *chan, botnet_entity_t *src, const char *text, int len)
00391 {
00392 return chan_msg(chan, src, text, len, 0);
00393 }
00394
00395 int localchan_msg(partychan_t *chan, botnet_entity_t *src, const char *text, int len)
00396 {
00397 return chan_msg(chan, src, text, len, 1);
00398 }
00399
00400
00401 partymember_common_t *partychan_get_common(partymember_t *p)
00402 {
00403 partymember_common_t *common;
00404 partychan_t *chan;
00405 partymember_t *mem;
00406 int i, j;
00407
00408 if (common_list_head) {
00409 common = common_list_head;
00410 common_list_head = common_list_head->next;
00411 }
00412 else {
00413 common = calloc(1, sizeof(*common));
00414 }
00415
00416 common->len = 0;
00417 for (i = 0; i < p->nchannels; i++) {
00418 chan = p->channels[i];
00419 if (chan->flags & PARTY_DELETED) continue;
00420 for (j = 0; j < chan->nmembers; j++) {
00421 if (chan->members[j].flags & PARTY_DELETED) continue;
00422 mem = chan->members[j].p;
00423 if (mem->flags & (PARTY_DELETED | PARTY_SELECTED)) continue;
00424 if (mem->bot) continue;
00425 mem->flags |= PARTY_SELECTED;
00426 if (common->len >= common->max) {
00427 common->max = common->len + 10;
00428 common->members = realloc(common->members, sizeof(*common->members) * common->max);
00429 }
00430 common->members[common->len] = mem;
00431 common->len++;
00432 }
00433 }
00434 for (i = 0; i < common->len; i++) common->members[i]->flags &= ~PARTY_SELECTED;
00435 return(common);
00436 }
00437
00438 int partychan_free_common(partymember_common_t *common)
00439 {
00440 common->len = 0;
00441 common->next = common_list_head;
00442 common_list_head = common;
00443 return(0);
00444 }