using BNEBotCore;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace BNEBotLauncher
{
public class LauncherServer : IDisposable
{
public LauncherServer(int port)
{
m_AcceptThread = new Thread(ServerProc);
m_AcceptThread.Start(port);
m_UpdateThread = new Thread(UpdateProc);
m_UpdateThread.Start();
}
private void ServerProc(object port)
{
m_Server = new TcpListener(IPAddress.Any, (int)port);
m_Server.Start();
while (!m_Exit)
{
try
{
TcpClient client = m_Server.AcceptTcpClient();
BotManagerConnection connection = new BotManagerConnection(client, () => { m_Exit = true; });
lock (m_DataLock)
{
m_Connections.Add(connection);
}
}
catch (SocketException)
{
// Just exit
break;
}
}
//m_Server.Stop();
}
private void UpdateProc()
{
while (!m_Exit)
{
if (m_Connections.Count > 0)
{
// TODO: for now, we are just sending the whole state every once in a while. We should rewrite
// this to only send update notifications
if ((DateTime.Now - m_LastInfoSend).TotalSeconds > 1)
{
m_LastInfoSend = DateTime.Now;
List<BotInfo> bots = BotProcessManager.GetBotInfo();
BotInfoCommand cmd = new BotInfoCommand()
{
UpdatedBots = bots
};
cmd.Finalize();
lock (m_DataLock)
{
List<BotManagerConnection> droppedConnections = null;
foreach (BotManagerConnection connection in m_Connections)
{
try
{
connection.SendMessage(cmd);
}
catch (IOException)
{
// An IO exception here means the client has disconnected
if (droppedConnections == null)
droppedConnections = new List<BotManagerConnection>();
droppedConnections.Add(connection);
}
}
if (droppedConnections != null)
{
foreach (BotManagerConnection connection in droppedConnections)
{
m_Connections.Remove(connection);
}
}
}
}
// Update our connections
lock (m_DataLock)
{
foreach (BotManagerConnection connection in m_Connections)
{
connection.Receive();
}
}
}
Thread.Sleep(100);
}
}
public bool IsRunning
{
get { return !m_Exit; }
}
#region IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (!m_Disposed)
{
if (disposing)
{
m_Exit = true;
m_Server.Stop();
//m_AcceptThread.Join();
m_UpdateThread.Join();
m_AcceptThread.Abort();
//m_UpdateThread.Abort();
}
}
m_Disposed = true;
}
private bool m_Disposed;
#endregion
private TcpListener m_Server;
private Thread m_AcceptThread;
private Thread m_UpdateThread;
private bool m_Exit;
private List<BotManagerConnection> m_Connections = new List<BotManagerConnection>();
private object m_DataLock = new object();
// FIXME: we are sending all data repeatedly for now
private DateTime m_LastInfoSend = DateTime.Now;
}
}