SocketSession.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Collections.ObjectModel;
  5. using System.IO;
  6. using System.Net;
  7. using System.Net.Sockets;
  8. using System.Security.Authentication;
  9. using System.Text;
  10. using System.Threading;
  11. using Microsoft.Extensions.Logging;
  12. using SuperSocket.Common;
  13. using SuperSocket.SocketBase;
  14. using SuperSocket.SocketBase.Command;
  15. using SuperSocket.SocketBase.Config;
  16. using SuperSocket.SocketBase.Protocol;
  17. namespace SuperSocket.SocketEngine
  18. {
  19. static class SocketState
  20. {
  21. public const int Normal = 0;//0000 0000
  22. public const int InClosing = 16;//0001 0000 >= 16
  23. public const int Closed = 16777216;//256 * 256 * 256; 0x01 0x00 0x00 0x00
  24. public const int InSending = 1;//0000 0001 > 1
  25. public const int InReceiving = 2;//0000 0010 > 2
  26. public const int InSendingReceivingMask = -4;// ~(InSending | InReceiving); 0xf0 0xff 0xff 0xff
  27. }
  28. /// <summary>
  29. /// Socket Session, all application session should base on this class
  30. /// </summary>
  31. abstract partial class SocketSession : ISocketSession
  32. {
  33. public IAppSession AppSession { get; private set; }
  34. protected readonly object SyncRoot = new object();
  35. //0x00 0x00 0x00 0x00
  36. //1st byte: Closed(Y/N) - 0x01
  37. //2nd byte: N/A
  38. //3th byte: CloseReason
  39. //Last byte: 0000 0000 - normal state
  40. //0000 0001: in sending
  41. //0000 0010: in receiving
  42. //0001 0000: in closing
  43. private int m_State = 0;
  44. private void AddStateFlag(int stateValue)
  45. {
  46. AddStateFlag(stateValue, false);
  47. }
  48. private bool AddStateFlag(int stateValue, bool notClosing)
  49. {
  50. while(true)
  51. {
  52. var oldState = m_State;
  53. if (notClosing)
  54. {
  55. // don't update the state if the connection has entered the closing procedure
  56. if (oldState >= SocketState.InClosing)
  57. {
  58. return false;
  59. }
  60. }
  61. var newState = m_State | stateValue;
  62. if(Interlocked.CompareExchange(ref m_State, newState, oldState) == oldState)
  63. return true;
  64. }
  65. }
  66. private bool TryAddStateFlag(int stateValue)
  67. {
  68. while (true)
  69. {
  70. var oldState = m_State;
  71. var newState = m_State | stateValue;
  72. //Already marked
  73. if (oldState == newState)
  74. {
  75. return false;
  76. }
  77. var compareState = Interlocked.CompareExchange(ref m_State, newState, oldState);
  78. if (compareState == oldState)
  79. return true;
  80. }
  81. }
  82. private void RemoveStateFlag(int stateValue)
  83. {
  84. while(true)
  85. {
  86. var oldState = m_State;
  87. var newState = m_State & (~stateValue);
  88. if(Interlocked.CompareExchange(ref m_State, newState, oldState) == oldState)
  89. return;
  90. }
  91. }
  92. private bool CheckState(int stateValue)
  93. {
  94. return (m_State & stateValue) == stateValue;
  95. }
  96. protected bool SyncSend { get; private set; }
  97. private ISmartPool<SendingQueue> m_SendingQueuePool;
  98. public SocketSession(Socket client)
  99. : this(Guid.NewGuid().ToString())
  100. {
  101. if (client == null)
  102. throw new ArgumentNullException("client");
  103. m_Client = client;
  104. LocalEndPoint = (IPEndPoint)client.LocalEndPoint;
  105. RemoteEndPoint = (IPEndPoint)client.RemoteEndPoint;
  106. }
  107. public SocketSession(string sessionID)
  108. {
  109. SessionID = sessionID;
  110. }
  111. public virtual void Initialize(IAppSession appSession)
  112. {
  113. AppSession = appSession;
  114. Config = appSession.Config;
  115. SyncSend = Config.SyncSend;
  116. if (m_SendingQueuePool == null)
  117. m_SendingQueuePool = ((SocketServerBase)((ISocketServerAccessor)appSession.AppServer).SocketServer).SendingQueuePool;
  118. SendingQueue queue;
  119. if (m_SendingQueuePool.TryGet(out queue))
  120. {
  121. m_SendingQueue = queue;
  122. queue.StartEnqueue();
  123. }
  124. }
  125. /// <summary>
  126. /// Gets or sets the session ID.
  127. /// </summary>
  128. /// <value>The session ID.</value>
  129. public string SessionID { get; private set; }
  130. /// <summary>
  131. /// Gets or sets the config.
  132. /// </summary>
  133. /// <value>
  134. /// The config.
  135. /// </value>
  136. public IServerConfig Config { get; set; }
  137. /// <summary>
  138. /// Starts this session.
  139. /// </summary>
  140. public abstract void Start();
  141. /// <summary>
  142. /// Says the welcome information when a client connectted.
  143. /// </summary>
  144. protected virtual void StartSession()
  145. {
  146. AppSession.StartSession();
  147. }
  148. /// <summary>
  149. /// Called when [close].
  150. /// </summary>
  151. protected virtual void OnClosed(CloseReason reason)
  152. {
  153. //Already closed
  154. if (!TryAddStateFlag(SocketState.Closed))
  155. return;
  156. //Before changing m_SendingQueue, must check m_IsClosed
  157. while (true)
  158. {
  159. var sendingQueue = m_SendingQueue;
  160. if (sendingQueue == null)
  161. break;
  162. //There is no sending was started after the m_Closed ws set to 'true'
  163. if (Interlocked.CompareExchange(ref m_SendingQueue, null, sendingQueue) == sendingQueue)
  164. {
  165. sendingQueue.Clear();
  166. m_SendingQueuePool.Push(sendingQueue);
  167. break;
  168. }
  169. }
  170. var closedHandler = Closed;
  171. if (closedHandler != null)
  172. {
  173. closedHandler(this, reason);
  174. }
  175. }
  176. /// <summary>
  177. /// Occurs when [closed].
  178. /// </summary>
  179. public Action<ISocketSession, CloseReason> Closed { get; set; }
  180. private SendingQueue m_SendingQueue;
  181. /// <summary>
  182. /// Tries to send array segment.
  183. /// </summary>
  184. /// <param name="segments">The segments.</param>
  185. /// <returns></returns>
  186. public bool TrySend(IList<ArraySegment<byte>> segments)
  187. {
  188. if (IsClosed)
  189. return false;
  190. var queue = m_SendingQueue;
  191. if (queue == null)
  192. return false;
  193. var trackID = queue.TrackID;
  194. if (!queue.Enqueue(segments, trackID))
  195. return false;
  196. StartSend(queue, trackID, true);
  197. return true;
  198. }
  199. /// <summary>
  200. /// Tries to send array segment.
  201. /// </summary>
  202. /// <param name="segment">The segment.</param>
  203. /// <returns></returns>
  204. public bool TrySend(ArraySegment<byte> segment)
  205. {
  206. if (IsClosed)
  207. return false;
  208. var queue = m_SendingQueue;
  209. if (queue == null)
  210. return false;
  211. var trackID = queue.TrackID;
  212. if (!queue.Enqueue(segment, trackID))
  213. return false;
  214. StartSend(queue, trackID, true);
  215. return true;
  216. }
  217. /// <summary>
  218. /// Sends in async mode.
  219. /// </summary>
  220. /// <param name="queue">The queue.</param>
  221. protected abstract void SendAsync(SendingQueue queue);
  222. /// <summary>
  223. /// Sends in sync mode.
  224. /// </summary>
  225. /// <param name="queue">The queue.</param>
  226. protected abstract void SendSync(SendingQueue queue);
  227. private void Send(SendingQueue queue)
  228. {
  229. if (SyncSend)
  230. {
  231. SendSync(queue);
  232. }
  233. else
  234. {
  235. SendAsync(queue);
  236. }
  237. }
  238. private void StartSend(SendingQueue queue, int sendingTrackID, bool initial)
  239. {
  240. if (initial)
  241. {
  242. if (!TryAddStateFlag(SocketState.InSending))
  243. {
  244. return;
  245. }
  246. var currentQueue = m_SendingQueue;
  247. if (currentQueue != queue || sendingTrackID != currentQueue.TrackID)
  248. {
  249. //Has been sent
  250. OnSendEnd();
  251. return;
  252. }
  253. }
  254. Socket client;
  255. if (IsInClosingOrClosed && TryValidateClosedBySocket(out client))
  256. {
  257. OnSendEnd(true);
  258. return;
  259. }
  260. SendingQueue newQueue;
  261. if (!m_SendingQueuePool.TryGet(out newQueue))
  262. {
  263. AppSession.Logger.LogError("There is no enougth sending queue can be used.");
  264. OnSendEnd(false);
  265. this.Close(CloseReason.InternalError);
  266. return;
  267. }
  268. var oldQueue = Interlocked.CompareExchange(ref m_SendingQueue, newQueue, queue);
  269. if (!ReferenceEquals(oldQueue, queue))
  270. {
  271. if (newQueue != null)
  272. m_SendingQueuePool.Push(newQueue);
  273. if (IsInClosingOrClosed)
  274. {
  275. OnSendEnd(true);
  276. }
  277. else
  278. {
  279. OnSendEnd(false);
  280. AppSession.Logger.LogError("Failed to switch the sending queue.");
  281. this.Close(CloseReason.InternalError);
  282. }
  283. return;
  284. }
  285. //Start to allow enqueue
  286. newQueue.StartEnqueue();
  287. queue.StopEnqueue();
  288. if (queue.Count == 0)
  289. {
  290. AppSession.Logger.LogError("There is no data to be sent in the queue.");
  291. m_SendingQueuePool.Push(queue);
  292. OnSendEnd(false);
  293. this.Close(CloseReason.InternalError);
  294. return;
  295. }
  296. Send(queue);
  297. }
  298. private void OnSendEnd()
  299. {
  300. OnSendEnd(IsInClosingOrClosed);
  301. }
  302. private void OnSendEnd(bool isInClosingOrClosed)
  303. {
  304. RemoveStateFlag(SocketState.InSending);
  305. if (isInClosingOrClosed)
  306. {
  307. Socket client;
  308. if (!TryValidateClosedBySocket(out client))
  309. {
  310. var sendingQueue = m_SendingQueue;
  311. //No data to be sent
  312. if (sendingQueue != null && sendingQueue.Count == 0)
  313. {
  314. if (client != null)// the socket instance is not closed yet, do it now
  315. InternalClose(client, GetCloseReasonFromState(), false);
  316. else// The UDP mode, the socket instance always is null, fire the closed event directly
  317. OnClosed(GetCloseReasonFromState());
  318. return;
  319. }
  320. return;
  321. }
  322. if (ValidateNotInSendingReceiving())
  323. {
  324. FireCloseEvent();
  325. }
  326. }
  327. }
  328. protected virtual void OnSendingCompleted(SendingQueue queue)
  329. {
  330. queue.Clear();
  331. m_SendingQueuePool.Push(queue);
  332. var newQueue = m_SendingQueue;
  333. if (IsInClosingOrClosed)
  334. {
  335. Socket client;
  336. //has data is being sent and the socket isn't closed
  337. if (newQueue.Count > 0 && !TryValidateClosedBySocket(out client))
  338. {
  339. StartSend(newQueue, newQueue.TrackID, false);
  340. return;
  341. }
  342. OnSendEnd(true);
  343. return;
  344. }
  345. if (newQueue.Count == 0)
  346. {
  347. OnSendEnd();
  348. if (newQueue.Count > 0)
  349. {
  350. StartSend(newQueue, newQueue.TrackID, true);
  351. }
  352. }
  353. else
  354. {
  355. StartSend(newQueue, newQueue.TrackID, false);
  356. }
  357. }
  358. public abstract void ApplySecureProtocol();
  359. public Stream GetUnderlyStream()
  360. {
  361. return new NetworkStream(Client);
  362. }
  363. private Socket m_Client;
  364. /// <summary>
  365. /// Gets or sets the client.
  366. /// </summary>
  367. /// <value>The client.</value>
  368. public Socket Client
  369. {
  370. get { return m_Client; }
  371. }
  372. protected bool IsInClosingOrClosed
  373. {
  374. get { return m_State >= SocketState.InClosing; }
  375. }
  376. protected bool IsClosed
  377. {
  378. get { return m_State >= SocketState.Closed; }
  379. }
  380. /// <summary>
  381. /// Gets the local end point.
  382. /// </summary>
  383. /// <value>The local end point.</value>
  384. public virtual IPEndPoint LocalEndPoint { get; protected set; }
  385. /// <summary>
  386. /// Gets the remote end point.
  387. /// </summary>
  388. /// <value>The remote end point.</value>
  389. public virtual IPEndPoint RemoteEndPoint { get; protected set; }
  390. /// <summary>
  391. /// Gets or sets the secure protocol.
  392. /// </summary>
  393. /// <value>The secure protocol.</value>
  394. public SslProtocols SecureProtocol { get; set; }
  395. protected virtual bool TryValidateClosedBySocket(out Socket socket)
  396. {
  397. socket = m_Client;
  398. //Already closed/closing
  399. return socket == null;
  400. }
  401. public virtual void Close(CloseReason reason)
  402. {
  403. //Already in closing procedure
  404. if (!TryAddStateFlag(SocketState.InClosing))
  405. return;
  406. Socket client;
  407. //No need to clean the socket instance
  408. if (TryValidateClosedBySocket(out client))
  409. return;
  410. //Some data is in sending
  411. if (CheckState(SocketState.InSending))
  412. {
  413. //Set closing reason only, don't close the socket directly
  414. AddStateFlag(GetCloseReasonValue(reason));
  415. return;
  416. }
  417. // In the udp mode, we needn't close the socket instance
  418. if (client != null)
  419. InternalClose(client, reason, true);
  420. else //In Udp mode, and the socket is not in the sending state, then fire the closed event directly
  421. OnClosed(reason);
  422. }
  423. private void InternalClose(Socket client, CloseReason reason, bool setCloseReason)
  424. {
  425. if (Interlocked.CompareExchange(ref m_Client, null, client) == client)
  426. {
  427. if (setCloseReason)
  428. AddStateFlag(GetCloseReasonValue(reason));
  429. client.SafeClose();
  430. if (ValidateNotInSendingReceiving())
  431. {
  432. OnClosed(reason);
  433. }
  434. }
  435. }
  436. protected void OnSendError(SendingQueue queue, CloseReason closeReason)
  437. {
  438. queue.Clear();
  439. m_SendingQueuePool.Push(queue);
  440. OnSendEnd();
  441. ValidateClosed(closeReason);
  442. }
  443. // the receive action won't be started for this connection any more
  444. protected void OnReceiveTerminated(CloseReason closeReason)
  445. {
  446. OnReceiveEnded();
  447. ValidateClosed(closeReason);
  448. }
  449. // return false if the connection has entered the closing procedure or has closed already
  450. protected bool OnReceiveStarted()
  451. {
  452. return AddStateFlag(SocketState.InReceiving, true);
  453. }
  454. protected void OnReceiveEnded()
  455. {
  456. RemoveStateFlag(SocketState.InReceiving);
  457. }
  458. /// <summary>
  459. /// Validates the socket is not in the sending or receiving operation.
  460. /// </summary>
  461. /// <returns></returns>
  462. private bool ValidateNotInSendingReceiving()
  463. {
  464. var oldState = m_State;
  465. if ((oldState & SocketState.InSendingReceivingMask) == oldState)
  466. {
  467. return true;
  468. }
  469. return false;
  470. }
  471. private const int m_CloseReasonMagic = 256;
  472. private int GetCloseReasonValue(CloseReason reason)
  473. {
  474. return ((int)reason + 1) * m_CloseReasonMagic;
  475. }
  476. private CloseReason GetCloseReasonFromState()
  477. {
  478. return (CloseReason)(m_State / m_CloseReasonMagic - 1);
  479. }
  480. private void FireCloseEvent()
  481. {
  482. OnClosed(GetCloseReasonFromState());
  483. }
  484. private void ValidateClosed(CloseReason closeReason)
  485. {
  486. if (IsClosed)
  487. return;
  488. if (CheckState(SocketState.InClosing))
  489. {
  490. if (ValidateNotInSendingReceiving())
  491. {
  492. FireCloseEvent();
  493. }
  494. }
  495. else
  496. {
  497. Close(closeReason);
  498. }
  499. }
  500. public abstract int OrigReceiveOffset { get; }
  501. protected virtual bool IsIgnorableSocketError(int socketErrorCode)
  502. {
  503. if (socketErrorCode == 10004 //Interrupted
  504. || socketErrorCode == 10053 //ConnectionAborted
  505. || socketErrorCode == 10054 //ConnectionReset
  506. || socketErrorCode == 10058 //Shutdown
  507. || socketErrorCode == 10060 //TimedOut
  508. || socketErrorCode == 995 //OperationAborted
  509. || socketErrorCode == -1073741299)
  510. {
  511. return true;
  512. }
  513. return false;
  514. }
  515. protected virtual bool IsIgnorableException(Exception e, out int socketErrorCode)
  516. {
  517. socketErrorCode = 0;
  518. if (e is ObjectDisposedException || e is NullReferenceException)
  519. return true;
  520. SocketException socketException = null;
  521. if (e is IOException)
  522. {
  523. if (e.InnerException is ObjectDisposedException || e.InnerException is NullReferenceException)
  524. return true;
  525. socketException = e.InnerException as SocketException;
  526. }
  527. else
  528. {
  529. socketException = e as SocketException;
  530. }
  531. if (socketException == null)
  532. return false;
  533. socketErrorCode = socketException.ErrorCode;
  534. if (Config.LogAllSocketException)
  535. return false;
  536. return IsIgnorableSocketError(socketErrorCode);
  537. }
  538. }
  539. }