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.

UDPRelay.cs 6.9 kB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using Shadowsocks.Encryption;
  5. using Shadowsocks.Model;
  6. using System.Net.Sockets;
  7. using System.Net;
  8. using System.Runtime.CompilerServices;
  9. using Shadowsocks.Controller.Strategy;
  10. namespace Shadowsocks.Controller
  11. {
  12. class UDPRelay : Listener.Service
  13. {
  14. private ShadowsocksController _controller;
  15. private LRUCache<IPEndPoint, UDPHandler> _cache;
  16. public UDPRelay(ShadowsocksController controller)
  17. {
  18. this._controller = controller;
  19. this._cache = new LRUCache<IPEndPoint, UDPHandler>(512); // todo: choose a smart number
  20. }
  21. public bool Handle(byte[] firstPacket, int length, Socket socket, object state)
  22. {
  23. if (socket.ProtocolType != ProtocolType.Udp)
  24. {
  25. return false;
  26. }
  27. if (length < 4)
  28. {
  29. return false;
  30. }
  31. Listener.UDPState udpState = (Listener.UDPState)state;
  32. IPEndPoint remoteEndPoint = (IPEndPoint)udpState.remoteEndPoint;
  33. UDPHandler handler = _cache.get(remoteEndPoint);
  34. if (handler == null)
  35. {
  36. handler = new UDPHandler(socket, _controller.GetCurrentStrategy().GetAServer(IStrategyCallerType.UDP, remoteEndPoint), remoteEndPoint);
  37. _cache.add(remoteEndPoint, handler);
  38. }
  39. handler.Send(firstPacket, length);
  40. handler.Receive();
  41. return true;
  42. }
  43. public class UDPHandler
  44. {
  45. private Socket _local;
  46. private Socket _remote;
  47. private Server _server;
  48. private byte[] _buffer = new byte[1500];
  49. private IPEndPoint _localEndPoint;
  50. private IPEndPoint _remoteEndPoint;
  51. public UDPHandler(Socket local, Server server, IPEndPoint localEndPoint)
  52. {
  53. _local = local;
  54. _server = server;
  55. _localEndPoint = localEndPoint;
  56. // TODO async resolving
  57. IPAddress ipAddress;
  58. bool parsed = IPAddress.TryParse(server.server, out ipAddress);
  59. if (!parsed)
  60. {
  61. IPHostEntry ipHostInfo = Dns.GetHostEntry(server.server);
  62. ipAddress = ipHostInfo.AddressList[0];
  63. }
  64. _remoteEndPoint = new IPEndPoint(ipAddress, server.server_port);
  65. _remote = new Socket(_remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
  66. }
  67. public void Send(byte[] data, int length)
  68. {
  69. IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password);
  70. byte[] dataIn = new byte[length - 3];
  71. Array.Copy(data, 3, dataIn, 0, length - 3);
  72. byte[] dataOut = new byte[length - 3 + 16];
  73. int outlen;
  74. encryptor.Encrypt(dataIn, dataIn.Length, dataOut, out outlen);
  75. _remote.SendTo(dataOut, _remoteEndPoint);
  76. }
  77. public void Receive()
  78. {
  79. EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
  80. _remote.BeginReceiveFrom(_buffer, 0, _buffer.Length, 0, ref remoteEndPoint, new AsyncCallback(RecvFromCallback), null);
  81. }
  82. public void RecvFromCallback(IAsyncResult ar)
  83. {
  84. try
  85. {
  86. EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
  87. int bytesRead = _remote.EndReceiveFrom(ar, ref remoteEndPoint);
  88. byte[] dataOut = new byte[bytesRead];
  89. int outlen;
  90. IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password);
  91. encryptor.Decrypt(_buffer, bytesRead, dataOut, out outlen);
  92. byte[] sendBuf = new byte[outlen + 3];
  93. Array.Copy(dataOut, 0, sendBuf, 3, outlen);
  94. _local.SendTo(sendBuf, outlen + 3, 0, _localEndPoint);
  95. Receive();
  96. }
  97. catch (ObjectDisposedException)
  98. {
  99. }
  100. catch (Exception)
  101. {
  102. }
  103. finally
  104. {
  105. }
  106. }
  107. public void Close()
  108. {
  109. try
  110. {
  111. _remote.Close();
  112. }
  113. catch (ObjectDisposedException)
  114. {
  115. }
  116. catch (Exception)
  117. {
  118. }
  119. finally
  120. {
  121. }
  122. }
  123. }
  124. }
  125. // cc by-sa 3.0 http://stackoverflow.com/a/3719378/1124054
  126. class LRUCache<K, V> where V : UDPRelay.UDPHandler
  127. {
  128. private int capacity;
  129. private Dictionary<K, LinkedListNode<LRUCacheItem<K, V>>> cacheMap = new Dictionary<K, LinkedListNode<LRUCacheItem<K, V>>>();
  130. private LinkedList<LRUCacheItem<K, V>> lruList = new LinkedList<LRUCacheItem<K, V>>();
  131. public LRUCache(int capacity)
  132. {
  133. this.capacity = capacity;
  134. }
  135. [MethodImpl(MethodImplOptions.Synchronized)]
  136. public V get(K key)
  137. {
  138. LinkedListNode<LRUCacheItem<K, V>> node;
  139. if (cacheMap.TryGetValue(key, out node))
  140. {
  141. V value = node.Value.value;
  142. lruList.Remove(node);
  143. lruList.AddLast(node);
  144. return value;
  145. }
  146. return default(V);
  147. }
  148. [MethodImpl(MethodImplOptions.Synchronized)]
  149. public void add(K key, V val)
  150. {
  151. if (cacheMap.Count >= capacity)
  152. {
  153. RemoveFirst();
  154. }
  155. LRUCacheItem<K, V> cacheItem = new LRUCacheItem<K, V>(key, val);
  156. LinkedListNode<LRUCacheItem<K, V>> node = new LinkedListNode<LRUCacheItem<K, V>>(cacheItem);
  157. lruList.AddLast(node);
  158. cacheMap.Add(key, node);
  159. }
  160. private void RemoveFirst()
  161. {
  162. // Remove from LRUPriority
  163. LinkedListNode<LRUCacheItem<K, V>> node = lruList.First;
  164. lruList.RemoveFirst();
  165. // Remove from cache
  166. cacheMap.Remove(node.Value.key);
  167. node.Value.value.Close();
  168. }
  169. }
  170. class LRUCacheItem<K, V>
  171. {
  172. public LRUCacheItem(K k, V v)
  173. {
  174. key = k;
  175. value = v;
  176. }
  177. public K key;
  178. public V value;
  179. }
  180. }