Unsupported library that attempts to punch holes through NAT
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

NatTraverser.java 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * To change this template, choose Tools | Templates
  3. * and open the template in the editor.
  4. */
  5. package com.md87.nat;
  6. import de.javawi.jstun.attribute.MappedAddress;
  7. import de.javawi.jstun.attribute.MessageAttribute;
  8. import de.javawi.jstun.attribute.MessageAttributeException;
  9. import de.javawi.jstun.attribute.MessageAttributeParsingException;
  10. import de.javawi.jstun.header.MessageHeader;
  11. import de.javawi.jstun.header.MessageHeaderParsingException;
  12. import de.javawi.jstun.test.DiscoveryInfo;
  13. import de.javawi.jstun.test.DiscoveryTest;
  14. import de.javawi.jstun.util.UtilityException;
  15. import java.io.IOException;
  16. import java.net.DatagramPacket;
  17. import java.net.DatagramSocket;
  18. import java.net.InetAddress;
  19. import java.net.InetSocketAddress;
  20. import java.net.NetworkInterface;
  21. import java.net.SocketException;
  22. import java.util.Enumeration;
  23. import java.util.HashMap;
  24. import java.util.Map;
  25. import java.util.concurrent.Semaphore;
  26. /**
  27. *
  28. * @author chris
  29. */
  30. public class NatTraverser {
  31. protected final CommsAgent agent;
  32. protected InetAddress address;
  33. protected DiscoveryInfo result;
  34. protected NatType theirType;
  35. protected NatType ourType;
  36. public NatTraverser(final CommsAgent agent) {
  37. this.agent = agent;
  38. }
  39. public void setInetAddress(final InetAddress address) {
  40. this.address = address;
  41. this.result = getDiscoveryInfo(address);
  42. addressUpdated();
  43. }
  44. public void findBestInetAddress() {
  45. final Semaphore threadSem = new Semaphore(0);
  46. NatType bestType = null;
  47. Map.Entry<InetAddress, DiscoveryInfo> best = null;
  48. for (final Map.Entry<InetAddress, DiscoveryInfo> info : getDiscoveryInfos().entrySet()) {
  49. if (info.getValue() == null) {
  50. return;
  51. }
  52. final NatType thisType = getTypeFromDI(info.getValue());
  53. if (thisType != null &&
  54. (bestType == null || thisType.ordinal() < bestType.ordinal())) {
  55. bestType = thisType;
  56. best = info;
  57. }
  58. }
  59. if (best != null) {
  60. this.address = best.getKey();
  61. this.result = best.getValue();
  62. addressUpdated();
  63. }
  64. }
  65. protected void addressUpdated() {
  66. try {
  67. ourType = getTypeFromDI(result);
  68. System.out.println("Using local IP: " + result.getLocalIP().getHostAddress()
  69. + " (remote: " + result.getPublicIP().getHostAddress() + "; iface: "
  70. + NetworkInterface.getByInetAddress(result.getLocalIP()).getName()
  71. + "; type: " + ourType + ")");
  72. agent.sendNATType(ourType);
  73. theirType = agent.readNATType();
  74. } catch (SocketException ex) {
  75. // Meh
  76. }
  77. }
  78. public DatagramSocket traverse() throws UnsupportedOperationException,
  79. SocketException, UtilityException, IOException,
  80. MessageHeaderParsingException, MessageAttributeParsingException, InterruptedException {
  81. if (!getTypeFromDI(result).canTraverseWith(theirType)) {
  82. throw new UnsupportedOperationException("Cannot traverse "
  83. + "between a " + ourType + " network and a "
  84. + theirType + " network.");
  85. }
  86. final DatagramSocket sock
  87. = new DatagramSocket(new InetSocketAddress(address, 0));
  88. sock.connect(InetAddress.getByName("stun.dmdirc.com"), 3478);
  89. MessageHeader sendMH = new MessageHeader(MessageHeader.MessageHeaderType.BindingRequest);
  90. sendMH.generateTransactionID();
  91. byte[] data = sendMH.getBytes();
  92. DatagramPacket send = new DatagramPacket(data, data.length);
  93. sock.send(send);
  94. MessageHeader receiveMH = new MessageHeader();
  95. while (!(receiveMH.equalTransactionID(sendMH))) {
  96. DatagramPacket receive = new DatagramPacket(new byte[200], 200);
  97. sock.receive(receive);
  98. receiveMH = MessageHeader.parseHeader(receive.getData());
  99. receiveMH.parseAttributes(receive.getData());
  100. }
  101. final MappedAddress ma = (MappedAddress) receiveMH.getMessageAttribute(MessageAttribute.MessageAttributeType.MappedAddress);
  102. System.out.println("I'm listening on " + address.getHostAddress() + ":"
  103. + sock.getLocalPort() + ". STUN server says I'm sending packets from "
  104. + ma.getAddress().getInetAddress().getHostAddress() + ":"
  105. + ma.getPort());
  106. agent.sendAddress(ma.getAddress().getInetAddress());
  107. agent.sendPort(ma.getPort());
  108. final InetAddress raddr = agent.readAddress();
  109. final int rport = agent.readPort();
  110. sock.disconnect();
  111. sock.connect(raddr, rport);
  112. boolean cont;
  113. do {
  114. cont = false;
  115. DatagramPacket p = new DatagramPacket("NatTraverser!".getBytes(), 13);
  116. try {
  117. sock.send(p);
  118. p = new DatagramPacket(new byte[13], 13);
  119. sock.receive(p);
  120. } catch (IOException ex) {
  121. ex.printStackTrace();
  122. cont = true;
  123. Thread.sleep(500);
  124. }
  125. } while (cont);
  126. return sock;
  127. }
  128. public static NatType getTypeFromDI(final DiscoveryInfo info) {
  129. if (info.isFullCone()) {
  130. return NatType.FULL_CONE;
  131. } else if (info.isOpenAccess()) {
  132. return NatType.OPEN;
  133. } else if (info.isPortRestrictedCone()) {
  134. return NatType.PORT_RESTRICTED_CONE;
  135. } else if (info.isRestrictedCone()) {
  136. return NatType.RESTRICTED_CONE;
  137. } else if (info.isSymmetric()) {
  138. return NatType.SYMMETRIC;
  139. } else {
  140. return null;
  141. }
  142. }
  143. protected Map<InetAddress, DiscoveryInfo> getDiscoveryInfos() {
  144. final Map<InetAddress, DiscoveryInfo> res
  145. = new HashMap<InetAddress, DiscoveryInfo>();
  146. try {
  147. final Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
  148. while (en.hasMoreElements()) {
  149. final Enumeration<InetAddress> inen = en.nextElement().getInetAddresses();
  150. while (inen.hasMoreElements()) {
  151. final InetAddress ia = inen.nextElement();
  152. res.put(ia, getDiscoveryInfo(ia));
  153. }
  154. }
  155. } catch (SocketException ex) {
  156. // Meh
  157. }
  158. return res;
  159. }
  160. protected DiscoveryInfo getDiscoveryInfo(final InetAddress iaddress) {
  161. try {
  162. return new DiscoveryTest(iaddress, "stun.dmdirc.com", 3478).test();
  163. } catch (IOException ex) {
  164. // Meh
  165. } catch (UtilityException ex) {
  166. // Meh
  167. } catch (MessageAttributeException ex) {
  168. // Meh
  169. } catch (MessageHeaderParsingException ex) {
  170. // Meh
  171. }
  172. return null;
  173. }
  174. }