using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Timers;
namespace AutobotServer
{
public class ServerInstance : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
var h = PropertyChanged;
if (null != h) h(this, new PropertyChangedEventArgs(propertyName));
}
#region Data
private int m_iInstanceId;
private ServerInstanceState m_eServerState;
private ServerCaller m_ServerCaller;
private Form1 m_pParentForm;
private ServerManager m_pParentManager;
private String m_sClientID;
private String m_sClientIDShort;
private int m_iMessageCount;
private DateTime m_oLastAlive;
public String ShortClientID { get { return this.m_sClientIDShort; } set { if (value != this.m_sClientIDShort) { this.m_sClientIDShort = value; OnPropertyChanged("m_sClientIDShort"); } } }
public String ClientID { get { return this.m_sClientID; } set { if (value != this.m_sClientID) { this.m_sClientID = value; OnPropertyChanged("m_sClientID"); } } }
public BindingList<StatusPair> m_lStats;
#endregion //Data
public enum ServerInstanceState
{
Idle,
Getting_MessageSize,
Getting_Message,
};
public ServerInstance( int a_iIntanceId
, System.Net.Sockets.Socket a_SocketForClient
, Form1 a_pParentForm
, ServerManager a_pParentManager
)
{
m_iInstanceId = a_iIntanceId;
m_pParentForm = a_pParentForm;
m_pParentManager = a_pParentManager;
m_iMessageCount = 0;
m_lStats = new BindingList<StatusPair>();
m_oLastAlive = DateTime.Now;
m_eServerState = ServerInstanceState.Idle;
m_ServerCaller = new ServerCaller(a_pParentForm, a_SocketForClient);
m_ServerCaller.TcpOutReceived += new TcpDataReceivedHandler(this.TcpOutputStream);
m_ServerCaller.TcpErrorReceived += new TcpDataReceivedHandler(this.TcpErrorStream);
m_ServerCaller.HasDataEventCB += new HasDataHandler(this.HasData);
m_ServerCaller.Completed += new EventHandler(this.processCompletedOrCanceled);
m_ServerCaller.Cancelled += new EventHandler(this.processCompletedOrCanceled);
m_ServerCaller.Failed += new System.Threading.ThreadExceptionEventHandler(this.processFailed);
m_ServerCaller.Start();
ClientID = "Waiting";
ShortClientID = "Waiting";
}
#region Ui Helper
public void BindUi(DataGridView a_dg)
{
a_dg.DataSource = m_lStats;
}
#endregion
#region Methods
public void Cancel()
{
m_ServerCaller.Cancel();
m_ServerCaller = null;
}
public void SendMessage(String a_Msg)
{
if (null!=m_ServerCaller)
{
string sMsgHeader = "Praveen_" + a_Msg.Length.ToString("D8") + "_" + m_iMessageCount.ToString("D7");
m_ServerCaller.SendData(sMsgHeader + a_Msg);
++m_iMessageCount;
}
}
private void LostConnection()
{
if (null != m_ServerCaller)
{
m_ServerCaller.Cancel();
m_ServerCaller = null;
}
m_pParentManager.ServerInstanceDied(this);
}
public void HasData(object sender, TcpDataReceivedEventArgs e)
{
if (null == m_ServerCaller)
{
return;
}
if (m_eServerState == ServerInstanceState.Idle)
{
m_eServerState = ServerInstanceState.Getting_MessageSize;
m_ServerCaller.ReadAmount(24);
}
}
public void TcpOutputStream(object sender, TcpDataReceivedEventArgs e)
{
if (null == m_ServerCaller)
{
return;
}
if (m_eServerState == ServerInstanceState.Getting_MessageSize)
{
if (24 == e.Text.Length && e.Text.Substring(0, 8) == "Praveen_")
{
int iSize = Convert.ToInt32(e.Text.Substring(8, 8));
int iMsgNumber = Convert.ToInt32(e.Text.Substring(17, 7));
m_eServerState = ServerInstanceState.Getting_Message;
m_ServerCaller.ReadAmount(iSize);
}
else
{
LostConnection();
}
}
else if (m_eServerState == ServerInstanceState.Getting_Message)
{
m_oLastAlive = DateTime.Now;
ProcessClientMessage(e.Text);
m_eServerState = ServerInstanceState.Idle;
}
}
public void TcpErrorStream(object sender, TcpDataReceivedEventArgs e)
{
LostConnection();
}
public void processCompletedOrCanceled(object sender, EventArgs e)
{
LostConnection();
}
public void processFailed(object sender, System.Threading.ThreadExceptionEventArgs e)
{
LostConnection();
}
public bool TryPing()
{
TimeSpan oElapsed = DateTime.Now - m_oLastAlive;
if(oElapsed.Seconds < 20)
{
return true;
}
else if (oElapsed.Seconds < 40)
{
SendMessage("ping");
return true;
}
else if (oElapsed.Seconds < 60)
{
return true;
}
return false;
}
private void UpdateStats(string a_sStats)
{
m_pParentForm.SuspendLayoutForAutoM(this);
foreach (var oPair in m_lStats)
{
oPair.CurrentCount = 0;
}
String[] sList = a_sStats.Split(',');
foreach (var sData in sList)
{
String[] sCouple = sData.Split(':');
int iVal = 0;
if(2==sCouple.Length && Int32.TryParse(sCouple[1], out iVal))
{
bool bFound = false;
foreach (var oPair in m_lStats)
{
if (oPair.Status.Equals(sCouple[0]))
{
oPair.CurrentCount = iVal;
bFound = true;
break;
}
}
if (!bFound)
{
m_lStats.Add(new StatusPair(sCouple[0], iVal));
}
}
}
m_pParentForm.ResumeLayoutForAutoM(this);
}
private void ProcessClientMessage(String a_sMsg)
{
// we expect only 1 System Message per message from server and needs to be lowercase
if (a_sMsg.StartsWith("chat ") && a_sMsg.Length > 5)
{
string sCommand = "[" + ShortClientID +"]" + a_sMsg.Substring(5);
m_pParentForm.IncomingChatMsg(sCommand);
return;
}
else if (a_sMsg.StartsWith("summary ") && a_sMsg.Length > 8)
{
UpdateStats(a_sMsg.Substring(8));
return;
}
else if (a_sMsg.StartsWith("machine ") && a_sMsg.Length > 8)
{
ClientID = a_sMsg.Substring(8);
string[] sIds = ClientID.Split(',');
if(sIds.Length > 0)
{
ShortClientID = sIds[0];
}
else
{
ShortClientID = ClientID;
}
return;
}
else if (a_sMsg.StartsWith("sysresponse ") && a_sMsg.Length > 12)
{
string sCommand = a_sMsg.Substring(12);
m_pParentForm.IncomingResponse(sCommand);
return;
}
String[] sList = a_sMsg.Split(',');
foreach (var aCmd in sList)
{
string oCmd = aCmd.Trim();
if (oCmd.StartsWith("ping"))
{
SendMessage("pong");
}
else if (oCmd.StartsWith("pong"))
{
}
else
{
//Unknown
}
}
}
#endregion // Methods
};
}