public Message Parse(string input)
        {
            var msg = new Message();
            var scanner = new Strscan(input);

            var m = scanner.Match(reSender);
            if (m != null)
            {
                msg.Sender = m.Groups[1].Value;
            }

            m = scanner.Match(reWord);
            msg.Command = m.Groups[1].Value.ToUpperInvariant();

            while(!scanner.AtEnd)
            {
                m = scanner.Match(reArgv);
                if (m.Groups["trailing"].Success)
                {
                    msg.Argv.Add(m.Groups["trailing"].Value);
                    break;
                }
                else
                {
                    msg.Argv.Add(m.Groups["middle"].Value);
                }
            }

            return msg;
        }
        public string Emit(Message msg)
        {
            if (msg.Tags.Count > 0) { throw new NotImplementedException(); }

            var output = new StringBuilder();
            if(!string.IsNullOrEmpty(msg.Sender))
            {
                output.Append(":").Append(msg.Sender).Append(" ");
            }
            output.Append(msg.Command);

            var argcopy = new Queue<string>(msg.Argv);
            while(argcopy.Count > 0)
            {
                output.Append(" ");
                if (argcopy.Count == 1)
                {
                    if(String.IsNullOrEmpty(argcopy.Peek()) || argcopy.Peek().Contains(" ") || argcopy.Peek().First() == ':')
                    {
                        output.Append(":");
                    }
                }
                output.Append(argcopy.Dequeue().Replace("\n", "\\n").Replace("\r","\\r"));
            }
            return output.ToString();
        }
Beispiel #3
0
        public void HandleMessage(Irc.Message msg)
        {
            if (msg.Argv.Count < 1)
            {
                downstream.SendNeedMoreParams("MONITOR");
            }

            switch (msg.Argv[0].ToUpperInvariant())
            {
            case "+":
            case "-":
            case "C":
                downstream.SendNumeric(Numeric.ERR_UNKNOWNSUBCOMMAND, "MONITOR", msg.Argv[0], "Use FriendServ for that");
                break;

            case "L":
                var idlist = new List <MappedIdentity>();
                client.Friends.FriendList.ForEach(i => idlist.Add(mapper.MapUser(i.Key, i.Value.Name)));
                downstream.Send(idlist.ChunkTrivialBetter(512 / 63).Select(i =>
                {
                    var m = new Irc.Message(downstream.ServerName, Numeric.RPL_MONLIST, downstream.ClientNick);
                    m.Argv.Add(String.Join(",", i.Select(j => j.IrcNick)));
                    return(m);
                }).AppendSingle(new Irc.Message(downstream.ServerName, Numeric.RPL_ENDOFMONLIST, "End of monitor list")));
                break;

            case "S":
                var msglist = new List <Irc.Message>();
                client.Friends.FriendList.ForEach(i =>
                {
                    var id       = mapper.MapUser(i.Key, i.Value.Name);
                    var num      = i.Value.IsOnline ? Numeric.RPL_MONONLINE : Numeric.RPL_MONOFFLINE;
                    var response = new Irc.Message(downstream.ServerName, num, "*", id.IrcNick);
                    msglist.Add(response);
                });
                downstream.Send(msglist);
                break;

            case "NON":
                client.Friends.FriendList.ForEach(i =>
                {
                    if (!i.Value.IsOnline)
                    {
                        return;
                    }
                    downstream.SendFromServer("NOTICE", downstream.ClientNick, "[PRESENCE] {0:IrcNick} is now online".Format(mapper.MapUser(i.Key, i.Value.Name)));
                });
                break;
            }
        }
        public void HandleMessage(Irc.Message msg)
        {
            if (msg.Argv.Count < 1)
            {
                downstream.SendNeedMoreParams("MONITOR");
            }

            switch(msg.Argv[0].ToUpperInvariant())
            {
                case "+":
                case "-":
                case "C":
                    downstream.SendNumeric(Numeric.ERR_UNKNOWNSUBCOMMAND, "MONITOR", msg.Argv[0], "Use FriendServ for that");
                    break;
                case "L":
                    var idlist = new List<MappedIdentity>();
                    client.Friends.FriendList.ForEach(i => idlist.Add(mapper.MapUser(i.Key, i.Value.Name)));
                    downstream.Send(idlist.ChunkTrivialBetter(512 / 63).Select(i =>
                    {
                        var m = new Irc.Message(downstream.ServerName, Numeric.RPL_MONLIST, downstream.ClientNick);
                        m.Argv.Add(String.Join(",", i.Select(j=>j.IrcNick)));
                        return m;
                    }).AppendSingle(new Irc.Message(downstream.ServerName, Numeric.RPL_ENDOFMONLIST, "End of monitor list")));
                    break;
                case "S":
                    var msglist = new List<Irc.Message>();
                    client.Friends.FriendList.ForEach(i =>
                    {
                        var id = mapper.MapUser(i.Key, i.Value.Name);
                        var num = i.Value.IsOnline ? Numeric.RPL_MONONLINE : Numeric.RPL_MONOFFLINE;
                        var response = new Irc.Message(downstream.ServerName, num, "*", id.IrcNick);
                        msglist.Add(response);
                    });
                    downstream.Send(msglist);
                    break;
                case "NON":
                    client.Friends.FriendList.ForEach(i =>
                    {
                        if(!i.Value.IsOnline) { return; }
                        downstream.SendFromServer("NOTICE", downstream.ClientNick, "[PRESENCE] {0:IrcNick} is now online".Format(mapper.MapUser(i.Key, i.Value.Name)));
                    });
                    break;
            }
        }
        private void OnWho(Message msg)
        {
            if (msg.Argv.Count < 1) { SendNeedMoreParams("WHO"); return; }

            var key = msg.Argv[0];
            if (channels.ContainsKey(key))
            {
                foreach(var i in channels[key].Members)
                {
                    var reply = new List<string>(new string[] { username, key, i.Subject.IrcIdent, i.Subject.IrcDomain });
                    reply.Add(mapper.Grid.IrcDomain);
                    reply.Add(i.Subject.IrcNick);
                    if (i.IsOperator) { reply.Add("H@"); }
                    else if (i.Position <= PositionCategory.Talk) { reply.Add("H+");}
                    else { reply.Add("H"); }
                    SendFromServer(Numeric.RPL_WHOREPLY, reply.ToArray());
                }
            }
            SendFromServer(Numeric.RPL_ENDOFWHO);
        }
 private void OnTopic(Message msg)
 {
     SendFromServer(Numeric.RPL_TOPIC, msg.Argv[0], channels[msg.Argv[0]].Topic);
 }
        private void OnRegistrationMessage(Message msg)
        {
            switch(msg.Command)
            {
                case "USER":
                    userMsgSent = true;
                    break;
                case "PASS":
                    password = msg.Argv[0];
                    break;
                case "NICK":
                    username = msg.Argv[0];
                    break;
            }

            if (username != null && password != null && userMsgSent)
            {
                var names = username.Split('.');
                string firstname = names[0];
                string lastname = names.Count() == 1 ? "resident" : names[1];

                SendFromServer("NOTICE", username, "Connecting to the grid");

                if (upstream.Connect(firstname, lastname, password))
                {
                    selfId = mapper.Client;
                    SendFromServer(Numeric.RPL_WELCOME, username, string.Format("Welcome to the Headless SL Client {0}", selfId.IrcFullId));
                    SendFromServer(Numeric.RPL_YOURHOST, username, "Your host is sl.local, running HeadlessSlClient 0.1");

                    var tokens = new List<string>(supportTokens);
                    foreach(var i in handlers)
                    {
                        tokens.AddRange(i.SupportTokens);
                    }

                    tokens.Add("are supported by this server");

                    SendNumeric(Numeric.RPL_ISUPPORT, tokens.ToArray());
                    state = ConnectionState.CONNECTED;
                }
            }
        }
        private void OnPrivmsg(Message msg)
        {
            if (msg.Argv.Count < 2)
            {
                SendNeedMoreParams("PRIVMSG");
                return;
            }

            var outmsg = new IntermediateMessage();
            outmsg.Timestamp = DateTime.UtcNow;
            outmsg.Sender = selfId;

            if (msg.Argv[1].StartsWith("\x01" + "ACTION "))
            {
                outmsg.Payload = "/me " + msg.Argv[1].Substring(8).TrimEnd('\x01');
            }
            else { outmsg.Payload = msg.Argv[1]; }

            if (msg.Argv[0].StartsWith("#"))
            {
                outmsg.Type = MessageType.Talk;
                channels[msg.Argv[0]].SendMessage(outmsg);
            }
            else if(msg.Argv[0].StartsWith("+"))
            {
                int chan;
                if (int.TryParse(msg.Argv[0].Substring(1), out chan))
                {
                    upstream.SendNonzeroLocal(chan, msg.Argv[1]);
                }
            }
            else
            {
                outmsg.Type = MessageType.IM;
                upstream.SendMessageTo(mapper.MapUser(msg.Argv[0]), outmsg);
            }
        }
        private void OnMode(Message msg)
        {
            if (msg.Argv.Count < 1) { SendNeedMoreParams("MODE"); return; }
            if (!channels.ContainsKey(msg.Argv[0]))
            {
                SendFromServer(Numeric.ERR_USERSDONTMATCH, "Don't touch their modes!");
                return;
            }
            if (msg.Argv.Count > 1) {
                if (msg.Argv[1] == "+b")
                {
                    SendFromServer(Numeric.RPL_ENDOFBANLIST, username, msg.Argv[0], "End of ban list");
                }
                else
                {
                    SendFromServer(Numeric.ERR_CHANOPRIVSNEEDED, msg.Argv[0], username, "Chanop functions are not supported");
                }
                return;
            }

            SendFromServer(Numeric.RPL_CHANNELMODEIS, username, msg.Argv[0], "+t");
        }
 private void OnConnectedMessage(Message msg)
 {
     switch(msg.Command)
     {
         case "PING":
             SendFromServer("PONG", msg.Argv.ToArray());
             break;
         case "QUIT":
             upstream.Disconnect();
             state = ConnectionState.CLOSED;
             break;
         case "JOIN":
             break;
         case "PART":
             if (msg.Argv.Count < 1)
             {
                 SendNeedMoreParams("PART");
                 break;
             }
             SendFromClient("JOIN", msg.Argv[0]);
             break;
         case "PRIVMSG":
             OnPrivmsg(msg);
             break;
         case "WHO":
             OnWho(msg);
             break;
         case "NAMES":
             if (msg.Argv.Count < 1) { SendNeedMoreParams("NAMES"); break; }
             OnNames(msg.Argv[0]);
             break;
         case "MODE":
             OnMode(msg);
             break;
         case "TOPIC":
             if (msg.Argv.Count < 1)
             {
                 SendNeedMoreParams("TOPIC");
                 break;
             }
             if (msg.Argv.Count > 1)
             {
                 SendFromServer(Numeric.ERR_CHANOPRIVSNEEDED, "You can't set topics");
                 break;
             }
             OnTopic(msg);
             break;
         case "USERHOST":
             if (msg.Argv.Count < 1)
             {
                 SendNeedMoreParams("USERHOST");
                 break;
             }
             var id = mapper.MapUser(msg.Argv[0]);
             SendFromServer(Numeric.RPL_USERHOST, username, String.Format("{0}=+{1}@{2}", id.IrcNick, id.IrcIdent, id.IrcDomain));
             break;
         default:
             SendFromServer(Numeric.ERR_UNKNOWNCOMMAND, username, msg.Command, "Not implemented!");
             break;
     }
 }
 private void DispatchMessage(Message msg)
 {
     switch (state)
     {
         case ConnectionState.REGISTRATION:
             OnRegistrationMessage(msg);
             break;
         case ConnectionState.CONNECTED:
             lock (handlers)
             {
                 if(handlerCallbacks.ContainsKey(msg.Command))
                 {
                     handlerCallbacks[msg.Command](msg);
                     break;
                 }
             }
             OnConnectedMessage(msg);
             break;
     }
 }
 public void Send(Message message)
 {
     var data = parser.Emit(message);
     lock (connection)
     {
         writer.Write(data + "\r\n");
         writer.Flush();
     }
 }