PageRenderTime 26ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/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
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Net.Sockets;
  5. using System.Net;
  6. using System.Windows.Forms;
  7. using System.IO;
  8. using System.Runtime.Serialization.Formatters.Binary;
  9. using System.Xml.Serialization;
  10. using System.Diagnostics;
  11. namespace TsChanManLibrary
  12. {
  13. public enum SocketPacketType
  14. {
  15. ChannelLaunch = 1,
  16. ChannelStopMessage = 2,
  17. GetAllChannelsFromServer = 3
  18. }
  19. public class SocketPacket
  20. {
  21. public SocketPacket(Socket s)
  22. { Soc = s; }
  23. public readonly Socket Soc;
  24. public byte[] dataBuffer = new byte[100000]; // 100 KB for one channel (including picture)
  25. }
  26. public class cSockets
  27. {
  28. private static Socket socketClient;
  29. private static Socket socketServer;
  30. private static AsyncCallback asyServerEndReceive = new AsyncCallback(AfterServerDataReceived);
  31. private static AsyncCallback asyClientEndReceive = new AsyncCallback(AfterClientDataReceived);
  32. public static bool IsServerStarted
  33. { get { return isServerStarted; } }
  34. private static bool isServerStarted;
  35. public delegate void ServerDataEventHandler(string sData);
  36. public static event ServerDataEventHandler OnDataReceived;
  37. /// <summary>
  38. /// As the client sends data packet by packet, each packet gets stored
  39. /// in 'ServerReceiveData' step by step - 'iServerRecvd' remebers how many
  40. /// bytes have been stored on the server
  41. /// </summary>
  42. private static byte[] ServerReceiveData = new byte[100000];
  43. private static int iServerRecvd = 0;
  44. /// <summary>
  45. /// Stores the data the client receives (eg. All channels from the server)
  46. /// </summary>
  47. private static List<byte> ClientReceiveData;
  48. private static SocketPacketType ClientSockPckType;
  49. #region "Server"
  50. /// <summary>
  51. /// This computer starts a server (listening to clients that connect on the
  52. /// port configured via cSettings.Cfg.iServerPort) asynchronisly
  53. /// </summary>
  54. public static void StartServer()
  55. {
  56. // Create the ServerSocket
  57. socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  58. IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, cSettings.Cfg.iServerPort);
  59. socketServer.Bind(ipLocal);
  60. socketServer.Listen(1); // Just allow one connection as clients won't stay connected for too long
  61. // Call "OnClientConnect" asynchronisly after Client connects to this server
  62. socketServer.BeginAccept(new AsyncCallback(OnClientConnect), null);
  63. isServerStarted = true;
  64. }
  65. /// <summary>
  66. /// Stops listening to the port specified in cSettings.Cfg.iServerPort
  67. /// </summary>
  68. public static void StopServer()
  69. {
  70. if (socketServer != null)
  71. { socketServer.Close(); }
  72. isServerStarted = false;
  73. }
  74. /// <summary>
  75. /// Gets called after client established a connection to this computer
  76. /// </summary>
  77. /// <param name="asyn"></param>
  78. private static void OnClientConnect(IAsyncResult asyn)
  79. {
  80. try
  81. {
  82. Socket socClient = socketServer.EndAccept(asyn);
  83. SocketPacket sP = new SocketPacket(socClient);
  84. // asyServerEndReceive = Asynch Callback to AfterServerDataReceived()
  85. socClient.BeginReceive(sP.dataBuffer, 0,
  86. sP.dataBuffer.Length,
  87. SocketFlags.None,
  88. asyServerEndReceive,
  89. sP);
  90. // Since the main Socket is now free, it can go back and wait for
  91. // other clients who are attempting to connect
  92. socketServer.BeginAccept(new AsyncCallback(OnClientConnect), null);
  93. }
  94. catch (ObjectDisposedException)
  95. { } // No need to handle anything as Exception occures if the connection is closeds
  96. }
  97. /// <summary>
  98. /// Get's called after a connected clients started sending data to this server
  99. /// </summary>
  100. /// <param name="iARes"></param>
  101. private static void AfterServerDataReceived(IAsyncResult iARes)
  102. {
  103. SocketPacket socketData = (SocketPacket)iARes.AsyncState;
  104. // Complete the BeginReceive() asynchronous call by EndReceive() method
  105. // which will return the number of bytes written to the stream
  106. // by the client
  107. int iReceived = socketData.Soc.EndReceive(iARes);
  108. try
  109. {
  110. // As we might already have data from the last packet, add the next
  111. // packet of data to the existing one
  112. for (int i = 0; i < iReceived; i++)
  113. {
  114. ServerReceiveData[iServerRecvd] = socketData.dataBuffer[i];
  115. iServerRecvd++;
  116. }
  117. // If we received data, wait for another packet, which might contain
  118. // more data we need
  119. if (iReceived != 0)
  120. {
  121. socketData.Soc.BeginReceive(socketData.dataBuffer, 0,
  122. socketData.dataBuffer.Length,
  123. SocketFlags.None,
  124. asyServerEndReceive,
  125. socketData);
  126. }
  127. else // It's over once we receive no more data
  128. {
  129. if (ServerReceiveData[0] != 0)
  130. {
  131. SocketPacketType SockPckType = (SocketPacketType)Enum.Parse(typeof(SocketPacketType), ServerReceiveData[0].ToString());
  132. // Represents the data to be sent back to the client
  133. byte[] DataToSend = null;
  134. if (SockPckType == SocketPacketType.ChannelLaunch)
  135. {
  136. ChannelType ChanType = (ChannelType)Enum.Parse(typeof(ChannelType), ServerReceiveData[1].ToString());
  137. byte[] ChannelData = new byte[ServerReceiveData.Length - 2];
  138. for (int y = 2; y < ServerReceiveData.Length - 2; y++)
  139. {
  140. ChannelData[y - 2] = ServerReceiveData[y];
  141. }
  142. ChannelBase c;
  143. if (ChanType == ChannelType.DVBSFull)
  144. { c = (ChannelDVBSFull)cHelper.DeserializeFromXML(typeof(ChannelDVBSFull), ChannelData); }
  145. else if (ChanType == ChannelType.DVBS)
  146. { c = (ChannelDVBS)cHelper.DeserializeFromXML(typeof(ChannelDVBS), ChannelData); }
  147. else if (ChanType == ChannelType.DVBC)
  148. { c = (ChannelDVBC)cHelper.DeserializeFromXML(typeof(ChannelDVBC), ChannelData); }
  149. else if (ChanType == ChannelType.DVBT)
  150. { c = (ChannelDVBT)cHelper.DeserializeFromXML(typeof(ChannelDVBT), ChannelData); }
  151. else
  152. { c = (ChannelBase)cHelper.DeserializeFromXML(typeof(ChannelBase), ChannelData); }
  153. cChannels cM = new cChannels(ChanType);
  154. cM.LaunchChannelFromClientData(c);
  155. // Inital wait time TSReader should take to tune into channel,
  156. // Parse the transport stream and starts VLC to stream
  157. System.Threading.Thread.Sleep(8500);
  158. bool vlcFound = false;
  159. bool tsrFound = false;
  160. int i = 0;
  161. while (vlcFound == false)
  162. {
  163. foreach (Process p in Process.GetProcesses())
  164. {
  165. try
  166. {
  167. if (!tsrFound && p.ProcessName == "TSReader")
  168. { tsrFound = true; }
  169. else if (!vlcFound && p.ProcessName == "vlc")
  170. { vlcFound = true; }
  171. else if (vlcFound && tsrFound)
  172. {
  173. DataToSend = cHelper.SerializeToXML("1|OK");
  174. break;
  175. }
  176. }
  177. catch (Exception)
  178. { } // Most likely "Access denied" - just continue with the next Process
  179. }
  180. // Acts as timeout
  181. System.Threading.Thread.Sleep(2000);
  182. if (i > 15) break;
  183. i++;
  184. }
  185. if (DataToSend == null)
  186. { DataToSend = cHelper.SerializeToXML("0|VLC or TSReader have not been started"); }
  187. }
  188. else if (SockPckType == SocketPacketType.ChannelStopMessage)
  189. {
  190. bool IsTSReaderClosed = false;
  191. // Look for the TSReader process and close TSReader
  192. foreach (Process P in Process.GetProcessesByName("TSReader"))
  193. {
  194. IsTSReaderClosed = true;
  195. P.CloseMainWindow();
  196. }
  197. // Prepare a message for the client to see if TSReader has bee closed
  198. if (IsTSReaderClosed)
  199. { DataToSend = cHelper.SerializeToXML("1|TSReader successfully closed"); }
  200. else
  201. { DataToSend = cHelper.SerializeToXML("0|No TSReader instance found"); }
  202. }
  203. else if (SockPckType == SocketPacketType.GetAllChannelsFromServer)
  204. {
  205. // Determite the channel type and send all the channels within this type
  206. // to the client
  207. ChannelType ChanType = (ChannelType)Enum.Parse(typeof(ChannelType), ServerReceiveData[1].ToString());
  208. cChannels c = new cChannels(ChanType);
  209. DataToSend = cHelper.SerializeToXML(c.currChannels);
  210. }
  211. // Insert A SocketType-Flag, so the client knows what to receive
  212. byte[] FinalData = new byte[DataToSend.Length + 1];
  213. DataToSend.CopyTo(FinalData, 1);
  214. FinalData[0] = Convert.ToByte(SockPckType);
  215. socketData.Soc.Send(FinalData);
  216. socketData.Soc.Close(); // No need to send anymore data
  217. // Reset data for the next client
  218. iServerRecvd = 0;
  219. ServerReceiveData = new byte[100000];
  220. }
  221. else
  222. { socketData.Soc.Shutdown(SocketShutdown.Both); }
  223. }
  224. }
  225. catch (ObjectDisposedException)
  226. { } // Just continue
  227. catch (Exception e)
  228. {
  229. socketData.Soc.Close();
  230. MessageBox.Show(e.Message);
  231. }
  232. }
  233. #endregion
  234. #region "Client"
  235. /// <summary>
  236. /// Get's called after the server sent a response saying if the desired channel could be started
  237. /// </summary>
  238. /// <param name="iARes"></param>
  239. private static void AfterClientDataReceived(IAsyncResult iARes)
  240. {
  241. SocketPacket theSockId = null;
  242. int ReceivedBytes = 0;
  243. try
  244. {
  245. theSockId = (SocketPacket)iARes.AsyncState;
  246. ReceivedBytes = theSockId.Soc.EndReceive(iARes);
  247. if (ReceivedBytes != 0) // Means there's still data to come...
  248. {
  249. if (ClientReceiveData == null)
  250. {
  251. ClientReceiveData = new List<byte>();
  252. ClientSockPckType = (SocketPacketType)Enum.Parse(typeof(SocketPacketType), theSockId.dataBuffer[0].ToString());
  253. // Seperate the SocketTypeFlag from the real data
  254. byte[] UsedData = new byte[theSockId.dataBuffer.Length - 1];
  255. for (int i = 0; i < ReceivedBytes; i++)
  256. {
  257. if (i != 0)
  258. { ClientReceiveData.Add(theSockId.dataBuffer[i]); }
  259. }
  260. }
  261. else
  262. {
  263. for (int i = 0; i < ReceivedBytes; i++)
  264. { ClientReceiveData.Add(theSockId.dataBuffer[i]); }
  265. }
  266. // Start listening to the rest of the data
  267. theSockId.Soc.BeginReceive(theSockId.dataBuffer, 0,
  268. theSockId.dataBuffer.Length,
  269. SocketFlags.None,
  270. asyClientEndReceive,
  271. theSockId);
  272. }
  273. else
  274. {
  275. byte[] RealData = ClientReceiveData.ToArray();
  276. ClientReceiveData = null;
  277. if (ClientSockPckType == SocketPacketType.ChannelLaunch || ClientSockPckType == SocketPacketType.ChannelStopMessage)
  278. {
  279. // Take the byte[] received from the server and convert it to string
  280. string text = (string)cHelper.DeserializeFromXML(typeof(string), RealData);
  281. if (OnDataReceived != null) { OnDataReceived(text); } // First notify event to have more responsive UI
  282. }
  283. else if (ClientSockPckType == SocketPacketType.GetAllChannelsFromServer)
  284. {
  285. List<ChannelBase> Channels = (List<ChannelBase>)cHelper.DeserializeFromXML(typeof(List<ChannelBase>), RealData);
  286. int iChCount = 0;
  287. int iChNew = 0;
  288. cChannels c = new cChannels(cSettings.Cfg.cTvHardware);
  289. foreach (ChannelBase cb in Channels)
  290. {
  291. if (!c.ChannelExists(cb))
  292. { c.AddChannel(cb); iChNew++; } // Add the channel to the current list
  293. iChCount++;
  294. }
  295. if (OnDataReceived != null) // Prepare a status message
  296. { OnDataReceived(iChNew + " new channels added (" + iChCount + " channels received)"); }
  297. }
  298. }
  299. }
  300. catch (ObjectDisposedException)
  301. {
  302. System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
  303. }
  304. catch (Exception)
  305. {
  306. if (OnDataReceived != null) { OnDataReceived("0|Could not process request received from server"); }
  307. }
  308. // After we received the server reponse, no more network communication is needed
  309. if (theSockId != null && ReceivedBytes == 0)
  310. {
  311. try
  312. {
  313. theSockId.Soc.Shutdown(SocketShutdown.Both);
  314. theSockId.Soc.Close();
  315. }
  316. catch (ObjectDisposedException)
  317. { System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n"); }
  318. }
  319. }
  320. public static void SendChannelDataToServer(ChannelBase cn)
  321. { SendDataToServer(SocketPacketType.ChannelLaunch, cn); }
  322. public static void StopChannelOnServer()
  323. { SendDataToServer(SocketPacketType.ChannelStopMessage, null); }
  324. public static void GetAllChannelsFromServer()
  325. { SendDataToServer(SocketPacketType.GetAllChannelsFromServer, null); }
  326. private static void SendDataToServer(SocketPacketType sockPckType, ChannelBase cn)
  327. {
  328. // The byte[] which will be sent to the server
  329. // The first byte represents the type of data with the same index as in SocketPacketType:
  330. // 1 == SocketPacketType.ChannelLaunch
  331. byte[] DataForServer = new byte[1];
  332. if (sockPckType == SocketPacketType.ChannelLaunch)
  333. {
  334. // Set the VLC command, so TSReader accepts it
  335. cn.VLCCommand = "<IP> " + cSettings.Cfg.sVlcServerCommand.Replace("{0}", cSettings.Cfg.sServerIP);
  336. byte[] ChannelInBytes = cHelper.SerializeToXML(cn); // Convert the channel to byte[]
  337. DataForServer = new byte[ChannelInBytes.Length + 2];
  338. DataForServer[1] = Convert.ToByte(cSettings.Cfg.cTvHardware);
  339. ChannelInBytes.CopyTo(DataForServer, 2);
  340. }
  341. else if (sockPckType == SocketPacketType.GetAllChannelsFromServer)
  342. {
  343. DataForServer = new byte[2];
  344. DataForServer[1] = Convert.ToByte(cSettings.Cfg.cTvHardware);
  345. }
  346. // Set the type of channel according to the SocketPacketType
  347. DataForServer[0] = Convert.ToByte(sockPckType);
  348. SocketClientInitalConnect();
  349. socketClient.Send(DataForServer, DataForServer.Length, 0);
  350. SocketPacket socP = new SocketPacket(socketClient);
  351. //Start listening to the data asynchronously
  352. socketClient.BeginReceive(socP.dataBuffer,
  353. 0, socP.dataBuffer.Length,
  354. SocketFlags.None,
  355. asyClientEndReceive,
  356. socP);
  357. // As the client won't send data to the server, just wait for a response
  358. socketClient.Shutdown(SocketShutdown.Send);
  359. }
  360. private static void SocketClientInitalConnect()
  361. {
  362. IPAddress ipa = IPAddress.Parse(cSettings.Cfg.sServerIP);
  363. EndPoint ep = new IPEndPoint(ipa, cSettings.Cfg.iServerPort);
  364. socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  365. try
  366. {
  367. socketClient.Connect(ep);
  368. }
  369. catch (Exception)
  370. { socketClient.Close(); return; }
  371. }
  372. #endregion
  373. }
  374. }