using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using BeWo.Data; using BeWo.Data.Access; using BeWo.Data.Entities; using BS.Shared; namespace BeWoChatServer { public class Server { // Fehlercodes zwischen 1000 und 1499 private static readonly object _Lock = string.Empty; private static readonly Dictionary clientList = new Dictionary(); protected static Socket serverSocket; private static AsyncCallback asyncCallback; private static int clientCount; public static void Main(string[] args) { try { serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); var server = new IPEndPoint(IPAddress.Any, 5000); serverSocket.Bind(server); serverSocket.Listen(4); serverSocket.BeginAccept(OnClientConnected, null); while (true) { } } catch (Exception e) { Debug.WriteLine("ChatServerException (1010): " + e.Message); } } public static void OnClientConnected(IAsyncResult asyncResult) { try { var workerSocket = serverSocket.EndAccept(asyncResult); Interlocked.Increment(ref clientCount); clientList.Add(workerSocket, 0); WaitForClientData(workerSocket, "", 0, 0); serverSocket.BeginAccept(OnClientConnected, null); } catch (SocketException e) { Debug.WriteLine("ChatServerException (1020): " + e.Message); } } public static void WaitForClientData(Socket socket, string clientName, long oid, long recipientPersonOid) { try { if (asyncCallback == null) { asyncCallback = OnReceiveData; } var packet = new Packet(socket, clientName, oid, recipientPersonOid); socket.BeginReceive(packet.DataBuffer, 0, packet.DataBuffer.Length, SocketFlags.None, asyncCallback, packet); } catch (Exception e) { Debug.WriteLine("ChatServerException (1030): " + e.Message); } } public static void OnReceiveData(IAsyncResult asyncResult) { var dataPacket = (Packet) asyncResult.AsyncState; try { var responseByteCount = dataPacket.Socket.EndReceive(asyncResult); var chars = new char[responseByteCount]; var decoder = Encoding.UTF8.GetDecoder(); decoder.GetChars(dataPacket.DataBuffer, 0, responseByteCount, chars, 0); if(chars.Count(f => f.Equals(';')) >= 4) { var message = new string(chars); dataPacket.GetData(message); } switch(dataPacket.DataIdentifier) { case DataIdentifier.Login: try { Monitor.Enter(_Lock); var endPoint = dataPacket.Socket.RemoteEndPoint; var endPointCollection = clientList.Select(s => s.Key.RemoteEndPoint).ToList(); var istEnthalten = endPointCollection.Contains(endPoint); if(istEnthalten) { clientList[dataPacket.Socket] = dataPacket.SenderPersonOid; } var notificationPacket = new Packet(dataPacket.Socket, dataPacket.ClientName, dataPacket.SenderPersonOid, 0) {DataIdentifier = DataIdentifier.StatusNotificationLogin, Tenant = dataPacket.Tenant}; foreach (var client in clientList.Where(w => !w.Value.Equals(dataPacket.SenderPersonOid))) { client.Key.Send(notificationPacket.GetDataStream()); } // Boradcast var abc = clientList.Where(w => w.Value != dataPacket.SenderPersonOid && w.Value > 0).Select(s => s.Value).Distinct().ToList(); var msg = ""; foreach(var oid in abc) { msg += oid; if(abc.IndexOf(oid) != abc.Count - 1) { msg += ","; } } if(msg.Length > 0) { var packet = new Packet {ChatMessage = msg, ClientName = dataPacket.ClientName, DataIdentifier = DataIdentifier.StatusNotificationLoginBroadcast, MessageTimeStamp = DateTime.Now, Tenant = dataPacket.Tenant, SenderPersonOid = dataPacket.SenderPersonOid}; dataPacket.Socket.Send(packet.GetDataStream()); } } finally { Monitor.Exit(_Lock); } break; case DataIdentifier.Message: if(responseByteCount == 0) { try { Monitor.Enter(_Lock); var notificationPacketLogout2 = new Packet(dataPacket.Socket, dataPacket.ClientName, dataPacket.SenderPersonOid, 0) {DataIdentifier = DataIdentifier.StatusNotificationLogout}; clientList.Remove(dataPacket.Socket); foreach(var client in clientList) { client.Key.Send(notificationPacketLogout2.GetDataStream()); } dataPacket.Socket.Close(); } finally { Monitor.Exit(_Lock); } return; } else { try { Monitor.Enter(_Lock); DefaultHibernateSessionManager.CurrentTenant = dataPacket.Tenant; var chatMessage = new ChatMessage { SenderPersonOid = dataPacket.SenderPersonOid, ChatText = dataPacket.ChatMessage, EmpfängerPersonOid = dataPacket.RecipientPersonOid, Uhrzeit = dataPacket.MessageTimeStamp, InsUser = dataPacket.ClientName }; DAOFactory.GenericDAO.Insert(chatMessage); // Testweise die Id einfügen if(chatMessage.Oid != null) { dataPacket.ServerseitigeOid = chatMessage.Oid.Value; } if(dataPacket.RecipientPersonOid > 0) { if (clientList.ContainsValue(dataPacket.RecipientPersonOid)) { var recipients = clientList.Where(w => w.Value.Equals(dataPacket.RecipientPersonOid)); foreach(var recipient in recipients) { recipient.Key.Send(dataPacket.GetDataStream()); } } var packet = new Packet { ClientseitigeOid = dataPacket.ClientseitigeOid, ServerseitigeOid = dataPacket.ServerseitigeOid, DataIdentifier = DataIdentifier.MessageResponse }; dataPacket.Socket.Send(packet.GetDataStream()); } } finally { Monitor.Exit(_Lock); } } break; case DataIdentifier.Logout: clientList.Remove(dataPacket.Socket); var notificationPacketLogout = new Packet(dataPacket.Socket, dataPacket.ClientName, dataPacket.SenderPersonOid, 0) {DataIdentifier = DataIdentifier.StatusNotificationLogout}; foreach (var client in clientList.Where(w => !w.Value.Equals(dataPacket.SenderPersonOid))) { client.Key.Send(notificationPacketLogout.GetDataStream()); } break; case DataIdentifier.Team: try { Monitor.Enter(_Lock); DefaultHibernateSessionManager.CurrentTenant = dataPacket.Tenant; var chatMessage = new ChatMessage { SenderPersonOid = dataPacket.SenderPersonOid, ChatText = dataPacket.ChatMessage, EmpfängerPersonOid = dataPacket.RecipientPersonOid, Uhrzeit = dataPacket.MessageTimeStamp, InsUser = dataPacket.ClientName, TeamOid = dataPacket.RecipientPersonOid }; var team = DAOFactory.GenericDAO.LoadByID(dataPacket.RecipientPersonOid); DAOFactory.GenericDAO.Insert(chatMessage); var personOids = team.MemberList.Select(s => s.Person.Oid.Value); if (chatMessage.Oid != null) { dataPacket.ServerseitigeOid = chatMessage.Oid.Value; } foreach(var recipient in clientList.Where(w => w.Value != dataPacket.SenderPersonOid && personOids.Contains(w.Value))) { recipient.Key.Send(dataPacket.GetDataStream()); } var packet = new Packet { ClientseitigeOid = dataPacket.ClientseitigeOid, ServerseitigeOid = dataPacket.ServerseitigeOid, DataIdentifier = DataIdentifier.MessageResponse }; dataPacket.Socket.Send(packet.GetDataStream()); } finally { Monitor.Exit(_Lock); } break; } WaitForClientData(dataPacket.Socket, dataPacket.ClientName, dataPacket.SenderPersonOid, dataPacket.RecipientPersonOid); } catch (Exception e) { var sender = dataPacket.Socket; var notificationPacketLogout = new Packet(dataPacket.Socket, dataPacket.ClientName, dataPacket.SenderPersonOid, 0) { DataIdentifier = DataIdentifier.StatusNotificationLogout }; try { Monitor.Enter(_Lock); if(clientList.ContainsKey(sender)) { clientList.Remove(sender); foreach(var client in clientList) { client.Key.Send(notificationPacketLogout.GetDataStream()); } sender.Close(); } } finally { Monitor.Exit(_Lock); } Debug.WriteLine("ChatServerException: " + e.Message); } } } }