/TsChanManLibrary/cSockets.cs
C# | 441 lines | 314 code | 67 blank | 60 comment | 75 complexity | 997c569ca2194f954afdd6128e99abe6 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Net.Sockets;
- using System.Net;
- using System.Windows.Forms;
- using System.IO;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.Xml.Serialization;
- using System.Diagnostics;
-
- namespace TsChanManLibrary
- {
- public enum SocketPacketType
- {
- ChannelLaunch = 1,
- ChannelStopMessage = 2,
- GetAllChannelsFromServer = 3
- }
-
- public class SocketPacket
- {
- public SocketPacket(Socket s)
- { Soc = s; }
-
- public readonly Socket Soc;
- public byte[] dataBuffer = new byte[100000]; // 100 KB for one channel (including picture)
- }
-
- public class cSockets
- {
- private static Socket socketClient;
- private static Socket socketServer;
-
- private static AsyncCallback asyServerEndReceive = new AsyncCallback(AfterServerDataReceived);
- private static AsyncCallback asyClientEndReceive = new AsyncCallback(AfterClientDataReceived);
-
- public static bool IsServerStarted
- { get { return isServerStarted; } }
-
- private static bool isServerStarted;
-
- public delegate void ServerDataEventHandler(string sData);
- public static event ServerDataEventHandler OnDataReceived;
-
- /// <summary>
- /// As the client sends data packet by packet, each packet gets stored
- /// in 'ServerReceiveData' step by step - 'iServerRecvd' remebers how many
- /// bytes have been stored on the server
- /// </summary>
- private static byte[] ServerReceiveData = new byte[100000];
- private static int iServerRecvd = 0;
-
- /// <summary>
- /// Stores the data the client receives (eg. All channels from the server)
- /// </summary>
- private static List<byte> ClientReceiveData;
- private static SocketPacketType ClientSockPckType;
-
- #region "Server"
-
- /// <summary>
- /// This computer starts a server (listening to clients that connect on the
- /// port configured via cSettings.Cfg.iServerPort) asynchronisly
- /// </summary>
- public static void StartServer()
- {
- // Create the ServerSocket
- socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, cSettings.Cfg.iServerPort);
-
- socketServer.Bind(ipLocal);
- socketServer.Listen(1); // Just allow one connection as clients won't stay connected for too long
-
- // Call "OnClientConnect" asynchronisly after Client connects to this server
- socketServer.BeginAccept(new AsyncCallback(OnClientConnect), null);
-
- isServerStarted = true;
- }
-
- /// <summary>
- /// Stops listening to the port specified in cSettings.Cfg.iServerPort
- /// </summary>
- public static void StopServer()
- {
- if (socketServer != null)
- { socketServer.Close(); }
- isServerStarted = false;
- }
-
- /// <summary>
- /// Gets called after client established a connection to this computer
- /// </summary>
- /// <param name="asyn"></param>
- private static void OnClientConnect(IAsyncResult asyn)
- {
- try
- {
- Socket socClient = socketServer.EndAccept(asyn);
-
- SocketPacket sP = new SocketPacket(socClient);
-
- // asyServerEndReceive = Asynch Callback to AfterServerDataReceived()
- socClient.BeginReceive(sP.dataBuffer, 0,
- sP.dataBuffer.Length,
- SocketFlags.None,
- asyServerEndReceive,
- sP);
-
- // Since the main Socket is now free, it can go back and wait for
- // other clients who are attempting to connect
- socketServer.BeginAccept(new AsyncCallback(OnClientConnect), null);
- }
- catch (ObjectDisposedException)
- { } // No need to handle anything as Exception occures if the connection is closeds
- }
-
- /// <summary>
- /// Get's called after a connected clients started sending data to this server
- /// </summary>
- /// <param name="iARes"></param>
- private static void AfterServerDataReceived(IAsyncResult iARes)
- {
- SocketPacket socketData = (SocketPacket)iARes.AsyncState;
-
- // Complete the BeginReceive() asynchronous call by EndReceive() method
- // which will return the number of bytes written to the stream
- // by the client
- int iReceived = socketData.Soc.EndReceive(iARes);
-
- try
- {
- // As we might already have data from the last packet, add the next
- // packet of data to the existing one
- for (int i = 0; i < iReceived; i++)
- {
- ServerReceiveData[iServerRecvd] = socketData.dataBuffer[i];
- iServerRecvd++;
- }
-
-
- // If we received data, wait for another packet, which might contain
- // more data we need
- if (iReceived != 0)
- {
- socketData.Soc.BeginReceive(socketData.dataBuffer, 0,
- socketData.dataBuffer.Length,
- SocketFlags.None,
- asyServerEndReceive,
- socketData);
- }
- else // It's over once we receive no more data
- {
- if (ServerReceiveData[0] != 0)
- {
- SocketPacketType SockPckType = (SocketPacketType)Enum.Parse(typeof(SocketPacketType), ServerReceiveData[0].ToString());
-
- // Represents the data to be sent back to the client
- byte[] DataToSend = null;
-
- if (SockPckType == SocketPacketType.ChannelLaunch)
- {
- ChannelType ChanType = (ChannelType)Enum.Parse(typeof(ChannelType), ServerReceiveData[1].ToString());
-
- byte[] ChannelData = new byte[ServerReceiveData.Length - 2];
- for (int y = 2; y < ServerReceiveData.Length - 2; y++)
- {
- ChannelData[y - 2] = ServerReceiveData[y];
- }
-
- ChannelBase c;
- if (ChanType == ChannelType.DVBSFull)
- { c = (ChannelDVBSFull)cHelper.DeserializeFromXML(typeof(ChannelDVBSFull), ChannelData); }
- else if (ChanType == ChannelType.DVBS)
- { c = (ChannelDVBS)cHelper.DeserializeFromXML(typeof(ChannelDVBS), ChannelData); }
- else if (ChanType == ChannelType.DVBC)
- { c = (ChannelDVBC)cHelper.DeserializeFromXML(typeof(ChannelDVBC), ChannelData); }
- else if (ChanType == ChannelType.DVBT)
- { c = (ChannelDVBT)cHelper.DeserializeFromXML(typeof(ChannelDVBT), ChannelData); }
- else
- { c = (ChannelBase)cHelper.DeserializeFromXML(typeof(ChannelBase), ChannelData); }
-
- cChannels cM = new cChannels(ChanType);
- cM.LaunchChannelFromClientData(c);
-
-
- // Inital wait time TSReader should take to tune into channel,
- // Parse the transport stream and starts VLC to stream
- System.Threading.Thread.Sleep(8500);
-
- bool vlcFound = false;
- bool tsrFound = false;
- int i = 0;
- while (vlcFound == false)
- {
- foreach (Process p in Process.GetProcesses())
- {
- try
- {
- if (!tsrFound && p.ProcessName == "TSReader")
- { tsrFound = true; }
- else if (!vlcFound && p.ProcessName == "vlc")
- { vlcFound = true; }
- else if (vlcFound && tsrFound)
- {
- DataToSend = cHelper.SerializeToXML("1|OK");
- break;
- }
- }
- catch (Exception)
- { } // Most likely "Access denied" - just continue with the next Process
- }
-
- // Acts as timeout
- System.Threading.Thread.Sleep(2000);
- if (i > 15) break;
-
- i++;
- }
- if (DataToSend == null)
- { DataToSend = cHelper.SerializeToXML("0|VLC or TSReader have not been started"); }
- }
- else if (SockPckType == SocketPacketType.ChannelStopMessage)
- {
- bool IsTSReaderClosed = false;
-
- // Look for the TSReader process and close TSReader
- foreach (Process P in Process.GetProcessesByName("TSReader"))
- {
- IsTSReaderClosed = true;
- P.CloseMainWindow();
- }
-
- // Prepare a message for the client to see if TSReader has bee closed
- if (IsTSReaderClosed)
- { DataToSend = cHelper.SerializeToXML("1|TSReader successfully closed"); }
- else
- { DataToSend = cHelper.SerializeToXML("0|No TSReader instance found"); }
- }
- else if (SockPckType == SocketPacketType.GetAllChannelsFromServer)
- {
- // Determite the channel type and send all the channels within this type
- // to the client
- ChannelType ChanType = (ChannelType)Enum.Parse(typeof(ChannelType), ServerReceiveData[1].ToString());
- cChannels c = new cChannels(ChanType);
- DataToSend = cHelper.SerializeToXML(c.currChannels);
- }
-
- // Insert A SocketType-Flag, so the client knows what to receive
- byte[] FinalData = new byte[DataToSend.Length + 1];
- DataToSend.CopyTo(FinalData, 1);
- FinalData[0] = Convert.ToByte(SockPckType);
-
- socketData.Soc.Send(FinalData);
- socketData.Soc.Close(); // No need to send anymore data
-
- // Reset data for the next client
- iServerRecvd = 0;
- ServerReceiveData = new byte[100000];
- }
- else
- { socketData.Soc.Shutdown(SocketShutdown.Both); }
- }
- }
- catch (ObjectDisposedException)
- { } // Just continue
- catch (Exception e)
- {
- socketData.Soc.Close();
- MessageBox.Show(e.Message);
- }
- }
- #endregion
-
- #region "Client"
- /// <summary>
- /// Get's called after the server sent a response saying if the desired channel could be started
- /// </summary>
- /// <param name="iARes"></param>
- private static void AfterClientDataReceived(IAsyncResult iARes)
- {
- SocketPacket theSockId = null;
- int ReceivedBytes = 0;
-
- try
- {
- theSockId = (SocketPacket)iARes.AsyncState;
-
- ReceivedBytes = theSockId.Soc.EndReceive(iARes);
-
- if (ReceivedBytes != 0) // Means there's still data to come...
- {
- if (ClientReceiveData == null)
- {
- ClientReceiveData = new List<byte>();
- ClientSockPckType = (SocketPacketType)Enum.Parse(typeof(SocketPacketType), theSockId.dataBuffer[0].ToString());
-
- // Seperate the SocketTypeFlag from the real data
- byte[] UsedData = new byte[theSockId.dataBuffer.Length - 1];
-
- for (int i = 0; i < ReceivedBytes; i++)
- {
- if (i != 0)
- { ClientReceiveData.Add(theSockId.dataBuffer[i]); }
- }
- }
- else
- {
- for (int i = 0; i < ReceivedBytes; i++)
- { ClientReceiveData.Add(theSockId.dataBuffer[i]); }
- }
-
- // Start listening to the rest of the data
- theSockId.Soc.BeginReceive(theSockId.dataBuffer, 0,
- theSockId.dataBuffer.Length,
- SocketFlags.None,
- asyClientEndReceive,
- theSockId);
- }
- else
- {
- byte[] RealData = ClientReceiveData.ToArray();
- ClientReceiveData = null;
-
- if (ClientSockPckType == SocketPacketType.ChannelLaunch || ClientSockPckType == SocketPacketType.ChannelStopMessage)
- {
- // Take the byte[] received from the server and convert it to string
- string text = (string)cHelper.DeserializeFromXML(typeof(string), RealData);
-
- if (OnDataReceived != null) { OnDataReceived(text); } // First notify event to have more responsive UI
- }
- else if (ClientSockPckType == SocketPacketType.GetAllChannelsFromServer)
- {
- List<ChannelBase> Channels = (List<ChannelBase>)cHelper.DeserializeFromXML(typeof(List<ChannelBase>), RealData);
-
- int iChCount = 0;
- int iChNew = 0;
- cChannels c = new cChannels(cSettings.Cfg.cTvHardware);
- foreach (ChannelBase cb in Channels)
- {
- if (!c.ChannelExists(cb))
- { c.AddChannel(cb); iChNew++; } // Add the channel to the current list
- iChCount++;
- }
-
- if (OnDataReceived != null) // Prepare a status message
- { OnDataReceived(iChNew + " new channels added (" + iChCount + " channels received)"); }
- }
- }
- }
- catch (ObjectDisposedException)
- {
- System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
- }
- catch (Exception)
- {
- if (OnDataReceived != null) { OnDataReceived("0|Could not process request received from server"); }
- }
-
- // After we received the server reponse, no more network communication is needed
- if (theSockId != null && ReceivedBytes == 0)
- {
- try
- {
- theSockId.Soc.Shutdown(SocketShutdown.Both);
- theSockId.Soc.Close();
- }
- catch (ObjectDisposedException)
- { System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n"); }
- }
- }
-
- public static void SendChannelDataToServer(ChannelBase cn)
- { SendDataToServer(SocketPacketType.ChannelLaunch, cn); }
-
- public static void StopChannelOnServer()
- { SendDataToServer(SocketPacketType.ChannelStopMessage, null); }
-
- public static void GetAllChannelsFromServer()
- { SendDataToServer(SocketPacketType.GetAllChannelsFromServer, null); }
-
- private static void SendDataToServer(SocketPacketType sockPckType, ChannelBase cn)
- {
- // The byte[] which will be sent to the server
- // The first byte represents the type of data with the same index as in SocketPacketType:
- // 1 == SocketPacketType.ChannelLaunch
- byte[] DataForServer = new byte[1];
-
- if (sockPckType == SocketPacketType.ChannelLaunch)
- {
- // Set the VLC command, so TSReader accepts it
- cn.VLCCommand = "<IP> " + cSettings.Cfg.sVlcServerCommand.Replace("{0}", cSettings.Cfg.sServerIP);
-
- byte[] ChannelInBytes = cHelper.SerializeToXML(cn); // Convert the channel to byte[]
-
- DataForServer = new byte[ChannelInBytes.Length + 2];
- DataForServer[1] = Convert.ToByte(cSettings.Cfg.cTvHardware);
- ChannelInBytes.CopyTo(DataForServer, 2);
- }
- else if (sockPckType == SocketPacketType.GetAllChannelsFromServer)
- {
- DataForServer = new byte[2];
- DataForServer[1] = Convert.ToByte(cSettings.Cfg.cTvHardware);
- }
-
- // Set the type of channel according to the SocketPacketType
- DataForServer[0] = Convert.ToByte(sockPckType);
-
- SocketClientInitalConnect();
-
- socketClient.Send(DataForServer, DataForServer.Length, 0);
-
- SocketPacket socP = new SocketPacket(socketClient);
-
- //Start listening to the data asynchronously
- socketClient.BeginReceive(socP.dataBuffer,
- 0, socP.dataBuffer.Length,
- SocketFlags.None,
- asyClientEndReceive,
- socP);
-
- // As the client won't send data to the server, just wait for a response
- socketClient.Shutdown(SocketShutdown.Send);
- }
-
- private static void SocketClientInitalConnect()
- {
- IPAddress ipa = IPAddress.Parse(cSettings.Cfg.sServerIP);
- EndPoint ep = new IPEndPoint(ipa, cSettings.Cfg.iServerPort);
- socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-
- try
- {
- socketClient.Connect(ep);
- }
- catch (Exception)
- { socketClient.Close(); return; }
- }
- #endregion
- }
- }