You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Listener.cs 4.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. using Shadowsocks.Model;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Text;
  7. namespace Shadowsocks.Controller
  8. {
  9. public class Listener
  10. {
  11. public interface Service
  12. {
  13. bool Handle(byte[] firstPacket, int length, Socket socket);
  14. }
  15. Configuration _config;
  16. bool _shareOverLAN;
  17. Socket _socket;
  18. IList<Service> _services;
  19. public Listener(IList<Service> services)
  20. {
  21. this._services = services;
  22. }
  23. public void Start(Configuration config)
  24. {
  25. this._config = config;
  26. this._shareOverLAN = config.shareOverLan;
  27. try
  28. {
  29. // Create a TCP/IP socket.
  30. _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  31. _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
  32. IPEndPoint localEndPoint = null;
  33. if (_shareOverLAN)
  34. {
  35. localEndPoint = new IPEndPoint(IPAddress.Any, _config.localPort);
  36. }
  37. else
  38. {
  39. localEndPoint = new IPEndPoint(IPAddress.Loopback, _config.localPort);
  40. }
  41. // Bind the socket to the local endpoint and listen for incoming connections.
  42. _socket.Bind(localEndPoint);
  43. _socket.Listen(1024);
  44. // Start an asynchronous socket to listen for connections.
  45. Console.WriteLine("Shadowsocks started");
  46. _socket.BeginAccept(
  47. new AsyncCallback(AcceptCallback),
  48. _socket);
  49. }
  50. catch (SocketException)
  51. {
  52. _socket.Close();
  53. throw;
  54. }
  55. }
  56. public void Stop()
  57. {
  58. if (_socket != null)
  59. {
  60. _socket.Close();
  61. _socket = null;
  62. }
  63. }
  64. public void AcceptCallback(IAsyncResult ar)
  65. {
  66. Socket listener = (Socket)ar.AsyncState;
  67. try
  68. {
  69. Socket conn = listener.EndAccept(ar);
  70. byte[] buf = new byte[4096];
  71. object[] state = new object[] {
  72. conn,
  73. buf
  74. };
  75. conn.BeginReceive(buf, 0, buf.Length, 0,
  76. new AsyncCallback(ReceiveCallback), state);
  77. }
  78. catch (ObjectDisposedException)
  79. {
  80. }
  81. catch (Exception e)
  82. {
  83. Console.WriteLine(e);
  84. }
  85. finally
  86. {
  87. try
  88. {
  89. listener.BeginAccept(
  90. new AsyncCallback(AcceptCallback),
  91. listener);
  92. }
  93. catch (ObjectDisposedException)
  94. {
  95. // do nothing
  96. }
  97. catch (Exception e)
  98. {
  99. Logging.LogUsefulException(e);
  100. }
  101. }
  102. }
  103. private void ReceiveCallback(IAsyncResult ar)
  104. {
  105. object[] state = (object[])ar.AsyncState;
  106. Socket conn = (Socket)state[0];
  107. byte[] buf = (byte[])state[1];
  108. try
  109. {
  110. int bytesRead = conn.EndReceive(ar);
  111. foreach (Service service in _services)
  112. {
  113. if (service.Handle(buf, bytesRead, conn))
  114. {
  115. return;
  116. }
  117. }
  118. // no service found for this
  119. // shouldn't happen
  120. conn.Close();
  121. }
  122. catch (Exception e)
  123. {
  124. Console.WriteLine(e);
  125. conn.Close();
  126. }
  127. }
  128. }
  129. }