/* Thor Server 2.0 Project - Codenamed "Stockholm" Copyright 2008 - 2009 Joe Hegarty This file is part of The Thor Server 2.0 Project - Codenamed "Stockholm". The Thor Server 2.0 Project - Codenamed "Stockholm" is free software: you can redistribute it and/or modify it under the terms of the Microsoft Public License The Thor Server Project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Microsoft Public License for more details. You should have received a copy of the Microsoft Public License along with The Thor Server Project. If not, see http://www.opensource.org/licenses/ms-pl.html */ using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; using StockholmLibrary.Util; namespace StockholmLibrary.Net { //------------------------------------ public class ConnectionManager { private const int LISTEN_QUEUE_SIZE = 5; private uint _connectionCount = 0; private Socket _listeningSocket = null; private AsyncCallback _socketConnectionCallback; private Thread _sendThread; private static object _peerListLock = new object(); private static List _peerList = new List(); //********************************************** public void StartListening(int portNumber) { _listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, portNumber); _listeningSocket.Bind(ipLocal); _listeningSocket.Listen(LISTEN_QUEUE_SIZE); Logging.LogEvent("ConnectionManager", "Listening on port " + portNumber, Logging.ELogLevel.INFO); _socketConnectionCallback = new AsyncCallback(OnClientConnect); _listeningSocket.BeginAccept(_socketConnectionCallback, null); _sendThread = new Thread(new ThreadStart(SendThread)); _sendThread.Name = "Send Thread"; _sendThread.Start(); } //********************************************** private void OnClientConnect(IAsyncResult asyn) { try { Peer newPeer = new Peer(this, _connectionCount++, _listeningSocket.EndAccept(asyn)); _listeningSocket.BeginAccept(_socketConnectionCallback, null); Logging.LogEvent("ConnectionManager", "New connection opened. Assigned id " + newPeer.PeerID, Logging.ELogLevel.INFO); lock (_peerListLock) { _peerList.Add(newPeer); } } catch (ObjectDisposedException) { Logging.LogEvent("ConnectionManager", "Socket closed before accept completed.", Logging.ELogLevel.INFO); } catch (SocketException e) { Logging.LogEvent("ConnectionManager", "Unhandled socket error: " + e.ToString(), Logging.ELogLevel.WARNING); } } //********************************************** public void OnClientDisconnect(Peer peer) { if (peer != null) { lock (_peerListLock) { _peerList.Remove(peer); } } } //********************************************** private static void SendThread() { Logging.LogEvent("ConnectionManager", "SendThread started succesfully", Logging.ELogLevel.INFO); while (Stockholm.Get().IsRunning) { lock (_peerListLock) { foreach (var peer in _peerList) { peer.Update(); } } Thread.Sleep(5); } } //********************************************** public ClientPacket Receive() { lock (_peerListLock) { foreach (var peer in _peerList) { ClientPacket packet = peer.Receive(); if (packet == null) continue; return packet; } } return null; } } }