Advertisement
Guest User

Untitled

a guest
Jan 8th, 2016
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.39 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Net.Sockets;
  7. using System.Runtime.InteropServices;
  8. using System.Text;
  9.  
  10. namespace Server {
  11.     partial class Static {
  12.         /**
  13.          * Todo código dentro desta #region não é de minha autoria, encontrei em algum site aleatório e não lembro
  14.          * o nome do cara que desenvolveu. Qualquer erro relacionado a este código não é de forma alguma minha culpa.
  15.          * Esse código serve de alguma maneira pra receber um "sinal" de que o console está fechando e assim eu possa
  16.          * salvar o banco de dados.
  17.          */
  18.         #region Console HOOK
  19.         [DllImport ("Kernel32")]
  20.         public static extern bool SetConsoleCtrlHandler (HandlerRoutine Handler, bool Add);
  21.  
  22.         public delegate bool HandlerRoutine (CtrlTypes CtrlType);
  23.  
  24.         public enum CtrlTypes {
  25.             CTRL_C_EVENT = 0,
  26.             CTRL_BREAK_EVENT,
  27.             CTRL_CLOSE_EVENT,
  28.             CTRL_LOGOFF_EVENT = 5,
  29.             CTRL_SHUTDOWN_EVENT
  30.         }
  31.  
  32.         private static bool ConsoleCtrlCheck (CtrlTypes ctrlType) {
  33.             OnClose ();
  34.             return true;
  35.         }
  36.         #endregion
  37.  
  38.         #region HEADERS
  39.         const string AUTH = "000";
  40.         const string LOGIN = "001";
  41.         const string REGISTER = "002";
  42.         const string MOTD = "003";
  43.         const string BASIC = "004";
  44.         const string CLOSE = "005";
  45.         const string CHAR_EXISTS = "006";
  46.         const string LOAD_CHAR = "007";
  47.         const string GRAPHICS = "008";
  48.         const string CREATE_CHAR = "009";
  49.         const string DELETE_CHAR = "010";
  50.         #endregion
  51.  
  52.         static HashSet<Client> Clients;
  53.         static HashSet<User> Users;
  54.         static Socket Listener;
  55.         static long HighIndex;
  56.  
  57.         /// <summary>
  58.         /// Ponto de entrada do programa.
  59.         /// </summary>
  60.         /// <param name="args"></param>
  61.         static void Main (string [] args) {
  62.             SetConsoleCtrlHandler (new HandlerRoutine (ConsoleCtrlCheck), true);
  63.             Settings.Initialize ();
  64.  
  65.             Console.Title = Settings.GetString ("Title");
  66.             Console.WriteLine ("Iniciando servidor...");
  67.  
  68.             Users = new HashSet<User> ();
  69.             Clients = new HashSet<Client> ();
  70.             HighIndex = 0;
  71.  
  72.             LoadDatabase ();
  73.             CreateListener ();
  74.  
  75.             Console.WriteLine ("Servidor iniciado!");
  76.             Console.Read ();
  77.         }
  78.  
  79.         /// <summary>
  80.         /// Cria o listener
  81.         /// </summary>
  82.         static void CreateListener () {
  83.             Listener = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  84.             Listener.Bind (new IPEndPoint (IPAddress.Any, Settings.GetInt ("Port")));
  85.             Listener.Listen (Settings.GetInt("Backlog"));
  86.             Listener.BeginAccept (OnConnectRequest, null);
  87.         }
  88.  
  89.         /// <summary>
  90.         /// Callback para novas conexões
  91.         /// </summary>
  92.         /// <param name="ar"></param>
  93.         static void OnConnectRequest (IAsyncResult ar) {
  94.             Client client = new Client (Listener.EndAccept (ar));
  95.             client.Index = HighIndex;
  96.             client.Socket.BeginReceive (client.Buffer, 0, client.Buffer.Length, SocketFlags.None, OnRead, client);
  97.             Clients.Add (client);
  98.             HighIndex++;
  99.             Listener.BeginAccept (OnConnectRequest, null);
  100.             Console.WriteLine ("Usuário {0} conectado!", client.Socket.RemoteEndPoint);
  101.         }
  102.  
  103.         /// <summary>
  104.         /// Callback para recebimento de mensagens.
  105.         /// </summary>
  106.         /// <param name="ar"></param>
  107.         static void OnRead (IAsyncResult ar) {
  108.             try {
  109.                 Client client = (Client)ar.AsyncState;
  110.                 int length = client.Socket.EndReceive (ar);
  111.                 if (length <= 0) {
  112.                     Console.WriteLine ("Usuário {0} desconectado!", client.Socket.RemoteEndPoint);
  113.                     client.Socket.Close ();
  114.                     if (Clients.Contains (client))
  115.                         Clients.Remove (client);
  116.                 } else {
  117.                     /* O padrão de mensagens trocadas entre client/server é: {header}{message}{separador}
  118.                        O header sempre terá 3 caracteres de comprimento, já a mensagem é ilimitada, ao final
  119.                        é adicionado um "\n" como separador. */
  120.                     string recv = Encoding.UTF8.GetString (client.Buffer, 0, length);
  121.                     string [] lines = recv.Split ('\n');
  122.                     for (int i = 0; i < lines.Length; i++) {
  123.                         if (string.IsNullOrWhiteSpace (lines [i]))
  124.                             continue;
  125.                         int index = lines [i].IndexOf ('>') + 1;
  126.                         Process (client, lines [i].Substring (0, index), lines [i].Substring (index, lines [i].LastIndexOf ('<') - index));
  127.                     }
  128.                     client.Socket.BeginReceive (client.Buffer, 0, client.Buffer.Length, SocketFlags.None, OnRead, client);
  129.                 }
  130.             } catch (SocketException) { }
  131.         }
  132.  
  133.         /// <summary>
  134.         /// Envia uma mensagem para um usuário.
  135.         /// </summary>
  136.         /// <param name="client"></param>
  137.         /// <param name="header"></param>
  138.         /// <param name="message"></param>
  139.         static void Send (Client client, string message) {
  140.             StringBuilder stringBuilder = new StringBuilder ();
  141.             stringBuilder.Append (message);
  142.             stringBuilder.Append ("\n");
  143.  
  144.             byte [] buffer = Encoding.UTF8.GetBytes (stringBuilder.ToString ());
  145.             client.Socket.BeginSend (buffer, 0, buffer.Length, SocketFlags.None, OnSend, client);
  146.         }
  147.  
  148.         /// <summary>
  149.         /// Envia uma mensagem para um usuário.
  150.         /// </summary>
  151.         /// <param name="index"></param>
  152.         /// <param name="header"></param>
  153.         /// <param name="message"></param>
  154.         static void Send (long index, string message) {
  155.             Send (Clients.Where (c => c.Index == index).First (), message);
  156.         }
  157.  
  158.         /// <summary>
  159.         /// Callback de envio de mensagens
  160.         /// </summary>
  161.         /// <param name="ar"></param>
  162.         static void OnSend (IAsyncResult ar) {
  163.             Client client = (Client)ar.AsyncState;
  164.             int length = client.Socket.EndSend (ar);
  165.             Console.WriteLine ("Enviado {0} bytes para {1}", length, client.Socket.RemoteEndPoint);
  166.         }
  167.  
  168.         /// <summary>
  169.         /// Método chamado quando o console está sendo fechado.
  170.         /// </summary>
  171.         static void OnClose () {
  172.             SaveDatabase ();
  173.         }
  174.  
  175.         /// <summary>
  176.         /// Carrega o banco de dados (usuários).
  177.         /// </summary>
  178.         static void LoadDatabase () {
  179.             Console.WriteLine ("Carregando contas de usuário...");
  180.             if (!File.Exists ("./users"))
  181.                 File.Create ("./users").Close ();
  182.  
  183.             string text = File.ReadAllText ("./users");
  184.             if (string.IsNullOrEmpty (text))
  185.                 return;
  186.  
  187.             string [] users = text.Split (';');
  188.             for (int i = 0; i < users.Length - 1; i++) {
  189.                 string [] user = users [i].Split (':');
  190.                 Users.Add (new User (user[0], user[1], user[2]));
  191.             }
  192.         }
  193.        
  194.         /// <summary>
  195.         /// Salva os usuários registrados.
  196.         /// </summary>
  197.         static void SaveDatabase () {
  198.             StringBuilder sb = new StringBuilder ();
  199.             foreach (var user in Users) { sb.AppendFormat ("{0}:{1}:{2};", user.Name, user.Password, user.Group); }
  200.             File.WriteAllText ("./users", sb.ToString ());
  201.         }
  202.        
  203.         /// <summary>
  204.         /// Processa os dados recebidos.
  205.         /// </summary>
  206.         /// <param name="client"></param>
  207.         /// <param name="header"></param>
  208.         /// <param name="message"></param>
  209.         static void Process (Client client, string header, string message) {
  210.             Console.WriteLine ("Recebido {1} de {0}", client.Socket.RemoteEndPoint, header);
  211.             string [] data;
  212.             switch (header) {
  213.                 case "<20>": // Encerra a conexão de testes
  214.                     Clients.Remove (client);
  215.                     break;
  216.                 case "<0>": // Autenticação
  217.                     Send (client, string.Format ("<0 {0}>'e' n={1}</0>", client.Index, Console.Title));
  218.                     break;
  219.                 case "<mod>": // Mensagem do dia?
  220.                     Send (client, string.Format ("<mod>{0}</mod>", Settings.GetString ("Motd")));
  221.                     break;
  222.                 case "<ver>": // Versão?
  223.                     Send (client, "<ver>1.7</ver>");
  224.                     break;
  225.                 case "<login>": // Login
  226.                     data = message.Split (':');
  227.  
  228.                     // Usuários com mesmo nome
  229.                     var users = Users.Where (u => u.Name == data [0]);
  230.                     // Usuários com mesma nome e senha
  231.                     var user = users.Where (u => u.Password == data [1]);
  232.  
  233.                     if (user.Count () > 0) {
  234.                         client.Name = data[0];
  235.                         client.Group = user.First ().Group;
  236.                         Send (client, "<login>allow</login>");
  237.                     } else {
  238.                         if (users.Count () > 0) { Send (client, "<login>wp</login>"); }
  239.                         else { Send (client, "<login>wu</login>"); }
  240.                     }
  241.                     break;
  242.                 case "<reges>": // Registro
  243.                     data = message.Split (':');
  244.                     var regUser = Users.Where (u => u.Name == data [0]);
  245.                     if (regUser.Count () <= 0) {
  246.                         Users.Add (new User (data [0], data [1]));
  247.                         Send (client, "<reges>success</reges>");
  248.                     } else { Send (client, "<reges>wu</reges>"); }
  249.                     break;
  250.                 case "<2>":
  251.                     Send (client, string.Format ("<2>{0}</2>", client.Name));
  252.                     break;
  253.                 case "<5>":
  254.                     Send (client, string.Format ("<5 {0}>{1}</5>", client.Index, message));
  255.                     break;
  256.             }
  257.         }
  258.     }
  259. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement