5 using System
.Net
.Sockets
;
7 //using Threads = System.Threading;
8 using System
.Threading
;
9 using System
.Collections
.Generic
;
14 public sealed class CilIrcConnection
: IrcConnection
17 IList
<IrcChannel
> channelsJoined
= new List
<IrcChannel
>();
20 //const int DefaultTime = 1000;
22 bool identified
= false;
25 TcpClient client
= new TcpClient();
33 //Timer readTimer = new Timer(DefaultTime);
35 volatile int nbTimes
= 0;
38 IParser parser
= new DefaultParser();
40 public override void Connect()
46 this.MessageReceived
+= AutomaticPong
;
47 this.MessageReceived
+= Identification
;
50 client
.LingerState
= new LingerOption(true, 2);
53 client
.Connect(Info
.Server
, Info
.Port
);
54 } catch (Exception e
) {
56 throw new ConnectionException("The connection to the server wasn't successful : "+e
.Message
, e
);
59 ns
= client
.GetStream();
60 sw
= new StreamWriter(ns
, Info
.Charset
);
61 sr
= new StreamReader(ns
, Info
.Charset
);
63 // Thread initialization
64 readThread
= new Thread(WorkerRead
);
65 readThread
.IsBackground
= true;
66 readThread
.Name
= "Read Thread";
67 readThread
.Priority
= ThreadPriority
.BelowNormal
;
70 // First identification pass try
71 if (!string.IsNullOrEmpty(Info
.Password
))
72 SendRawMessage(Rfc
.Pass(Info
.Password
));
73 SendRawMessage(Rfc
.Nick(Info
.Pseudo
));
74 SendRawMessage(Rfc
.User(Info
.Pseudo
, Info
.RealName
));
78 public override void Disconnect()
80 if (client
== null || !client
.Connected
)
83 SendRawMessage(Rfc
.Quit("Powered by Monologue"));
87 protected override void Dispose (bool managedRes
)
89 foreach (IrcChannel chan
in JoinedChannels
)
91 // Disconnect the machine
107 public override void SendRawMessage(string message
)
109 if (string.IsNullOrEmpty(message
))
110 throw new ArgumentNullException("message");
112 OnMessageSent(new MessageEventArgs(message
));
114 // Check if the message is correctly finished with a \r\n sequence
115 if (message
.EndsWith(Rfc
.Crlf
))
118 sw
.WriteLine(message
);
124 public override IrcChannel
JoinChannel(string channelName
)
126 IrcChannel temp
= new CilIrcChannel(channelName
, this);
127 channelsJoined
.Add(temp
);
128 OnChannelCreated(new ChannelEventArgs(temp
));
132 public override IrcChannel
[] JoinedChannels
{
134 IrcChannel
[] temp
= new IrcChannel
[channelsJoined
.Count
];
135 channelsJoined
.CopyTo(temp
, 0);
141 public override string Nick
{
142 get { return Info.Pseudo; }
144 if (string.IsNullOrEmpty(value))
152 public override string RealName
{
153 get { return Info.RealName; }
156 public override string Server
{
157 get { return Info.Server; }
160 public bool IsIdentified
{
161 get { return identified; }
165 #region private helpers methods
166 private void UpdateNickname()
168 this.SendRawMessage(Rfc
.Nick(Info
.Pseudo
));
171 private void WorkerRead()
178 if (!client
.Connected
)
181 // Sleep if the channel is idle
182 if (Info
.UsePassiveMode
&& client
.Available
== 0 && identified
) {
183 if (sleepTime
< 5000 && ++nbTimes
% 1500 == 0)
185 if (nbTimes
== int.MaxValue
) {
189 Thread
.Sleep(sleepTime
);
196 while ((temp
= sr
.ReadLine()) != null)
197 OnMessageReceived(new MessageEventArgs(temp
));
198 } catch (IOException ex
) {
199 Logger
.Error(string.Format("Exception while reading data. Inner Exception : {O} ::: Error code : {1}", ex
.InnerException
.Message
,
200 (ex
.InnerException
is SocketException
) ? ((SocketException
)ex
.InnerException
).ErrorCode
.ToString() : "No code"), ex
);
202 // Let other things happens
207 // Big hack, but don't know why some server are reluctant to accept my Nick, User and all messages
208 // thus if they want the war so be it (I repeatidly send them the connection commands until they accept
210 private void Identification(object sender
, MessageEventArgs e
)
212 // Some server return an 451 error and other nothing
213 if (((parser
.RetrieveMessageType(e
.Message
) == MessageType
.Reply
&&
214 parser
.RetrieveNumericalReply(e
.Message
) == 451)) || ++messageCount
== 3) {
215 // Resend the connection commands
216 if (!string.IsNullOrEmpty(Info
.Password
))
217 SendRawMessage(Rfc
.Pass(Info
.Password
));
218 SendRawMessage(Rfc
.Nick(Info
.Pseudo
));
219 SendRawMessage(Rfc
.User(Info
.Pseudo
, Info
.RealName
));
221 if (parser
.RetrieveMessageType(e
.Message
) == MessageType
.Reply
222 && parser
.RetrieveNumericalReply(e
.Message
) == 1) {
223 this.MessageReceived
-= Identification
;
224 OnIdentified(new ConnectionEventArgs(this.Server
, Info
.Port
));
230 // An automatic wrapper which call PONG at each PING messages
231 private void AutomaticPong(object sender
, MessageEventArgs e
)
233 if (string.IsNullOrEmpty(e
.Message
))
236 if (parser
.RetrieveMessageType(e
.Message
) == MessageType
.Action
237 && parser
.RetrieveAction(e
.Message
) == ActionType
.Ping
) {
239 SendRawMessage(Rfc
.Pong(parser
.RetrieveParameters(e
.Message
)));