예제 #1
0
        /// <summary>
        /// IRC protocol implementation per IRC RFC 2812 https://tools.ietf.org/html/rfc2812
        /// </summary>
        public void ReadProtocol()
        {
            var command = _sr.ReadLine();

            Console.WriteLine(command);

            IRCCommand cmd = IRCCommand.Parse(command);

            if (command == null || cmd == null)
            {
                return;
            }

            switch (cmd.Command)
            {
            case "001":     //RPL_WELCOME
            case "002":     //RPL_YOURHOST
            case "003":     //RPL_CREATED
            case "004":     //RPL_MYINFO
            case "NOTICE":  //NOTICE
                OnServerMessage(command);
                SendCommand("JOIN " + Channel);
                break;

            case "332":
                OnServerMessage(command);
                break;

            case "353":     //RPL_NAMREPLY
                //make sure if for this channel,
                //i think i might get lists for all
                //channels in the server.
                if (cmd.Arguments[2] == Channel)
                {
                    //lists of users for the channel we are connected
                    //lets ignore the type of channels for now (@, =, *)
                    var ulea = new UserListEventArgs
                    {
                        Users = new List <string>(cmd.Arguments[3].Split(' '))
                    };


                    //checks if the command before this one was a 353,
                    //if it is, that means the list of users was not completely
                    //received, so this packet is a continuation of the list.
                    //otherwise, this is the beginning of the list.
                    if (_previousCommand != "353")
                    {
                        ulea.Type = UserListMessageType.ListStart;
                    }
                    else if (_previousCommand == "353")
                    {
                        ulea.Type = UserListMessageType.ListContinue;
                    }

                    OnUserList(ulea);
                }
                break;

            case "366":     //RPL_ENDOFNAMES
                //this is the end of the list of users.
                OnUserList(new UserListEventArgs()
                {
                    Type = UserListMessageType.ListEnd
                });
                break;

            case "433":     //ERR_NICKNAMEINUSE
                //tries to log in with a different nickname
                SendCommand("NICK " + Nickname + "_" + new Random().Next(100));
                break;

            case "PRIVMSG":     //new message to the channel, or private
                ReceivedEventArgs rec = new ReceivedEventArgs
                {
                    MessageFrom = cmd.Prefix.Substring(0, cmd.Prefix.IndexOf("!", StringComparison.Ordinal))
                };

                //TODO: handle messages that are for specific users, and show them in a unique way
                //maybe something like FromUser > ToUser: Hello, World!

                //let us worry about
                //public and private messages only
                if (cmd.Arguments[0] == Nickname)
                {
                    rec.Type = MessageType.MessageToMe;
                }
                else
                {
                    rec.Type = MessageType.MessageToChannel;
                }

                rec.Message = cmd.Arguments[1];
                OnReceived(rec);
                break;

            case "PING":     //reply with pong :p
                SendCommand("PONG " + command.Substring(5));
                break;

            case "JOIN":     //someone joined the channel
                //two options: We could either re-ask for the entire list
                //or simply add the specific user
                string userJoined = cmd.Prefix.Substring(0, cmd.Prefix.IndexOf("!", StringComparison.Ordinal));
                if (userJoined != Nickname)
                {
                    OnUserJoined(userJoined);
                }
                else
                {
                    //this is when I joined the channel.
                    OnConnected();
                    IsConnected = true;
                }
                break;

            case "PART":     //someone has left/quit the channel
            case "QUIT":
                string userLeft = cmd.Prefix.Substring(0, cmd.Prefix.IndexOf("!", StringComparison.Ordinal));
                if (userLeft != Nickname)
                {
                    OnUserQuit(userLeft);
                }
                else
                {
                    //leave chatroom gracefully
                    OnQuit();
                    IsConnected = false;
                }
                break;

            case "NICK":     //change in nick

                if (cmd.Arguments != null && cmd.Arguments.Count > 0)
                {
                    var newNickname = cmd.Arguments[0];
                    var oldNickname = cmd.Prefix.Substring(0, cmd.Prefix.IndexOf("!", StringComparison.Ordinal));

                    //raise this event to update the nickname in the lists
                    OnNicknameChanged(oldNickname, newNickname, NicknameChangedType.NickChanged);
                }

                break;

            case "ERROR":
                OnQuit();
                IsConnected = false;
                break;
            }

            _previousCommand = cmd.Command;
        }
예제 #2
0
        /// <summary>
        /// Get the IRC command, per IRC RFC 2812 https://tools.ietf.org/html/rfc2812
        /// </summary>
        /// <param name="raw">Raw string to be parsed.</param>
        /// <returns>An IRCCommand object with all the members to make sense out of the protocol.</returns>
        public static IRCCommand Parse(string raw)
        {
            IRCCommand tmp = null;

            if (!string.IsNullOrEmpty(raw))
            {
                string trailing = null;

                try
                {
                    if (raw.StartsWith(":"))
                    {
                        tmp = new IRCCommand();
                        var prefixEnd = raw.IndexOf(" ", StringComparison.Ordinal);
                        tmp.Prefix = raw.Substring(1, prefixEnd - 1);

                        var trailingStart = raw.IndexOf(" :", StringComparison.Ordinal);

                        if (trailingStart > -1)
                        {
                            trailing = raw.Substring(trailingStart + 2);
                        }
                        else
                        {
                            trailingStart = raw.Length;
                        }

                        var commandAndParameters = raw.Substring(prefixEnd + 1, trailingStart - prefixEnd - 1).Split(' ');

                        tmp.Command = commandAndParameters.First(); //this is the command

                        if (commandAndParameters.Length > 1)
                            tmp.Arguments = commandAndParameters.Skip(1).ToList(); //dont take the first one, thats the command

                        if (!string.IsNullOrEmpty(trailing))
                        {
                            if (tmp.Arguments == null)
                            {
                                tmp.Arguments = new List<string>();
                            }

                            tmp.Arguments = tmp.Arguments.Concat(new[] { trailing }).ToList();
                        }

                    }
                    else
                    {
                        if (raw.ToLower().StartsWith("ping"))
                        {
                            tmp = new IRCCommand
                            {
                                Command = "PING",
                                Arguments = new List<string> {raw.Substring(5)}
                            };
                        }
                        else if (raw.ToLower().StartsWith("error"))
                        {
                            tmp = new IRCCommand
                            {
                                Command = "ERROR",
                                Arguments = new List<string>()
                            };

                            tmp.Arguments.AddRange(raw.Split(':').Skip(1));
                        }
                    }
                }
                catch
                {
                    tmp = null;
                }
            }
            return tmp;
        }
예제 #3
0
        /// <summary>
        /// Get the IRC command, per IRC RFC 2812 https://tools.ietf.org/html/rfc2812
        /// </summary>
        /// <param name="raw">Raw string to be parsed.</param>
        /// <returns>An IRCCommand object with all the members to make sense out of the protocol.</returns>
        public static IRCCommand Parse(string raw)
        {
            IRCCommand tmp = null;

            if (!string.IsNullOrEmpty(raw))
            {
                string trailing = null;

                try
                {
                    if (raw.StartsWith(":"))
                    {
                        tmp = new IRCCommand();
                        var prefixEnd = raw.IndexOf(" ", StringComparison.Ordinal);
                        tmp.Prefix = raw.Substring(1, prefixEnd - 1);

                        var trailingStart = raw.IndexOf(" :", StringComparison.Ordinal);

                        if (trailingStart > -1)
                        {
                            trailing = raw.Substring(trailingStart + 2);
                        }
                        else
                        {
                            trailingStart = raw.Length;
                        }

                        var commandAndParameters = raw.Substring(prefixEnd + 1, trailingStart - prefixEnd - 1).Split(' ');

                        tmp.Command = commandAndParameters.First(); //this is the command

                        if (commandAndParameters.Length > 1)
                        {
                            tmp.Arguments = commandAndParameters.Skip(1).ToList(); //dont take the first one, thats the command
                        }
                        if (!string.IsNullOrEmpty(trailing))
                        {
                            if (tmp.Arguments == null)
                            {
                                tmp.Arguments = new List <string>();
                            }

                            tmp.Arguments = tmp.Arguments.Concat(new[] { trailing }).ToList();
                        }
                    }
                    else
                    {
                        if (raw.ToLower().StartsWith("ping"))
                        {
                            tmp = new IRCCommand
                            {
                                Command   = "PING",
                                Arguments = new List <string> {
                                    raw.Substring(5)
                                }
                            };
                        }
                        else if (raw.ToLower().StartsWith("error"))
                        {
                            tmp = new IRCCommand
                            {
                                Command   = "ERROR",
                                Arguments = new List <string>()
                            };

                            tmp.Arguments.AddRange(raw.Split(':').Skip(1));
                        }
                    }
                }
                catch
                {
                    tmp = null;
                }
            }
            return(tmp);
        }