PageRenderTime 38ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Misc/ServerList.vala

http://valauo.googlecode.com/
Vala | 191 lines | 115 code | 33 blank | 43 comment | 24 complexity | 20b0e7504f63870f8a7a8f1cd114ab6c MD5 | raw file
Possible License(s): GPL-3.0
  1. using System;
  2. using System.IO;
  3. using System.Net;
  4. using System.Net.NetworkInformation;
  5. using System.Net.Sockets;
  6. using Server;
  7. using Server.Network;
  8. namespace Server.Misc
  9. {
  10. public class ServerList
  11. {
  12. /*
  13. * The default setting for Address, a value of 'null', will use your local IP address. If all of your local IP addresses
  14. * are private network addresses and AutoDetect is 'true' then RunUO will attempt to discover your public IP address
  15. * for you automatically.
  16. *
  17. * If you do not plan on allowing clients outside of your LAN to connect, you can set AutoDetect to 'false' and leave
  18. * Address set to 'null'.
  19. *
  20. * If your public IP address cannot be determined, you must change the value of Address to your public IP address
  21. * manually to allow clients outside of your LAN to connect to your server. Address can be either an IP address or
  22. * a hostname that will be resolved when RunUO starts.
  23. *
  24. * If you want players outside your LAN to be able to connect to your server and you are behind a router, you must also
  25. * forward TCP port 2593 to your private IP address. The procedure for doing this varies by manufacturer but generally
  26. * involves configuration of the router through your web browser.
  27. *
  28. * ServerList will direct connecting clients depending on both the address they are connecting from and the address and
  29. * port they are connecting to. If it is determined that both ends of a connection are private IP addresses, ServerList
  30. * will direct the client to the local private IP address. If a client is connecting to a local public IP address, they
  31. * will be directed to whichever address and port they initially connected to. This allows multihomed servers to function
  32. * properly and fully supports listening on multiple ports. If a client with a public IP address is connecting to a
  33. * locally private address, the server will direct the client to either the AutoDetected IP address or the manually entered
  34. * IP address or hostname, whichever is applicable. Loopback clients will be directed to loopback.
  35. *
  36. * If you would like to listen on additional ports (i.e. 22, 23, 80, for clients behind highly restrictive egress
  37. * firewalls) or specific IP adddresses you can do so by modifying the file SocketOptions.cs found in this directory.
  38. */
  39. public static readonly string Address = null;
  40. public static readonly string ServerName = "RunUO TC";
  41. public static readonly bool AutoDetect = true;
  42. public static void Initialize()
  43. {
  44. if ( Address == null ) {
  45. if ( AutoDetect )
  46. AutoDetection();
  47. }
  48. else {
  49. Resolve( Address, out m_PublicAddress );
  50. }
  51. EventSink.ServerList += new ServerListEventHandler( EventSink_ServerList );
  52. }
  53. private static IPAddress m_PublicAddress;
  54. private static void EventSink_ServerList( ServerListEventArgs e )
  55. {
  56. try
  57. {
  58. NetState ns = e.State;
  59. Socket s = ns.Socket;
  60. IPEndPoint ipep = (IPEndPoint)s.LocalEndPoint;
  61. IPAddress localAddress = ipep.Address;
  62. int localPort = ipep.Port;
  63. if ( IsPrivateNetwork( localAddress ) ) {
  64. ipep = (IPEndPoint)s.RemoteEndPoint;
  65. if ( !IsPrivateNetwork( ipep.Address ) && m_PublicAddress != null )
  66. localAddress = m_PublicAddress;
  67. }
  68. e.AddServer( ServerName, new IPEndPoint( localAddress, localPort ) );
  69. }
  70. catch
  71. {
  72. e.Rejected = true;
  73. }
  74. }
  75. private static void AutoDetection()
  76. {
  77. if ( !HasPublicIPAddress() ) {
  78. Console.Write( "ServerList: Auto-detecting public IP address..." );
  79. m_PublicAddress = FindPublicAddress();
  80. if ( m_PublicAddress != null )
  81. stdout.printf( "done ({0})", m_PublicAddress.ToString() );
  82. else
  83. stdout.printf( "failed" );
  84. }
  85. }
  86. private static void Resolve( string addr, out IPAddress outValue )
  87. {
  88. if ( IPAddress.TryParse( addr, out outValue ) )
  89. return;
  90. try {
  91. IPHostEntry iphe = Dns.GetHostEntry( addr );
  92. if ( iphe.AddressList.Length > 0 )
  93. outValue = iphe.AddressList[iphe.AddressList.Length - 1];
  94. }
  95. catch {
  96. }
  97. }
  98. private static bool HasPublicIPAddress()
  99. {
  100. NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
  101. foreach ( NetworkInterface adapter in adapters ) {
  102. IPInterfaceProperties properties = adapter.GetIPProperties();
  103. foreach ( IPAddressInformation unicast in properties.UnicastAddresses ) {
  104. IPAddress ip = unicast.Address;
  105. if ( !IPAddress.IsLoopback( ip ) && ip.AddressFamily != AddressFamily.InterNetworkV6 && !IsPrivateNetwork( ip ) )
  106. return true;
  107. }
  108. }
  109. return false;
  110. /*
  111. IPHostEntry iphe = Dns.GetHostEntry( Dns.GetHostName() );
  112. IPAddress[] ips = iphe.AddressList;
  113. for ( int i = 0; i < ips.Length; ++i )
  114. {
  115. if ( ips[i].AddressFamily != AddressFamily.InterNetworkV6 && !IsPrivateNetwork( ips[i] ) )
  116. return true;
  117. }
  118. return false;
  119. */
  120. }
  121. private static bool IsPrivateNetwork( IPAddress ip )
  122. {
  123. // 10.0.0.0/8
  124. // 172.16.0.0/12
  125. // 192.168.0.0/16
  126. if ( ip.AddressFamily == AddressFamily.InterNetworkV6 )
  127. return false;
  128. if ( Utility.IPMatch( "192.168.*", ip ) )
  129. return true;
  130. else if ( Utility.IPMatch( "10.*", ip ) )
  131. return true;
  132. else if ( Utility.IPMatch( "172.16-31.*", ip ) )
  133. return true;
  134. else
  135. return false;
  136. }
  137. private static IPAddress FindPublicAddress()
  138. {
  139. try {
  140. WebRequest req = HttpWebRequest.Create( "http://www.runuo.com/ip.php" );
  141. req.Timeout = 15000;
  142. WebResponse res = req.GetResponse();
  143. Stream s = res.GetResponseStream();
  144. StreamReader sr = new StreamReader( s );
  145. IPAddress ip = IPAddress.Parse( sr.ReadLine() );
  146. sr.Close();
  147. s.Close();
  148. res.Close();
  149. return ip;
  150. } catch {
  151. return null;
  152. }
  153. }
  154. }
  155. }