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

/SteamKit3/SteamKit3/Networking/TcpConnection.cs

https://bitbucket.org/VoiDeD/steamre/
C# | 173 lines | 114 code | 36 blank | 23 comment | 23 complexity | 6064d0b93ce8994840b2f0569aa469ef MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0, BSD-3-Clause
  1. /*
  2. * This file is subject to the terms and conditions defined in
  3. * file 'license.txt', which is part of this source code package.
  4. */
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Text;
  8. using System.Net.Sockets;
  9. using System.Net;
  10. using System.Diagnostics;
  11. using System.IO;
  12. using System.Threading;
  13. namespace SteamKit3
  14. {
  15. class TcpConnection : Connection
  16. {
  17. const uint MAGIC = 0x31305456; // "VT01"
  18. Socket sock;
  19. Thread netThread;
  20. NetworkStream stream;
  21. BinaryReader reader;
  22. /// <summary>
  23. /// Connects to the specified end point.
  24. /// </summary>
  25. /// <param name="endPoint">The end point.</param>
  26. public override void Connect( IPEndPoint endPoint )
  27. {
  28. Disconnect();
  29. sock = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
  30. var socketConnect = new SocketAsyncEventArgs();
  31. socketConnect.RemoteEndPoint = endPoint;
  32. socketConnect.Completed += ( sender, e ) =>
  33. {
  34. if ( e.SocketError == SocketError.Success )
  35. {
  36. stream = new NetworkStream( sock, true );
  37. reader = new BinaryReader( stream );
  38. netThread = new Thread( NetLoop );
  39. netThread.Name = "TcpConnection Thread";
  40. netThread.Start();
  41. OnConnected( EventArgs.Empty );
  42. return;
  43. }
  44. OnDisconnected( EventArgs.Empty );
  45. };
  46. sock.ConnectAsync( socketConnect );
  47. }
  48. /// <summary>
  49. /// Disconnects this instance.
  50. /// </summary>
  51. public override void Disconnect()
  52. {
  53. if ( sock == null || !sock.Connected )
  54. return;
  55. if ( sock != null )
  56. {
  57. try
  58. {
  59. sock.Shutdown( SocketShutdown.Both );
  60. sock.Disconnect( true );
  61. sock.Close();
  62. sock = null;
  63. }
  64. catch { }
  65. }
  66. }
  67. /// <summary>
  68. /// Sends the specified client net message.
  69. /// </summary>
  70. /// <param name="clientMsg">The client net message.</param>
  71. public override void Send( IClientMsg clientMsg )
  72. {
  73. if ( sock == null || !sock.Connected )
  74. return;
  75. byte[] data = clientMsg.Serialize();
  76. if ( NetFilter != null )
  77. {
  78. data = NetFilter.ProcessOutgoing( data );
  79. }
  80. using ( MemoryStream ms = new MemoryStream() )
  81. using ( BinaryWriter bw = new BinaryWriter( ms ) )
  82. {
  83. bw.Write( data.Length );
  84. bw.Write( TcpConnection.MAGIC );
  85. bw.Write( data );
  86. data = ms.ToArray();
  87. }
  88. var sockSend = new SocketAsyncEventArgs();
  89. sockSend.SetBuffer( data, 0, data.Length );
  90. sockSend.Completed += ( sender, e ) =>
  91. {
  92. if ( e.SocketError == SocketError.Success )
  93. return;
  94. // report send failure?
  95. };
  96. sock.SendAsync( sockSend );
  97. }
  98. // this is now a steamkit meme
  99. /// <summary>
  100. /// Nets the loop.
  101. /// </summary>
  102. void NetLoop()
  103. {
  104. try
  105. {
  106. while ( sock.Connected )
  107. {
  108. // the tcp packet header is considerably less complex than the udp one
  109. // it only consists of the packet length, followed by the "VT01" magic
  110. byte[] packetHeader = reader.ReadBytes( 8 );
  111. if ( packetHeader.Length != 8 )
  112. throw new IOException( "Connection lost while reading packet header" );
  113. using ( MemoryStream ms = new MemoryStream( packetHeader ) )
  114. using ( BinaryReader br = new BinaryReader( ms ) )
  115. {
  116. uint packetLen = br.ReadUInt32();
  117. uint packetMagic = br.ReadUInt32();
  118. if ( packetMagic != TcpConnection.MAGIC )
  119. throw new IOException( "RecvCompleted got a packet with invalid magic!" );
  120. // rest of the packet is the physical data
  121. byte[] packData = reader.ReadBytes( ( int )packetLen );
  122. if ( packData.Length != packetLen )
  123. throw new IOException( "Connection lost while reading packet payload" );
  124. if ( NetFilter != null )
  125. packData = NetFilter.ProcessIncoming( packData );
  126. OnNetMsgReceived( new NetMsgEventArgs( packData, sock.RemoteEndPoint as IPEndPoint ) );
  127. }
  128. }
  129. }
  130. catch ( IOException e )
  131. {
  132. Log.Error( "Socket exception", e );
  133. OnDisconnected( EventArgs.Empty );
  134. }
  135. }
  136. }
  137. }