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