using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Windows.Forms; namespace chatServ { public partial class formServer : Form { static Dictionary> whoiswho; static Dictionary msg; static MyQueue sms; static Thread listenerThread; static TcpListener listener; static Statistics stats; static System.Windows.Forms.Timer timer1sec; static int port; static bool bIsRunning = false; delegate void SetTextCallback(string text); private BackgroundWorker backgroundWorker1; // private static Random random; /*\________________________________________ | ___________________ \ | _/\_ | public stuff | | | ^_^ |_________________| | |_________________________________________*/ // -------------------[ constructor public formServer() { InitializeComponent(); // begin timer1sec = new System.Windows.Forms.Timer(); timer1sec.Interval = 1000; timer1sec.Tick += new EventHandler(Refresh1sec); // fix coupla odds // RichTextBox.CheckForIllegalCrossThreadCalls = false; serverMsg.DetectUrls = true; serverMsg.ReadOnly = true; // init my parms bIsRunning = false; listener = null; // allocate my tables stats = new Statistics(); whoiswho = new Dictionary>(); sms = new MyQueue(); // load server msg.s msg = new Dictionary(); msg.Add(0110, "Error resolving DNS or IP."); msg.Add(0115, "Error dealing with socket."); msg.Add(0120, "Error with connx."); msg.Add(0195, "Stream.Read failed."); msg.Add(0200, "Server happily started."); msg.Add(0210, "Server stopped on demand."); msg.Add(0300, "Welcome Admin ;)"); msg.Add(5100, "Server is fine and well."); msg.Add(5110, "Already running."); msg.Add(5550, "Server stopped."); msg.Add(5551, "Already stopped."); msg.Add(5600, "Port number is null."); msg.Add(5610, "Port number out of range."); } /*_______________________________________________ | ________________ \ | _/\_ | BACK OFF | | | \ ^_^ |______________| | | protected && private use only | |________________________________________________*/ private void RefreshUserList() { } private void PingClients() { } private void Refresh1sec(Object myObject, EventArgs myEventArgs) { stats.IncrUptime(1000); labelUptime.Text = stats.Uptime(); //PingUsers(); } // Identification Friend or Foe private bool IFF(string str) { int tot = 0; for (int i = 0; i < 14; i++) tot += (int)str[i]; if (tot == 0x049F) return true; return false; } // new user ? private bool IsPresentIP(IPAddress checkme) { foreach (KeyValuePair> kvp in whoiswho) { if (kvp.Key == checkme) return true; } return false; } // how many alias do ya have private bool IsPresentNick( IPAddress ip, string nick) { LinkedList tmp = whoiswho[ip]; foreach (User usr in tmp) { if (usr.Nick() == nick) return true; } return false; } // any command ? userlevel ?? private void ParseInput( string str) { if (str[0] == '<') { int nickStart = str.IndexOf('<') + 1; int nickEnd = str.IndexOf('>') - 1; string nick = str.Substring(nickStart, nickEnd); string newMsg = str.Substring(nickEnd + 2); if ( newMsg[0].CompareTo("/") == 1 ) { if (newMsg[1] == 'm' || newMsg[1] == 'M') { if (newMsg[2] == 'e' || newMsg[2] == 'E') { if (newMsg[3] == ' ') { AddMsg(10, 99, str); } } if (newMsg[2] == ' ') { // send pvt } } } else { AddMsg(99, 99, str); } } } private void SendOutput( string who) { UnicodeEncoding encoder = new UnicodeEncoding(); byte[] buff = encoder.GetBytes(who); int len = buff.GetLength(0); foreach (KeyValuePair> kvp in whoiswho) { LinkedList tmp = kvp.Value; foreach (User usr in tmp) { NetworkStream stream = null; try { stream = usr.Sox().GetStream(); } catch { AddMsg(1, 6, msg[120]); return; } stream.Write(buff, 0, len); } } } // format dat darn string private void RTBRefresh( string text) { if (serverMsg.InvokeRequired) { SetTextCallback d = new SetTextCallback(RTBRefresh); this.Invoke(d, new object[] { text }); } else { serverMsg.Rtf = @"{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fswiss\fprq2\fcharset0 Microsoft Sans Serif, 8.25;}}{\colortbl ;\red0\green0\blue0; \red127\green127\blue127; \red160\green160\blue160; \red196\green196\blue196; \red255\green255\blue255; \red195\green0\blue0; \red220\green220\blue0; \red0\green195\blue0; \red127\green0\blue127; \red255\green0\blue255; \red0\green196\blue100; \red0\green0\blue255; \red0\green127\blue127; \red0\green127\blue255; \red0\green255\blue255; \red255\green255\blue0; \red175\green145\blue0; \red0\green127\blue0; }{\fs16\cf4 " + sms.ToString() + "\\par}"; } } // color and enqueue the msg private void AddMsg(int sender, int code, string msg) { string tmp = "\\cf4 " + DateTime.Now.ToString("yyyy.MM.dd-H:mm:ss - "); switch (sender) { case 0: // server tmp += "\\cf5[\\cf14Server\\cf5] "; break; case 1: // debug tmp += "\\cf5[\\cf17Debug\\cf5] "; break; case 10: // /me tmp += "\\cf16* " + msg.Substring(1, msg.IndexOf('>') - 1) + " " + msg.Substring(msg.IndexOf(' ') + 1) + "\\par"; stats.IncrMsgCnt(); break; // case 10: // operserv // case 20: // chanserv // case 30: // nickserv case 31: tmp += "\\cf17>>>\\cf8 " + msg + " has joined #channel"; break; case 32: tmp += "\\cf11<<<\\cf8 " + msg + " has parted #channel"; break; case 99: // regular msg tmp += "\\cf8" + "<" + "\\cf4" + msg.Substring(1, msg.IndexOf('>') - 1) + "\\cf8" + "> " + "\\cf4" + msg.Substring(msg.IndexOf('>') + 1) + "\\par"; stats.IncrMsgCnt(); break; } switch (code) { case 6: // kernel msg tmp += "\\cf6 " + msg + "\\par"; break; case 7: // OK msg tmp += "\\cf7 " + msg + "\\par"; break; case 8: // highlight msg tmp += "\\cf8 " + msg + "\\par"; break; case 99: // no further decoration break; } // enqueue the msg sms.Enqueue(tmp); if ( sender == 10 || sender == 31 || sender == 32 || sender == 99 ) SendOutput(tmp); RTBRefresh( @"{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fswiss\fprq2\fcharset0 Microsoft Sans Serif, 8.25;}}{\colortbl ;\red0\green0\blue0; \red127\green127\blue127; \red160\green160\blue160; \red196\green196\blue196; \red255\green255\blue255; \red195\green0\blue0; \red220\green220\blue0; \red0\green195\blue0; \red127\green0\blue127; \red255\green0\blue255; \red0\green196\blue100; \red0\green0\blue255; \red0\green127\blue127; \red0\green127\blue255; \red0\green255\blue255; \red255\green255\blue0; \red175\green145\blue0; \red0\green127\blue0; }{\fs16\cf4 " + sms.ToString() + "\\par}" ); } protected void ListenerThread() { if (bIsRunning) { labelMsg.Text = msg[5110]; return; } // if listener never been initialized if (listener == null) { if (port_s.Text == null) { labelMsg.Text = msg[5600]; return; } port = Convert.ToInt32(port_s.Text); if (port < 1050 || port > 0xfffe) { labelMsg.Text = msg[5610]; return; } try { listener = new TcpListener(IPAddress.Any, port); } catch { AddMsg(1, 6, msg[110]); return; } } // else initialize it try { listener.Start(512); } catch { AddMsg(1, 6, msg[115]); return; } // init msg timer1sec.Start(); stats.StartRel(); // port_s.ReadOnly = true; bIsRunning = true; labelMsg.Text = msg[5100]; AddMsg(0, 7, msg[200]); AddMsg(0, 8, msg[300]); while (bIsRunning) { // any conn ? if (listener.Pending()) { NetworkStream stream = null; TcpClient clientConn = listener.AcceptTcpClient(); try { stream = clientConn.GetStream(); } catch { AddMsg(1, 6, msg[120]); return; } // get the user IP IPAddress userIP = IPAddress.Parse(((IPEndPoint) clientConn.Client.RemoteEndPoint).Address.ToString()); byte[] buffer = new Byte[1024]; if ((stream.Read(buffer, 0, 1024)) <= 0) { AddMsg(1, 6, msg[195]); return; } string strTemp = buffer.ToString(); string[] parms = strTemp.Split('$'); if (!IsPresentIP(userIP)) { if (IFF(parms[0])) { LinkedList nickNames = new LinkedList(); User user = new User( clientConn, parms[1], DateTime.Now); nickNames.AddLast(user); whoiswho.Add(userIP, nickNames); // send MOTD Byte[] bar; if (System.IO.File.Exists("motd.rtf")) { bar = System.IO.File.ReadAllBytes("motd.rtf"); stream.Write(bar, 0, bar.GetLength(0)); } AddMsg(31, 99, parms[1]); } } else { if ( ! IsPresentNick(userIP, parms[1])) { // add nick to its pool at its IP index User user = new User( clientConn, parms[1], DateTime.Now); whoiswho[userIP].AddLast(user); // LAST MINUTE NOTE: // DANGER OF DUPLICATED NICKS !! // implement a nick_validation !!!! } ParseInput(strTemp.ToString()); } // close = else } // close = if listener pending } // close = while } // END of ListenerThread() private void buttonStart_Click(object sender, EventArgs e) { listenerThread = new Thread(new ThreadStart(ListenerThread)); listenerThread.IsBackground = true; listenerThread.Name = "Listener"; listenerThread.Start(); } private void buttonStop_Click(object sender, EventArgs e) { if (!bIsRunning) { labelMsg.Text = msg[5551]; return; } listener.Stop(); timer1sec.Stop(); foreach (KeyValuePair> kvp in whoiswho) { LinkedList tmp = kvp.Value; foreach (User usr in tmp) { usr.Sox().Close(); } } bIsRunning = false; port_s.ReadOnly = false; AddMsg(0, 6, msg[210]); labelMsg.Text = msg[5550]; } private void buttonExit_Click(object sender, EventArgs e) { if (bIsRunning) listener.Stop(); // remeber to close all the sockets !! this.Close(); } } // EOC - end of class /*_____________________________________ | ________________ \ | _/\_ | BACK OFF | | | \ ^_^ |______________| | | internal use only | \_____________________________________*/ internal class MyQueue : Queue { public override string ToString() { string result = ""; foreach (string mystr in this) result += mystr; return result; } } // EOC - end of class internal class User { private TcpClient sox; private DateTime timeEntry; private int level; private string nick; // contructor public User( TcpClient tc, string nn, DateTime dt) { sox = tc; nick = nn.ToString(); timeEntry = dt; // TEMP !!!! level = 1; // normal user } public string Nick() { return nick.ToString(); } public DateTime Timentry() { return timeEntry; } public int Level() { return level; } public TcpClient Sox() { return sox; } } // EOC - end of class internal class Statistics { private static Int64 msgCount; private static DateTime uptime; private static DateTime startRelative; private static DateTime endRelative; private static DateTime startAbsolut; private static DateTime endAbsolut; // constructor public Statistics() { startAbsolut = DateTime.Now; msgCount = 0; uptime = new DateTime(0); startRelative = new DateTime(0); endRelative = new DateTime(0); endAbsolut = new DateTime(0); } public Int64 MsgCount() { return msgCount; } public string Uptime() { return uptime.Millisecond.ToString("H:mm:ss"); } public void IncrMsgCnt() { ++msgCount; } public void IncrUptime(double ticks) { uptime.AddMilliseconds(ticks); } public void StartRel() { startRelative = DateTime.Now; } } // EOC - end of class }