1 // ==============================================================
2 // This file is part of MegaGlest Shared Library (www.glest.org)
3 //
4 // Copyright (C) 2009-2010 Titus Tscharntke (info@titusgames.de) and
5 // Mark Vejvoda (mark_vejvoda@hotmail.com)
6 //
7 // You can redistribute this code and/or modify it under
8 // the terms of the GNU General Public License as published
9 // by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version
11 // ==============================================================
12
13 #include "ircclient.h"
14 #include "util.h"
15 #include "platform_common.h"
16 #include "socket.h"
17 #include "cache_manager.h"
18
19 #if !defined(DISABLE_IRCCLIENT)
20
21 #include <libircclient.h>
22 // upstream moved some defines into new headers as of 1.6
23 #include <libirc_rfcnumeric.h>
24
25 #endif
26
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include "conversion.h"
32
33 using namespace Shared::Util;
34 using namespace Shared::PlatformCommon;
35
36 namespace Shared { namespace PlatformCommon {
37
38 const char *IRCThread::globalCacheContainerName = NULL;
39 const int IRC_SERVER_PORT = 6667;
40 //bool IRCThread::debugEnabled = true;
41 bool IRCThread::debugEnabled = false;
42
43 #if !defined(DISABLE_IRCCLIENT)
addlog(const char * fmt,...)44 void addlog (const char * fmt, ...) {
45 //FILE * fp;
46 char buf[8096];
47 va_list va_alist;
48
49 va_start (va_alist, fmt);
50 #if defined (WIN32)
51 _vsnprintf (buf, sizeof(buf), fmt, va_alist);
52 #else
53 vsnprintf (buf, sizeof(buf), fmt, va_alist);
54 #endif
55 va_end (va_alist);
56
57 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: %s\n", buf);
58
59 //if(SystemFlags::VERBOSE_MODE_ENABLED == true) {
60 // if ( (fp = fopen ("irctest.log", "ab")) != 0 ) {
61 // fprintf (fp, "%s\n", buf);
62 // fclose (fp);
63 // }
64 //}
65 }
66
dump_event(irc_session_t * session,const char * event,const char * origin,const char ** params,unsigned int count)67 void dump_event (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) {
68 char buf[512]="";
69 unsigned int cnt=0;
70 buf[0] = '\0';
71
72 for ( cnt = 0; cnt < count; cnt++ ) {
73 if ( cnt ) {
74 strcat (buf, "|");
75 }
76 #ifdef WIN32
77 strncat (buf, params[cnt],min((int)strlen(params[cnt]),511));
78 #else
79 strncat (buf, params[cnt],std::min((int)strlen(params[cnt]),511));
80 #endif
81 }
82
83 addlog ("Event \"%s\", origin: \"%s\", params: %d [%s]", event, origin ? origin : "NULL", cnt, buf);
84
85 IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
86 if(ctx != NULL) {
87 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
88 if(ctx->getQuitStatus()) {
89 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
90 return;
91 }
92 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
93 if(difftime(time(NULL),ctx->getLastNickListUpdate()) >= 7) {
94 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
95 ctx->setLastNickListUpdate(time(NULL));
96 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
97 ctx->GetIRCConnectedNickList(ctx->getChannel(),false);
98 }
99 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
100 }
101 }
102
get_nickname(const char * sourceNick,char * destNick,size_t maxDestBufferSize)103 void get_nickname(const char *sourceNick,char *destNick,size_t maxDestBufferSize) {
104 string sourceNickStr = sourceNick;
105 if(sourceNickStr != "" && sourceNickStr[0] == '@') {
106 sourceNickStr.erase(0,1);
107 }
108
109 irc_target_get_nick(sourceNickStr.c_str(),destNick,maxDestBufferSize);
110 }
111
event_notice(irc_session_t * session,const char * event,const char * origin,const char ** params,unsigned int count)112 void event_notice (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) {
113 dump_event (session, event, origin, params, count);
114
115 if(origin == NULL) {
116 return;
117 }
118
119 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf("NOTICE from '%s': %s", origin, params[1]);
120
121 //if(strcasecmp (origin, "nickserv")) {
122 // return;
123 //}
124
125 if(strstr (params[1], "This nick is not registered") == params[1]) {
126 //std::string regcmd = "REGISTER " + gCfg.irc_nickserv_pass + " NOMAIL";
127 //gLog.Add (CLog::INFO, "Registering our nick with NICKSERV");
128 //irc_cmd_msg (session, "nickserv", regcmd.c_str());
129 }
130 else if(strstr (params[1], "This nickname is registered and protected") == params[1]) {
131 //std::string identcmd = "IDENTIFY " + gCfg.irc_nickserv_pass;
132 //gLog.Add (CLog::INFO, "Identifying our nick with NICKSERV");
133 //irc_cmd_msg (session, "nickserv", identcmd.c_str());
134
135 // IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
136 // if(ctx != NULL) {
137 // if(ctx->getExecute_cmd_onconnect() != "") {
138 // irc_cmd_msg(session, "nickserv", ctx->getExecute_cmd_onconnect().c_str());
139 // }
140 // }
141 }
142 else if(strstr (params[1], "Password accepted - you are now recognized") == params[1]) {
143 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf("Nickserv authentication succeed.");
144 }
145 }
146
event_join(irc_session_t * session,const char * event,const char * origin,const char ** params,unsigned int count)147 void event_join(irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) {
148
149 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
150
151 dump_event (session, event, origin, params, count);
152
153 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
154
155 IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
156
157 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
158
159 if(ctx != NULL) {
160
161 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
162
163 if(ctx->getHasJoinedChannel() == false) {
164
165 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
166
167 irc_cmd_user_mode (session, "+i");
168
169 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
170
171 //irc_cmd_msg (session, params[0], "MG Bot says hello!");
172 ctx->setHasJoinedChannel(true);
173
174 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
175
176 //ctx->GetIRCConnectedNickList(ctx->getChannel(),true);
177 ctx->GetIRCConnectedNickList(ctx->getChannel(),false);
178
179 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
180 }
181 else {
182 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
183
184 char realNick[128]="";
185 get_nickname(origin,realNick,127);
186 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: user joined channel realNick [%s] origin [%s]\n", realNick,origin);
187
188 bool foundNick = false;
189
190 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
191
192 MutexSafeWrapper safeMutex(ctx->getMutexNickList(),string(__FILE__) + "_" + intToStr(__LINE__));
193 std::vector<string> nickList = ctx->getCachedNickList();
194 for(unsigned int i = 0;
195 i < nickList.size(); ++i) {
196 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: looking for match [%s] realNick [%s]\n", nickList[i].c_str(),realNick);
197
198 if(nickList[i] == realNick) {
199 foundNick = true;
200 break;
201 }
202 }
203 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
204
205 if(foundNick == false) {
206 nickList.push_back(realNick);
207 }
208
209 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
210 }
211
212 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
213
214 if(ctx->getWantToLeaveChannel() == true) {
215 ctx->leaveChannel();
216 }
217
218 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
219 }
220 }
221
event_connect(irc_session_t * session,const char * event,const char * origin,const char ** params,unsigned int count)222 void event_connect (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) {
223 IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
224
225 dump_event(session, event, origin, params, count);
226
227 //IRC: Event "433", origin: "leguin.freenode.net", params: 3 [*|softcoder|Nickname is already in use.]
228 // printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
229 // if(strstr (params[1], "Nickname is already in use") == params[1]) {
230 // IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
231 // if(ctx != NULL) {
232 // if(ctx->getExecute_cmd_onconnect() != "") {
233 // irc_cmd_msg(session, "nickserv", ctx->getExecute_cmd_onconnect().c_str());
234 // }
235 // }
236 // }
237 // else
238 if(ctx != NULL) {
239 irc_cmd_join(session, ctx->getChannel().c_str(), 0);
240 }
241 }
242
event_privmsg(irc_session_t * session,const char * event,const char * origin,const char ** params,unsigned int count)243 void event_privmsg (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) {
244 dump_event (session, event, origin, params, count);
245
246 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("'%s' said me (%s): %s\n",origin ? origin : "someone",params[0], params[1] );
247 }
248
dcc_recv_callback(irc_session_t * session,irc_dcc_t id,int status,void * ctx,const char * data,unsigned int length)249 void dcc_recv_callback (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length) {
250
251 switch (status)
252 {
253 case LIBIRC_ERR_CLOSED:
254 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC %d: chat closed\n", id);
255 break;
256
257 case 0:
258 if ( !data ) {
259 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC %d: chat connected\n", id);
260 irc_dcc_msg (session, id, "Hehe");
261 }
262 else {
263 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC %d: %s\n", id, data);
264
265 static int count = 1;
266 char buf[12]="";
267 sprintf (buf, "DCC [%d]: %d", id, count++);
268 irc_dcc_msg (session, id, buf);
269 }
270 break;
271
272 default:
273 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC %d: error %s\n", id, irc_strerror(status));
274 break;
275 }
276 }
277
dcc_file_recv_callback(irc_session_t * session,irc_dcc_t id,int status,void * ctx,const char * data,unsigned int length)278 void dcc_file_recv_callback (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length) {
279 if ( status == 0 && length == 0 ) {
280 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("File sent successfully\n");
281
282 if ( ctx ) {
283 fclose ((FILE*) ctx);
284 }
285 }
286 else if ( status ) {
287 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("File sent error: %d\n", status);
288
289 if ( ctx ) {
290 fclose ((FILE*) ctx);
291 }
292 }
293 else {
294 if ( ctx ) {
295 fwrite (data, 1, length, (FILE*) ctx);
296 }
297 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("File sent progress: %u\n", length);
298 }
299 }
300
event_channel(irc_session_t * session,const char * event,const char * origin,const char ** params,unsigned int count)301 void event_channel(irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) {
302 //IRC: Event "433", origin: "leguin.freenode.net", params: 3 [*|softcoder|Nickname is already in use.]
303 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf("In [%s::%s] Line: %d count = %u origin = %s\n",__FILE__,__FUNCTION__,__LINE__,count,(origin ? origin : "null"));
304
305 if ( count != 2 )
306 return;
307
308 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: '%s' said in channel %s: %s\n",origin ? origin : "someone",params[0], params[1] );
309
310 if ( !origin ) {
311 return;
312 }
313
314 char realNick[128]="";
315 get_nickname(origin,realNick,127);
316 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: event signalled realNick [%s] origin [%s]\n", realNick,origin);
317
318 IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
319 if(ctx != NULL) {
320 MutexSafeWrapper safeMutex(ctx->getMutexIRCCB(),string(__FILE__) + "_" + intToStr(__LINE__));
321 IRCCallbackInterface *cb = ctx->getCallbackObj(false);
322 if(cb != NULL) {
323 cb->IRC_CallbackEvent(IRC_evt_chatText, realNick, params, count);
324 }
325 }
326
327 // if ( !strcmp (params[1], "quit") )
328 // irc_cmd_quit (session, "of course, Master!");
329 //
330 // if ( !strcmp (params[1], "help") ) {
331 // irc_cmd_msg (session, params[0], "quit, help, dcc chat, dcc send, ctcp");
332 // }
333 //
334 // if ( !strcmp (params[1], "ctcp") ) {
335 // irc_cmd_ctcp_request (session, realNick, "PING 223");
336 // irc_cmd_ctcp_request (session, realNick, "FINGER");
337 // irc_cmd_ctcp_request (session, realNick, "VERSION");
338 // irc_cmd_ctcp_request (session, realNick, "TIME");
339 // }
340 //
341 // if ( !strcmp (params[1], "dcc chat") ) {
342 // irc_dcc_t dccid;
343 // irc_dcc_chat (session, 0, realNick, dcc_recv_callback, &dccid);
344 // if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC chat ID: %d\n", dccid);
345 // }
346 //
347 // if ( !strcmp (params[1], "dcc send") ) {
348 // irc_dcc_t dccid;
349 // irc_dcc_sendfile (session, 0, realNick, "irctest.c", dcc_file_recv_callback, &dccid);
350 // if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC send ID: %d\n", dccid);
351 // }
352 //
353 // if ( !strcmp (params[1], "topic") ) {
354 // irc_cmd_topic (session, params[0], 0);
355 // }
356 // else if ( strstr (params[1], "topic ") == params[1] ) {
357 // irc_cmd_topic (session, params[0], params[1] + 6);
358 // }
359 //
360 // if ( strstr (params[1], "mode ") == params[1] )
361 // irc_cmd_channel_mode (session, params[0], params[1] + 5);
362 //
363 // if ( strstr (params[1], "nick ") == params[1] )
364 // irc_cmd_nick (session, params[1] + 5);
365 //
366 // if ( strstr (params[1], "whois ") == params[1] )
367 // irc_cmd_whois (session, params[1] + 5);
368 }
369
irc_event_dcc_chat(irc_session_t * session,const char * nick,const char * addr,irc_dcc_t dccid)370 void irc_event_dcc_chat(irc_session_t * session, const char * nick, const char * addr, irc_dcc_t dccid) {
371 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC chat [%d] requested from '%s' (%s)\n", dccid, nick, addr);
372
373 irc_dcc_accept (session, dccid, 0, dcc_recv_callback);
374 }
375
irc_event_dcc_send(irc_session_t * session,const char * nick,const char * addr,const char * filename,unsigned long size,irc_dcc_t dccid)376 void irc_event_dcc_send(irc_session_t * session, const char * nick, const char * addr, const char * filename, unsigned long size, irc_dcc_t dccid) {
377 FILE * fp;
378 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("DCC send [%d] requested from '%s' (%s): %s (%lu bytes)\n", dccid, nick, addr, filename, size);
379
380 if ( (fp = fopen ("file", "wb")) == 0 ) {
381 abort();
382 }
383 irc_dcc_accept (session, dccid, fp, dcc_file_recv_callback);
384 }
385
event_leave(irc_session_t * session,const char * event,const char * origin,const char ** params,unsigned count)386 void event_leave(irc_session_t *session, const char *event, const char *origin, const char ** params, unsigned count) {
387 char buf[24]="";
388 sprintf (buf, "%s", event);
389
390 // someone left the channel.
391 if(origin) {
392 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: user left channel [%s]\n", origin);
393
394 char realNick[128]="";
395 get_nickname(origin,realNick,127);
396 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: user left channel realNick [%s] origin [%s]\n", realNick,origin);
397
398 IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
399 if(ctx != NULL) {
400 MutexSafeWrapper safeMutex(ctx->getMutexNickList(),string(__FILE__) + "_" + intToStr(__LINE__));
401 std::vector<string> &nickList = ctx->getCachedNickList();
402 for(unsigned int i = 0;
403 i < nickList.size(); ++i) {
404 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: lookingfor match [%s] realNick [%s]\n", nickList[i].c_str(),realNick);
405
406 if(nickList[i] == realNick) {
407 nickList.erase(nickList.begin() + i);
408 break;
409 }
410 }
411 }
412 }
413
414 dump_event (session, buf, origin, params, count);
415 }
event_numeric(irc_session_t * session,unsigned int event,const char * origin,const char ** params,unsigned int count)416 void event_numeric(irc_session_t * session, unsigned int event, const char * origin, const char ** params, unsigned int count) {
417 char buf[24]="";
418 sprintf (buf, "%u", event);
419
420 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d event = %u\n", __LINE__, event);
421
422 switch (event) {
423 case LIBIRC_RFC_ERR_NICKNAMEINUSE :
424 case LIBIRC_RFC_ERR_NICKCOLLISION :
425 //irc_auto_rename_nick(session);
426 //IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
427 //if(ctx != NULL) {
428 // {
429 // //IRC: Event "433", origin: "leguin.freenode.net", params: 3 [*|softcoder|Nickname is already in use.]
430 // printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
431 // //if(strstr (params[1], "Nickname is already in use") == params[1]) {
432 // IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
433 // if(ctx != NULL) {
434 // if(ctx->getExecute_cmd_onconnect() != "") {
435 // irc_cmd_msg(session, "nickserv", ctx->getExecute_cmd_onconnect().c_str());
436 // }
437 // }
438 // //}
439 // }
440 break;
441
442 case LIBIRC_RFC_ERR_NOTREGISTERED :
443 //irc_auto_rename_nick(session);
444 //IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
445 //if(ctx != NULL) {
446 // {
447 //===> IRC: Event "451", origin: "leguin.freenode.net", params: 2 [*|You have not registered]
448 // printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
449 // //if(strstr (params[1], "Nickname is already in use") == params[1]) {
450 // IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
451 // if(ctx != NULL) {
452 // //if(ctx->getExecute_cmd_onconnect() != "") {
453 // //irc_cmd_msg(session, "nickserv", ctx->getExecute_cmd_onconnect().c_str());
454 // string cmd = "REGISTER " + ctx->getNick() + " NOMAIL";
455 // irc_cmd_msg (session, "nickserv", cmd.c_str());
456 // //}
457 // }
458 // //}
459 // }
460 break;
461
462 case LIBIRC_RFC_RPL_TOPIC :
463 break;
464 case LIBIRC_RFC_RPL_NAMREPLY :
465 {
466 if(event == LIBIRC_RFC_RPL_NAMREPLY) {
467
468 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: LIBIRC_RFC_RPL_NAMREPLY count = %u\n", count);
469
470 std::vector<string> nickList;
471 if(count >= 4) {
472 for(unsigned int i = 3; i < count && params[i]; ++i) {
473 vector<string> tokens;
474 Tokenize(params[i],tokens," ");
475
476 for(unsigned int j = 0; j < tokens.size(); ++j) {
477
478 char realNick[128]="";
479 get_nickname(tokens[j].c_str(),realNick,127);
480 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: LIBIRC_RFC_RPL_NAMREPLY user joined channel realNick [%s] tokens[j] [%s]\n", realNick,tokens[j].c_str());
481
482 // Only show MegaGlest users in the user list
483 //if(strncmp(&realNick[0],"MG_",3) == 0) {
484 nickList.push_back(realNick);
485 //}
486 }
487 }
488 }
489
490 IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
491 if(ctx != NULL) {
492 MutexSafeWrapper safeMutex(ctx->getMutexNickList(),string(__FILE__) + "_" + intToStr(__LINE__));
493 ctx->setCachedNickList(nickList);
494 }
495 }
496 break;
497 }
498 case LIBIRC_RFC_RPL_ENDOFNAMES:
499 {
500 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("!!!!! ===> IRC: Line: %d event = %u\n", __LINE__, event);
501
502 IRCThread *ctx = (IRCThread *)irc_get_ctx(session);
503 if(ctx != NULL) {
504 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d event = %u\n", __LINE__, event);
505
506 ctx->setEventDataDone(true);
507 }
508 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d event = %u\n", __LINE__, event);
509 }
510 break;
511 }
512
513 dump_event (session, buf, origin, params, count);
514 }
515
516 #endif
517
getEventDataDone()518 bool IRCThread::getEventDataDone() {
519 MutexSafeWrapper safeMutex(&mutexEventDataDone,string(__FILE__) + "_" + intToStr(__LINE__));
520 bool result = eventDataDone;
521 safeMutex.ReleaseLock();
522
523 return result;
524 }
setEventDataDone(bool value)525 void IRCThread::setEventDataDone(bool value) {
526 MutexSafeWrapper safeMutex(&mutexEventDataDone,string(__FILE__) + "_" + intToStr(__LINE__));
527 eventDataDone=value;
528 }
529
IRCThread(const std::vector<string> & argv,IRCCallbackInterface * callbackObj)530 IRCThread::IRCThread(const std::vector<string> &argv, IRCCallbackInterface *callbackObj) : BaseThread() {
531 uniqueID = "IRCThread";
532 this->argv = argv;
533 this->callbackObj = callbackObj;
534 ircSession = NULL;
535 eventData.clear();
536 setEventDataDone(false);
537 hasJoinedChannel = false;
538 lastNickListUpdate = time(NULL);
539 wantToLeaveChannel = false;
540 playerName = "";
541 }
542
disconnect()543 void IRCThread::disconnect() {
544 #if !defined(DISABLE_IRCCLIENT)
545
546 MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
547 bool validSession = (ircSession != NULL);
548 safeMutex.ReleaseLock();
549
550 if(validSession == true) {
551 setCallbackObj(NULL);
552 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Quitting Channel\n");
553
554 MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
555 if(ircSession != NULL) {
556 irc_disconnect(ircSession);
557 }
558 safeMutex1.ReleaseLock();
559
560 BaseThread::signalQuit();
561 hasJoinedChannel = false;
562 }
563 #else
564 BaseThread::signalQuit();
565 #endif
566 }
567
signalQuit()568 void IRCThread::signalQuit() {
569 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: signalQuit [%p]\n",ircSession);
570
571 #if !defined(DISABLE_IRCCLIENT)
572
573 MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
574 bool validSession = (ircSession != NULL);
575 safeMutex.ReleaseLock();
576
577 if(validSession == true) {
578 setCallbackObj(NULL);
579 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Quitting Channel\n");
580
581 MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
582 if(ircSession != NULL) {
583 irc_cmd_quit(ircSession, "MG Bot is closing!");
584 }
585 safeMutex1.ReleaseLock();
586 hasJoinedChannel = false;
587 }
588 BaseThread::signalQuit();
589
590 #else
591 BaseThread::signalQuit();
592 #endif
593 }
594
shutdownAndWait()595 bool IRCThread::shutdownAndWait() {
596 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: shutdownAndWait [%p]\n",ircSession);
597
598 signalQuit();
599 return BaseThread::shutdownAndWait();
600 }
601
SendIRCCmdMessage(string target,string msg)602 void IRCThread::SendIRCCmdMessage(string target, string msg) {
603 MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
604 bool validSession = (ircSession != NULL);
605 safeMutex.ReleaseLock();
606
607 if(validSession == true && hasJoinedChannel == true) {
608 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] sending IRC command to [%s] cmd [%s]\n",__FILE__,__FUNCTION__,__LINE__,target.c_str(),msg.c_str());
609
610 #if !defined(DISABLE_IRCCLIENT)
611 MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
612 int ret = 0;
613 if(ircSession != NULL) {
614 ret = irc_cmd_msg (ircSession, target.c_str(), msg.c_str());
615 }
616 safeMutex1.ReleaseLock();
617
618 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] sending IRC command to [%s] cmd [%s] ret = %d\n",__FILE__,__FUNCTION__,__LINE__,target.c_str(),msg.c_str(),ret);
619 #endif
620 }
621 }
622
GetIRCConnectedNickList(string target,bool waitForCompletion)623 std::vector<string> IRCThread::GetIRCConnectedNickList(string target, bool waitForCompletion) {
624 setEventDataDone(false);
625
626 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
627 MutexSafeWrapper safeMutexSession(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
628 bool validSession = (ircSession != NULL);
629 safeMutexSession.ReleaseLock();
630
631 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
632
633 if(validSession == true && hasJoinedChannel == true) {
634 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] sending IRC nick list command to [%s]\n",__FILE__,__FUNCTION__,__LINE__,target.c_str());
635
636 #if !defined(DISABLE_IRCCLIENT)
637
638 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
639
640 MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
641
642 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
643 int ret = irc_cmd_names (ircSession, target.c_str());
644 safeMutex1.ReleaseLock();
645
646 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
647 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] sending IRC nick list command to [%s] ret = %d\n",__FILE__,__FUNCTION__,__LINE__,target.c_str(),ret);
648
649 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
650
651 if(waitForCompletion == true) {
652
653 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
654
655 for(time_t tElapsed = time(NULL);
656 getEventDataDone() == false &&
657 this->getQuitStatus() == false &&
658 difftime(time(NULL),tElapsed) <= 5;) {
659 sleep(50);
660 }
661
662 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
663 }
664
665 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
666 #endif
667 }
668
669 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
670
671 MutexSafeWrapper safeMutex(&mutexNickList,string(__FILE__) + "_" + intToStr(__LINE__));
672 std::vector<string> nickList = eventData;
673 safeMutex.ReleaseLock();
674
675 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
676
677 return nickList;
678 }
679
isConnected(bool mutexLockRequired)680 bool IRCThread::isConnected(bool mutexLockRequired) {
681 bool ret = false;
682 if(this->getQuitStatus() == false) {
683 MutexSafeWrapper safeMutex(NULL,string(__FILE__) + "_" + intToStr(__LINE__));
684 int lockStatus = 0;
685 if(mutexLockRequired == true) {
686 lockStatus = safeMutex.setMutexAndTryLock(&mutexIRCSession);
687 }
688 bool validSession = (lockStatus == SDL_MUTEX_TIMEDOUT || (lockStatus == 0 && ircSession != NULL));
689 if(mutexLockRequired == true && lockStatus == 0) {
690 safeMutex.ReleaseLock();
691 }
692
693 if(validSession == true) {
694 #if !defined(DISABLE_IRCCLIENT)
695 MutexSafeWrapper safeMutex1(NULL,string(__FILE__) + "_" + intToStr(__LINE__));
696 if(ircSession != NULL) {
697 lockStatus = 0;
698 if(mutexLockRequired == true) {
699 lockStatus = safeMutex1.setMutexAndTryLock(&mutexIRCSession);
700 }
701 ret = (lockStatus == SDL_MUTEX_TIMEDOUT || (lockStatus == 0 && irc_is_connected(ircSession) != 0));
702 }
703 if(mutexLockRequired == true && lockStatus == 0) {
704 safeMutex1.ReleaseLock();
705 }
706 }
707 #endif
708 }
709
710 return ret;
711 }
712
getNickList()713 std::vector<string> IRCThread::getNickList() {
714 MutexSafeWrapper safeMutex(&mutexNickList,string(__FILE__) + "_" + intToStr(__LINE__));
715 std::vector<string> nickList = eventData;
716 safeMutex.ReleaseLock();
717
718 return nickList;
719 }
720
getCallbackObj(bool lockObj)721 IRCCallbackInterface * IRCThread::getCallbackObj(bool lockObj) {
722 MutexSafeWrapper safeMutex(NULL,string(__FILE__) + "_" + intToStr(__LINE__));
723 if(lockObj == true) {
724 safeMutex.setMutex(&mutexIRCCB);
725 }
726 return callbackObj;
727 }
setCallbackObj(IRCCallbackInterface * cb)728 void IRCThread::setCallbackObj(IRCCallbackInterface *cb) {
729 MutexSafeWrapper safeMutex(&mutexIRCCB,string(__FILE__) + "_" + intToStr(__LINE__));
730 callbackObj=cb;
731 }
732
execute()733 void IRCThread::execute() {
734 {
735 RunningStatusSafeWrapper runningStatus(this);
736 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] argv.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,argv.size());
737 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: IRCThread::execute Line: %d\n", __LINE__);
738
739 if(getQuitStatus() == true) {
740 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
741 return;
742 }
743
744 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"IRC thread is running\n");
745 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
746
747 try {
748 #if !defined(DISABLE_IRCCLIENT)
749 irc_callbacks_t callbacks;
750
751 MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
752 ircSession=NULL;
753 safeMutex.ReleaseLock(true);
754
755 if(argv.size() != 5) {
756 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC Usage: <server> <nick> <channel> : got params [%ld]\n",(long int)argv.size());
757 return;
758 }
759
760 memset (&callbacks, 0, sizeof(callbacks));
761
762 callbacks.event_connect = event_connect;
763 callbacks.event_join = event_join;
764 callbacks.event_nick = dump_event;
765 callbacks.event_quit = dump_event;
766 callbacks.event_part = event_leave;
767 callbacks.event_mode = dump_event;
768 callbacks.event_topic = dump_event;
769 callbacks.event_kick = dump_event;
770 callbacks.event_channel = event_channel;
771 callbacks.event_privmsg = event_privmsg;
772 callbacks.event_notice = event_notice;
773 callbacks.event_invite = dump_event;
774 callbacks.event_umode = dump_event;
775 callbacks.event_ctcp_rep = dump_event;
776 callbacks.event_ctcp_action = dump_event;
777 callbacks.event_unknown = dump_event;
778 callbacks.event_numeric = event_numeric;
779
780 callbacks.event_dcc_chat_req = irc_event_dcc_chat;
781 callbacks.event_dcc_send_req = irc_event_dcc_send;
782
783 if(this->getQuitStatus() == true) {
784 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
785 return;
786 }
787 safeMutex.Lock();
788 ircSession = irc_create_session (&callbacks);
789 bool validSession = (ircSession != NULL);
790
791 if(validSession == false) {
792 safeMutex.ReleaseLock();
793 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC Could not create session\n");
794 return;
795 }
796 safeMutex.ReleaseLock(true);
797
798 // this->execute_cmd_onconnect = "";
799 // if(argv.size() >= 5) {
800 // this->execute_cmd_onconnect = argv[4]; // /msg NickServ identify <password>.
801 // }
802
803 // this->password = "";
804 // if(argv.size() >= 5) {
805 // this->password = argv[4];
806 // }
807 this->username = argv[1];
808 if(argv.size() >= 4) {
809 this->username = argv[3];
810 }
811 this->channel = argv[2];
812 this->nick = argv[1];
813
814 safeMutex.Lock();
815 irc_set_ctx(ircSession, this);
816 safeMutex.ReleaseLock(true);
817
818 if(this->getQuitStatus() == true) {
819 return;
820 }
821
822 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
823
824 safeMutex.Lock();
825 if(irc_connect(ircSession, argv[0].c_str(), IRC_SERVER_PORT, 0, this->nick.c_str(), this->username.c_str(), "megaglest")) {
826 safeMutex.ReleaseLock();
827 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC Could not connect: %s\n", irc_strerror (irc_errno(ircSession)));
828 return;
829 }
830 safeMutex.ReleaseLock();
831
832 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
833
834 if(this->getQuitStatus() == true) {
835 return;
836 }
837
838 if(this->getQuitStatus() == true) {
839 return;
840 }
841
842 //printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
843 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
844
845 for(int iAttempts=1;
846 this->getQuitStatus() == false && iAttempts <= 7; ++iAttempts) {
847 //if(irc_run(ircSession)) {
848
849 int run_result = irc_run_session(ircSession);
850 if(run_result && this->getQuitStatus() == false) {
851 //printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
852
853 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC Could not run the session: %s run_result = %d\n", irc_strerror (irc_errno(ircSession)), run_result);
854 printf ("===> IRC Could not run the session: %s run_result = %d\n", irc_strerror (irc_errno(ircSession)), run_result);
855 }
856 }
857
858 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
859
860 //printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
861 #else
862 for(;this->getQuitStatus() == false;) {
863 sleep(50);
864 }
865 #endif
866 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC exiting IRC CLient!\n");
867 //printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
868 }
869 catch(const exception &ex) {
870 SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
871 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
872 }
873 catch(...) {
874 SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] UNKNOWN Error\n",__FILE__,__FUNCTION__,__LINE__);
875 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__);
876 }
877
878 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] IRC thread is exiting\n",__FILE__,__FUNCTION__,__LINE__);
879 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
880 //printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
881
882
883 //printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
884 // Delete ourself when the thread is done (no other actions can happen after this
885 // such as the mutex which modifies the running status of this method
886 MutexSafeWrapper safeMutex(&mutexIRCCB,string(__FILE__) + "_" + intToStr(__LINE__));
887 IRCCallbackInterface *cb = getCallbackObj(false);
888 if(cb != NULL) {
889 //printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
890 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC: Line: %d\n", __LINE__);
891 cb->IRC_CallbackEvent(IRC_evt_exitThread, NULL, NULL, 0);
892 }
893 safeMutex.ReleaseLock();
894
895 }
896 //printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
897
898 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In IRCThread() calling delete ...\n");
899
900 //printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
901 setDeleteAfterExecute(true);
902 }
903
irc_run_session(irc_session_t * session)904 int IRCThread::irc_run_session(irc_session_t * session) {
905 // if ( session->state != LIBIRC_STATE_CONNECTING )
906 // {
907 // session->lasterror = LIBIRC_ERR_STATE;
908 // return 1;
909 // }
910
911 MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
912
913 if ( isConnected(false) == false ) {
914 //session->lasterror = LIBIRC_ERR_STATE;
915 return 1;
916 }
917 safeMutex.ReleaseLock(true);
918
919 bool isSessionConnected = true;
920 while ( isSessionConnected == true && this->getQuitStatus() == false) {
921 struct timeval tv;
922 fd_set in_set, out_set;
923 int maxfd = 0;
924
925 tv.tv_usec = 250000;
926 tv.tv_sec = 0;
927
928 // Init sets
929 FD_ZERO (&in_set);
930 FD_ZERO (&out_set);
931
932 safeMutex.Lock();
933 irc_add_select_descriptors (session, &in_set, &out_set, &maxfd);
934 safeMutex.ReleaseLock(true);
935
936 if ( select (maxfd + 1, &in_set, &out_set, 0, &tv) < 0 ) {
937 int lastSocketError = Socket::getLastSocketError();
938 if ( lastSocketError == PLATFORM_SOCKET_INTERRUPTED ) {
939 continue;
940 }
941
942 //session->lasterror = LIBIRC_ERR_TERMINATED;
943 return 2;
944 }
945
946 safeMutex.Lock();
947 if ( irc_process_select_descriptors (session, &in_set, &out_set) ) {
948 safeMutex.ReleaseLock();
949 return 3;
950 }
951
952 isSessionConnected = isConnected(false);
953 safeMutex.ReleaseLock(true);
954 }
955
956 return 0;
957 }
958
~IRCThread()959 IRCThread::~IRCThread() {
960 //printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
961
962 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In ~IRCThread() ...\n");
963
964 if(IRCThread::globalCacheContainerName != NULL) {
965 //printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
966
967 IRCThread * &ircClient = CacheManager::getCachedItem< IRCThread * >(IRCThread::globalCacheContainerName);
968 ircClient = NULL;
969 }
970
971 //printf("In ~IRCThread Line: %d [%p]\n",__LINE__,this);
972 }
973
normalizeNick(char * nick)974 void normalizeNick(char *nick) {
975 // http://tools.ietf.org/html/rfc1459#section-2.3.1
976 // <target> ::= <to> [ "," <target> ]
977 // <to> ::= <channel> | <user> '@' <servername> | <nick> | <mask>
978 // <channel> ::= ('#' | '&') <chstring>
979 // <servername> ::= <host>
980 // <host> ::= see RFC 952 [DNS:4] for details on allowed hostnames
981 // <nick> ::= <letter> { <letter> | <number> | <special> }
982 // <mask> ::= ('#' | '$') <chstring>
983 // <chstring> ::= <any 8bit code except SPACE, BELL, NUL, CR, LF and
984 // comma (',')>
985 //
986 // Other parameter syntaxes are:
987 //
988 // <user> ::= <nonwhite> { <nonwhite> }
989 // <letter> ::= 'a' ... 'z' | 'A' ... 'Z'
990 // <number> ::= '0' ... '9'
991 // <special> ::= '-' | '[' | ']' | '\' | '`' | '^' | '{' | '}'
992
993 if(nick != NULL && strlen(nick) > 0) {
994 char *newNick = new char[strlen(nick)+1];
995 memset(newNick,0,strlen(nick)+1);
996 bool nickChanged = false;
997
998 for(unsigned int i = 0; i < strlen(nick); ++i) {
999 if(nick[i] == '-' || nick[i] == '[' || nick[i] == ']' || nick[i] == '_' ||
1000 nick[i] == '\\' || nick[i] == '`' || nick[i] == '^' ||
1001 nick[i] == '{' || nick[i] == '}' ||
1002 (nick[i] >= '0' && nick[i] <= '9') ||
1003 (nick[i] >= 'a' && nick[i] <= 'z') ||
1004 (nick[i] >= 'A' && nick[i] <= 'Z')) {
1005 strncat(newNick,&nick[i],1);
1006 }
1007 else {
1008 strcat(newNick,"-");
1009 nickChanged = true;
1010 }
1011 }
1012
1013 if(nickChanged == true) {
1014 strcpy(nick,newNick);
1015 }
1016
1017 delete [] newNick;
1018 }
1019 }
1020
connectToHost()1021 void IRCThread::connectToHost() {
1022 bool connectRequired = false;
1023
1024 MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
1025 bool validSession = (ircSession != NULL);
1026 safeMutex.ReleaseLock();
1027
1028 if(validSession == false) {
1029 connectRequired = true;
1030 }
1031 else {
1032 #if !defined(DISABLE_IRCCLIENT)
1033
1034 MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
1035 int result = irc_is_connected(ircSession);
1036 if(result != 1) {
1037 connectRequired = true;
1038 }
1039 safeMutex1.ReleaseLock();
1040 #endif
1041 }
1042
1043 if(connectRequired == false) {
1044 #if !defined(DISABLE_IRCCLIENT)
1045 MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
1046 if(irc_connect(ircSession, argv[0].c_str(), IRC_SERVER_PORT, 0, this->nick.c_str(), this->username.c_str(), "megaglest")) {
1047 safeMutex1.ReleaseLock();
1048
1049 if(SystemFlags::VERBOSE_MODE_ENABLED || IRCThread::debugEnabled) printf ("===> IRC Could not connect: %s\n", irc_strerror (irc_errno(ircSession)));
1050 return;
1051 }
1052 safeMutex1.ReleaseLock();
1053 #endif
1054 }
1055 }
1056
joinChannel()1057 void IRCThread::joinChannel() {
1058 wantToLeaveChannel = false;
1059 connectToHost();
1060
1061 MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
1062 bool validSession = (ircSession != NULL);
1063 safeMutex.ReleaseLock();
1064
1065 if(validSession == true) {
1066 #if !defined(DISABLE_IRCCLIENT)
1067
1068 MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
1069 IRCThread *ctx = (IRCThread *)irc_get_ctx(ircSession);
1070 if(ctx != NULL) {
1071 eventData.clear();
1072 setEventDataDone(false);
1073 hasJoinedChannel = false;
1074 lastNickListUpdate = time(NULL);
1075
1076 irc_cmd_join(ircSession, ctx->getChannel().c_str(), 0);
1077 safeMutex.ReleaseLock();
1078 }
1079 safeMutex.ReleaseLock();
1080 #endif
1081 }
1082 }
1083
leaveChannel()1084 void IRCThread::leaveChannel() {
1085 wantToLeaveChannel = true;
1086
1087 MutexSafeWrapper safeMutex(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
1088 bool validSession = (ircSession != NULL);
1089 safeMutex.ReleaseLock();
1090
1091 if(validSession == true) {
1092 #if !defined(DISABLE_IRCCLIENT)
1093
1094 MutexSafeWrapper safeMutex1(&mutexIRCSession,string(__FILE__) + "_" + intToStr(__LINE__));
1095 IRCThread *ctx = (IRCThread *)irc_get_ctx(ircSession);
1096 if(ctx != NULL) {
1097 irc_cmd_part(ircSession,ctx->getChannel().c_str());
1098 safeMutex.ReleaseLock();
1099 }
1100 safeMutex.ReleaseLock();
1101 #endif
1102 }
1103 }
1104
1105 }}//end namespace
1106