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(); }
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(); } }